carray 3.0.2 → 3.0.4
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 +568 -0
- data/README.md +6 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +220 -0
- data/ext/ca_axis_group.c +201 -123
- data/ext/ca_binop_dispatch.c +46 -52
- data/ext/ca_binop_dispatch.h +1 -1
- data/ext/ca_categorical_iterator.c +249 -183
- data/ext/ca_compare.c +7 -12
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +38 -23
- data/ext/ca_kernel_iterator.c +1765 -2076
- data/ext/ca_kernel_iterator.h +584 -566
- data/ext/ca_monop_dispatch.c +86 -63
- data/ext/ca_monop_dispatch.h +5 -0
- data/ext/ca_obj_array.c +223 -56
- data/ext/ca_obj_bincmp.c +172 -138
- data/ext/ca_obj_binop.c +116 -230
- data/ext/ca_obj_bitarray.c +40 -26
- data/ext/ca_obj_bitfield.c +100 -68
- data/ext/ca_obj_block.c +19 -9
- data/ext/ca_obj_byte_swap.c +45 -46
- data/ext/ca_obj_const_string.c +269 -44
- data/ext/ca_obj_face.c +612 -89
- data/ext/ca_obj_face.h +111 -47
- data/ext/ca_obj_fake.c +36 -79
- data/ext/ca_obj_farray.c +7 -3
- data/ext/ca_obj_field.c +33 -8
- data/ext/ca_obj_fixlen_string.c +23 -24
- data/ext/ca_obj_grid.c +541 -210
- data/ext/ca_obj_meld.c +331 -111
- data/ext/ca_obj_moncmp.c +80 -65
- data/ext/ca_obj_monop.c +177 -149
- data/ext/ca_obj_object.c +664 -248
- data/ext/ca_obj_record.c +63 -23
- data/ext/ca_obj_reduce.c +18 -16
- data/ext/ca_obj_refer.c +140 -58
- data/ext/ca_obj_remap.c +85 -24
- data/ext/ca_obj_repeat.c +24 -9
- data/ext/ca_obj_roll.c +121 -16
- data/ext/ca_obj_select.c +61 -58
- data/ext/ca_obj_select_axis.c +73 -107
- data/ext/ca_obj_shift.c +32 -102
- data/ext/ca_obj_stack.c +372 -122
- data/ext/ca_obj_stride.c +348 -140
- data/ext/ca_obj_string.c +88 -22
- data/ext/ca_obj_tile.c +38 -21
- data/ext/ca_obj_time.c +45 -31
- data/ext/ca_obj_timedelta.c +43 -29
- data/ext/ca_obj_transpose.c +17 -6
- data/ext/ca_obj_triop.c +125 -141
- data/ext/ca_obj_window.c +330 -44
- 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 +104 -81
- 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 +542 -0
- data/ext/carray.h +241 -92
- data/ext/carray_access.c +608 -276
- data/ext/carray_address_basis.c +494 -97
- data/ext/carray_attribute.c +129 -4
- data/ext/carray_bincount.c +39 -7
- data/ext/carray_broadcast.c +56 -19
- data/ext/carray_build_flags.h +1 -1
- data/ext/carray_call_cfunc.c +108 -28
- data/ext/carray_cast.c +1576 -223
- data/ext/carray_cast_func.rb +77 -24
- data/ext/carray_class.c +4 -3
- data/ext/carray_conversion.c +208 -75
- data/ext/carray_copy.c +82 -24
- data/ext/carray_core.c +646 -162
- data/ext/carray_count.c +171 -88
- data/ext/carray_element.c +94 -60
- data/ext/carray_factorize.c +670 -324
- data/ext/carray_generate.c +260 -83
- data/ext/carray_histogram.c +209 -106
- data/ext/carray_hold.c +14 -16
- data/ext/carray_index_classifier.c +422 -243
- data/ext/carray_internal.h +692 -3
- data/ext/carray_kernels_bincmp.c +7 -0
- data/ext/carray_kernels_binop.c +487 -120
- data/ext/carray_kernels_init.c +653 -50
- data/ext/carray_kernels_moncmp.c +15 -8
- data/ext/carray_kernels_monop.c +99 -43
- data/ext/carray_kernels_reduce_aggregate.c +3925 -6112
- data/ext/carray_kernels_reduce_boolean.c +112 -36
- data/ext/carray_kernels_reduce_cumulative.c +2127 -6903
- data/ext/carray_kernels_reduce_extreme.c +3032 -2892
- data/ext/carray_kernels_reduce_variance.c +439 -500
- data/ext/carray_kernels_scan.c +1097 -488
- data/ext/carray_kernels_search.c +3787 -2176
- data/ext/carray_kernels_sort.c +1200 -920
- data/ext/carray_kernels_triop.c +479 -7
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +967 -153
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +910 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +299 -100
- data/ext/carray_memory_view.c +872 -758
- data/ext/carray_operator.c +1171 -364
- data/ext/carray_order.c +505 -133
- data/ext/carray_partition.c +112 -65
- data/ext/carray_random.c +327 -239
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +346 -78
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +249 -86
- data/ext/carray_sort.c +224 -227
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +118 -39
- data/ext/carray_test.c +193 -69
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +579 -113
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +19 -4
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1202 -1014
- data/ext/ruby_carray.c +17 -5
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +160 -17
- data/lib/carray/autoload_carray.rb +23 -27
- data/lib/carray/autoload_method_extension.rb +20 -5
- data/lib/carray/axis_group.rb +360 -63
- data/lib/carray/basics.rb +162 -28
- data/lib/carray/bincount_nd.rb +18 -2
- data/lib/carray/block_iterator.rb +231 -58
- data/lib/carray/boolean_reduce.rb +34 -42
- data/lib/carray/categorical.rb +242 -52
- data/lib/carray/categorical_iterator.rb +437 -827
- data/lib/carray/complex.rb +41 -34
- data/lib/carray/conditional.rb +150 -14
- data/lib/carray/const_string.rb +59 -4
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +7 -1
- data/lib/carray/frame/column_verbs.rb +70 -0
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +82 -7
- data/lib/carray/frame/csv_parser.rb +688 -87
- data/lib/carray/frame/describe.rb +80 -0
- data/lib/carray/frame/frame.rb +369 -45
- data/lib/carray/frame/group.rb +631 -90
- data/lib/carray/frame/io.rb +506 -79
- data/lib/carray/frame/join.rb +411 -62
- data/lib/carray/frame/records.rb +116 -19
- data/lib/carray/frame/reshape.rb +455 -0
- data/lib/carray/frame/sort.rb +30 -18
- data/lib/carray/frame/verbs.rb +868 -61
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +4 -0
- data/lib/carray/fuse_source.rb +118 -2
- data/lib/carray/fusion.rb +257 -42
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +54 -13
- data/lib/carray/iterator.rb +99 -9
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +216 -193
- data/lib/carray/mask_gap_fill.rb +112 -92
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +52 -21
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +18 -2
- data/lib/carray/methods/bit_string.rb +15 -4
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +18 -10
- data/lib/carray/methods/factorize.rb +2 -2
- data/lib/carray/methods/gather_nd.rb +25 -5
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +140 -10
- data/lib/carray/methods/join.rb +2 -7
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +182 -45
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +11 -6
- 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/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +65 -17
- data/lib/carray/segment_iterator.rb +1221 -0
- data/lib/carray/serialize.rb +214 -30
- data/lib/carray/slab_iterator.rb +101 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +12 -4
- data/lib/carray/struct.rb +137 -58
- data/lib/carray/struct_builder.rb +124 -17
- data/lib/carray/time.rb +1222 -186
- data/lib/carray/window_iterator.rb +242 -81
- data/lib/carray.rb +9 -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 +5 -1
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +5 -4
- data/yard-stubs/ca_obj_roll.rb +2 -3
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +9 -5
- data/yard-stubs/carray_access.rb +11 -5
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_broadcast.rb +1 -1
- data/yard-stubs/carray_cast.rb +88 -43
- data/yard-stubs/carray_conversion.rb +15 -2
- data/yard-stubs/carray_copy.rb +12 -5
- data/yard-stubs/carray_core.rb +3 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +60 -12
- data/yard-stubs/carray_math.rb +52 -14
- data/yard-stubs/carray_median_percentile.rb +15 -8
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +61 -29
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +21 -9
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +10 -2
- data/yard-stubs/carray_sort.rb +49 -8
- data/yard-stubs/carray_test.rb +15 -3
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -5
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_kernels_map.c +0 -3467
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/ext/ca_axis_group.c
CHANGED
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
--------------------------------------------------------------------------- */
|
|
34
34
|
|
|
35
35
|
#include "carray.h"
|
|
36
|
+
#include "carray_internal.h" /* CA_EXTREMUM_REPLACES, ca_obj_extremum_replaces */
|
|
36
37
|
#include "ca_kernel_iterator.h"
|
|
37
38
|
#include <math.h>
|
|
38
39
|
|
|
@@ -64,8 +65,8 @@ group_op_code (VALUE vop)
|
|
|
64
65
|
else if ( id == rb_intern("max_addr") ) return GR_MAXADDR;
|
|
65
66
|
else if ( id == rb_intern("all") ) return GR_ALL;
|
|
66
67
|
else if ( id == rb_intern("any") ) return GR_ANY;
|
|
67
|
-
rb_raise(rb_eArgError, "axis_group_reduce: unsupported op :%
|
|
68
|
-
|
|
68
|
+
rb_raise(rb_eArgError, "axis_group_reduce: unsupported op :%"PRIsVALUE,
|
|
69
|
+
rb_id2str(id));
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
/* ---- per-slab-element composite-code walk, templated on the load type ----
|
|
@@ -206,16 +207,16 @@ group_op_code (VALUE vop)
|
|
|
206
207
|
only while nothing else has landed, the first number displaces it, and a
|
|
207
208
|
group of nothing but NaN answers NaN (for a position, UNDEF). `v` is the
|
|
208
209
|
widened load, so testing it for NaN is the same question for every source
|
|
209
|
-
type and costs an integer body nothing.
|
|
210
|
-
|
|
210
|
+
type and costs an integer body nothing. The replacement test is the
|
|
211
|
+
shared CA_EXTREMUM_REPLACES; the first member is taken whatever it is.
|
|
212
|
+
seen_num[] says whether a number has landed (the positions read it);
|
|
213
|
+
cnt[] says whether anything has. */
|
|
211
214
|
#define GMINMAX(T, A, CMP) \
|
|
212
215
|
do { \
|
|
213
216
|
A *acc = (A *) co->ptr; \
|
|
214
217
|
A av = (A) rv; \
|
|
215
|
-
if (
|
|
216
|
-
|
|
217
|
-
else if ( av CMP acc[o] ) acc[o] = av; \
|
|
218
|
-
} else if ( cnt[o] == 0 ) acc[o] = av; \
|
|
218
|
+
if ( cnt[o] == 0 || CA_EXTREMUM_REPLACES(av, acc[o], CMP) ) acc[o] = av; \
|
|
219
|
+
if ( v == v ) seen_num[o] = 1; \
|
|
219
220
|
cnt[o] += 1; \
|
|
220
221
|
} while (0)
|
|
221
222
|
|
|
@@ -282,7 +283,7 @@ group_op_code (VALUE vop)
|
|
|
282
283
|
#define GACC_XOR \
|
|
283
284
|
( ((boolean8_t *) co->ptr)[o] ^= (*(boolean8_t *)(p + gw_doff[e]) ? 1 : 0) )
|
|
284
285
|
|
|
285
|
-
/*
|
|
286
|
+
/* __reduce_by_axis_groups__(group_axes, bundles, op) — group-reduces self along
|
|
286
287
|
* the union of `group_axes` (ascending source-axis indices = the slab) into
|
|
287
288
|
* composite groups described by `bundles`, preserving the band (= non-grouped)
|
|
288
289
|
* axes. Internal: the Ruby surface is CAGroupIterator.
|
|
@@ -310,7 +311,7 @@ group_op_code (VALUE vop)
|
|
|
310
311
|
Empty / all-masked groups follow the CArray zero-contribution contract: an
|
|
311
312
|
identity-bearing op returns its identity (sum 0, prod 1, count 0, all true,
|
|
312
313
|
any false), a ratio / extremum returns UNDEF. Sample variance / stddev:
|
|
313
|
-
n
|
|
314
|
+
n < 2 UNDEF, n >= 2 the formula.
|
|
314
315
|
*/
|
|
315
316
|
static VALUE
|
|
316
317
|
rb_ca_axis_group_reduce (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
|
|
@@ -321,7 +322,7 @@ rb_ca_axis_group_reduce (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
|
|
|
321
322
|
GetCArray(self, src);
|
|
322
323
|
|
|
323
324
|
if ( src->ndim <= 0 ) {
|
|
324
|
-
rb_raise(
|
|
325
|
+
rb_raise(rb_eArgError, "axis_group_reduce: scalar source");
|
|
325
326
|
}
|
|
326
327
|
|
|
327
328
|
/* --- group (slab) axes --- */
|
|
@@ -351,7 +352,7 @@ rb_ca_axis_group_reduce (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
|
|
|
351
352
|
/* --- bundles: small per-group code tables (metadata, kept alive) --- */
|
|
352
353
|
Check_Type(vbundles, T_ARRAY);
|
|
353
354
|
int n_bundles = (int) RARRAY_LEN(vbundles);
|
|
354
|
-
if ( n_bundles <= 0 || n_bundles > CA_RANK_MAX ) {
|
|
355
|
+
if ( n_bundles <= 0 || n_bundles > CA_RANK_MAX ) { /* rank-check: a count of key bundles */
|
|
355
356
|
rb_raise(rb_eArgError, "axis_group_reduce: bad bundle count %d", n_bundles);
|
|
356
357
|
}
|
|
357
358
|
int32_t *bundle_codes[CA_RANK_MAX];
|
|
@@ -361,7 +362,8 @@ rb_ca_axis_group_reduce (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
|
|
|
361
362
|
int bundle_slot[CA_RANK_MAX][CA_RANK_MAX];
|
|
362
363
|
ca_size_t bundle_cstride[CA_RANK_MAX][CA_RANK_MAX];
|
|
363
364
|
CArray *bundle_ca[CA_RANK_MAX];
|
|
364
|
-
volatile VALUE keep = rb_ary_new(); /*
|
|
365
|
+
volatile VALUE keep = rb_ary_new(); /* keeps the int32 code views alive */
|
|
366
|
+
volatile VALUE h_codes[CA_RANK_MAX]; /* holders of the copied code tables */
|
|
365
367
|
|
|
366
368
|
ca_size_t K_total = 1;
|
|
367
369
|
long consumed_total = 0;
|
|
@@ -384,20 +386,16 @@ rb_ca_axis_group_reduce (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
|
|
|
384
386
|
and the end of the walk can raise -- a validation just below, a gather
|
|
385
387
|
that cannot convert a cell, an object-lane callback into Ruby -- and a
|
|
386
388
|
raise jumps over every detach, leaving the source materialised with
|
|
387
|
-
nothing left to release it. The copy rides a temporary buffer
|
|
388
|
-
unwind collects.
|
|
389
|
+
nothing left to release it. The copy rides ALLOCV, a temporary buffer
|
|
390
|
+
that the unwind collects. Not a String: a String held only by `keep`
|
|
391
|
+
can be moved by compaction, taking the bytes under bundle_codes with
|
|
392
|
+
it. */
|
|
389
393
|
VALUE v32 = rb_ca_wrap_readonly(vcodes, INT2NUM(CA_INT32));
|
|
390
394
|
rb_ary_push((VALUE) keep, v32);
|
|
391
395
|
GetCArray(v32, bundle_ca[bi]);
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
rb_ary_push((VALUE) keep, vbuf);
|
|
396
|
-
ca_attach(bundle_ca[bi]);
|
|
397
|
-
memcpy(RSTRING_PTR(vbuf), bundle_ca[bi]->ptr, nbytes);
|
|
398
|
-
ca_detach(bundle_ca[bi]);
|
|
399
|
-
bundle_codes[bi] = (int32_t *) RSTRING_PTR(vbuf);
|
|
400
|
-
}
|
|
396
|
+
h_codes[bi] = 0;
|
|
397
|
+
bundle_codes[bi] = ALLOCV_N(int32_t, h_codes[bi], bundle_ca[bi]->elements);
|
|
398
|
+
ca_copy_data(bundle_ca[bi], (char *) bundle_codes[bi]);
|
|
401
399
|
|
|
402
400
|
int nb = (int) RARRAY_LEN(vbaxes);
|
|
403
401
|
if ( nb <= 0 || nb > src->ndim ) {
|
|
@@ -477,9 +475,9 @@ rb_ca_axis_group_reduce (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
|
|
|
477
475
|
case CA_INT32: case CA_UINT32: case CA_INT64: case CA_UINT64:
|
|
478
476
|
case CA_FLOAT32: case CA_FLOAT64: break;
|
|
479
477
|
default:
|
|
480
|
-
rb_raise(
|
|
481
|
-
"
|
|
482
|
-
src->data_type);
|
|
478
|
+
rb_raise(rb_eCADataTypeError,
|
|
479
|
+
"axis_group: %"PRIsVALUE" over a group is not supported for data type %s",
|
|
480
|
+
rb_sym2str(vop), ca_type_name[src->data_type]);
|
|
483
481
|
}
|
|
484
482
|
|
|
485
483
|
/* output data type per op */
|
|
@@ -618,8 +616,8 @@ rb_ca_axis_group_reduce (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
|
|
|
618
616
|
/* Empty / all-masked groups follow the same zero-contribution contract as
|
|
619
617
|
CArray reductions (ERI, matching the categorical sibling): an identity-
|
|
620
618
|
bearing op returns its identity (sum 0, prod 1, count 0, all true, any
|
|
621
|
-
false), a ratio / extremum returns UNDEF. Sample variance/stddev: n
|
|
622
|
-
UNDEF
|
|
619
|
+
false), a ratio / extremum returns UNDEF. Sample variance/stddev: n<2
|
|
620
|
+
UNDEF (n-1 is zero), n>=2 the formula. */
|
|
623
621
|
if ( op == GR_COUNT ) {
|
|
624
622
|
int64_t *out = (int64_t *) co->ptr;
|
|
625
623
|
for ( ca_size_t o = 0; o < nout; o++ ) out[o] = (int64_t) cnt[o];
|
|
@@ -664,8 +662,7 @@ rb_ca_axis_group_reduce (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
|
|
|
664
662
|
break;
|
|
665
663
|
case GR_VARIANCE:
|
|
666
664
|
case GR_STDDEV:
|
|
667
|
-
if ( cnt[o]
|
|
668
|
-
else if ( cnt[o] == 1 ) { out[o] = 0.0; } /* n=1 contract */
|
|
665
|
+
if ( cnt[o] < 2 ) { out[o] = 0.0; MARK_UNDEF(o); }
|
|
669
666
|
else { double var = sumsq[o] / ( (double) cnt[o] - 1.0 );
|
|
670
667
|
out[o] = ( op == GR_STDDEV ) ? sqrt(var) : var; }
|
|
671
668
|
break;
|
|
@@ -684,6 +681,7 @@ rb_ca_axis_group_reduce (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
|
|
|
684
681
|
ALLOCV_END(h_prod); ALLOCV_END(h_seen); ALLOCV_END(h_xbuf);
|
|
685
682
|
ALLOCV_END(h_nz); ALLOCV_END(h_mnaddr); ALLOCV_END(h_mxaddr);
|
|
686
683
|
ALLOCV_END(h_band);
|
|
684
|
+
for ( int bi = 0; bi < n_bundles; bi++ ) ALLOCV_END(h_codes[bi]);
|
|
687
685
|
|
|
688
686
|
RB_GC_GUARD(keep);
|
|
689
687
|
return vout;
|
|
@@ -854,7 +852,9 @@ group_scan_build_plan (ca_iter_state *st, boolean8_t *m,
|
|
|
854
852
|
emits its own value: a per-group `seen` byte initialises the accumulator
|
|
855
853
|
lazily on first hit — no sentinel like HUGE_VAL, which an integer data type could
|
|
856
854
|
not represent. CMP is > for max, < for min: a later member replaces the
|
|
857
|
-
running extremum when
|
|
855
|
+
running extremum when CA_EXTREMUM_REPLACES (a NaN never does, and a
|
|
856
|
+
number displaces a leading NaN, as the core cummax / cummin and the
|
|
857
|
+
reduce twins above do). A cell masked within its group holds the
|
|
858
858
|
current extremum once a member has been seen (output NOT masked, like sum);
|
|
859
859
|
before any member the extremum is undefined so the cell stays UNDEF (the
|
|
860
860
|
CArray reduction contract: empty max/min has no value — deliberately NOT the
|
|
@@ -895,7 +895,9 @@ group_scan_build_plan (ca_iter_state *st, boolean8_t *m,
|
|
|
895
895
|
} \
|
|
896
896
|
T rv = *(T *)(p + sw_doff[e]); \
|
|
897
897
|
if ( ! seen[code] ) { acce[code] = rv; seen[code] = 1; } \
|
|
898
|
-
else if ( rv
|
|
898
|
+
else if ( CA_EXTREMUM_REPLACES(rv, acce[code], CMP) ) { \
|
|
899
|
+
acce[code] = rv; \
|
|
900
|
+
} \
|
|
899
901
|
outp[addr] = acce[code]; \
|
|
900
902
|
} \
|
|
901
903
|
} \
|
|
@@ -933,19 +935,19 @@ group_scan_build_plan (ca_iter_state *st, boolean8_t *m,
|
|
|
933
935
|
both unmasked (matching core object cumsum / cumprod); cummax / cummin hold
|
|
934
936
|
the running VALUE only once a member has been seen and stay UNDEF before that
|
|
935
937
|
(no identity for arbitrary objects). GW_SKIP (excluded) stays UNDEF. accn /
|
|
936
|
-
seen are reset at each band; acco carries the running VALUE.
|
|
938
|
+
seen are reset at each band; acco carries the running VALUE.
|
|
939
|
+
Expanded only in group_scan_object_body, whose walk state is c->st. */
|
|
937
940
|
#define GROUP_SCAN_OBJECT_WALK(EMIT, HOLD) \
|
|
938
941
|
do { \
|
|
939
|
-
ca_iter_state st; \
|
|
940
942
|
char *p; \
|
|
941
943
|
boolean8_t *m; \
|
|
942
944
|
ca_size_t b = 0; \
|
|
943
945
|
int ready = 0; \
|
|
944
|
-
CA_FOR_EACH_SLAB(st, ca, axes, (int8_t) ngroup, CA_KERNEL_READ, p, m) {
|
|
945
|
-
ca_size_t SE = st.slab_elements;
|
|
946
|
+
CA_FOR_EACH_SLAB(c->st, ca, axes, (int8_t) ngroup, CA_KERNEL_READ, p, m) {\
|
|
947
|
+
ca_size_t SE = c->st.slab_elements; \
|
|
946
948
|
if ( SE > 0 ) { \
|
|
947
949
|
if ( ! ready ) { \
|
|
948
|
-
group_scan_build_plan(&st, m, n_bundles, bundle_codes, bundle_k
|
|
950
|
+
group_scan_build_plan(&c->st, m, n_bundles, bundle_codes, bundle_k,\
|
|
949
951
|
bundle_placeval, bundle_nconsumed, \
|
|
950
952
|
bundle_slot, bundle_cstride, ngroup, \
|
|
951
953
|
grstride, sw_code, sw_doff, sw_moff, sw_addr);\
|
|
@@ -970,6 +972,137 @@ group_scan_build_plan (ca_iter_state *st, boolean8_t *m,
|
|
|
970
972
|
} \
|
|
971
973
|
} while (0)
|
|
972
974
|
|
|
975
|
+
/* Marks output cell o UNDEF, creating the output mask on first use. Used
|
|
976
|
+
by the scan walks, in functions that hold the output as `co` and the mask
|
|
977
|
+
pointer as `omask`. */
|
|
978
|
+
#define MARK_OUT_UNDEF(o) do { \
|
|
979
|
+
if ( ! omask ) { \
|
|
980
|
+
ca_create_mask(co); \
|
|
981
|
+
omask = (boolean8_t *) co->mask->ptr; \
|
|
982
|
+
} \
|
|
983
|
+
omask[o] = 1; \
|
|
984
|
+
} while (0)
|
|
985
|
+
|
|
986
|
+
/* The CA_OBJECT lane of __scan_by_axis_groups__. Every cell calls into Ruby,
|
|
987
|
+
so the walk can raise part way; its state lives in the caller's frame, in
|
|
988
|
+
c->st, and ca_iter_ensure finishes it however this body leaves. The
|
|
989
|
+
buffers are ALLOCV-backed, so the unwind collects them. */
|
|
990
|
+
typedef struct {
|
|
991
|
+
ca_iter_state st;
|
|
992
|
+
CArray *ca;
|
|
993
|
+
CArray *co;
|
|
994
|
+
int op;
|
|
995
|
+
int8_t *axes;
|
|
996
|
+
long ngroup;
|
|
997
|
+
int n_bundles;
|
|
998
|
+
int32_t **bundle_codes;
|
|
999
|
+
ca_size_t *bundle_k;
|
|
1000
|
+
ca_size_t *bundle_placeval;
|
|
1001
|
+
int *bundle_nconsumed;
|
|
1002
|
+
int (*bundle_slot)[CA_RANK_MAX];
|
|
1003
|
+
ca_size_t (*bundle_cstride)[CA_RANK_MAX];
|
|
1004
|
+
ca_size_t *grstride;
|
|
1005
|
+
ca_size_t *band_addr;
|
|
1006
|
+
ca_size_t K_total;
|
|
1007
|
+
ca_size_t *sw_code;
|
|
1008
|
+
ca_size_t *sw_doff;
|
|
1009
|
+
ca_size_t *sw_moff;
|
|
1010
|
+
ca_size_t *sw_addr;
|
|
1011
|
+
ca_size_t *accn;
|
|
1012
|
+
char *seen;
|
|
1013
|
+
VALUE *acco;
|
|
1014
|
+
} group_scan_object_t;
|
|
1015
|
+
|
|
1016
|
+
static VALUE
|
|
1017
|
+
group_scan_object_body (VALUE arg)
|
|
1018
|
+
{
|
|
1019
|
+
group_scan_object_t *c = (group_scan_object_t *) arg;
|
|
1020
|
+
CArray *ca = c->ca;
|
|
1021
|
+
CArray *co = c->co;
|
|
1022
|
+
int op = c->op;
|
|
1023
|
+
int8_t *axes = c->axes;
|
|
1024
|
+
long ngroup = c->ngroup;
|
|
1025
|
+
int n_bundles = c->n_bundles;
|
|
1026
|
+
int32_t **bundle_codes = c->bundle_codes;
|
|
1027
|
+
ca_size_t *bundle_k = c->bundle_k;
|
|
1028
|
+
ca_size_t *bundle_placeval = c->bundle_placeval;
|
|
1029
|
+
int *bundle_nconsumed = c->bundle_nconsumed;
|
|
1030
|
+
int (*bundle_slot)[CA_RANK_MAX] = c->bundle_slot;
|
|
1031
|
+
ca_size_t (*bundle_cstride)[CA_RANK_MAX] = c->bundle_cstride;
|
|
1032
|
+
ca_size_t *grstride = c->grstride;
|
|
1033
|
+
ca_size_t *band_addr = c->band_addr;
|
|
1034
|
+
ca_size_t K_total = c->K_total;
|
|
1035
|
+
ca_size_t *sw_code = c->sw_code;
|
|
1036
|
+
ca_size_t *sw_doff = c->sw_doff;
|
|
1037
|
+
ca_size_t *sw_moff = c->sw_moff;
|
|
1038
|
+
ca_size_t *sw_addr = c->sw_addr;
|
|
1039
|
+
ca_size_t *accn = c->accn;
|
|
1040
|
+
char *seen = c->seen;
|
|
1041
|
+
VALUE *acco = c->acco;
|
|
1042
|
+
boolean8_t *omask = NULL;
|
|
1043
|
+
|
|
1044
|
+
if ( op == GS_CUMCOUNT ) { /* int64 1-based running count */
|
|
1045
|
+
int64_t *outi = (int64_t *) co->ptr;
|
|
1046
|
+
GROUP_SCAN_OBJECT_WALK(
|
|
1047
|
+
accn[code] += 1; outi[addr] = (int64_t) accn[code];,
|
|
1048
|
+
outi[addr] = (int64_t) accn[code];
|
|
1049
|
+
);
|
|
1050
|
+
}
|
|
1051
|
+
else { /* object running VALUE */
|
|
1052
|
+
VALUE *outo = (VALUE *) co->ptr;
|
|
1053
|
+
switch ( op ) {
|
|
1054
|
+
case GS_CUMSUM:
|
|
1055
|
+
/* Identity 0 (matching the core object cumsum): a group's acc is lazily
|
|
1056
|
+
seeded to 0 (Fixnum, so 0 + ev promotes to ev's class), so a cell
|
|
1057
|
+
masked before any present member holds 0 unmasked and an all-masked
|
|
1058
|
+
group yields 0 everywhere. seen doubles as the per-band init flag. */
|
|
1059
|
+
GROUP_SCAN_OBJECT_WALK(
|
|
1060
|
+
if ( ! seen[code] ) { acco[code] = INT2FIX(0); seen[code] = 1; }
|
|
1061
|
+
acco[code] = rb_funcall(acco[code], rb_intern("+"), 1, ev);
|
|
1062
|
+
outo[addr] = acco[code];,
|
|
1063
|
+
if ( ! seen[code] ) { acco[code] = INT2FIX(0); seen[code] = 1; }
|
|
1064
|
+
outo[addr] = acco[code];
|
|
1065
|
+
);
|
|
1066
|
+
break;
|
|
1067
|
+
case GS_CUMPROD:
|
|
1068
|
+
/* Identity 1, same lazy-init as cumsum. */
|
|
1069
|
+
GROUP_SCAN_OBJECT_WALK(
|
|
1070
|
+
if ( ! seen[code] ) { acco[code] = INT2FIX(1); seen[code] = 1; }
|
|
1071
|
+
acco[code] = rb_funcall(acco[code], rb_intern("*"), 1, ev);
|
|
1072
|
+
outo[addr] = acco[code];,
|
|
1073
|
+
if ( ! seen[code] ) { acco[code] = INT2FIX(1); seen[code] = 1; }
|
|
1074
|
+
outo[addr] = acco[code];
|
|
1075
|
+
);
|
|
1076
|
+
break;
|
|
1077
|
+
case GS_CUMMAX:
|
|
1078
|
+
/* No identity: seed from the first member, hold only once seen; a cell
|
|
1079
|
+
masked before any member stays UNDEF (empty-max contract). */
|
|
1080
|
+
GROUP_SCAN_OBJECT_WALK(
|
|
1081
|
+
if ( ! seen[code] ) { acco[code] = ev; seen[code] = 1; }
|
|
1082
|
+
else if ( ca_obj_extremum_replaces(ev, acco[code], rb_intern(">")) ) {
|
|
1083
|
+
acco[code] = ev;
|
|
1084
|
+
}
|
|
1085
|
+
outo[addr] = acco[code];,
|
|
1086
|
+
if ( seen[code] ) { outo[addr] = acco[code]; }
|
|
1087
|
+
else { MARK_OUT_UNDEF(addr); }
|
|
1088
|
+
);
|
|
1089
|
+
break;
|
|
1090
|
+
case GS_CUMMIN:
|
|
1091
|
+
GROUP_SCAN_OBJECT_WALK(
|
|
1092
|
+
if ( ! seen[code] ) { acco[code] = ev; seen[code] = 1; }
|
|
1093
|
+
else if ( ca_obj_extremum_replaces(ev, acco[code], rb_intern("<")) ) {
|
|
1094
|
+
acco[code] = ev;
|
|
1095
|
+
}
|
|
1096
|
+
outo[addr] = acco[code];,
|
|
1097
|
+
if ( seen[code] ) { outo[addr] = acco[code]; }
|
|
1098
|
+
else { MARK_OUT_UNDEF(addr); }
|
|
1099
|
+
);
|
|
1100
|
+
break;
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
return Qnil;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
973
1106
|
static int
|
|
974
1107
|
group_scan_op_code (VALUE vop)
|
|
975
1108
|
{
|
|
@@ -979,12 +1112,12 @@ group_scan_op_code (VALUE vop)
|
|
|
979
1112
|
else if ( id == rb_intern("cummax") ) return GS_CUMMAX;
|
|
980
1113
|
else if ( id == rb_intern("cummin") ) return GS_CUMMIN;
|
|
981
1114
|
else if ( id == rb_intern("cumprod") ) return GS_CUMPROD;
|
|
982
|
-
rb_raise(rb_eArgError, "axis_group_scan: unsupported op :%
|
|
1115
|
+
rb_raise(rb_eArgError, "axis_group_scan: unsupported op :%"PRIsVALUE, rb_id2str(id));
|
|
983
1116
|
}
|
|
984
1117
|
|
|
985
|
-
/*
|
|
1118
|
+
/* __scan_by_axis_groups__(group_axes, bundles, op) — group-keyed segment scan of
|
|
986
1119
|
* self over the union of `group_axes` into composite groups described by
|
|
987
|
-
* `bundles` (same argument shape as
|
|
1120
|
+
* `bundles` (same argument shape as __reduce_by_axis_groups__). Internal.
|
|
988
1121
|
*
|
|
989
1122
|
* Unlike the reduce the grouped axes are not collapsed: the result is a new
|
|
990
1123
|
* CArray of the same shape as self, each cell holding the running statistic of
|
|
@@ -1022,7 +1155,7 @@ rb_ca_axis_group_scan (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
|
|
|
1022
1155
|
GetCArray(self, src);
|
|
1023
1156
|
|
|
1024
1157
|
if ( src->ndim <= 0 ) {
|
|
1025
|
-
rb_raise(
|
|
1158
|
+
rb_raise(rb_eArgError, "axis_group_scan: scalar source");
|
|
1026
1159
|
}
|
|
1027
1160
|
|
|
1028
1161
|
/* --- group (slab) axes (same validation as reduce) --- */
|
|
@@ -1054,7 +1187,7 @@ rb_ca_axis_group_scan (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
|
|
|
1054
1187
|
/* --- bundles: small per-group code tables (same as reduce) --- */
|
|
1055
1188
|
Check_Type(vbundles, T_ARRAY);
|
|
1056
1189
|
int n_bundles = (int) RARRAY_LEN(vbundles);
|
|
1057
|
-
if ( n_bundles <= 0 || n_bundles > CA_RANK_MAX ) {
|
|
1190
|
+
if ( n_bundles <= 0 || n_bundles > CA_RANK_MAX ) { /* rank-check: a count of key bundles */
|
|
1058
1191
|
rb_raise(rb_eArgError, "axis_group_scan: bad bundle count %d", n_bundles);
|
|
1059
1192
|
}
|
|
1060
1193
|
int32_t *bundle_codes[CA_RANK_MAX];
|
|
@@ -1065,6 +1198,7 @@ rb_ca_axis_group_scan (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
|
|
|
1065
1198
|
ca_size_t bundle_cstride[CA_RANK_MAX][CA_RANK_MAX];
|
|
1066
1199
|
CArray *bundle_ca[CA_RANK_MAX];
|
|
1067
1200
|
volatile VALUE keep = rb_ary_new();
|
|
1201
|
+
volatile VALUE h_codes[CA_RANK_MAX];
|
|
1068
1202
|
|
|
1069
1203
|
ca_size_t K_total = 1;
|
|
1070
1204
|
long consumed_total = 0;
|
|
@@ -1087,20 +1221,16 @@ rb_ca_axis_group_scan (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
|
|
|
1087
1221
|
and the end of the walk can raise -- a validation just below, a gather
|
|
1088
1222
|
that cannot convert a cell, an object-lane callback into Ruby -- and a
|
|
1089
1223
|
raise jumps over every detach, leaving the source materialised with
|
|
1090
|
-
nothing left to release it. The copy rides a temporary buffer
|
|
1091
|
-
unwind collects.
|
|
1224
|
+
nothing left to release it. The copy rides ALLOCV, a temporary buffer
|
|
1225
|
+
that the unwind collects. Not a String: a String held only by `keep`
|
|
1226
|
+
can be moved by compaction, taking the bytes under bundle_codes with
|
|
1227
|
+
it. */
|
|
1092
1228
|
VALUE v32 = rb_ca_wrap_readonly(vcodes, INT2NUM(CA_INT32));
|
|
1093
1229
|
rb_ary_push((VALUE) keep, v32);
|
|
1094
1230
|
GetCArray(v32, bundle_ca[bi]);
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
rb_ary_push((VALUE) keep, vbuf);
|
|
1099
|
-
ca_attach(bundle_ca[bi]);
|
|
1100
|
-
memcpy(RSTRING_PTR(vbuf), bundle_ca[bi]->ptr, nbytes);
|
|
1101
|
-
ca_detach(bundle_ca[bi]);
|
|
1102
|
-
bundle_codes[bi] = (int32_t *) RSTRING_PTR(vbuf);
|
|
1103
|
-
}
|
|
1231
|
+
h_codes[bi] = 0;
|
|
1232
|
+
bundle_codes[bi] = ALLOCV_N(int32_t, h_codes[bi], bundle_ca[bi]->elements);
|
|
1233
|
+
ca_copy_data(bundle_ca[bi], (char *) bundle_codes[bi]);
|
|
1104
1234
|
|
|
1105
1235
|
int nb = (int) RARRAY_LEN(vbaxes);
|
|
1106
1236
|
if ( nb <= 0 || nb > src->ndim ) {
|
|
@@ -1160,7 +1290,7 @@ rb_ca_axis_group_scan (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
|
|
|
1160
1290
|
case CA_INT32: case CA_UINT32: case CA_INT64: case CA_UINT64:
|
|
1161
1291
|
case CA_FLOAT32: case CA_FLOAT64: case CA_OBJECT: break;
|
|
1162
1292
|
default:
|
|
1163
|
-
rb_raise(
|
|
1293
|
+
rb_raise(rb_eCADataTypeError,
|
|
1164
1294
|
"axis_group_scan: unsupported source data_type %d",
|
|
1165
1295
|
src->data_type);
|
|
1166
1296
|
}
|
|
@@ -1232,75 +1362,23 @@ rb_ca_axis_group_scan (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
|
|
|
1232
1362
|
double acc_init = ( op == GS_CUMPROD ) ? 1.0 : 0.0;
|
|
1233
1363
|
|
|
1234
1364
|
boolean8_t *omask = NULL;
|
|
1235
|
-
#define MARK_OUT_UNDEF(o) do { \
|
|
1236
|
-
if ( ! omask ) { \
|
|
1237
|
-
ca_create_mask(co); \
|
|
1238
|
-
omask = (boolean8_t *) co->mask->ptr; \
|
|
1239
|
-
} \
|
|
1240
|
-
omask[o] = 1; \
|
|
1241
|
-
} while (0)
|
|
1242
1365
|
|
|
1243
1366
|
if ( src->data_type == CA_OBJECT ) {
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
GROUP_SCAN_OBJECT_WALK(
|
|
1247
|
-
accn[code] += 1; outi[addr] = (int64_t) accn[code];,
|
|
1248
|
-
outi[addr] = (int64_t) accn[code];
|
|
1249
|
-
);
|
|
1250
|
-
}
|
|
1251
|
-
else { /* object running VALUE */
|
|
1252
|
-
VALUE *outo = (VALUE *) co->ptr;
|
|
1367
|
+
group_scan_object_t c;
|
|
1368
|
+
if ( op != GS_CUMCOUNT ) {
|
|
1253
1369
|
acco = ALLOCV_N(VALUE, h_acco, K_total);
|
|
1254
|
-
switch ( op ) {
|
|
1255
|
-
case GS_CUMSUM:
|
|
1256
|
-
/* Identity 0 (matching the core object cumsum): a group's acc is lazily
|
|
1257
|
-
seeded to 0 (Fixnum, so 0 + ev promotes to ev's class), so a cell
|
|
1258
|
-
masked before any present member holds 0 unmasked and an all-masked
|
|
1259
|
-
group yields 0 everywhere. seen doubles as the per-band init flag. */
|
|
1260
|
-
GROUP_SCAN_OBJECT_WALK(
|
|
1261
|
-
if ( ! seen[code] ) { acco[code] = INT2FIX(0); seen[code] = 1; }
|
|
1262
|
-
acco[code] = rb_funcall(acco[code], rb_intern("+"), 1, ev);
|
|
1263
|
-
outo[addr] = acco[code];,
|
|
1264
|
-
if ( ! seen[code] ) { acco[code] = INT2FIX(0); seen[code] = 1; }
|
|
1265
|
-
outo[addr] = acco[code];
|
|
1266
|
-
);
|
|
1267
|
-
break;
|
|
1268
|
-
case GS_CUMPROD:
|
|
1269
|
-
/* Identity 1, same lazy-init as cumsum. */
|
|
1270
|
-
GROUP_SCAN_OBJECT_WALK(
|
|
1271
|
-
if ( ! seen[code] ) { acco[code] = INT2FIX(1); seen[code] = 1; }
|
|
1272
|
-
acco[code] = rb_funcall(acco[code], rb_intern("*"), 1, ev);
|
|
1273
|
-
outo[addr] = acco[code];,
|
|
1274
|
-
if ( ! seen[code] ) { acco[code] = INT2FIX(1); seen[code] = 1; }
|
|
1275
|
-
outo[addr] = acco[code];
|
|
1276
|
-
);
|
|
1277
|
-
break;
|
|
1278
|
-
case GS_CUMMAX:
|
|
1279
|
-
/* No identity: seed from the first member, hold only once seen; a cell
|
|
1280
|
-
masked before any member stays UNDEF (empty-max contract). */
|
|
1281
|
-
GROUP_SCAN_OBJECT_WALK(
|
|
1282
|
-
if ( ! seen[code] ) { acco[code] = ev; seen[code] = 1; }
|
|
1283
|
-
else if ( NUM2INT(rb_funcall(ev, rb_intern("<=>"), 1, acco[code])) > 0 ) {
|
|
1284
|
-
acco[code] = ev;
|
|
1285
|
-
}
|
|
1286
|
-
outo[addr] = acco[code];,
|
|
1287
|
-
if ( seen[code] ) { outo[addr] = acco[code]; }
|
|
1288
|
-
else { MARK_OUT_UNDEF(addr); }
|
|
1289
|
-
);
|
|
1290
|
-
break;
|
|
1291
|
-
case GS_CUMMIN:
|
|
1292
|
-
GROUP_SCAN_OBJECT_WALK(
|
|
1293
|
-
if ( ! seen[code] ) { acco[code] = ev; seen[code] = 1; }
|
|
1294
|
-
else if ( NUM2INT(rb_funcall(ev, rb_intern("<=>"), 1, acco[code])) < 0 ) {
|
|
1295
|
-
acco[code] = ev;
|
|
1296
|
-
}
|
|
1297
|
-
outo[addr] = acco[code];,
|
|
1298
|
-
if ( seen[code] ) { outo[addr] = acco[code]; }
|
|
1299
|
-
else { MARK_OUT_UNDEF(addr); }
|
|
1300
|
-
);
|
|
1301
|
-
break;
|
|
1302
|
-
}
|
|
1303
1370
|
}
|
|
1371
|
+
c.ca = ca; c.co = co; c.op = op;
|
|
1372
|
+
c.axes = axes; c.ngroup = ngroup;
|
|
1373
|
+
c.n_bundles = n_bundles; c.bundle_codes = bundle_codes;
|
|
1374
|
+
c.bundle_k = bundle_k; c.bundle_placeval = bundle_placeval;
|
|
1375
|
+
c.bundle_nconsumed = bundle_nconsumed;
|
|
1376
|
+
c.bundle_slot = bundle_slot; c.bundle_cstride = bundle_cstride;
|
|
1377
|
+
c.grstride = grstride; c.band_addr = band_addr; c.K_total = K_total;
|
|
1378
|
+
c.sw_code = sw_code; c.sw_doff = sw_doff;
|
|
1379
|
+
c.sw_moff = sw_moff; c.sw_addr = sw_addr;
|
|
1380
|
+
c.accn = accn; c.seen = seen; c.acco = acco;
|
|
1381
|
+
ca_iter_ensure(1, &c.st, group_scan_object_body, (VALUE) &c);
|
|
1304
1382
|
}
|
|
1305
1383
|
else { /* native data type dispatch */
|
|
1306
1384
|
switch ( op ) {
|
|
@@ -1330,11 +1408,11 @@ rb_ca_axis_group_scan (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
|
|
|
1330
1408
|
break;
|
|
1331
1409
|
}
|
|
1332
1410
|
}
|
|
1333
|
-
#undef MARK_OUT_UNDEF
|
|
1334
1411
|
|
|
1335
1412
|
ALLOCV_END(h_band2); ALLOCV_END(h_code); ALLOCV_END(h_doff);
|
|
1336
1413
|
ALLOCV_END(h_moff); ALLOCV_END(h_addr); ALLOCV_END(h_accd);
|
|
1337
1414
|
ALLOCV_END(h_accn); ALLOCV_END(h_seen); ALLOCV_END(h_acco);
|
|
1415
|
+
for ( int bi = 0; bi < n_bundles; bi++ ) ALLOCV_END(h_codes[bi]);
|
|
1338
1416
|
|
|
1339
1417
|
RB_GC_GUARD(keep);
|
|
1340
1418
|
return vout;
|
|
@@ -1343,8 +1421,8 @@ rb_ca_axis_group_scan (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
|
|
|
1343
1421
|
void
|
|
1344
1422
|
Init_ca_axis_group (void)
|
|
1345
1423
|
{
|
|
1346
|
-
rb_define_method(rb_cCArray, "
|
|
1424
|
+
rb_define_method(rb_cCArray, "__reduce_by_axis_groups__",
|
|
1347
1425
|
rb_ca_axis_group_reduce, 3);
|
|
1348
|
-
rb_define_method(rb_cCArray, "
|
|
1426
|
+
rb_define_method(rb_cCArray, "__scan_by_axis_groups__",
|
|
1349
1427
|
rb_ca_axis_group_scan, 3);
|
|
1350
1428
|
}
|
data/ext/ca_binop_dispatch.c
CHANGED
|
@@ -27,39 +27,56 @@
|
|
|
27
27
|
/* vv kernel lookup */
|
|
28
28
|
/* ------------------------------------------------------------------- */
|
|
29
29
|
|
|
30
|
+
/* The kernel table of each op id. The eager operators hold the tables
|
|
31
|
+
themselves; ca_binop_op_id_of_table maps one back to its op id, so that
|
|
32
|
+
both ask ca_op_raises_on_cell the same question. */
|
|
33
|
+
static ca_binop_func_t * const ca_binop_tables[CA_BINOP_COUNT] = {
|
|
34
|
+
[CA_BINOP_ADD] = ca_binop_add,
|
|
35
|
+
[CA_BINOP_SUB] = ca_binop_sub,
|
|
36
|
+
[CA_BINOP_MUL] = ca_binop_mul,
|
|
37
|
+
[CA_BINOP_DIV] = ca_binop_div,
|
|
38
|
+
[CA_BINOP_POW] = ca_binop_power,
|
|
39
|
+
[CA_BINOP_BIT_AND] = ca_binop_bit_and_i,
|
|
40
|
+
[CA_BINOP_BIT_OR] = ca_binop_bit_or_i,
|
|
41
|
+
[CA_BINOP_BIT_XOR] = ca_binop_bit_xor_i,
|
|
42
|
+
[CA_BINOP_BIT_LSHIFT]= ca_binop_bit_lshift,
|
|
43
|
+
[CA_BINOP_BIT_RSHIFT]= ca_binop_bit_rshift,
|
|
44
|
+
[CA_BINOP_MOD] = ca_binop_mod,
|
|
45
|
+
[CA_BINOP_QUO] = ca_binop_quo_i,
|
|
46
|
+
[CA_BINOP_RCP_MUL] = ca_binop_rcp_mul,
|
|
47
|
+
[CA_BINOP_IPOWER] = ca_binop_ipower,
|
|
48
|
+
[CA_BINOP_COPYSIGN] = ca_binop_copysign,
|
|
49
|
+
[CA_BINOP_LOGADDEXP] = ca_binop_logaddexp,
|
|
50
|
+
[CA_BINOP_NEXTAFTER] = ca_binop_nextafter,
|
|
51
|
+
[CA_BINOP_FMOD] = ca_binop_fmod,
|
|
52
|
+
[CA_BINOP_ATAN2] = ca_binop_atan2,
|
|
53
|
+
[CA_BINOP_HYPOT] = ca_binop_hypot,
|
|
54
|
+
[CA_BINOP_PMAX] = ca_binop_pmax,
|
|
55
|
+
[CA_BINOP_PMIN] = ca_binop_pmin,
|
|
56
|
+
[CA_BINOP_MAXIMUM] = ca_binop_maximum,
|
|
57
|
+
[CA_BINOP_MINIMUM] = ca_binop_minimum,
|
|
58
|
+
[CA_BINOP_AND] = ca_binop_and,
|
|
59
|
+
[CA_BINOP_OR] = ca_binop_or,
|
|
60
|
+
[CA_BINOP_XOR] = ca_binop_xor,
|
|
61
|
+
};
|
|
62
|
+
|
|
30
63
|
ca_binop_func_t
|
|
31
64
|
ca_binop_kernel_lookup_vv (uint16_t op_id, int8_t common_dt)
|
|
32
65
|
{
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
case CA_BINOP_QUO: return ca_binop_quo_i [common_dt];
|
|
46
|
-
case CA_BINOP_RCP_MUL: return ca_binop_rcp_mul [common_dt];
|
|
47
|
-
case CA_BINOP_IPOWER: return ca_binop_ipower [common_dt];
|
|
48
|
-
case CA_BINOP_COPYSIGN: return ca_binop_copysign [common_dt];
|
|
49
|
-
case CA_BINOP_LOGADDEXP: return ca_binop_logaddexp [common_dt];
|
|
50
|
-
case CA_BINOP_NEXTAFTER: return ca_binop_nextafter [common_dt];
|
|
51
|
-
case CA_BINOP_FMOD: return ca_binop_fmod [common_dt];
|
|
52
|
-
case CA_BINOP_ATAN2: return ca_binop_atan2 [common_dt];
|
|
53
|
-
case CA_BINOP_HYPOT: return ca_binop_hypot [common_dt];
|
|
54
|
-
case CA_BINOP_PMAX: return ca_binop_pmax [common_dt];
|
|
55
|
-
case CA_BINOP_PMIN: return ca_binop_pmin [common_dt];
|
|
56
|
-
case CA_BINOP_MAXIMUM: return ca_binop_maximum [common_dt];
|
|
57
|
-
case CA_BINOP_MINIMUM: return ca_binop_minimum [common_dt];
|
|
58
|
-
case CA_BINOP_AND: return ca_binop_and [common_dt];
|
|
59
|
-
case CA_BINOP_OR: return ca_binop_or [common_dt];
|
|
60
|
-
case CA_BINOP_XOR: return ca_binop_xor [common_dt];
|
|
61
|
-
default: return NULL;
|
|
66
|
+
if ( op_id >= CA_BINOP_COUNT || ! ca_binop_tables[op_id] ) return NULL;
|
|
67
|
+
return ca_binop_tables[op_id][common_dt];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* The op id whose kernel table is `table`, or -1 for a table no op id
|
|
71
|
+
names. */
|
|
72
|
+
int
|
|
73
|
+
ca_binop_op_id_of_table (ca_binop_func_t table[])
|
|
74
|
+
{
|
|
75
|
+
int op_id;
|
|
76
|
+
for ( op_id = 0; op_id < CA_BINOP_COUNT; op_id++ ) {
|
|
77
|
+
if ( ca_binop_tables[op_id] == table ) return op_id;
|
|
62
78
|
}
|
|
79
|
+
return -1;
|
|
63
80
|
}
|
|
64
81
|
|
|
65
82
|
/* ------------------------------------------------------------------- */
|
|
@@ -99,26 +116,3 @@ ca_binop_kernel_input_data_types (uint16_t op_id, int8_t l_dt, int8_t r_dt,
|
|
|
99
116
|
if ( out_r_in_dt ) *out_r_in_dt = common;
|
|
100
117
|
}
|
|
101
118
|
|
|
102
|
-
/* ------------------------------------------------------------------- */
|
|
103
|
-
/* trapping-op predicate */
|
|
104
|
-
/* ------------------------------------------------------------------- */
|
|
105
|
-
|
|
106
|
-
int
|
|
107
|
-
ca_binop_is_trapping (uint16_t op_id, int8_t common_dt)
|
|
108
|
-
{
|
|
109
|
-
/* Integer DIV / MOD / QUO / FMOD can SIGFPE on a zero divisor. Float
|
|
110
|
-
DIV returns NaN/Inf and does NOT trap, so it is not classified
|
|
111
|
-
trapping. */
|
|
112
|
-
int is_integer = ( common_dt >= CA_INT8 && common_dt <= CA_UINT64 );
|
|
113
|
-
if ( ! is_integer ) return 0;
|
|
114
|
-
|
|
115
|
-
switch (op_id) {
|
|
116
|
-
case CA_BINOP_DIV:
|
|
117
|
-
case CA_BINOP_MOD:
|
|
118
|
-
case CA_BINOP_QUO:
|
|
119
|
-
case CA_BINOP_FMOD:
|
|
120
|
-
return 1;
|
|
121
|
-
default:
|
|
122
|
-
return 0;
|
|
123
|
-
}
|
|
124
|
-
}
|
data/ext/ca_binop_dispatch.h
CHANGED
|
@@ -147,6 +147,6 @@ void ca_binop_kernel_input_data_types (uint16_t op_id, int8_t l_dt, int8_t r_dt,
|
|
|
147
147
|
When trapping AND either operand has a mask, xfer_stride must pass
|
|
148
148
|
a slab mask to the kernel so masked cells are skipped (otherwise
|
|
149
149
|
masked-zero divisors crash with SIGFPE). See §3.4 rev3. */
|
|
150
|
-
int
|
|
150
|
+
int ca_binop_op_id_of_table (ca_binop_func_t table[]);
|
|
151
151
|
|
|
152
152
|
#endif /* CA_BINOP_DISPATCH_H */
|