carray 3.0.3 → 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 +264 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +1 -6
- data/ext/ca_axis_group.c +27 -27
- data/ext/ca_binop_dispatch.c +1 -29
- data/ext/ca_binop_dispatch.h +0 -1
- data/ext/ca_categorical_iterator.c +205 -134
- data/ext/ca_compare.c +7 -18
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1234 -1994
- data/ext/ca_kernel_iterator.h +391 -437
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +96 -39
- data/ext/ca_obj_bincmp.c +24 -21
- data/ext/ca_obj_binop.c +15 -26
- data/ext/ca_obj_bitarray.c +3 -2
- data/ext/ca_obj_bitfield.c +5 -6
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +5 -6
- data/ext/ca_obj_const_string.c +173 -19
- data/ext/ca_obj_face.c +238 -57
- data/ext/ca_obj_face.h +19 -0
- data/ext/ca_obj_fake.c +15 -29
- data/ext/ca_obj_farray.c +6 -3
- data/ext/ca_obj_field.c +17 -5
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +406 -132
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +67 -57
- data/ext/ca_obj_object.c +157 -51
- data/ext/ca_obj_record.c +12 -7
- data/ext/ca_obj_reduce.c +13 -8
- data/ext/ca_obj_refer.c +25 -27
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +6 -5
- data/ext/ca_obj_select.c +14 -9
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +11 -1
- data/ext/ca_obj_stack.c +179 -34
- data/ext/ca_obj_stride.c +162 -115
- data/ext/ca_obj_string.c +71 -4
- data/ext/ca_obj_tile.c +6 -5
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +5 -3
- data/ext/ca_obj_triop.c +23 -32
- data/ext/ca_obj_window.c +190 -26
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +181 -75
- data/ext/carray_access.c +184 -96
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +89 -6
- data/ext/carray_bincount.c +10 -8
- data/ext/carray_broadcast.c +13 -8
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +108 -0
- data/ext/carray_cast.c +142 -24
- data/ext/carray_cast_func.rb +46 -6
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +16 -7
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +147 -55
- data/ext/carray_count.c +50 -20
- data/ext/carray_element.c +76 -33
- data/ext/carray_factorize.c +118 -64
- data/ext/carray_generate.c +191 -50
- data/ext/carray_histogram.c +62 -17
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +336 -29
- data/ext/carray_kernels_bincmp.c +4453 -0
- data/ext/carray_kernels_binop.c +11368 -0
- data/ext/carray_kernels_init.c +1734 -0
- data/ext/carray_kernels_moncmp.c +2104 -0
- data/ext/carray_kernels_monop.c +18369 -0
- data/ext/carray_kernels_reduce_aggregate.c +23818 -0
- data/ext/carray_kernels_reduce_boolean.c +406 -0
- data/ext/carray_kernels_reduce_cumulative.c +10086 -0
- data/ext/carray_kernels_reduce_extreme.c +17634 -0
- data/ext/carray_kernels_reduce_variance.c +3849 -0
- data/ext/carray_kernels_scan.c +4302 -0
- data/ext/carray_kernels_search.c +33829 -0
- data/ext/carray_kernels_sort.c +10906 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +292 -72
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +124 -47
- data/ext/carray_order.c +384 -76
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +67 -13
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +63 -38
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +91 -28
- data/ext/carray_sort.c +35 -35
- data/ext/carray_struct.c +19 -18
- data/ext/carray_test.c +26 -5
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +246 -45
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +198 -240
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +126 -22
- data/lib/carray/autoload_carray.rb +8 -31
- data/lib/carray/autoload_method_extension.rb +14 -5
- data/lib/carray/axis_group.rb +255 -106
- data/lib/carray/basics.rb +78 -10
- data/lib/carray/bincount_nd.rb +12 -2
- data/lib/carray/block_iterator.rb +126 -23
- data/lib/carray/boolean_reduce.rb +17 -17
- data/lib/carray/categorical.rb +165 -43
- data/lib/carray/categorical_iterator.rb +130 -27
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +14 -5
- 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/convert.rb +69 -0
- data/lib/carray/frame/csv_parser.rb +111 -17
- data/lib/carray/frame/describe.rb +3 -2
- data/lib/carray/frame/frame.rb +246 -21
- data/lib/carray/frame/group.rb +510 -95
- data/lib/carray/frame/io.rb +115 -28
- data/lib/carray/frame/join.rb +312 -51
- data/lib/carray/frame/records.rb +83 -7
- data/lib/carray/frame/reshape.rb +42 -35
- data/lib/carray/frame/sort.rb +7 -19
- data/lib/carray/frame/verbs.rb +188 -48
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +11 -4
- data/lib/carray/fusion.rb +40 -16
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +31 -8
- data/lib/carray/iterator.rb +85 -7
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +182 -183
- data/lib/carray/mask_gap_fill.rb +63 -57
- data/lib/carray/meld_reduce.rb +12 -14
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +16 -0
- data/lib/carray/methods/bit_string.rb +1 -1
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +3 -1
- data/lib/carray/methods/gather_nd.rb +14 -5
- data/lib/carray/methods/insert_block.rb +2 -2
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +53 -36
- data/lib/carray/methods/join.rb +1 -6
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +47 -51
- data/lib/carray/methods/mode.rb +1 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/resize.rb +3 -3
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +3 -3
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +53 -8
- data/lib/carray/segment_iterator.rb +313 -82
- data/lib/carray/serialize.rb +24 -10
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +8 -1
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +19 -8
- data/lib/carray/time.rb +726 -104
- data/lib/carray/window_iterator.rb +122 -16
- data/lib/carray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +4 -0
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +2 -1
- data/yard-stubs/ca_obj_roll.rb +2 -2
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_cast.rb +10 -0
- data/yard-stubs/carray_conversion.rb +2 -1
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +26 -2
- data/yard-stubs/carray_math.rb +27 -1
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +29 -18
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +14 -9
- data/yard-stubs/carray_slab.rb +9 -2
- data/yard-stubs/carray_sort.rb +6 -5
- data/yard-stubs/carray_test.rb +5 -3
- metadata +25 -3
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
|
@@ -1,120 +1,109 @@
|
|
|
1
1
|
/* ---------------------------------------------------------------------------
|
|
2
2
|
|
|
3
|
-
ca_categorical_iterator.c —
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
The output position is data-dependent (cursor[code]++), which the aligned
|
|
21
|
-
kernel_iterator macros do not model, so the flat inputs are materialised here:
|
|
22
|
-
ca_attach aliases a contiguous entity (codes / a contiguous value) and gathers
|
|
23
|
-
a view. Codes dispatch on their native integer type (no coercion); the value
|
|
24
|
-
move is a bytes-wide memcpy (grouped shares the value data type, so no value-type
|
|
25
|
-
dispatch is needed).
|
|
26
|
-
|
|
27
|
-
Surface (private): codes.__categorical_scatter__(value, cursor, grouped, k)
|
|
3
|
+
ca_categorical_iterator.c — kernels for CACategorical and CACategoricalIterator.
|
|
4
|
+
|
|
5
|
+
addresses_by_category orders the cells of a categorical by category, the
|
|
6
|
+
counting sort behind CACategorical#sort_addr: one pass over the codes
|
|
7
|
+
writes each cell's address at its category's cursor (a mutable copy of the
|
|
8
|
+
segment starts), so every cell of category 0 comes first, then 1, ..., in
|
|
9
|
+
source order within a category (stable). A cell in no category -- a masked
|
|
10
|
+
code, or a code outside 0...k -- is written in the same pass at a second
|
|
11
|
+
cursor that starts after the last category, so the excluded cells follow
|
|
12
|
+
in source order.
|
|
13
|
+
|
|
14
|
+
The output position depends on the code, which the aligned kernel_iterator
|
|
15
|
+
macros do not model, so the codes are materialised here: ca_attach aliases a
|
|
16
|
+
contiguous entity and gathers a view.
|
|
17
|
+
|
|
18
|
+
Surface (private): codes.addresses_by_category(cursor, k, nvalid)
|
|
28
19
|
self = codes (integer, carries the exclusion mask), read flat
|
|
29
|
-
value = payload (any data type, may carry a mask), read flat, same length
|
|
30
20
|
cursor = int64 length-k segment starts (mutated in place, consumed)
|
|
31
|
-
grouped = pre-allocated contiguous entity of the value data type, length nvalid
|
|
32
21
|
k = number of categories
|
|
33
|
-
|
|
22
|
+
nvalid = number of cells in a category (where the excluded cells start)
|
|
23
|
+
Returns a new int64 CArray of codes.elements addresses.
|
|
34
24
|
|
|
35
25
|
--------------------------------------------------------------------------- */
|
|
36
26
|
|
|
37
27
|
#include "carray.h"
|
|
38
28
|
#include "carray_internal.h" /* CA_EXTREMUM_REPLACES */
|
|
29
|
+
#include "ca_sort_kernels.h" /* ca_partition_nan_f64 */
|
|
39
30
|
#include <stdlib.h> /* qsort */
|
|
40
31
|
#include <math.h> /* floor */
|
|
41
32
|
|
|
42
|
-
#define
|
|
33
|
+
#define ADDRESSES_BY_CATEGORY_BODY(CODE_T) \
|
|
43
34
|
do { \
|
|
44
35
|
const CODE_T *cp = (const CODE_T *) codes->ptr; \
|
|
45
36
|
for ( j = 0; j < n; j++ ) { \
|
|
46
|
-
if ( cmask && cmask[j] ) continue; /* excluded by codes mask */ \
|
|
47
37
|
c = (int64_t) cp[j]; \
|
|
48
|
-
if ( c < 0 || c >= k )
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
38
|
+
if ( ( cmask && cmask[j] ) || c < 0 || c >= k ) { \
|
|
39
|
+
if ( tail >= (int64_t) n ) { overrun = 1; break; } \
|
|
40
|
+
out[tail++] = (int64_t) j; /* in no category */ \
|
|
41
|
+
continue; \
|
|
42
|
+
} \
|
|
43
|
+
if ( cur[c] < 0 || cur[c] >= nvalid ) { overrun = 1; break; } \
|
|
44
|
+
out[cur[c]++] = (int64_t) j; \
|
|
53
45
|
} \
|
|
54
46
|
} while (0)
|
|
55
47
|
|
|
56
48
|
static VALUE
|
|
57
|
-
|
|
58
|
-
VALUE rgrouped, VALUE rk)
|
|
49
|
+
rb_ca_addresses_by_category (VALUE self, VALUE rcursor, VALUE rk, VALUE rnvalid)
|
|
59
50
|
{
|
|
60
|
-
CArray *codes, *
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
GetCArray(
|
|
68
|
-
GetCArray(rcursor,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
rb_raise(rb_eArgError,
|
|
76
|
-
"__categorical_scatter__: value length %lld != codes length %lld",
|
|
77
|
-
(long long) value->elements, (long long) n);
|
|
51
|
+
CArray *codes, *cursor, *result;
|
|
52
|
+
VALUE rresult;
|
|
53
|
+
int64_t k, c, *cur, *out, tail, nvalid;
|
|
54
|
+
ca_size_t n, j, dim;
|
|
55
|
+
int overrun = 0;
|
|
56
|
+
boolean8_t *cmask;
|
|
57
|
+
|
|
58
|
+
GetCArray(self, codes);
|
|
59
|
+
GetCArray(rcursor, cursor);
|
|
60
|
+
k = (int64_t) NUM2LL(rk);
|
|
61
|
+
nvalid = (int64_t) NUM2LL(rnvalid);
|
|
62
|
+
n = codes->elements;
|
|
63
|
+
|
|
64
|
+
if ( cursor->data_type != CA_INT64 || cursor->elements != k ||
|
|
65
|
+
! ca_is_entity(cursor) ) {
|
|
66
|
+
rb_raise(rb_eArgError, "addresses_by_category: cursor must be an int64[k] entity");
|
|
78
67
|
}
|
|
79
|
-
if (
|
|
80
|
-
rb_raise(rb_eArgError, "
|
|
68
|
+
if ( nvalid < 0 || nvalid > (int64_t) n ) {
|
|
69
|
+
rb_raise(rb_eArgError, "addresses_by_category: nvalid %lld out of 0..%lld",
|
|
70
|
+
(long long) nvalid, (long long) n);
|
|
81
71
|
}
|
|
82
|
-
if ( grouped->bytes != bytes ) {
|
|
83
|
-
rb_raise(rb_eArgError, "__categorical_scatter__: grouped/value data type mismatch");
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
ca_attach_n(2, codes, value); /* window: detached before each raise inside */
|
|
87
|
-
cmask = ca_mask_ptr(codes);
|
|
88
|
-
vmask = ca_mask_ptr(value);
|
|
89
|
-
cur = (int64_t *) cursor->ptr;
|
|
90
|
-
gp = grouped->ptr;
|
|
91
|
-
vp = value->ptr;
|
|
92
|
-
|
|
93
|
-
if ( vmask ) { /* grouped needs a mask to receive it */
|
|
94
|
-
ca_create_mask(grouped);
|
|
95
|
-
gmask = (boolean8_t *) grouped->mask->ptr;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
72
|
switch ( codes->data_type ) {
|
|
99
|
-
case CA_INT8:
|
|
100
|
-
case
|
|
101
|
-
|
|
102
|
-
case CA_UINT16: CATEGORICAL_SCATTER_BODY(uint16_t); break;
|
|
103
|
-
case CA_INT32: CATEGORICAL_SCATTER_BODY(int32_t); break;
|
|
104
|
-
case CA_UINT32: CATEGORICAL_SCATTER_BODY(uint32_t); break;
|
|
105
|
-
case CA_INT64: CATEGORICAL_SCATTER_BODY(int64_t); break;
|
|
106
|
-
case CA_UINT64: CATEGORICAL_SCATTER_BODY(uint64_t); break;
|
|
73
|
+
case CA_INT8: case CA_UINT8: case CA_INT16: case CA_UINT16:
|
|
74
|
+
case CA_INT32: case CA_UINT32: case CA_INT64: case CA_UINT64:
|
|
75
|
+
break;
|
|
107
76
|
default:
|
|
108
|
-
ca_detach(codes);
|
|
109
|
-
ca_detach(value);
|
|
110
77
|
rb_raise(rb_eCADataTypeError,
|
|
111
|
-
"
|
|
78
|
+
"addresses_by_category: integer codes required (got data_type %d)",
|
|
112
79
|
codes->data_type);
|
|
113
80
|
}
|
|
114
81
|
|
|
82
|
+
dim = n;
|
|
83
|
+
rresult = rb_carray_new(CA_INT64, 1, &dim, 0, NULL);
|
|
84
|
+
GetCArray(rresult, result);
|
|
85
|
+
out = (int64_t *) result->ptr;
|
|
86
|
+
cur = (int64_t *) cursor->ptr;
|
|
87
|
+
tail = nvalid;
|
|
88
|
+
|
|
89
|
+
ca_attach(codes); /* window: nothing below raises */
|
|
90
|
+
cmask = ca_mask_ptr(codes);
|
|
91
|
+
switch ( codes->data_type ) {
|
|
92
|
+
case CA_INT8: ADDRESSES_BY_CATEGORY_BODY(int8_t); break;
|
|
93
|
+
case CA_UINT8: ADDRESSES_BY_CATEGORY_BODY(uint8_t); break;
|
|
94
|
+
case CA_INT16: ADDRESSES_BY_CATEGORY_BODY(int16_t); break;
|
|
95
|
+
case CA_UINT16: ADDRESSES_BY_CATEGORY_BODY(uint16_t); break;
|
|
96
|
+
case CA_INT32: ADDRESSES_BY_CATEGORY_BODY(int32_t); break;
|
|
97
|
+
case CA_UINT32: ADDRESSES_BY_CATEGORY_BODY(uint32_t); break;
|
|
98
|
+
case CA_INT64: ADDRESSES_BY_CATEGORY_BODY(int64_t); break;
|
|
99
|
+
case CA_UINT64: ADDRESSES_BY_CATEGORY_BODY(uint64_t); break;
|
|
100
|
+
}
|
|
115
101
|
ca_detach(codes);
|
|
116
|
-
|
|
117
|
-
|
|
102
|
+
if ( overrun ) {
|
|
103
|
+
rb_raise(rb_eArgError,
|
|
104
|
+
"addresses_by_category: the cursor and nvalid do not match the codes");
|
|
105
|
+
}
|
|
106
|
+
return rresult;
|
|
118
107
|
}
|
|
119
108
|
|
|
120
109
|
/* ---------------------------------------------------------------------------
|
|
@@ -151,7 +140,22 @@ rb_ca_categorical_scatter (VALUE self, VALUE rvalue, VALUE rcursor,
|
|
|
151
140
|
#define CAT_NAN_NEVER(v) (0)
|
|
152
141
|
#define CAT_NAN_CHECK(v) ((v) != (v))
|
|
153
142
|
|
|
154
|
-
|
|
143
|
+
/* Whether v takes the place of the accumulator acc: never when v is NaN,
|
|
144
|
+
always when acc is NaN and v is not. */
|
|
145
|
+
#define CAT_REPLACES(v, acc, CMP, ISNAN) \
|
|
146
|
+
( ! ISNAN(v) && ( ISNAN(acc) || (v) CMP (acc) ) )
|
|
147
|
+
|
|
148
|
+
/* A segment without masked cells of at least CAT_LANES_FROM cells is read
|
|
149
|
+
with eight independent sums and eight min / max lanes, so no add or
|
|
150
|
+
compare waits on the one before it; a shorter one would spend more on
|
|
151
|
+
setting up and merging the lanes than it saves.
|
|
152
|
+
Each lane starts from the segment's first value; a lane can end on NaN
|
|
153
|
+
only if every value it saw was NaN, so merging the lanes with the same
|
|
154
|
+
rule gives the answer one lane would. The sums are added in a different
|
|
155
|
+
order than the cells, which is the license every float reduction has. */
|
|
156
|
+
#define CAT_LANES_FROM 64
|
|
157
|
+
|
|
158
|
+
#define REDUCEAT_MOMENTS_BODY(T, ISNAN, LANES_FROM) \
|
|
155
159
|
do { \
|
|
156
160
|
const T *gp = (const T *) grouped->ptr; \
|
|
157
161
|
T *minv = (T *) minp, *maxv = (T *) maxp; \
|
|
@@ -161,16 +165,95 @@ rb_ca_categorical_scatter (VALUE self, VALUE rvalue, VALUE rcursor,
|
|
|
161
165
|
ca_size_t j, cnt = 0; \
|
|
162
166
|
double sacc = 0.0; \
|
|
163
167
|
T mn = 0, mx = 0; int seen = 0; \
|
|
164
|
-
|
|
165
|
-
if (
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
if (
|
|
171
|
-
if (
|
|
168
|
+
if ( ! gm && hi - lo < (ca_size_t) (LANES_FROM) ) { \
|
|
169
|
+
if ( hi > lo ) { \
|
|
170
|
+
mn = mx = gp[lo]; \
|
|
171
|
+
for ( j = lo; j < hi; j++ ) { \
|
|
172
|
+
T v = gp[j]; \
|
|
173
|
+
sacc += (double) v; \
|
|
174
|
+
if ( CAT_REPLACES(v, mn, <, ISNAN) ) mn = v; \
|
|
175
|
+
if ( CAT_REPLACES(v, mx, >, ISNAN) ) mx = v; \
|
|
172
176
|
} \
|
|
173
|
-
cnt
|
|
177
|
+
cnt = hi - lo; seen = 1; \
|
|
178
|
+
} \
|
|
179
|
+
} \
|
|
180
|
+
else if ( ! gm ) { \
|
|
181
|
+
{ \
|
|
182
|
+
double s0 = 0, s1 = 0, s2 = 0, s3 = 0, s4 = 0, s5 = 0, s6 = 0, s7 = 0; \
|
|
183
|
+
T n0, n1, n2, n3, n4, n5, n6, n7, x0, x1, x2, x3, x4, x5, x6, x7; \
|
|
184
|
+
n0 = n1 = n2 = n3 = n4 = n5 = n6 = n7 = gp[lo]; \
|
|
185
|
+
x0 = x1 = x2 = x3 = x4 = x5 = x6 = x7 = gp[lo]; \
|
|
186
|
+
for ( j = lo; j + 8 <= hi; j += 8 ) { \
|
|
187
|
+
T v0 = gp[j], v1 = gp[j+1], v2 = gp[j+2], v3 = gp[j+3]; \
|
|
188
|
+
T v4 = gp[j+4], v5 = gp[j+5], v6 = gp[j+6], v7 = gp[j+7]; \
|
|
189
|
+
s0 += (double) v0; s1 += (double) v1; \
|
|
190
|
+
s2 += (double) v2; s3 += (double) v3; \
|
|
191
|
+
s4 += (double) v4; s5 += (double) v5; \
|
|
192
|
+
s6 += (double) v6; s7 += (double) v7; \
|
|
193
|
+
if ( CAT_REPLACES(v0, n0, <, ISNAN) ) n0 = v0; \
|
|
194
|
+
if ( CAT_REPLACES(v1, n1, <, ISNAN) ) n1 = v1; \
|
|
195
|
+
if ( CAT_REPLACES(v2, n2, <, ISNAN) ) n2 = v2; \
|
|
196
|
+
if ( CAT_REPLACES(v3, n3, <, ISNAN) ) n3 = v3; \
|
|
197
|
+
if ( CAT_REPLACES(v4, n4, <, ISNAN) ) n4 = v4; \
|
|
198
|
+
if ( CAT_REPLACES(v5, n5, <, ISNAN) ) n5 = v5; \
|
|
199
|
+
if ( CAT_REPLACES(v6, n6, <, ISNAN) ) n6 = v6; \
|
|
200
|
+
if ( CAT_REPLACES(v7, n7, <, ISNAN) ) n7 = v7; \
|
|
201
|
+
if ( CAT_REPLACES(v0, x0, >, ISNAN) ) x0 = v0; \
|
|
202
|
+
if ( CAT_REPLACES(v1, x1, >, ISNAN) ) x1 = v1; \
|
|
203
|
+
if ( CAT_REPLACES(v2, x2, >, ISNAN) ) x2 = v2; \
|
|
204
|
+
if ( CAT_REPLACES(v3, x3, >, ISNAN) ) x3 = v3; \
|
|
205
|
+
if ( CAT_REPLACES(v4, x4, >, ISNAN) ) x4 = v4; \
|
|
206
|
+
if ( CAT_REPLACES(v5, x5, >, ISNAN) ) x5 = v5; \
|
|
207
|
+
if ( CAT_REPLACES(v6, x6, >, ISNAN) ) x6 = v6; \
|
|
208
|
+
if ( CAT_REPLACES(v7, x7, >, ISNAN) ) x7 = v7; \
|
|
209
|
+
} \
|
|
210
|
+
for ( ; j < hi; j++ ) { \
|
|
211
|
+
T v = gp[j]; \
|
|
212
|
+
s0 += (double) v; \
|
|
213
|
+
if ( CAT_REPLACES(v, n0, <, ISNAN) ) n0 = v; \
|
|
214
|
+
if ( CAT_REPLACES(v, x0, >, ISNAN) ) x0 = v; \
|
|
215
|
+
} \
|
|
216
|
+
sacc = ((s0 + s1) + (s2 + s3)) + ((s4 + s5) + (s6 + s7)); \
|
|
217
|
+
mn = n0; \
|
|
218
|
+
if ( CAT_REPLACES(n1, mn, <, ISNAN) ) mn = n1; \
|
|
219
|
+
if ( CAT_REPLACES(n2, mn, <, ISNAN) ) mn = n2; \
|
|
220
|
+
if ( CAT_REPLACES(n3, mn, <, ISNAN) ) mn = n3; \
|
|
221
|
+
if ( CAT_REPLACES(n4, mn, <, ISNAN) ) mn = n4; \
|
|
222
|
+
if ( CAT_REPLACES(n5, mn, <, ISNAN) ) mn = n5; \
|
|
223
|
+
if ( CAT_REPLACES(n6, mn, <, ISNAN) ) mn = n6; \
|
|
224
|
+
if ( CAT_REPLACES(n7, mn, <, ISNAN) ) mn = n7; \
|
|
225
|
+
mx = x0; \
|
|
226
|
+
if ( CAT_REPLACES(x1, mx, >, ISNAN) ) mx = x1; \
|
|
227
|
+
if ( CAT_REPLACES(x2, mx, >, ISNAN) ) mx = x2; \
|
|
228
|
+
if ( CAT_REPLACES(x3, mx, >, ISNAN) ) mx = x3; \
|
|
229
|
+
if ( CAT_REPLACES(x4, mx, >, ISNAN) ) mx = x4; \
|
|
230
|
+
if ( CAT_REPLACES(x5, mx, >, ISNAN) ) mx = x5; \
|
|
231
|
+
if ( CAT_REPLACES(x6, mx, >, ISNAN) ) mx = x6; \
|
|
232
|
+
if ( CAT_REPLACES(x7, mx, >, ISNAN) ) mx = x7; \
|
|
233
|
+
/* Of equal values a lane keeps its first, but the merge does not \
|
|
234
|
+
know which lane saw its value first in cell order. Only 0.0 and \
|
|
235
|
+
-0.0 are equal and tell apart: take the first zero, as one loop \
|
|
236
|
+
over the cells does. */ \
|
|
237
|
+
if ( mn == 0 ) { \
|
|
238
|
+
for ( j = lo; j < hi; j++ ) { if ( gp[j] == 0 ) { mn = gp[j]; break; } } \
|
|
239
|
+
} \
|
|
240
|
+
if ( mx == 0 ) { \
|
|
241
|
+
for ( j = lo; j < hi; j++ ) { if ( gp[j] == 0 ) { mx = gp[j]; break; } } \
|
|
242
|
+
} \
|
|
243
|
+
cnt = hi - lo; seen = 1; \
|
|
244
|
+
} \
|
|
245
|
+
} \
|
|
246
|
+
else { \
|
|
247
|
+
for ( j = lo; j < hi && gm[j]; j++ ) ; /* skip to the first present */ \
|
|
248
|
+
if ( j < hi ) { mn = mx = gp[j]; seen = 1; } \
|
|
249
|
+
for ( ; j < hi; j++ ) { \
|
|
250
|
+
T v = gp[j]; \
|
|
251
|
+
if ( gm[j] ) continue; /* masked value cell */ \
|
|
252
|
+
sacc += (double) v; \
|
|
253
|
+
cnt++; \
|
|
254
|
+
if ( CAT_REPLACES(v, mn, <, ISNAN) ) mn = v; \
|
|
255
|
+
if ( CAT_REPLACES(v, mx, >, ISNAN) ) mx = v; \
|
|
256
|
+
} \
|
|
174
257
|
} \
|
|
175
258
|
countp[c] = (int64_t) cnt; \
|
|
176
259
|
sump[c] = sacc; \
|
|
@@ -221,16 +304,16 @@ rb_ca_reduceat_moments (VALUE self, VALUE roffsets, VALUE rcounts,
|
|
|
221
304
|
maxm = (boolean8_t *) maxs->mask->ptr;
|
|
222
305
|
|
|
223
306
|
switch ( grouped->data_type ) {
|
|
224
|
-
case CA_INT8: REDUCEAT_MOMENTS_BODY(int8_t); break;
|
|
225
|
-
case CA_UINT8: REDUCEAT_MOMENTS_BODY(uint8_t); break;
|
|
226
|
-
case CA_INT16: REDUCEAT_MOMENTS_BODY(int16_t); break;
|
|
227
|
-
case CA_UINT16: REDUCEAT_MOMENTS_BODY(uint16_t); break;
|
|
228
|
-
case CA_INT32: REDUCEAT_MOMENTS_BODY(int32_t); break;
|
|
229
|
-
case CA_UINT32: REDUCEAT_MOMENTS_BODY(uint32_t); break;
|
|
230
|
-
case CA_INT64: REDUCEAT_MOMENTS_BODY(int64_t); break;
|
|
231
|
-
case CA_UINT64: REDUCEAT_MOMENTS_BODY(uint64_t); break;
|
|
232
|
-
case CA_FLOAT32: REDUCEAT_MOMENTS_BODY(float32_t); break;
|
|
233
|
-
case CA_FLOAT64: REDUCEAT_MOMENTS_BODY(float64_t); break;
|
|
307
|
+
case CA_INT8: REDUCEAT_MOMENTS_BODY(int8_t, CAT_NAN_NEVER, CA_LENGTH_MAX); break;
|
|
308
|
+
case CA_UINT8: REDUCEAT_MOMENTS_BODY(uint8_t, CAT_NAN_NEVER, CA_LENGTH_MAX); break;
|
|
309
|
+
case CA_INT16: REDUCEAT_MOMENTS_BODY(int16_t, CAT_NAN_NEVER, CA_LENGTH_MAX); break;
|
|
310
|
+
case CA_UINT16: REDUCEAT_MOMENTS_BODY(uint16_t, CAT_NAN_NEVER, CA_LENGTH_MAX); break;
|
|
311
|
+
case CA_INT32: REDUCEAT_MOMENTS_BODY(int32_t, CAT_NAN_NEVER, CA_LENGTH_MAX); break;
|
|
312
|
+
case CA_UINT32: REDUCEAT_MOMENTS_BODY(uint32_t, CAT_NAN_NEVER, CA_LENGTH_MAX); break;
|
|
313
|
+
case CA_INT64: REDUCEAT_MOMENTS_BODY(int64_t, CAT_NAN_NEVER, CA_LENGTH_MAX); break;
|
|
314
|
+
case CA_UINT64: REDUCEAT_MOMENTS_BODY(uint64_t, CAT_NAN_NEVER, CA_LENGTH_MAX); break;
|
|
315
|
+
case CA_FLOAT32: REDUCEAT_MOMENTS_BODY(float32_t, CAT_NAN_CHECK, CAT_LANES_FROM); break;
|
|
316
|
+
case CA_FLOAT64: REDUCEAT_MOMENTS_BODY(float64_t, CAT_NAN_CHECK, CAT_LANES_FROM); break;
|
|
234
317
|
default:
|
|
235
318
|
rb_raise(rb_eCADataTypeError,
|
|
236
319
|
"__reduceat_moments__: numeric value required (got data_type %d)",
|
|
@@ -294,19 +377,12 @@ ca_nth_element_double (double *a, ca_size_t n, ca_size_t kth)
|
|
|
294
377
|
{ double f = (double) (m - 1) * p / 100.0; \
|
|
295
378
|
ca_size_t ki = (ca_size_t) floor(f); \
|
|
296
379
|
double vlo, vhi; \
|
|
297
|
-
/*
|
|
298
|
-
ki-th element here is the ki-th of the sorted segment.
|
|
299
|
-
runs on the numeric prefix
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
ca_size_t nnum = m, t0 = 0; \
|
|
304
|
-
while ( t0 < nnum ) { \
|
|
305
|
-
if ( scratch[t0] != scratch[t0] ) { \
|
|
306
|
-
double tmp = scratch[--nnum]; \
|
|
307
|
-
scratch[nnum] = scratch[t0]; scratch[t0] = tmp; \
|
|
308
|
-
} else t0++; \
|
|
309
|
-
} \
|
|
380
|
+
/* NaN to the tail, where CArray's sort puts it (ca_partition_nan), \
|
|
381
|
+
so the ki-th element here is the ki-th of the sorted segment. \
|
|
382
|
+
Selection runs on the numeric prefix; a position or an upper \
|
|
383
|
+
neighbour landing in the tail is NaN. The blend is \
|
|
384
|
+
CArray#percentile's, so both answer alike for NaN and infinities. */\
|
|
385
|
+
ca_size_t nnum = ca_partition_nan_f64(scratch, m); \
|
|
310
386
|
if ( ki < nnum ) { \
|
|
311
387
|
ca_nth_element_double(scratch, nnum, ki); /* scratch[ki] = ki-th */ \
|
|
312
388
|
vlo = scratch[ki]; \
|
|
@@ -316,9 +392,7 @@ ca_nth_element_double (double *a, ca_size_t n, ca_size_t kth)
|
|
|
316
392
|
for ( t = ki + 2; t < nnum; t++ ) if ( scratch[t] < mn ) mn = scratch[t]; \
|
|
317
393
|
vhi = mn; \
|
|
318
394
|
} else vhi = (double) NAN; \
|
|
319
|
-
|
|
320
|
-
outp[c] = ( r == 0.0 || ki + 1 >= m ) ? vlo \
|
|
321
|
-
: vlo * (1.0 - r) + vhi * r; } } \
|
|
395
|
+
outp[c] = ca_percentile_linear(vlo, vhi, f - (double) ki, ki, m); } \
|
|
322
396
|
} \
|
|
323
397
|
} while (0)
|
|
324
398
|
|
|
@@ -693,19 +767,16 @@ cmp_double (const void *a, const void *b)
|
|
|
693
767
|
scratch[m++] = (double) gp[jj]; \
|
|
694
768
|
} \
|
|
695
769
|
if ( m == 0 ) { for ( t = 0; t < 5; t++ ) { outp[t][c] = 0.0; outm[t][c] = 1; } continue; } \
|
|
770
|
+
/* NaN sorts last, as in the core's sort, so a position or an upper \
|
|
771
|
+
neighbour in the tail is NaN, as the core answers. */ \
|
|
696
772
|
qsort(scratch, (size_t) m, sizeof(double), cmp_double); \
|
|
697
|
-
{ ca_size_t nnum = m; \
|
|
698
|
-
while ( nnum > 0 && scratch[nnum-1] != scratch[nnum-1] ) nnum--; \
|
|
699
773
|
for ( t = 0; t < 5; t++ ) { \
|
|
700
774
|
double f = (double) (m - 1) * P[t] / 100.0; \
|
|
701
775
|
ca_size_t ki = (ca_size_t) floor(f); \
|
|
702
|
-
double
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
double vhi = (ki + 1 < nnum) ? scratch[ki+1] : vlo; \
|
|
707
|
-
outp[t][c] = vlo + (f - (double) ki) * (vhi - vlo); \
|
|
708
|
-
} } \
|
|
776
|
+
double vhi = (ki + 1 < m) ? scratch[ki+1] : scratch[ki]; \
|
|
777
|
+
outp[t][c] = ca_percentile_linear(scratch[ki], vhi, f - (double) ki, \
|
|
778
|
+
ki, m); \
|
|
779
|
+
} \
|
|
709
780
|
} \
|
|
710
781
|
} while (0)
|
|
711
782
|
|
|
@@ -857,7 +928,7 @@ rb_ca_reduceat_wsum_wmean (VALUE self, VALUE roffsets, VALUE rwg,
|
|
|
857
928
|
|
|
858
929
|
Not aligned kernel_iterator: output position depends on the codes value
|
|
859
930
|
(data-dependent scatter), so ca_attach materialises the inputs into
|
|
860
|
-
contiguous flat buffers — same pattern as sibling
|
|
931
|
+
contiguous flat buffers — same pattern as sibling addresses_by_category.
|
|
861
932
|
|
|
862
933
|
Surface (private):
|
|
863
934
|
h.__fiber_scatter_moments__(codes, axis, K, counts_out, sums_out)
|
|
@@ -1397,8 +1468,8 @@ rb_ca_fiber_scatter_wsum_wmean (VALUE self, VALUE rcodes, VALUE rweights,
|
|
|
1397
1468
|
void
|
|
1398
1469
|
Init_ca_categorical_iterator (void)
|
|
1399
1470
|
{
|
|
1400
|
-
rb_define_private_method(rb_cCArray, "
|
|
1401
|
-
|
|
1471
|
+
rb_define_private_method(rb_cCArray, "addresses_by_category",
|
|
1472
|
+
rb_ca_addresses_by_category, 3);
|
|
1402
1473
|
rb_define_private_method(rb_cCArray, "__fiber_scatter_moments__",
|
|
1403
1474
|
rb_ca_fiber_scatter_moments, 7);
|
|
1404
1475
|
rb_define_private_method(rb_cCArray, "__fiber_scatter_prod__",
|
data/ext/ca_compare.c
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
#include "ruby.h"
|
|
15
15
|
#include "carray.h"
|
|
16
16
|
#include "ca_compare.h"
|
|
17
|
-
#include "carray_internal.h" /*
|
|
17
|
+
#include "carray_internal.h" /* CA_FLOAT_ORDER_CMP, ca_obj_order_cmp */
|
|
18
18
|
#include <math.h>
|
|
19
19
|
|
|
20
20
|
#define DEFINE_ELEM_CMP(type) \
|
|
@@ -28,18 +28,14 @@ elem_cmp_## type (const void *va, const void *vb) \
|
|
|
28
28
|
return 0; \
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
/* Float order: NaN
|
|
31
|
+
/* Float order: NaN after every number (CA_FLOAT_ORDER_CMP). */
|
|
32
32
|
#define DEFINE_ELEM_CMP_FLOAT(type) \
|
|
33
33
|
static int \
|
|
34
34
|
elem_cmp_## type (const void *va, const void *vb) \
|
|
35
35
|
{ \
|
|
36
|
-
const type
|
|
37
|
-
const type
|
|
38
|
-
|
|
39
|
-
if ( isnan(*b) && ( ! isnan(*a) ) ) return -1; \
|
|
40
|
-
if ( *a > *b ) return 1; \
|
|
41
|
-
if ( *a < *b ) return -1; \
|
|
42
|
-
return 0; \
|
|
36
|
+
const type a = *(const type *) va; \
|
|
37
|
+
const type b = *(const type *) vb; \
|
|
38
|
+
return CA_FLOAT_ORDER_CMP(a, b); \
|
|
43
39
|
}
|
|
44
40
|
|
|
45
41
|
DEFINE_ELEM_CMP(boolean8_t)
|
|
@@ -54,18 +50,11 @@ DEFINE_ELEM_CMP(uint64_t)
|
|
|
54
50
|
DEFINE_ELEM_CMP_FLOAT(float32_t)
|
|
55
51
|
DEFINE_ELEM_CMP_FLOAT(float64_t)
|
|
56
52
|
|
|
57
|
-
/* CA_OBJECT:
|
|
58
|
-
after every other value, and a pair `<=>` cannot order raises
|
|
59
|
-
"comparison of A with B failed". */
|
|
53
|
+
/* CA_OBJECT: the object order (ca_obj_order_cmp). */
|
|
60
54
|
static int
|
|
61
55
|
elem_cmp_VALUE (const void *va, const void *vb)
|
|
62
56
|
{
|
|
63
|
-
const VALUE *
|
|
64
|
-
const VALUE *b = (const VALUE *) vb;
|
|
65
|
-
int nan_a = CA_OBJ_ISNAN(*a);
|
|
66
|
-
int nan_b = CA_OBJ_ISNAN(*b);
|
|
67
|
-
if ( nan_a || nan_b ) return nan_a - nan_b;
|
|
68
|
-
return ca_obj_cmp(*a, *b);
|
|
57
|
+
return ca_obj_order_cmp(*(const VALUE *) va, *(const VALUE *) vb);
|
|
69
58
|
}
|
|
70
59
|
|
|
71
60
|
/* FIXLEN / retired / otherwise unorderable data_types: callers must handle
|
data/ext/ca_group_iter.c
CHANGED
|
@@ -14,13 +14,14 @@
|
|
|
14
14
|
Split summary:
|
|
15
15
|
- ca_argv_has_group / rb_ca_fetch_group : here (called by carray_access.c)
|
|
16
16
|
- CAGroupIterator + the tier-1 reduction methods driving
|
|
17
|
-
|
|
17
|
+
__reduce_by_axis_groups__ : here
|
|
18
18
|
- reduce_plan / bundle assembly / output-axis permutation (metadata) : Ruby
|
|
19
|
-
- the O(N) compute kernel
|
|
19
|
+
- the O(N) compute kernel __reduce_by_axis_groups__ : ca_axis_group.c
|
|
20
20
|
|
|
21
21
|
--------------------------------------------------------------------------- */
|
|
22
22
|
|
|
23
23
|
#include "carray.h"
|
|
24
|
+
#include "carray_internal.h" /* ca_check_rank_fits */
|
|
24
25
|
|
|
25
26
|
/* lib/carray/axis_group.rb registers these classes here on first load (and
|
|
26
27
|
loading is wired so that load happens as soon as any categorical exists —
|
|
@@ -34,7 +35,7 @@ static VALUE rb_cCAGroupIterator = Qnil;
|
|
|
34
35
|
static ID id_value, id_spec, id_axis_group, id_reduce_plan, id_parse_axis;
|
|
35
36
|
static ID id_axis_group_reduce, id_reshape, id_transpose, id_labels;
|
|
36
37
|
|
|
37
|
-
/* CArray.
|
|
38
|
+
/* CArray.register_axis_group_classes(CACategorical, AxisGroup) — called
|
|
38
39
|
from the top of lib/carray/axis_group.rb so the C type gate can recognise
|
|
39
40
|
the classifier/spec types without triggering autoload on every [] call. */
|
|
40
41
|
static VALUE
|
|
@@ -120,7 +121,7 @@ rb_ca_fetch_group (int argc, VALUE *argv, VALUE self)
|
|
|
120
121
|
validates the slot layout = one slot per source axis). */
|
|
121
122
|
spec = rb_funcallv(self, id_axis_group, argc, argv);
|
|
122
123
|
}
|
|
123
|
-
return rb_funcall(rb_cCAGroupIterator, rb_intern("
|
|
124
|
+
return rb_funcall(rb_cCAGroupIterator, rb_intern("build_for"), 2, self, spec);
|
|
124
125
|
}
|
|
125
126
|
|
|
126
127
|
/* --- CAGroupIterator -------------------------------------------------------
|
|
@@ -175,9 +176,7 @@ group_iter_shape_output (VALUE result, VALUE group_dims, VALUE perm, VALUE squee
|
|
|
175
176
|
ng = RARRAY_LEN(group_dims);
|
|
176
177
|
nband = cr->ndim - 1;
|
|
177
178
|
nd = ng + nband;
|
|
178
|
-
|
|
179
|
-
rb_raise(rb_eArgError, "axis_group: output ndim %ld too large", nd);
|
|
180
|
-
}
|
|
179
|
+
ca_check_rank_fits(nd, "axis_group");
|
|
181
180
|
for ( i = 0; i < ng; i++ ) {
|
|
182
181
|
dims[i] = RARRAY_AREF(group_dims, i);
|
|
183
182
|
}
|
|
@@ -219,7 +218,7 @@ group_iter_shape_output (VALUE result, VALUE group_dims, VALUE perm, VALUE squee
|
|
|
219
218
|
static VALUE
|
|
220
219
|
group_iter_reduce (int argc, VALUE *argv, VALUE self)
|
|
221
220
|
{
|
|
222
|
-
ID op_id = rb_frame_this_func();
|
|
221
|
+
ID op_id = rb_frame_this_func(); /* frame-name: picks the op, names no error */
|
|
223
222
|
VALUE op_sym = ID2SYM(op_id);
|
|
224
223
|
VALUE value = rb_ivar_get(self, id_value);
|
|
225
224
|
VALUE spec = rb_ivar_get(self, id_spec);
|
|
@@ -247,7 +246,7 @@ group_iter_reduce (int argc, VALUE *argv, VALUE self)
|
|
|
247
246
|
|
|
248
247
|
/* min_count: / fill_value: are applied to the grouped result; any other
|
|
249
248
|
keyword is refused before the work is done. */
|
|
250
|
-
rb_funcall(
|
|
249
|
+
rb_funcall(self, rb_intern("check_reduce_keywords"), 2,
|
|
251
250
|
op_sym, NIL_P(kw) ? rb_hash_new() : kw);
|
|
252
251
|
|
|
253
252
|
/* group reduction */
|
|
@@ -262,14 +261,14 @@ group_iter_reduce (int argc, VALUE *argv, VALUE self)
|
|
|
262
261
|
/* a count reads only the mask, so a payload the kernel cannot read
|
|
263
262
|
(object, fixlen, ...) is counted through a boolean stand-in */
|
|
264
263
|
if ( op_id == rb_intern("count") || op_id == rb_intern("count_not_masked") ) {
|
|
265
|
-
value = rb_funcall(rb_cAxisGroup, rb_intern("
|
|
264
|
+
value = rb_funcall(rb_cAxisGroup, rb_intern("count_stand_in"), 1, value);
|
|
266
265
|
}
|
|
267
266
|
result = rb_funcall(value, id_axis_group_reduce, 3,
|
|
268
267
|
group_axes, bundles, op_sym);
|
|
269
268
|
result = group_iter_shape_output(result, group_dims, perm, squeeze);
|
|
270
269
|
if ( ! NIL_P(kw) ) {
|
|
271
|
-
result = rb_funcall(
|
|
272
|
-
|
|
270
|
+
result = rb_funcall(self, rb_intern("finish_reduction"), 3,
|
|
271
|
+
op_sym, kw, result);
|
|
273
272
|
}
|
|
274
273
|
return result;
|
|
275
274
|
}
|
|
@@ -282,21 +281,21 @@ Init_ca_group_iter (void)
|
|
|
282
281
|
id_axis_group = rb_intern("axis_group");
|
|
283
282
|
id_reduce_plan = rb_intern("reduce_plan");
|
|
284
283
|
id_parse_axis = rb_intern("parse_axis");
|
|
285
|
-
id_axis_group_reduce = rb_intern("
|
|
284
|
+
id_axis_group_reduce = rb_intern("__reduce_by_axis_groups__");
|
|
286
285
|
id_reshape = rb_intern("reshape");
|
|
287
286
|
id_transpose = rb_intern("transpose");
|
|
288
287
|
id_labels = rb_intern("labels");
|
|
289
288
|
|
|
290
|
-
|
|
291
|
-
|
|
289
|
+
rb_define_private_method(rb_singleton_class(rb_cCArray), "register_axis_group_classes",
|
|
290
|
+
rb_ca_register_axis_group_classes, 2);
|
|
292
291
|
|
|
293
292
|
rb_cCAGroupIterator =
|
|
294
293
|
rb_define_class("CAGroupIterator",
|
|
295
294
|
rb_const_get(rb_cObject, rb_intern("CAIterator")));
|
|
296
295
|
rb_gc_register_address(&rb_cCAGroupIterator);
|
|
297
296
|
|
|
298
|
-
|
|
299
|
-
|
|
297
|
+
rb_define_private_method(rb_singleton_class(rb_cCAGroupIterator), "build_for",
|
|
298
|
+
rb_ca_group_iter_build, 2);
|
|
300
299
|
rb_define_method(rb_cCAGroupIterator, "value", rb_ca_group_iter_value, 0);
|
|
301
300
|
rb_define_method(rb_cCAGroupIterator, "spec", rb_ca_group_iter_spec, 0);
|
|
302
301
|
rb_define_method(rb_cCAGroupIterator, "labels", rb_ca_group_iter_labels, -1);
|