carray 3.0.1 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +520 -0
- data/README.md +2 -2
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +33 -4
- data/ext/ca_axis_group.c +202 -96
- data/ext/ca_categorical_iterator.c +108 -54
- data/ext/ca_kernel_iterator.c +317 -51
- data/ext/ca_kernel_iterator.h +142 -35
- data/ext/ca_obj_array.c +62 -20
- data/ext/ca_obj_block.c +4 -4
- data/ext/ca_obj_const_string.c +85 -26
- data/ext/ca_obj_face.c +24 -0
- data/ext/ca_obj_face.h +15 -0
- data/ext/ca_obj_fixlen_string.c +18 -5
- data/ext/ca_obj_meld.c +123 -25
- data/ext/ca_obj_object.c +8 -0
- data/ext/ca_obj_select.c +49 -34
- data/ext/ca_obj_stack.c +3 -8
- data/ext/ca_obj_stride.c +72 -1
- data/ext/ca_obj_string.c +8 -4
- data/ext/ca_obj_window.c +8 -2
- data/ext/ca_op_ipower.c +1 -2
- data/ext/ca_rng_normal.h +42 -0
- data/ext/ca_rng_xoshiro256pp.h +105 -0
- data/ext/ca_sweep_engine.c +307 -143
- data/ext/ca_sweep_engine.h +26 -5
- data/ext/carray.h +21 -2
- data/ext/carray_access.c +32 -20
- data/ext/carray_address_basis.c +590 -0
- data/ext/carray_broadcast.c +3 -3
- data/ext/carray_call_cfunc.c +667 -483
- data/ext/carray_cast.c +115 -41
- data/ext/carray_copy.c +55 -30
- data/ext/carray_core.c +83 -3
- data/ext/carray_count.c +9 -10
- data/ext/carray_factorize.c +46 -25
- data/ext/carray_internal.h +17 -0
- data/ext/carray_kernels_reduce_aggregate.c +168 -0
- data/ext/carray_kernels_reduce_cumulative.c +270 -1
- data/ext/carray_kernels_reduce_extreme.c +554 -8
- data/ext/carray_kernels_scan.c +4 -4
- data/ext/carray_kernels_search.c +94 -14
- data/ext/carray_loop.c +7 -1
- data/ext/carray_mask.c +23 -8
- data/ext/carray_median_percentile.c +55 -0
- data/ext/carray_operator.c +4 -4
- data/ext/carray_order.c +1 -1
- data/ext/carray_random.c +384 -40
- data/ext/carray_slab.c +13 -0
- data/ext/carray_sort.c +20 -22
- data/ext/mk_call_cfunc.rb +103 -116
- data/ext/mkkernel.rb +297 -29
- data/ext/ruby_carray.c +10 -1
- data/ext/version.h +4 -4
- data/lib/carray/autoload_carray.rb +5 -3
- data/lib/carray/autoload_method_extension.rb +12 -0
- data/lib/carray/axis_group.rb +77 -0
- data/lib/carray/basics.rb +4 -0
- data/lib/carray/block_iterator.rb +92 -16
- data/lib/carray/categorical.rb +150 -33
- data/lib/carray/categorical_iterator.rb +207 -80
- data/lib/carray/const_string.rb +131 -27
- data/lib/carray/construct.rb +40 -0
- data/lib/carray/data_type_extension.rb +3 -0
- data/lib/carray/data_type_limits.rb +91 -0
- data/lib/carray/fixlen_string.rb +1 -1
- data/lib/carray/frame/csv_parser.rb +11 -4
- data/lib/carray/frame/frame.rb +81 -10
- data/lib/carray/frame/group.rb +36 -3
- data/lib/carray/frame/io.rb +67 -15
- data/lib/carray/frame/records.rb +18 -4
- data/lib/carray/frame/verbs.rb +14 -11
- data/lib/carray/inspect.rb +42 -9
- data/lib/carray/iterator.rb +143 -0
- data/lib/carray/lazy.rb +0 -37
- data/lib/carray/mask_gap_fill.rb +3 -1
- data/lib/carray/methods/discovery_along.rb +74 -0
- data/lib/carray/methods/factorize.rb +50 -0
- data/lib/carray/methods/is_in.rb +13 -2
- data/lib/carray/methods/locate_addr.rb +75 -2
- data/lib/carray/methods/mask_duplicates.rb +35 -1
- data/lib/carray/methods/nunique.rb +22 -1
- data/lib/carray/methods/repeat.rb +110 -0
- data/lib/carray/methods/unique.rb +41 -1
- data/lib/carray/rng.rb +86 -0
- data/lib/carray/slab_iterator.rb +58 -13
- data/lib/carray/string_operation_extension.rb +5 -1
- data/lib/carray/time.rb +18 -2
- data/lib/carray/window_iterator.rb +142 -20
- data/lib/carray.rb +2 -0
- data/yard-stubs/ca_obj_block.rb +2 -7
- data/yard-stubs/ca_obj_window.rb +10 -2
- data/yard-stubs/carray_access.rb +1 -1
- data/yard-stubs/carray_broadcast.rb +1 -1
- data/yard-stubs/carray_core.rb +0 -80
- data/yard-stubs/carray_count.rb +7 -2
- data/yard-stubs/carray_lazy.rb +205 -0
- data/yard-stubs/carray_math.rb +1486 -3
- data/yard-stubs/carray_median_percentile.rb +16 -2
- data/yard-stubs/carray_order.rb +9 -69
- data/yard-stubs/carray_slab.rb +9 -7
- data/yard-stubs/carray_sort.rb +7 -5
- metadata +9 -1
data/ext/carray_kernels_scan.c
CHANGED
|
@@ -1810,7 +1810,7 @@ cummax_ki_native_f32 (VALUE self, CArray *ca, int axis)
|
|
|
1810
1810
|
? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
|
|
1811
1811
|
: NULL;
|
|
1812
1812
|
CA_SLAB_SCAN_T_GATED(float, float, st_in, pi, mi,
|
|
1813
|
-
st_out, po, mo_fiber,
|
|
1813
|
+
st_out, po, mo_fiber, NAN, acc = fmax(acc, v); r = acc);
|
|
1814
1814
|
ca_iter_state_sync_slab(&st_out);
|
|
1815
1815
|
}
|
|
1816
1816
|
ca_iter_state_finish(&st_in);
|
|
@@ -1862,7 +1862,7 @@ cummax_ki_native_f64 (VALUE self, CArray *ca, int axis)
|
|
|
1862
1862
|
? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
|
|
1863
1863
|
: NULL;
|
|
1864
1864
|
CA_SLAB_SCAN_T_GATED(double, double, st_in, pi, mi,
|
|
1865
|
-
st_out, po, mo_fiber,
|
|
1865
|
+
st_out, po, mo_fiber, NAN, acc = fmax(acc, v); r = acc);
|
|
1866
1866
|
ca_iter_state_sync_slab(&st_out);
|
|
1867
1867
|
}
|
|
1868
1868
|
ca_iter_state_finish(&st_in);
|
|
@@ -2498,7 +2498,7 @@ cummin_ki_native_f32 (VALUE self, CArray *ca, int axis)
|
|
|
2498
2498
|
? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
|
|
2499
2499
|
: NULL;
|
|
2500
2500
|
CA_SLAB_SCAN_T_GATED(float, float, st_in, pi, mi,
|
|
2501
|
-
st_out, po, mo_fiber,
|
|
2501
|
+
st_out, po, mo_fiber, NAN, acc = fmin(acc, v); r = acc);
|
|
2502
2502
|
ca_iter_state_sync_slab(&st_out);
|
|
2503
2503
|
}
|
|
2504
2504
|
ca_iter_state_finish(&st_in);
|
|
@@ -2550,7 +2550,7 @@ cummin_ki_native_f64 (VALUE self, CArray *ca, int axis)
|
|
|
2550
2550
|
? op_mask + (ca_size_t)(po - co_root) / (ca_size_t) co->bytes
|
|
2551
2551
|
: NULL;
|
|
2552
2552
|
CA_SLAB_SCAN_T_GATED(double, double, st_in, pi, mi,
|
|
2553
|
-
st_out, po, mo_fiber,
|
|
2553
|
+
st_out, po, mo_fiber, NAN, acc = fmin(acc, v); r = acc);
|
|
2554
2554
|
ca_iter_state_sync_slab(&st_out);
|
|
2555
2555
|
}
|
|
2556
2556
|
ca_iter_state_finish(&st_in);
|
data/ext/carray_kernels_search.c
CHANGED
|
@@ -4247,7 +4247,7 @@ rb_ca_find_value_index_ki (VALUE self, VALUE rval, VALUE raxis)
|
|
|
4247
4247
|
}
|
|
4248
4248
|
if ( self_face_comparable ) {
|
|
4249
4249
|
if ( rval_is_face ) {
|
|
4250
|
-
rval =
|
|
4250
|
+
rval = ca_face_operand_descend(rval, "find_value_index_ki");
|
|
4251
4251
|
}
|
|
4252
4252
|
} else if ( self_was_face ) {
|
|
4253
4253
|
if ( rb_respond_to(self_ref, rb_intern("to_comparable")) ) {
|
|
@@ -8724,7 +8724,7 @@ rb_ca_bsearch_ki (VALUE self, VALUE rval, VALUE raxis)
|
|
|
8724
8724
|
}
|
|
8725
8725
|
if ( self_face_comparable ) {
|
|
8726
8726
|
if ( rval_is_face ) {
|
|
8727
|
-
rval =
|
|
8727
|
+
rval = ca_face_operand_descend(rval, "bsearch_ki");
|
|
8728
8728
|
}
|
|
8729
8729
|
} else if ( self_was_face ) {
|
|
8730
8730
|
if ( rb_respond_to(self_ref, rb_intern("to_comparable")) ) {
|
|
@@ -13046,7 +13046,7 @@ rb_ca_search_ki (int argc, VALUE *argv, VALUE self)
|
|
|
13046
13046
|
}
|
|
13047
13047
|
if ( self_face_comparable ) {
|
|
13048
13048
|
if ( rval_is_face ) {
|
|
13049
|
-
rval =
|
|
13049
|
+
rval = ca_face_operand_descend(rval, "search_ki");
|
|
13050
13050
|
}
|
|
13051
13051
|
} else if ( self_was_face ) {
|
|
13052
13052
|
if ( rb_respond_to(self_ref, rb_intern("to_comparable")) ) {
|
|
@@ -16724,12 +16724,32 @@ search_nearest_ki_native_object (VALUE self, CArray *ca, VALUE rval, int axis)
|
|
|
16724
16724
|
{
|
|
16725
16725
|
/* CA_OBJECT nearest: minimum of query_val.distance(cell), compared
|
|
16726
16726
|
with `<` (matches the legacy flat proc_nearest_addr_VALUE). */
|
|
16727
|
+
/* Nearest needs a metric. #distance is the protocol the 2.0 flat
|
|
16728
|
+
kernel used, back when Numeric#distance was a monkey patch; it
|
|
16729
|
+
is an opt-in refinement now, and a refinement does not reach an
|
|
16730
|
+
rb_funcall from C -- so a number reaching here answers no more
|
|
16731
|
+
than a String does. Measure a number the way #distance itself
|
|
16732
|
+
does, keep #distance for anything that defines a real one, and
|
|
16733
|
+
refuse the rest by name rather than let a bare NoMethodError out
|
|
16734
|
+
of the loop below. */
|
|
16735
|
+
ID nearest_id = rb_intern("distance");
|
|
16736
|
+
int nearest_by_distance = rb_respond_to(query_val, nearest_id);
|
|
16737
|
+
if ( ! nearest_by_distance && ! rb_obj_is_kind_of(query_val, rb_cNumeric) ) {
|
|
16738
|
+
rb_raise(rb_eCADataTypeError,
|
|
16739
|
+
"search_nearest: nearest needs a distance, and %s is neither a "
|
|
16740
|
+
"number nor answers #distance (define one on the stored "
|
|
16741
|
+
"objects, or use search / bsearch for an exact match)",
|
|
16742
|
+
rb_obj_classname(query_val));
|
|
16743
|
+
}
|
|
16727
16744
|
result = (ca_size_t) -1;
|
|
16728
16745
|
VALUE best = Qnil;
|
|
16729
16746
|
for ( ca_size_t i = 0; i < slab_n; i++ ) {
|
|
16730
16747
|
if ( mask_in && mask_in[i * slab_mask_stride] ) continue;
|
|
16731
16748
|
VALUE v = *(VALUE *)(slab_ptr + i * slab_stride);
|
|
16732
|
-
VALUE dist =
|
|
16749
|
+
VALUE dist = nearest_by_distance
|
|
16750
|
+
? rb_funcall(query_val, nearest_id, 1, v)
|
|
16751
|
+
: rb_funcall(rb_funcall(query_val, '-', 1, v),
|
|
16752
|
+
rb_intern("abs"), 0);
|
|
16733
16753
|
if ( NIL_P(best) || RTEST(rb_funcall(dist, rb_intern("<"), 1, best)) ) {
|
|
16734
16754
|
best = dist; result = i;
|
|
16735
16755
|
}
|
|
@@ -16975,12 +16995,32 @@ search_nearest_ki_native_object (VALUE self, CArray *ca, VALUE rval, int axis)
|
|
|
16975
16995
|
{
|
|
16976
16996
|
/* CA_OBJECT nearest: minimum of query_val.distance(cell), compared
|
|
16977
16997
|
with `<` (matches the legacy flat proc_nearest_addr_VALUE). */
|
|
16998
|
+
/* Nearest needs a metric. #distance is the protocol the 2.0 flat
|
|
16999
|
+
kernel used, back when Numeric#distance was a monkey patch; it
|
|
17000
|
+
is an opt-in refinement now, and a refinement does not reach an
|
|
17001
|
+
rb_funcall from C -- so a number reaching here answers no more
|
|
17002
|
+
than a String does. Measure a number the way #distance itself
|
|
17003
|
+
does, keep #distance for anything that defines a real one, and
|
|
17004
|
+
refuse the rest by name rather than let a bare NoMethodError out
|
|
17005
|
+
of the loop below. */
|
|
17006
|
+
ID nearest_id = rb_intern("distance");
|
|
17007
|
+
int nearest_by_distance = rb_respond_to(query_val, nearest_id);
|
|
17008
|
+
if ( ! nearest_by_distance && ! rb_obj_is_kind_of(query_val, rb_cNumeric) ) {
|
|
17009
|
+
rb_raise(rb_eCADataTypeError,
|
|
17010
|
+
"search_nearest: nearest needs a distance, and %s is neither a "
|
|
17011
|
+
"number nor answers #distance (define one on the stored "
|
|
17012
|
+
"objects, or use search / bsearch for an exact match)",
|
|
17013
|
+
rb_obj_classname(query_val));
|
|
17014
|
+
}
|
|
16978
17015
|
result = (ca_size_t) -1;
|
|
16979
17016
|
VALUE best = Qnil;
|
|
16980
17017
|
for ( ca_size_t i = 0; i < slab_n; i++ ) {
|
|
16981
17018
|
if ( mask_in && mask_in[i * slab_mask_stride] ) continue;
|
|
16982
17019
|
VALUE v = *(VALUE *)(slab_ptr + i * slab_stride);
|
|
16983
|
-
VALUE dist =
|
|
17020
|
+
VALUE dist = nearest_by_distance
|
|
17021
|
+
? rb_funcall(query_val, nearest_id, 1, v)
|
|
17022
|
+
: rb_funcall(rb_funcall(query_val, '-', 1, v),
|
|
17023
|
+
rb_intern("abs"), 0);
|
|
16984
17024
|
if ( NIL_P(best) || RTEST(rb_funcall(dist, rb_intern("<"), 1, best)) ) {
|
|
16985
17025
|
best = dist; result = i;
|
|
16986
17026
|
}
|
|
@@ -17055,7 +17095,7 @@ rb_ca_search_nearest_ki (VALUE self, VALUE rval, VALUE raxis)
|
|
|
17055
17095
|
}
|
|
17056
17096
|
if ( self_face_comparable ) {
|
|
17057
17097
|
if ( rval_is_face ) {
|
|
17058
|
-
rval =
|
|
17098
|
+
rval = ca_face_operand_descend(rval, "search_nearest_ki");
|
|
17059
17099
|
}
|
|
17060
17100
|
} else if ( self_was_face ) {
|
|
17061
17101
|
if ( rb_respond_to(self_ref, rb_intern("to_comparable")) ) {
|
|
@@ -21801,7 +21841,7 @@ rb_ca_bsearch_addr_ki (VALUE self, VALUE rval, VALUE raxis)
|
|
|
21801
21841
|
}
|
|
21802
21842
|
if ( self_face_comparable ) {
|
|
21803
21843
|
if ( rval_is_face ) {
|
|
21804
|
-
rval =
|
|
21844
|
+
rval = ca_face_operand_descend(rval, "bsearch_addr_ki");
|
|
21805
21845
|
}
|
|
21806
21846
|
} else if ( self_was_face ) {
|
|
21807
21847
|
if ( rb_respond_to(self_ref, rb_intern("to_comparable")) ) {
|
|
@@ -26403,7 +26443,7 @@ rb_ca_search_addr_ki (int argc, VALUE *argv, VALUE self)
|
|
|
26403
26443
|
}
|
|
26404
26444
|
if ( self_face_comparable ) {
|
|
26405
26445
|
if ( rval_is_face ) {
|
|
26406
|
-
rval =
|
|
26446
|
+
rval = ca_face_operand_descend(rval, "search_addr_ki");
|
|
26407
26447
|
}
|
|
26408
26448
|
} else if ( self_was_face ) {
|
|
26409
26449
|
if ( rb_respond_to(self_ref, rb_intern("to_comparable")) ) {
|
|
@@ -30338,12 +30378,32 @@ for ( int8_t mm = 0; mm < st.outer_ndim; mm++ ) {
|
|
|
30338
30378
|
{
|
|
30339
30379
|
/* CA_OBJECT nearest (view_flat addr): minimum of
|
|
30340
30380
|
query_val.distance(cell), compared with `<`. */
|
|
30381
|
+
/* Nearest needs a metric. #distance is the protocol the 2.0 flat
|
|
30382
|
+
kernel used, back when Numeric#distance was a monkey patch; it
|
|
30383
|
+
is an opt-in refinement now, and a refinement does not reach an
|
|
30384
|
+
rb_funcall from C -- so a number reaching here answers no more
|
|
30385
|
+
than a String does. Measure a number the way #distance itself
|
|
30386
|
+
does, keep #distance for anything that defines a real one, and
|
|
30387
|
+
refuse the rest by name rather than let a bare NoMethodError out
|
|
30388
|
+
of the loop below. */
|
|
30389
|
+
ID nearest_id = rb_intern("distance");
|
|
30390
|
+
int nearest_by_distance = rb_respond_to(query_val, nearest_id);
|
|
30391
|
+
if ( ! nearest_by_distance && ! rb_obj_is_kind_of(query_val, rb_cNumeric) ) {
|
|
30392
|
+
rb_raise(rb_eCADataTypeError,
|
|
30393
|
+
"search_nearest_addr: nearest needs a distance, and %s is neither a "
|
|
30394
|
+
"number nor answers #distance (define one on the stored "
|
|
30395
|
+
"objects, or use search / bsearch for an exact match)",
|
|
30396
|
+
rb_obj_classname(query_val));
|
|
30397
|
+
}
|
|
30341
30398
|
result = (ca_size_t) -1;
|
|
30342
30399
|
VALUE best = Qnil;
|
|
30343
30400
|
for ( ca_size_t i = 0; i < slab_n; i++ ) {
|
|
30344
30401
|
if ( mask_in && mask_in[i * slab_mask_stride] ) continue;
|
|
30345
30402
|
VALUE v = *(VALUE *)(slab_ptr + i * slab_stride);
|
|
30346
|
-
VALUE dist =
|
|
30403
|
+
VALUE dist = nearest_by_distance
|
|
30404
|
+
? rb_funcall(query_val, nearest_id, 1, v)
|
|
30405
|
+
: rb_funcall(rb_funcall(query_val, '-', 1, v),
|
|
30406
|
+
rb_intern("abs"), 0);
|
|
30347
30407
|
if ( NIL_P(best) || RTEST(rb_funcall(dist, rb_intern("<"), 1, best)) ) {
|
|
30348
30408
|
best = dist; result = i;
|
|
30349
30409
|
}
|
|
@@ -30596,12 +30656,32 @@ rb_raise(rb_eNotImpError, "search_nearest_addr_ki: view_flat semantics with CArr
|
|
|
30596
30656
|
{
|
|
30597
30657
|
/* CA_OBJECT nearest (view_flat addr): minimum of
|
|
30598
30658
|
query_val.distance(cell), compared with `<`. */
|
|
30659
|
+
/* Nearest needs a metric. #distance is the protocol the 2.0 flat
|
|
30660
|
+
kernel used, back when Numeric#distance was a monkey patch; it
|
|
30661
|
+
is an opt-in refinement now, and a refinement does not reach an
|
|
30662
|
+
rb_funcall from C -- so a number reaching here answers no more
|
|
30663
|
+
than a String does. Measure a number the way #distance itself
|
|
30664
|
+
does, keep #distance for anything that defines a real one, and
|
|
30665
|
+
refuse the rest by name rather than let a bare NoMethodError out
|
|
30666
|
+
of the loop below. */
|
|
30667
|
+
ID nearest_id = rb_intern("distance");
|
|
30668
|
+
int nearest_by_distance = rb_respond_to(query_val, nearest_id);
|
|
30669
|
+
if ( ! nearest_by_distance && ! rb_obj_is_kind_of(query_val, rb_cNumeric) ) {
|
|
30670
|
+
rb_raise(rb_eCADataTypeError,
|
|
30671
|
+
"search_nearest_addr: nearest needs a distance, and %s is neither a "
|
|
30672
|
+
"number nor answers #distance (define one on the stored "
|
|
30673
|
+
"objects, or use search / bsearch for an exact match)",
|
|
30674
|
+
rb_obj_classname(query_val));
|
|
30675
|
+
}
|
|
30599
30676
|
result = (ca_size_t) -1;
|
|
30600
30677
|
VALUE best = Qnil;
|
|
30601
30678
|
for ( ca_size_t i = 0; i < slab_n; i++ ) {
|
|
30602
30679
|
if ( mask_in && mask_in[i * slab_mask_stride] ) continue;
|
|
30603
30680
|
VALUE v = *(VALUE *)(slab_ptr + i * slab_stride);
|
|
30604
|
-
VALUE dist =
|
|
30681
|
+
VALUE dist = nearest_by_distance
|
|
30682
|
+
? rb_funcall(query_val, nearest_id, 1, v)
|
|
30683
|
+
: rb_funcall(rb_funcall(query_val, '-', 1, v),
|
|
30684
|
+
rb_intern("abs"), 0);
|
|
30605
30685
|
if ( NIL_P(best) || RTEST(rb_funcall(dist, rb_intern("<"), 1, best)) ) {
|
|
30606
30686
|
best = dist; result = i;
|
|
30607
30687
|
}
|
|
@@ -30676,7 +30756,7 @@ rb_ca_search_nearest_addr_ki (VALUE self, VALUE rval, VALUE raxis)
|
|
|
30676
30756
|
}
|
|
30677
30757
|
if ( self_face_comparable ) {
|
|
30678
30758
|
if ( rval_is_face ) {
|
|
30679
|
-
rval =
|
|
30759
|
+
rval = ca_face_operand_descend(rval, "search_nearest_addr_ki");
|
|
30680
30760
|
}
|
|
30681
30761
|
} else if ( self_was_face ) {
|
|
30682
30762
|
if ( rb_respond_to(self_ref, rb_intern("to_comparable")) ) {
|
|
@@ -31230,7 +31310,7 @@ rb_ca_linear_section_binary_ki (VALUE self, VALUE rval, VALUE raxis)
|
|
|
31230
31310
|
}
|
|
31231
31311
|
if ( self_face_comparable ) {
|
|
31232
31312
|
if ( rval_is_face ) {
|
|
31233
|
-
rval =
|
|
31313
|
+
rval = ca_face_operand_descend(rval, "linear_section_binary_ki");
|
|
31234
31314
|
}
|
|
31235
31315
|
} else if ( self_was_face ) {
|
|
31236
31316
|
if ( rb_respond_to(self_ref, rb_intern("to_comparable")) ) {
|
|
@@ -31679,7 +31759,7 @@ rb_ca_linear_section_linear_ki (VALUE self, VALUE rval, VALUE raxis)
|
|
|
31679
31759
|
}
|
|
31680
31760
|
if ( self_face_comparable ) {
|
|
31681
31761
|
if ( rval_is_face ) {
|
|
31682
|
-
rval =
|
|
31762
|
+
rval = ca_face_operand_descend(rval, "linear_section_linear_ki");
|
|
31683
31763
|
}
|
|
31684
31764
|
} else if ( self_was_face ) {
|
|
31685
31765
|
if ( rb_respond_to(self_ref, rb_intern("to_comparable")) ) {
|
|
@@ -32090,7 +32170,7 @@ rb_ca_linear_fetch_ki (VALUE self, VALUE rval, VALUE raxis)
|
|
|
32090
32170
|
}
|
|
32091
32171
|
if ( self_face_comparable ) {
|
|
32092
32172
|
if ( rval_is_face ) {
|
|
32093
|
-
rval =
|
|
32173
|
+
rval = ca_face_operand_descend(rval, "linear_fetch_ki");
|
|
32094
32174
|
}
|
|
32095
32175
|
} else if ( self_was_face ) {
|
|
32096
32176
|
if ( rb_respond_to(self_ref, rb_intern("to_comparable")) ) {
|
data/ext/carray_loop.c
CHANGED
|
@@ -120,6 +120,13 @@ rb_ca_index_walk (VALUE self, CArray *ca, int8_t level,
|
|
|
120
120
|
volatile VALUE ret = Qnil;
|
|
121
121
|
ca_size_t i;
|
|
122
122
|
if ( level == ca->ndim - 1 ) {
|
|
123
|
+
/* One value-yield buffer for the whole innermost run. It was once an
|
|
124
|
+
ALLOCA_N inside the loop, which never releases per iteration: the C
|
|
125
|
+
stack grew by (ndim + 1) VALUEs per cell and a long enough axis
|
|
126
|
+
raised SystemStackError (a 1-D each_with_index / map_with_index!
|
|
127
|
+
died around a million cells on the main stack, and far earlier on a
|
|
128
|
+
Thread's smaller one). */
|
|
129
|
+
VALUE argv[CA_RANK_MAX + 1];
|
|
123
130
|
for (i=0; i<ca->dim[level]; i++) {
|
|
124
131
|
volatile VALUE obj;
|
|
125
132
|
idx[level] = i;
|
|
@@ -132,7 +139,6 @@ rb_ca_index_walk (VALUE self, CArray *ca, int8_t level,
|
|
|
132
139
|
that want the whole subscript should write |*idx|. */
|
|
133
140
|
if ( mode & CA_LOOP_WITH_VALUE ) {
|
|
134
141
|
int argc = (int)ca->ndim + 1;
|
|
135
|
-
VALUE *argv = ALLOCA_N(VALUE, argc);
|
|
136
142
|
argv[0] = rb_ca_fetch_index(self, idx);
|
|
137
143
|
MEMCPY(argv + 1, RARRAY_CONST_PTR(ridx), VALUE, ca->ndim);
|
|
138
144
|
obj = rb_yield_values2(argc, argv);
|
data/ext/carray_mask.c
CHANGED
|
@@ -660,32 +660,47 @@ ca_unmask (void *ap, char *fill_value)
|
|
|
660
660
|
}
|
|
661
661
|
}
|
|
662
662
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
{
|
|
666
|
-
CArray *ca = (CArray *) ap;
|
|
663
|
+
typedef struct {
|
|
664
|
+
CArray *ca;
|
|
667
665
|
CArray *co;
|
|
666
|
+
char *fill_value;
|
|
667
|
+
} ca_unmask_copy_args_t;
|
|
668
|
+
|
|
669
|
+
static VALUE
|
|
670
|
+
ca_unmask_copy_fill (VALUE arg)
|
|
671
|
+
{
|
|
672
|
+
ca_unmask_copy_args_t *a = (ca_unmask_copy_args_t *) arg;
|
|
673
|
+
CArray *ca = a->ca, *co = a->co;
|
|
668
674
|
char *q;
|
|
669
675
|
boolean8_t *m;
|
|
670
676
|
ca_size_t i;
|
|
671
677
|
|
|
672
|
-
co = ca_template(ca);
|
|
673
678
|
ca_copy_data(ca, co->ptr);
|
|
674
679
|
|
|
675
|
-
if ( fill_value && ca_has_mask(ca) ) {
|
|
680
|
+
if ( a->fill_value && ca_has_mask(ca) ) {
|
|
676
681
|
ca_attach(ca);
|
|
677
682
|
q = co->ptr;
|
|
678
683
|
m = (boolean8_t *) ca->mask->ptr;
|
|
679
684
|
for (i=0; i<ca->elements; i++) {
|
|
680
685
|
if ( *m ) {
|
|
681
|
-
memcpy(q, fill_value, ca->bytes);
|
|
686
|
+
memcpy(q, a->fill_value, ca->bytes);
|
|
682
687
|
}
|
|
683
688
|
m++; q+=co->bytes;
|
|
684
689
|
}
|
|
685
690
|
ca_detach(ca);
|
|
686
691
|
}
|
|
692
|
+
return Qnil;
|
|
693
|
+
}
|
|
687
694
|
|
|
688
|
-
|
|
695
|
+
CArray *
|
|
696
|
+
ca_unmask_copy (void *ap, char *fill_value)
|
|
697
|
+
{
|
|
698
|
+
ca_unmask_copy_args_t a;
|
|
699
|
+
a.ca = (CArray *) ap;
|
|
700
|
+
a.co = ca_template(a.ca);
|
|
701
|
+
a.fill_value = fill_value;
|
|
702
|
+
ca_fill_or_free(a.co, ca_unmask_copy_fill, (VALUE) &a);
|
|
703
|
+
return a.co;
|
|
689
704
|
}
|
|
690
705
|
|
|
691
706
|
void
|
|
@@ -336,6 +336,48 @@ median_flat (VALUE self, long min_count, VALUE fill_value, int keep_axis)
|
|
|
336
336
|
Every function in this block (down to the median entry) is [object].
|
|
337
337
|
===================================================================== */
|
|
338
338
|
|
|
339
|
+
/* [object] Is this operand's arithmetic the arithmetic interpolation means?
|
|
340
|
+
`lo` / `hi` are a stored object on the flat path and an object CArray of
|
|
341
|
+
them on the per-axis one, so look through a CArray to an element. An
|
|
342
|
+
empty one has nothing to interpolate and passes. */
|
|
343
|
+
static int
|
|
344
|
+
mp_object_interpolates (VALUE v)
|
|
345
|
+
{
|
|
346
|
+
if ( rb_obj_is_kind_of(v, rb_cNumeric) ) {
|
|
347
|
+
return 1;
|
|
348
|
+
}
|
|
349
|
+
if ( rb_obj_is_kind_of(v, rb_cCArray) ) {
|
|
350
|
+
CArray *ca;
|
|
351
|
+
GetCArray(v, ca);
|
|
352
|
+
if ( ca->elements == 0 ) {
|
|
353
|
+
return 1;
|
|
354
|
+
}
|
|
355
|
+
return rb_obj_is_kind_of(rb_ca_fetch_addr(v, 0), rb_cNumeric) ? 1 : 0;
|
|
356
|
+
}
|
|
357
|
+
return 0;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/* [object] Refuse to interpolate between two elements that have no
|
|
361
|
+
arithmetic meaning it. A String has both a `*` and a `+`, and
|
|
362
|
+
String#* truncates the Float weight to zero -- so :linear quietly
|
|
363
|
+
returned "" instead of failing, which is the reason this guard is
|
|
364
|
+
here rather than a rescue. The three picking methods need no
|
|
365
|
+
arithmetic and are the way through. */
|
|
366
|
+
static void
|
|
367
|
+
mp_require_interpolable (const char *who, VALUE method, VALUE lo)
|
|
368
|
+
{
|
|
369
|
+
if ( mp_object_interpolates(lo) ) {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
rb_raise(rb_eCADataTypeError,
|
|
373
|
+
"%s: method: :%s interpolates between two elements, which %s "
|
|
374
|
+
"does not support; use method: :lower, :higher or :nearest to "
|
|
375
|
+
"pick an element instead",
|
|
376
|
+
who, rb_id2name(SYM2ID(method)),
|
|
377
|
+
rb_obj_classname(rb_obj_is_kind_of(lo, rb_cCArray)
|
|
378
|
+
? rb_ca_fetch_addr(lo, 0) : lo));
|
|
379
|
+
}
|
|
380
|
+
|
|
339
381
|
/* [object] recv.mid(axis: raxis) -- e.g. min/max/sort along an axis. */
|
|
340
382
|
static VALUE
|
|
341
383
|
obj_call_axis (VALUE recv, ID mid, VALUE raxis)
|
|
@@ -419,6 +461,17 @@ median_object_axis (VALUE self, long axis, long n, int keep_axis)
|
|
|
419
461
|
long k = n / 2 - 1;
|
|
420
462
|
VALUE lo, hi;
|
|
421
463
|
obj_kth_pair(self, axis, k, n, &lo, &hi);
|
|
464
|
+
/* An even count has no middle element, only the average of two -- so
|
|
465
|
+
a column whose objects have no arithmetic has a median only at odd
|
|
466
|
+
length. percentile(50, method: :lower) names one either way. */
|
|
467
|
+
if ( ! mp_object_interpolates(lo) ) {
|
|
468
|
+
rb_raise(rb_eCADataTypeError,
|
|
469
|
+
"median: an even number of elements has no middle one, and "
|
|
470
|
+
"%s cannot be averaged; use percentile(50, method: :lower) "
|
|
471
|
+
"(or :higher / :nearest) to pick an element instead",
|
|
472
|
+
rb_obj_classname(rb_obj_is_kind_of(lo, rb_cCArray)
|
|
473
|
+
? rb_ca_fetch_addr(lo, 0) : lo));
|
|
474
|
+
}
|
|
422
475
|
result = rb_funcall(rb_funcall(lo, id_plus, 1, hi), id_div, 1, DBL2NUM(2.0));
|
|
423
476
|
} else {
|
|
424
477
|
VALUE kv = obj_kth_one(self, axis, (n - 1) / 2);
|
|
@@ -480,12 +533,14 @@ pct_compute_object (VALUE method, long k, double r, long n, VALUE lo, VALUE hi)
|
|
|
480
533
|
}
|
|
481
534
|
if ( method == sym_linear ) {
|
|
482
535
|
if ( r == 0.0 || k + 1 >= n ) return rb_funcall(lo, id_mul, 1, DBL2NUM(1.0));
|
|
536
|
+
mp_require_interpolable("percentile", method, lo);
|
|
483
537
|
VALUE a = rb_funcall(lo, id_mul, 1, DBL2NUM(1.0 - r));
|
|
484
538
|
VALUE b = rb_funcall(hi, id_mul, 1, DBL2NUM(r));
|
|
485
539
|
return rb_funcall(a, id_plus, 1, b);
|
|
486
540
|
}
|
|
487
541
|
if ( method == sym_midpoint ) {
|
|
488
542
|
if ( k + 1 >= n ) return rb_funcall(lo, id_mul, 1, DBL2NUM(1.0));
|
|
543
|
+
mp_require_interpolable("percentile", method, lo);
|
|
489
544
|
return rb_funcall(rb_funcall(lo, id_plus, 1, hi), id_div, 1, DBL2NUM(2.0));
|
|
490
545
|
}
|
|
491
546
|
rb_raise(rb_eArgError, "percentile: invalid method (BUG)");
|
data/ext/carray_operator.c
CHANGED
|
@@ -633,7 +633,7 @@ rb_ca_call_binop (volatile VALUE self, volatile VALUE other,
|
|
|
633
633
|
ca_size_t i1, i2, i3;
|
|
634
634
|
int fast_path;
|
|
635
635
|
|
|
636
|
-
/* do implicit casting
|
|
636
|
+
/* do implicit casting */
|
|
637
637
|
rb_ca_cast_self_or_other(&self, &other);
|
|
638
638
|
|
|
639
639
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca1);
|
|
@@ -1030,7 +1030,7 @@ rb_ca_call_binop_bang (VALUE self, VALUE other, ca_binop_func_t func[])
|
|
|
1030
1030
|
|
|
1031
1031
|
rb_ca_modify(self);
|
|
1032
1032
|
|
|
1033
|
-
/* do implicit casting
|
|
1033
|
+
/* do implicit casting */
|
|
1034
1034
|
rb_ca_cast_other(&self, &other);
|
|
1035
1035
|
|
|
1036
1036
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca1);
|
|
@@ -1572,7 +1572,7 @@ rb_ca_call_bincmp (volatile VALUE self, volatile VALUE other,
|
|
|
1572
1572
|
for fixlen-storage Faces (memcmp is already correct there). */
|
|
1573
1573
|
ca_face_reconcile_comparison(&self, &other);
|
|
1574
1574
|
|
|
1575
|
-
/* do implicit casting
|
|
1575
|
+
/* do implicit casting */
|
|
1576
1576
|
rb_ca_cast_self_or_other(&self, &other);
|
|
1577
1577
|
|
|
1578
1578
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca1);
|
|
@@ -1804,7 +1804,7 @@ rb_ca_coerce (VALUE self, VALUE other)
|
|
|
1804
1804
|
return rb_ca_coerce(self, rb_funcall(other,rb_intern("to_ca"),0));
|
|
1805
1805
|
}
|
|
1806
1806
|
else {
|
|
1807
|
-
/* do implicit casting
|
|
1807
|
+
/* do implicit casting */
|
|
1808
1808
|
rb_ca_cast_self_or_other(&self, &other);
|
|
1809
1809
|
return rb_assoc_new(other, self);
|
|
1810
1810
|
}
|
data/ext/carray_order.c
CHANGED
|
@@ -854,7 +854,7 @@ rb_ca_linear_section_m (int argc, VALUE *argv, VALUE self)
|
|
|
854
854
|
}
|
|
855
855
|
if ( self_comparable ) {
|
|
856
856
|
if ( val_is_face ) {
|
|
857
|
-
val =
|
|
857
|
+
val = ca_face_operand_descend(val, "linear_section");
|
|
858
858
|
}
|
|
859
859
|
}
|
|
860
860
|
else if ( self_is_face ) {
|