carray 3.0.2 → 3.0.3
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 +304 -0
- data/README.md +3 -4
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +225 -0
- data/ext/ca_axis_group.c +177 -99
- data/ext/ca_binop_dispatch.c +54 -32
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +66 -71
- data/ext/ca_compare.c +8 -2
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +27 -11
- data/ext/ca_kernel_iterator.c +663 -214
- data/ext/ca_kernel_iterator.h +231 -167
- data/ext/ca_monop_dispatch.c +4 -4
- data/ext/ca_monop_dispatch.h +4 -0
- data/ext/ca_obj_array.c +132 -22
- data/ext/ca_obj_bincmp.c +152 -121
- data/ext/ca_obj_binop.c +107 -210
- data/ext/ca_obj_bitarray.c +37 -24
- data/ext/ca_obj_bitfield.c +95 -62
- data/ext/ca_obj_block.c +1 -0
- data/ext/ca_obj_byte_swap.c +40 -40
- data/ext/ca_obj_const_string.c +96 -25
- data/ext/ca_obj_face.c +406 -64
- data/ext/ca_obj_face.h +92 -47
- data/ext/ca_obj_fake.c +21 -50
- data/ext/ca_obj_farray.c +1 -0
- data/ext/ca_obj_field.c +16 -3
- data/ext/ca_obj_fixlen_string.c +21 -21
- data/ext/ca_obj_grid.c +181 -124
- data/ext/ca_obj_meld.c +189 -107
- data/ext/ca_obj_moncmp.c +61 -61
- data/ext/ca_obj_monop.c +125 -107
- data/ext/ca_obj_object.c +543 -233
- data/ext/ca_obj_record.c +51 -16
- data/ext/ca_obj_reduce.c +5 -8
- data/ext/ca_obj_refer.c +117 -33
- data/ext/ca_obj_remap.c +57 -17
- data/ext/ca_obj_repeat.c +21 -5
- data/ext/ca_obj_roll.c +115 -11
- data/ext/ca_obj_select.c +47 -49
- data/ext/ca_obj_select_axis.c +58 -60
- data/ext/ca_obj_shift.c +22 -102
- data/ext/ca_obj_stack.c +223 -118
- data/ext/ca_obj_stride.c +195 -34
- data/ext/ca_obj_string.c +17 -18
- data/ext/ca_obj_tile.c +32 -16
- data/ext/ca_obj_time.c +23 -25
- data/ext/ca_obj_timedelta.c +21 -23
- data/ext/ca_obj_transpose.c +12 -3
- data/ext/ca_obj_triop.c +110 -117
- data/ext/ca_obj_window.c +149 -27
- data/ext/ca_op_ipower.c +24 -11
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +102 -79
- data/ext/ca_sweep_engine.h +7 -20
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +463 -0
- data/ext/carray.h +70 -27
- data/ext/carray_access.c +455 -211
- data/ext/carray_address_basis.c +177 -36
- data/ext/carray_attribute.c +45 -3
- data/ext/carray_bincount.c +32 -2
- data/ext/carray_broadcast.c +46 -14
- data/ext/carray_call_cfunc.c +0 -28
- data/ext/carray_cast.c +1444 -209
- data/ext/carray_cast_func.rb +34 -21
- data/ext/carray_conversion.c +197 -73
- data/ext/carray_copy.c +32 -11
- data/ext/carray_core.c +514 -122
- data/ext/carray_count.c +140 -87
- data/ext/carray_element.c +18 -27
- data/ext/carray_factorize.c +569 -277
- data/ext/carray_generate.c +76 -40
- data/ext/carray_histogram.c +152 -94
- data/ext/carray_hold.c +2 -1
- data/ext/carray_index_classifier.c +63 -96
- data/ext/carray_internal.h +385 -3
- data/ext/carray_lazy.c +834 -79
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +682 -316
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +221 -76
- data/ext/carray_memory_view.c +254 -248
- data/ext/carray_operator.c +1089 -359
- data/ext/carray_order.c +133 -69
- data/ext/carray_partition.c +102 -56
- data/ext/carray_random.c +273 -239
- data/ext/carray_scatter.c +308 -65
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +170 -70
- data/ext/carray_sort.c +215 -218
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +99 -21
- data/ext/carray_test.c +167 -64
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_utils.c +363 -98
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +0 -2
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1076 -846
- data/ext/ruby_carray.c +7 -1
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +39 -0
- data/lib/carray/autoload_carray.rb +19 -0
- data/lib/carray/autoload_method_extension.rb +6 -0
- data/lib/carray/axis_group.rb +174 -26
- data/lib/carray/basics.rb +91 -25
- data/lib/carray/bincount_nd.rb +6 -0
- data/lib/carray/block_iterator.rb +118 -48
- data/lib/carray/boolean_reduce.rb +21 -29
- data/lib/carray/categorical.rb +94 -26
- data/lib/carray/categorical_iterator.rb +333 -826
- data/lib/carray/complex.rb +36 -29
- data/lib/carray/conditional.rb +94 -7
- data/lib/carray/const_string.rb +46 -0
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +13 -7
- data/lib/carray/frame/csv_parser.rb +589 -82
- data/lib/carray/frame/describe.rb +79 -0
- data/lib/carray/frame/frame.rb +124 -25
- data/lib/carray/frame/group.rb +189 -63
- data/lib/carray/frame/io.rb +412 -72
- data/lib/carray/frame/join.rb +134 -46
- data/lib/carray/frame/records.rb +37 -16
- data/lib/carray/frame/reshape.rb +448 -0
- data/lib/carray/frame/sort.rb +26 -2
- data/lib/carray/frame/verbs.rb +715 -48
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +111 -2
- data/lib/carray/fusion.rb +229 -38
- data/lib/carray/inspect.rb +29 -11
- data/lib/carray/iterator.rb +14 -2
- data/lib/carray/lazy.rb +54 -30
- data/lib/carray/mask_gap_fill.rb +66 -52
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +40 -7
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bincount.rb +2 -2
- data/lib/carray/methods/bit_string.rb +14 -3
- data/lib/carray/methods/composition.rb +16 -10
- data/lib/carray/methods/factorize.rb +2 -2
- data/lib/carray/methods/gather_nd.rb +13 -2
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_in.rb +117 -4
- data/lib/carray/methods/join.rb +1 -1
- data/lib/carray/methods/locate_addr.rb +177 -36
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/repeat.rb +1 -20
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +11 -2
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/runtime.rb +14 -11
- data/lib/carray/segment_iterator.rb +990 -0
- data/lib/carray/serialize.rb +197 -27
- data/lib/carray/slab_iterator.rb +51 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string_operation_extension.rb +4 -3
- data/lib/carray/struct.rb +142 -51
- data/lib/carray/struct_builder.rb +110 -14
- data/lib/carray/table.rb +2 -2
- data/lib/carray/time.rb +517 -103
- data/lib/carray/window_iterator.rb +127 -72
- data/lib/carray.rb +2 -2
- data/yard-stubs/ca_obj_array.rb +4 -4
- data/yard-stubs/ca_obj_bitarray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +23 -12
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +1 -1
- data/yard-stubs/ca_obj_refer.rb +3 -3
- data/yard-stubs/ca_obj_roll.rb +0 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +1 -2
- data/yard-stubs/carray_access.rb +5 -4
- data/yard-stubs/carray_broadcast.rb +1 -1
- data/yard-stubs/carray_cast.rb +78 -43
- data/yard-stubs/carray_conversion.rb +13 -1
- data/yard-stubs/carray_copy.rb +8 -3
- data/yard-stubs/carray_core.rb +3 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +34 -10
- data/yard-stubs/carray_math.rb +25 -13
- data/yard-stubs/carray_median_percentile.rb +10 -6
- data/yard-stubs/carray_order.rb +34 -13
- data/yard-stubs/carray_scatter.rb +10 -3
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +2 -1
- data/yard-stubs/carray_sort.rb +43 -3
- data/yard-stubs/carray_test.rb +10 -0
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +11 -19
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_build_flags.h +0 -3
- data/ext/carray_config.h +0 -28
- data/ext/carray_kernels_bincmp.c +0 -4446
- data/ext/carray_kernels_binop.c +0 -11001
- data/ext/carray_kernels_init.c +0 -1131
- data/ext/carray_kernels_map.c +0 -3467
- data/ext/carray_kernels_moncmp.c +0 -2097
- data/ext/carray_kernels_monop.c +0 -18313
- data/ext/carray_kernels_reduce_aggregate.c +0 -26005
- data/ext/carray_kernels_reduce_boolean.c +0 -330
- data/ext/carray_kernels_reduce_cumulative.c +0 -14862
- data/ext/carray_kernels_reduce_extreme.c +0 -17494
- data/ext/carray_kernels_reduce_variance.c +0 -3910
- data/ext/carray_kernels_scan.c +0 -3693
- data/ext/carray_kernels_search.c +0 -32218
- data/ext/carray_kernels_sort.c +0 -10626
- data/ext/carray_kernels_triop.c +0 -1392
data/ext/carray_math_kernel.h
CHANGED
|
@@ -41,6 +41,8 @@
|
|
|
41
41
|
|
|
42
42
|
#include "ruby.h"
|
|
43
43
|
#include "carray.h"
|
|
44
|
+
#include "carray_internal.h" /* ca_integer_arg, ca_calling_method_name */
|
|
45
|
+
#include "ca_obj_face.h" /* ca_face_refuse_numeric */
|
|
44
46
|
#include <math.h>
|
|
45
47
|
|
|
46
48
|
/* Externals (link-time; kept out of carray.h to keep the header lean). */
|
|
@@ -50,6 +52,7 @@ extern VALUE rb_ca_insert_axis (int argc, VALUE *argv, VALUE self); /* c
|
|
|
50
52
|
static ID id_axis, id_sort_copy, id_is_not_masked;
|
|
51
53
|
/* object lane (arbitrary Ruby objects -> arithmetic is irreducibly funcall) */
|
|
52
54
|
static ID id_plus, id_div, id_mul, id_min, id_max, id_sort, id_copy;
|
|
55
|
+
static ID id_rationalize;
|
|
53
56
|
static ID id_aref, id_aset;
|
|
54
57
|
static VALUE sym_linear, sym_lower, sym_higher, sym_nearest, sym_midpoint;
|
|
55
58
|
|
|
@@ -71,13 +74,14 @@ mp_is_numeric (int8_t dt)
|
|
|
71
74
|
_(CA_INT64, int64_t) _(CA_UINT64, uint64_t) \
|
|
72
75
|
_(CA_FLOAT32, float32_t) _(CA_FLOAT64, double)
|
|
73
76
|
|
|
74
|
-
/* [numeric]
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
fmin ignores NaN (fmin(x,NaN)==x), so a
|
|
78
|
-
NaN and stays branch-free
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
/* [numeric] sorted[k+1] of a fiber partitioned at k = the min over the
|
|
78
|
+
upper region [k+1, n-1]. NaN sorts after every number, so it is the
|
|
79
|
+
upper element only when the region holds nothing else. stride = element
|
|
80
|
+
stride along the reduce axis. fmin ignores NaN (fmin(x,NaN)==x), so a
|
|
81
|
+
+INFINITY seed skips NaN and the loop stays branch-free and vectorised.
|
|
82
|
+
A result of +INFINITY is either a +INFINITY in the region or a region of
|
|
83
|
+
NaN only; the rescan that tells them apart runs only in that case. An
|
|
84
|
+
empty region (k == n-1) answers the kth value. */
|
|
81
85
|
#define MP_GEN_MINUP(CT, T) \
|
|
82
86
|
static double \
|
|
83
87
|
mp_minup_##T (const T *b, ca_size_t f0, long k, long n, long stride) { \
|
|
@@ -86,8 +90,11 @@ mp_is_numeric (int8_t dt)
|
|
|
86
90
|
double v = (double) b[f0 + (ca_size_t)(ai * stride)]; \
|
|
87
91
|
hi = fmin(hi, v); \
|
|
88
92
|
} \
|
|
89
|
-
|
|
90
|
-
|
|
93
|
+
if ( hi != (double) INFINITY ) return hi; \
|
|
94
|
+
if ( k + 1 >= n ) return (double) b[f0 + (ca_size_t)(k * stride)]; \
|
|
95
|
+
for ( long ai = k + 1; ai < n; ai++ ) \
|
|
96
|
+
if ( (double) b[f0 + (ca_size_t)(ai * stride)] == hi ) return hi; \
|
|
97
|
+
return (double) NAN; \
|
|
91
98
|
}
|
|
92
99
|
MP_TYPES(MP_GEN_MINUP)
|
|
93
100
|
|
|
@@ -137,7 +144,12 @@ static VALUE
|
|
|
137
144
|
mp_axis_all_masked (VALUE self, long axis, int keep_axis)
|
|
138
145
|
{
|
|
139
146
|
int8_t ax = (int8_t) axis;
|
|
140
|
-
|
|
147
|
+
CArray *ca;
|
|
148
|
+
GetCArray(self, ca);
|
|
149
|
+
VALUE out = rb_ca_new_reduced(self, &ax, 1,
|
|
150
|
+
(ca->data_type == CA_OBJECT) ? CA_OBJECT
|
|
151
|
+
: CA_FLOAT64,
|
|
152
|
+
keep_axis);
|
|
141
153
|
CArray *co;
|
|
142
154
|
GetCArray(out, co);
|
|
143
155
|
ca_create_mask(co);
|
|
@@ -240,7 +252,7 @@ median_fill (double *op, int8_t dt, const char *base,
|
|
|
240
252
|
MP_TYPES(MP_CASE)
|
|
241
253
|
#undef MP_CASE
|
|
242
254
|
default:
|
|
243
|
-
rb_raise(rb_eCADataTypeError, "median:
|
|
255
|
+
rb_raise(rb_eCADataTypeError, "median: source data_type :%s not supported", ca_type_name[dt]);
|
|
244
256
|
}
|
|
245
257
|
}
|
|
246
258
|
|
|
@@ -298,13 +310,13 @@ median_flat (VALUE self, long min_count, VALUE fill_value, int keep_axis)
|
|
|
298
310
|
if ( RTEST(rb_ca_has_mask(self)) ) {
|
|
299
311
|
CArray *mc; GetCArray(self, mc);
|
|
300
312
|
long cnt = (long) ca_count_not_masked(mc); /* = elements - count_masked */
|
|
301
|
-
if ( cnt
|
|
313
|
+
if ( ca_too_few_present(cnt, min_count, 1) ) filled = 1;
|
|
302
314
|
else src = rb_ca_fetch(self, ID2SYM(id_is_not_masked));
|
|
303
315
|
}
|
|
304
316
|
if ( !filled ) {
|
|
305
317
|
CArray *sc;
|
|
306
318
|
GetCArray(src, sc);
|
|
307
|
-
if ( sc->elements
|
|
319
|
+
if ( ca_too_few_present(sc->elements, min_count, 1) ) filled = 1;
|
|
308
320
|
}
|
|
309
321
|
|
|
310
322
|
if ( filled ) {
|
|
@@ -348,15 +360,60 @@ mp_object_interpolates (VALUE v)
|
|
|
348
360
|
}
|
|
349
361
|
if ( rb_obj_is_kind_of(v, rb_cCArray) ) {
|
|
350
362
|
CArray *ca;
|
|
363
|
+
ca_size_t i;
|
|
351
364
|
GetCArray(v, ca);
|
|
352
|
-
|
|
353
|
-
|
|
365
|
+
for ( i = 0; i < ca->elements; i++ ) {
|
|
366
|
+
VALUE e = rb_ca_fetch_addr(v, i);
|
|
367
|
+
if ( e != CA_UNDEF && ! rb_obj_is_kind_of(e, rb_cNumeric) ) {
|
|
368
|
+
return 0;
|
|
369
|
+
}
|
|
354
370
|
}
|
|
355
|
-
return
|
|
371
|
+
return 1;
|
|
356
372
|
}
|
|
357
373
|
return 0;
|
|
358
374
|
}
|
|
359
375
|
|
|
376
|
+
/* [object] The element an interpolation refusal names: lo itself, or the
|
|
377
|
+
first element of a CArray of them that has no arithmetic. */
|
|
378
|
+
static VALUE
|
|
379
|
+
mp_first_non_numeric (VALUE v)
|
|
380
|
+
{
|
|
381
|
+
if ( rb_obj_is_kind_of(v, rb_cCArray) ) {
|
|
382
|
+
CArray *ca;
|
|
383
|
+
ca_size_t i;
|
|
384
|
+
GetCArray(v, ca);
|
|
385
|
+
for ( i = 0; i < ca->elements; i++ ) {
|
|
386
|
+
VALUE e = rb_ca_fetch_addr(v, i);
|
|
387
|
+
if ( e != CA_UNDEF && ! rb_obj_is_kind_of(e, rb_cNumeric) ) {
|
|
388
|
+
return e;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return v;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/* [object] An order statistic answers in the elements' own terms: a pick
|
|
396
|
+
is the element itself, and an average or an interpolation is done with
|
|
397
|
+
the elements' own arithmetic and an exact weight, so a Rational or a
|
|
398
|
+
BigDecimal stays exact and a Float stays a Float. */
|
|
399
|
+
|
|
400
|
+
/* The interpolation weight r (0 <= r < 1) as a Rational. */
|
|
401
|
+
static VALUE
|
|
402
|
+
obj_weight (double r)
|
|
403
|
+
{
|
|
404
|
+
return rb_funcall(DBL2NUM(r), id_rationalize, 0);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/* The midpoint of lo and hi, (lo + hi) * (1/2): exact for an Integer or a
|
|
408
|
+
Rational, and the same for a cell (the flat path) and for a CArray of
|
|
409
|
+
them (the per-axis path). */
|
|
410
|
+
static VALUE
|
|
411
|
+
obj_midpoint (VALUE lo, VALUE hi)
|
|
412
|
+
{
|
|
413
|
+
return rb_funcall(rb_funcall(lo, id_plus, 1, hi), id_mul, 1,
|
|
414
|
+
rb_rational_new(INT2FIX(1), INT2FIX(2)));
|
|
415
|
+
}
|
|
416
|
+
|
|
360
417
|
/* [object] Refuse to interpolate between two elements that have no
|
|
361
418
|
arithmetic meaning it. A String has both a `*` and a `+`, and
|
|
362
419
|
String#* truncates the Float weight to zero -- so :linear quietly
|
|
@@ -370,12 +427,10 @@ mp_require_interpolable (const char *who, VALUE method, VALUE lo)
|
|
|
370
427
|
return;
|
|
371
428
|
}
|
|
372
429
|
rb_raise(rb_eCADataTypeError,
|
|
373
|
-
"%s: method: :%
|
|
374
|
-
"does not support; use method: :lower, :higher
|
|
375
|
-
"pick an element instead",
|
|
376
|
-
who,
|
|
377
|
-
rb_obj_classname(rb_obj_is_kind_of(lo, rb_cCArray)
|
|
378
|
-
? rb_ca_fetch_addr(lo, 0) : lo));
|
|
430
|
+
"%s: method: :%"PRIsVALUE" interpolates between two elements, "
|
|
431
|
+
"which %"PRIsVALUE" does not support; use method: :lower, :higher "
|
|
432
|
+
"or :nearest to pick an element instead",
|
|
433
|
+
who, rb_sym2str(method), rb_obj_class(mp_first_non_numeric(lo)));
|
|
379
434
|
}
|
|
380
435
|
|
|
381
436
|
/* [object] recv.mid(axis: raxis) -- e.g. min/max/sort along an axis. */
|
|
@@ -467,15 +522,14 @@ median_object_axis (VALUE self, long axis, long n, int keep_axis)
|
|
|
467
522
|
if ( ! mp_object_interpolates(lo) ) {
|
|
468
523
|
rb_raise(rb_eCADataTypeError,
|
|
469
524
|
"median: an even number of elements has no middle one, and "
|
|
470
|
-
"%
|
|
471
|
-
"(or :higher / :nearest) to pick an element instead",
|
|
472
|
-
|
|
473
|
-
? rb_ca_fetch_addr(lo, 0) : lo));
|
|
525
|
+
"%"PRIsVALUE" cannot be averaged; use percentile(50, method: "
|
|
526
|
+
":lower) (or :higher / :nearest) to pick an element instead",
|
|
527
|
+
rb_obj_class(mp_first_non_numeric(lo)));
|
|
474
528
|
}
|
|
475
|
-
result =
|
|
529
|
+
result = obj_midpoint(lo, hi);
|
|
476
530
|
} else {
|
|
477
531
|
VALUE kv = obj_kth_one(self, axis, (n - 1) / 2);
|
|
478
|
-
result =
|
|
532
|
+
result = kv;
|
|
479
533
|
}
|
|
480
534
|
if ( keep_axis ) {
|
|
481
535
|
VALUE ia[1] = { LONG2NUM(axis) };
|
|
@@ -493,13 +547,13 @@ median_object_flat (VALUE self, long min_count, VALUE fill_value, int keep_axis)
|
|
|
493
547
|
if ( RTEST(rb_ca_has_mask(self)) ) {
|
|
494
548
|
CArray *mc; GetCArray(self, mc);
|
|
495
549
|
long cnt = (long) ca_count_not_masked(mc); /* = elements - count_masked */
|
|
496
|
-
if ( cnt
|
|
550
|
+
if ( ca_too_few_present(cnt, min_count, 1) ) filled = 1;
|
|
497
551
|
else src = rb_ca_fetch(self, ID2SYM(id_is_not_masked));
|
|
498
552
|
}
|
|
499
553
|
if ( !filled ) {
|
|
500
554
|
CArray *sc;
|
|
501
555
|
GetCArray(src, sc);
|
|
502
|
-
if ( sc->elements
|
|
556
|
+
if ( ca_too_few_present(sc->elements, min_count, 1) ) filled = 1;
|
|
503
557
|
}
|
|
504
558
|
if ( filled ) {
|
|
505
559
|
result = NIL_P(fill_value) ? CA_UNDEF : fill_value;
|
|
@@ -517,31 +571,28 @@ median_object_flat (VALUE self, long min_count, VALUE fill_value, int keep_axis)
|
|
|
517
571
|
pre-fetched). Reached ONLY by CA_OBJECT percentile/quantile -- never
|
|
518
572
|
by numeric (that path uses pct_compute) and never by median.
|
|
519
573
|
The :linear / :midpoint interpolation funcalls are irreducible for
|
|
520
|
-
arbitrary objects; the
|
|
521
|
-
match the numeric "always Float" output contract. */
|
|
574
|
+
arbitrary objects; the pick methods return the element itself. */
|
|
522
575
|
static VALUE
|
|
523
576
|
pct_compute_object (VALUE method, long k, double r, long n, VALUE lo, VALUE hi)
|
|
524
577
|
{
|
|
525
|
-
if ( method == sym_lower ) return
|
|
526
|
-
if ( method == sym_higher )
|
|
527
|
-
VALUE v = (r == 0.0) ? lo : hi;
|
|
528
|
-
return rb_funcall(v, id_mul, 1, DBL2NUM(1.0));
|
|
529
|
-
}
|
|
578
|
+
if ( method == sym_lower ) return lo;
|
|
579
|
+
if ( method == sym_higher ) return (r == 0.0) ? lo : hi;
|
|
530
580
|
if ( method == sym_nearest ) {
|
|
531
581
|
int use_k = (r < 0.5) || (r == 0.5 && (k % 2 == 0));
|
|
532
|
-
return
|
|
582
|
+
return use_k ? lo : hi;
|
|
533
583
|
}
|
|
534
584
|
if ( method == sym_linear ) {
|
|
535
|
-
if ( r == 0.0 || k + 1 >= n ) return
|
|
585
|
+
if ( r == 0.0 || k + 1 >= n ) return lo;
|
|
536
586
|
mp_require_interpolable("percentile", method, lo);
|
|
537
|
-
VALUE
|
|
538
|
-
VALUE
|
|
587
|
+
VALUE w = obj_weight(r);
|
|
588
|
+
VALUE a = rb_funcall(lo, id_mul, 1, rb_funcall(INT2FIX(1), rb_intern("-"), 1, w));
|
|
589
|
+
VALUE b = rb_funcall(hi, id_mul, 1, w);
|
|
539
590
|
return rb_funcall(a, id_plus, 1, b);
|
|
540
591
|
}
|
|
541
592
|
if ( method == sym_midpoint ) {
|
|
542
|
-
if ( k + 1 >= n ) return
|
|
593
|
+
if ( k + 1 >= n ) return lo;
|
|
543
594
|
mp_require_interpolable("percentile", method, lo);
|
|
544
|
-
return
|
|
595
|
+
return obj_midpoint(lo, hi);
|
|
545
596
|
}
|
|
546
597
|
rb_raise(rb_eArgError, "percentile: invalid method (BUG)");
|
|
547
598
|
}
|
|
@@ -550,11 +601,8 @@ pct_compute_object (VALUE method, long k, double r, long n, VALUE lo, VALUE hi)
|
|
|
550
601
|
static VALUE
|
|
551
602
|
pct_object_one_partition (VALUE self, long axis, long n, double p, VALUE method)
|
|
552
603
|
{
|
|
553
|
-
if ( p == 100.0 )
|
|
554
|
-
return rb_funcall(obj_call_axis(self, id_max, LONG2NUM(axis)),
|
|
555
|
-
id_mul, 1, DBL2NUM(1.0));
|
|
556
604
|
if ( n == 1 )
|
|
557
|
-
return
|
|
605
|
+
return obj_slice(self, axis, 0);
|
|
558
606
|
double f = (n - 1) * p / 100.0;
|
|
559
607
|
long k = (long) floor(f);
|
|
560
608
|
double r = f - k;
|
|
@@ -570,9 +618,9 @@ static VALUE
|
|
|
570
618
|
pct_object_one_sorted (VALUE sorted, long axis, long n, double p, VALUE method)
|
|
571
619
|
{
|
|
572
620
|
if ( p == 100.0 )
|
|
573
|
-
return
|
|
621
|
+
return obj_slice(sorted, axis, n - 1);
|
|
574
622
|
if ( n == 1 )
|
|
575
|
-
return
|
|
623
|
+
return obj_slice(sorted, axis, 0);
|
|
576
624
|
double f = (n - 1) * p / 100.0;
|
|
577
625
|
long k = (long) floor(f);
|
|
578
626
|
double r = f - k;
|
|
@@ -652,7 +700,7 @@ pct_object_axis_masked_one (VALUE self, VALUE sorted, long axis, double p,
|
|
|
652
700
|
for ( long j = 0; j < M; j++ )
|
|
653
701
|
if ( !sm[f0 + (ca_size_t)(j * INNER)] ) np++;
|
|
654
702
|
}
|
|
655
|
-
if ( np
|
|
703
|
+
if ( ca_too_few_present(np, min_count, 1) ) {
|
|
656
704
|
if ( is_undef ) {
|
|
657
705
|
if ( !co->mask ) ca_create_mask(co);
|
|
658
706
|
((boolean8_t *) co->mask->ptr)[oc] = 1;
|
|
@@ -738,13 +786,13 @@ percentile_object_flat (VALUE self, VALUE pers, long min_count, VALUE fill_value
|
|
|
738
786
|
if ( RTEST(rb_ca_has_mask(self)) ) {
|
|
739
787
|
CArray *mc; GetCArray(self, mc);
|
|
740
788
|
long cnt = (long) ca_count_not_masked(mc); /* = elements - count_masked */
|
|
741
|
-
if ( cnt
|
|
789
|
+
if ( ca_too_few_present(cnt, min_count, 1) ) filled = 1;
|
|
742
790
|
else src = rb_ca_fetch(self, ID2SYM(id_is_not_masked));
|
|
743
791
|
}
|
|
744
792
|
if ( !filled ) {
|
|
745
793
|
CArray *sc;
|
|
746
794
|
GetCArray(src, sc);
|
|
747
|
-
if ( sc->elements
|
|
795
|
+
if ( ca_too_few_present(sc->elements, min_count, 1) ) filled = 1;
|
|
748
796
|
}
|
|
749
797
|
if ( filled ) {
|
|
750
798
|
VALUE fill = NIL_P(fill_value) ? CA_UNDEF : fill_value;
|
|
@@ -765,7 +813,7 @@ static VALUE median_axis_masked (VALUE self, long axis, long min_count,
|
|
|
765
813
|
/* [entry] median(axis:, min_count:, fill_value:, keep_axis:). Dispatches
|
|
766
814
|
fixlen -> reject, object -> object lane, numeric -> numeric lane. */
|
|
767
815
|
static VALUE
|
|
768
|
-
|
|
816
|
+
rb_ca_median_m_body (int argc, VALUE *argv, VALUE self)
|
|
769
817
|
{
|
|
770
818
|
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
771
819
|
VALUE raxis = Qnil, rmin_count = INT2FIX(0), fill_value = Qnil, rkeep = Qfalse;
|
|
@@ -776,6 +824,15 @@ rb_ca_median_m (int argc, VALUE *argv, VALUE self)
|
|
|
776
824
|
|
|
777
825
|
CArray *ca;
|
|
778
826
|
GetCArray(self, ca);
|
|
827
|
+
/* A lazy expression is computed whole here, so a registered evaluator
|
|
828
|
+
may compute it instead. */
|
|
829
|
+
{
|
|
830
|
+
volatile VALUE evaluated = ca_lazy_evaluated(self);
|
|
831
|
+
if ( ! NIL_P(evaluated) ) {
|
|
832
|
+
self = evaluated;
|
|
833
|
+
GetCArray(self, ca);
|
|
834
|
+
}
|
|
835
|
+
}
|
|
779
836
|
/* Boolean rides the f64 lane: 0/1 -> 0.0/1.0, so median interpolates and
|
|
780
837
|
returns a float (a 2-element median averages to 0.5), matching how the
|
|
781
838
|
numeric lane treats integer input. */
|
|
@@ -784,17 +841,25 @@ rb_ca_median_m (int argc, VALUE *argv, VALUE self)
|
|
|
784
841
|
GetCArray(self, ca);
|
|
785
842
|
}
|
|
786
843
|
int8_t dt = ca->data_type;
|
|
787
|
-
if ( ca_is_fixlen_type(ca) )
|
|
844
|
+
if ( ca_is_fixlen_type(ca) ) {
|
|
845
|
+
ca_face_refuse_numeric(self, "median", rb_eCADataTypeError);
|
|
788
846
|
rb_raise(rb_eCADataTypeError,
|
|
789
847
|
"median: not defined for fixlen (no numeric midpoint); "
|
|
790
848
|
"use a numeric or object array");
|
|
849
|
+
}
|
|
791
850
|
int is_obj = (dt == CA_OBJECT);
|
|
792
851
|
if ( !is_obj && !mp_is_numeric(dt) )
|
|
793
|
-
rb_raise(rb_eCADataTypeError, "median:
|
|
852
|
+
rb_raise(rb_eCADataTypeError, "median: source data_type :%s not supported", ca_type_name[dt]);
|
|
794
853
|
|
|
795
|
-
long min_count =
|
|
796
|
-
|
|
797
|
-
|
|
854
|
+
long min_count = ca_min_count_arg(rmin_count, NULL);
|
|
855
|
+
/* fill_value: UNDEF leaves the result undefined; any other fill is what
|
|
856
|
+
a store into the float64 result would make of it. */
|
|
857
|
+
if ( fill_value == CA_UNDEF ) {
|
|
858
|
+
fill_value = Qnil;
|
|
859
|
+
}
|
|
860
|
+
else if ( ! NIL_P(fill_value) && ! is_obj ) {
|
|
861
|
+
fill_value = ca_fill_as(fill_value, CA_FLOAT64);
|
|
862
|
+
}
|
|
798
863
|
int keep_axis = RTEST(rkeep);
|
|
799
864
|
|
|
800
865
|
if ( !NIL_P(raxis) ) {
|
|
@@ -858,7 +923,7 @@ pct_fill (double *op, int8_t dt, const char *base, int from_sorted,
|
|
|
858
923
|
MP_TYPES(MP_CASE)
|
|
859
924
|
#undef MP_CASE
|
|
860
925
|
default:
|
|
861
|
-
rb_raise(rb_eCADataTypeError, "percentile:
|
|
926
|
+
rb_raise(rb_eCADataTypeError, "percentile: source data_type :%s not supported", ca_type_name[dt]);
|
|
862
927
|
}
|
|
863
928
|
}
|
|
864
929
|
|
|
@@ -886,7 +951,7 @@ pct_fill (double *op, int8_t dt, const char *base, int from_sorted,
|
|
|
886
951
|
for ( long j = 0; j < M; j++ ) \
|
|
887
952
|
if ( !sm[f0 + (ca_size_t)(j * INNER)] ) np++; \
|
|
888
953
|
} \
|
|
889
|
-
if ( np
|
|
954
|
+
if ( ca_too_few_present(np, min_count, 1) ) { \
|
|
890
955
|
if ( is_undef ) { \
|
|
891
956
|
if ( !co->mask ) ca_create_mask(co); \
|
|
892
957
|
((boolean8_t *) co->mask->ptr)[oc] = 1; \
|
|
@@ -927,7 +992,7 @@ pct_fill_masked (CArray *co, int8_t dt, const char *base, const boolean8_t *sm,
|
|
|
927
992
|
MP_TYPES(MP_CASE)
|
|
928
993
|
#undef MP_CASE
|
|
929
994
|
default:
|
|
930
|
-
rb_raise(rb_eCADataTypeError, "percentile:
|
|
995
|
+
rb_raise(rb_eCADataTypeError, "percentile: source data_type :%s not supported", ca_type_name[dt]);
|
|
931
996
|
}
|
|
932
997
|
}
|
|
933
998
|
|
|
@@ -1116,7 +1181,7 @@ pct_flat (VALUE self, VALUE pers_ary, long min_count, VALUE fill_value,
|
|
|
1116
1181
|
if ( RTEST(rb_ca_has_mask(self)) ) {
|
|
1117
1182
|
CArray *mc; GetCArray(self, mc);
|
|
1118
1183
|
long cnt = (long) ca_count_not_masked(mc); /* = elements - count_masked */
|
|
1119
|
-
if ( cnt
|
|
1184
|
+
if ( ca_too_few_present(cnt, min_count, 1) ) {
|
|
1120
1185
|
masked_out = 1; is_undef = NIL_P(fill_value);
|
|
1121
1186
|
if ( !is_undef ) fillv = NUM2DBL(fill_value);
|
|
1122
1187
|
} else {
|
|
@@ -1126,7 +1191,7 @@ pct_flat (VALUE self, VALUE pers_ary, long min_count, VALUE fill_value,
|
|
|
1126
1191
|
if ( !masked_out ) {
|
|
1127
1192
|
CArray *sc;
|
|
1128
1193
|
GetCArray(src, sc);
|
|
1129
|
-
if ( sc->elements
|
|
1194
|
+
if ( ca_too_few_present(sc->elements, min_count, 1) ) {
|
|
1130
1195
|
masked_out = 1; is_undef = NIL_P(fill_value);
|
|
1131
1196
|
if ( !is_undef ) fillv = NUM2DBL(fill_value);
|
|
1132
1197
|
}
|
|
@@ -1174,7 +1239,10 @@ pct_flatten_validate_pers (VALUE pers)
|
|
|
1174
1239
|
rb_raise(rb_eArgError, "percentile: at least one p value required");
|
|
1175
1240
|
for ( long i = 0; i < len; i++ ) {
|
|
1176
1241
|
VALUE p = rb_ary_entry(pers, i);
|
|
1177
|
-
|
|
1242
|
+
/* Written as "inside", so that NaN -- which fails every comparison --
|
|
1243
|
+
is refused rather than let through. */
|
|
1244
|
+
if ( !rb_obj_is_kind_of(p, rb_cNumeric) ||
|
|
1245
|
+
!(NUM2DBL(p) >= 0.0 && NUM2DBL(p) <= 100.0) )
|
|
1178
1246
|
rb_raise(rb_eArgError,
|
|
1179
1247
|
"percentile: p must be Numeric in [0,100] (got %"PRIsVALUE")",
|
|
1180
1248
|
rb_inspect(p));
|
|
@@ -1186,9 +1254,8 @@ pct_flatten_validate_pers (VALUE pers)
|
|
|
1186
1254
|
keep_axis:). Dispatches fixlen -> reject, object -> object lane,
|
|
1187
1255
|
numeric -> numeric lane. */
|
|
1188
1256
|
static VALUE
|
|
1189
|
-
|
|
1257
|
+
rb_ca_percentile_kw (int argc, VALUE *argv, VALUE ropt, VALUE self)
|
|
1190
1258
|
{
|
|
1191
|
-
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
1192
1259
|
VALUE raxis = Qnil, rmin_count = INT2FIX(0), fill_value = Qnil,
|
|
1193
1260
|
method = sym_linear, rkeep = Qfalse;
|
|
1194
1261
|
rb_scan_options(ropt, "axis,min_count,fill_value,method,keep_axis",
|
|
@@ -1196,6 +1263,15 @@ rb_ca_percentile_m (int argc, VALUE *argv, VALUE self)
|
|
|
1196
1263
|
|
|
1197
1264
|
CArray *ca;
|
|
1198
1265
|
GetCArray(self, ca);
|
|
1266
|
+
/* A lazy expression is computed whole here, so a registered evaluator
|
|
1267
|
+
may compute it instead. */
|
|
1268
|
+
{
|
|
1269
|
+
volatile VALUE evaluated = ca_lazy_evaluated(self);
|
|
1270
|
+
if ( ! NIL_P(evaluated) ) {
|
|
1271
|
+
self = evaluated;
|
|
1272
|
+
GetCArray(self, ca);
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1199
1275
|
/* Boolean rides the f64 lane (0/1 -> 0.0/1.0), so percentile / quantile
|
|
1200
1276
|
interpolate and return a float, matching the integer lane. */
|
|
1201
1277
|
if ( ca->data_type == CA_BOOLEAN ) {
|
|
@@ -1203,16 +1279,24 @@ rb_ca_percentile_m (int argc, VALUE *argv, VALUE self)
|
|
|
1203
1279
|
GetCArray(self, ca);
|
|
1204
1280
|
}
|
|
1205
1281
|
int8_t dt = ca->data_type;
|
|
1206
|
-
if ( ca_is_fixlen_type(ca) )
|
|
1282
|
+
if ( ca_is_fixlen_type(ca) ) {
|
|
1283
|
+
ca_face_refuse_numeric(self, "percentile", rb_eCADataTypeError);
|
|
1207
1284
|
rb_raise(rb_eCADataTypeError,
|
|
1208
1285
|
"percentile: not defined for fixlen; use a numeric or object array");
|
|
1286
|
+
}
|
|
1209
1287
|
int is_obj = (dt == CA_OBJECT);
|
|
1210
1288
|
if ( !is_obj && !mp_is_numeric(dt) )
|
|
1211
|
-
rb_raise(rb_eCADataTypeError, "percentile:
|
|
1289
|
+
rb_raise(rb_eCADataTypeError, "percentile: source data_type :%s not supported", ca_type_name[dt]);
|
|
1212
1290
|
|
|
1213
|
-
long min_count =
|
|
1214
|
-
|
|
1215
|
-
|
|
1291
|
+
long min_count = ca_min_count_arg(rmin_count, NULL);
|
|
1292
|
+
/* fill_value: UNDEF leaves the result undefined; any other fill is what
|
|
1293
|
+
a store into the float64 result would make of it. */
|
|
1294
|
+
if ( fill_value == CA_UNDEF ) {
|
|
1295
|
+
fill_value = Qnil;
|
|
1296
|
+
}
|
|
1297
|
+
else if ( ! NIL_P(fill_value) && ! is_obj ) {
|
|
1298
|
+
fill_value = ca_fill_as(fill_value, CA_FLOAT64);
|
|
1299
|
+
}
|
|
1216
1300
|
|
|
1217
1301
|
VALUE pers = pct_flatten_validate_pers(rb_ary_new_from_values(argc, argv));
|
|
1218
1302
|
pct_validate_method(method);
|
|
@@ -1230,7 +1314,7 @@ rb_ca_percentile_m (int argc, VALUE *argv, VALUE self)
|
|
|
1230
1314
|
flattened first and follows the same rule (length 1 unwraps). */
|
|
1231
1315
|
VALUE result;
|
|
1232
1316
|
if ( !NIL_P(raxis) ) {
|
|
1233
|
-
long axis = rb_ca_normalize_axis_value(self, raxis,
|
|
1317
|
+
long axis = rb_ca_normalize_axis_value(self, raxis, NULL);
|
|
1234
1318
|
/* mask / min_count / fill_value require the per-fiber select (each fiber
|
|
1235
1319
|
has its own n_present); the plain partition/sort path assumes a
|
|
1236
1320
|
uniform n. These paths bake keep_axis into the reduced output. */
|
|
@@ -1271,11 +1355,18 @@ rb_ca_percentile_m (int argc, VALUE *argv, VALUE self)
|
|
|
1271
1355
|
return result;
|
|
1272
1356
|
}
|
|
1273
1357
|
|
|
1358
|
+
static VALUE
|
|
1359
|
+
rb_ca_percentile_m_body (int argc, VALUE *argv, VALUE self)
|
|
1360
|
+
{
|
|
1361
|
+
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
1362
|
+
return rb_ca_percentile_kw(argc, argv, ropt, self);
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1274
1365
|
/* [entry] quantile(axis:, keep_axis:) = percentile(0, 25, 50, 75, 100, ...).
|
|
1275
1366
|
Return shape: Array<Float> len 5 (flat) or Array<CArray> len 5 (per-axis),
|
|
1276
1367
|
matching percentile's multi-p wrapping since we pass 5 fixed p values. */
|
|
1277
1368
|
static VALUE
|
|
1278
|
-
|
|
1369
|
+
rb_ca_quantile_m_body (int argc, VALUE *argv, VALUE self)
|
|
1279
1370
|
{
|
|
1280
1371
|
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
1281
1372
|
if ( argc != 0 )
|
|
@@ -1285,9 +1376,62 @@ rb_ca_quantile_m (int argc, VALUE *argv, VALUE self)
|
|
|
1285
1376
|
VALUE opts = rb_hash_new();
|
|
1286
1377
|
if ( !NIL_P(raxis) ) rb_hash_aset(opts, ID2SYM(rb_intern("axis")), raxis);
|
|
1287
1378
|
rb_hash_aset(opts, ID2SYM(rb_intern("keep_axis")), rkeep);
|
|
1288
|
-
VALUE pa[
|
|
1289
|
-
|
|
1290
|
-
|
|
1379
|
+
VALUE pa[5] = { INT2FIX(0), INT2FIX(25), INT2FIX(50), INT2FIX(75), INT2FIX(100) };
|
|
1380
|
+
return rb_ca_percentile_kw(5, pa, opts, self);
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
|
|
1384
|
+
typedef struct { int argc; VALUE *argv; VALUE self; } mp_median_call_t;
|
|
1385
|
+
|
|
1386
|
+
static VALUE
|
|
1387
|
+
mp_median_answer_body (VALUE p)
|
|
1388
|
+
{
|
|
1389
|
+
mp_median_call_t *c = (mp_median_call_t *) p;
|
|
1390
|
+
return rb_ca_median_m_body(c->argc, c->argv, c->self);
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
/* An error raised by the methods this one calls names this one. */
|
|
1394
|
+
static VALUE
|
|
1395
|
+
rb_ca_median_m (int argc, VALUE *argv, VALUE self)
|
|
1396
|
+
{
|
|
1397
|
+
mp_median_call_t c = { argc, argv, self };
|
|
1398
|
+
return ca_answer_as_caller(mp_median_answer_body, (VALUE) &c);
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
|
|
1402
|
+
typedef struct { int argc; VALUE *argv; VALUE self; } mp_percentile_call_t;
|
|
1403
|
+
|
|
1404
|
+
static VALUE
|
|
1405
|
+
mp_percentile_answer_body (VALUE p)
|
|
1406
|
+
{
|
|
1407
|
+
mp_percentile_call_t *c = (mp_percentile_call_t *) p;
|
|
1408
|
+
return rb_ca_percentile_m_body(c->argc, c->argv, c->self);
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
/* An error raised by the methods this one calls names this one. */
|
|
1412
|
+
static VALUE
|
|
1413
|
+
rb_ca_percentile_m (int argc, VALUE *argv, VALUE self)
|
|
1414
|
+
{
|
|
1415
|
+
mp_percentile_call_t c = { argc, argv, self };
|
|
1416
|
+
return ca_answer_as_caller(mp_percentile_answer_body, (VALUE) &c);
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
|
|
1420
|
+
typedef struct { int argc; VALUE *argv; VALUE self; } mp_quantile_call_t;
|
|
1421
|
+
|
|
1422
|
+
static VALUE
|
|
1423
|
+
mp_quantile_answer_body (VALUE p)
|
|
1424
|
+
{
|
|
1425
|
+
mp_quantile_call_t *c = (mp_quantile_call_t *) p;
|
|
1426
|
+
return rb_ca_quantile_m_body(c->argc, c->argv, c->self);
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
/* An error raised by the methods this one calls names this one. */
|
|
1430
|
+
static VALUE
|
|
1431
|
+
rb_ca_quantile_m (int argc, VALUE *argv, VALUE self)
|
|
1432
|
+
{
|
|
1433
|
+
mp_quantile_call_t c = { argc, argv, self };
|
|
1434
|
+
return ca_answer_as_caller(mp_quantile_answer_body, (VALUE) &c);
|
|
1291
1435
|
}
|
|
1292
1436
|
|
|
1293
1437
|
void
|
|
@@ -1297,6 +1441,7 @@ Init_carray_median_percentile (void)
|
|
|
1297
1441
|
id_sort_copy = rb_intern("sort_copy");
|
|
1298
1442
|
id_is_not_masked = rb_intern("is_not_masked");
|
|
1299
1443
|
id_plus = rb_intern("+"); id_div = rb_intern("/"); id_mul = rb_intern("*");
|
|
1444
|
+
id_rationalize = rb_intern("rationalize");
|
|
1300
1445
|
id_min = rb_intern("min"); id_max = rb_intern("max");
|
|
1301
1446
|
id_sort = rb_intern("sort"); id_copy = rb_intern("copy");
|
|
1302
1447
|
id_aref = rb_intern("[]"); id_aset = rb_intern("[]=");
|