carray 3.0.3 → 3.0.5
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 +469 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_array_pool.c +25 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +14 -26
- 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 +231 -153
- data/ext/ca_compare.c +9 -20
- data/ext/ca_composite_dispatch.c +9 -9
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1240 -2000
- data/ext/ca_kernel_iterator.h +502 -519
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +152 -45
- data/ext/ca_obj_bincmp.c +25 -21
- data/ext/ca_obj_binop.c +16 -26
- data/ext/ca_obj_bitarray.c +8 -3
- data/ext/ca_obj_bitfield.c +63 -49
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +7 -7
- data/ext/ca_obj_const_string.c +188 -22
- data/ext/ca_obj_face.c +280 -58
- 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 +30 -8
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +455 -134
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +113 -67
- data/ext/ca_obj_object.c +210 -52
- data/ext/ca_obj_record.c +15 -7
- data/ext/ca_obj_reduce.c +17 -8
- data/ext/ca_obj_refer.c +42 -35
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +31 -10
- data/ext/ca_obj_select.c +48 -14
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +41 -7
- data/ext/ca_obj_stack.c +180 -34
- data/ext/ca_obj_stride.c +190 -134
- data/ext/ca_obj_string.c +80 -4
- data/ext/ca_obj_tile.c +32 -11
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +13 -7
- data/ext/ca_obj_triop.c +26 -32
- data/ext/ca_obj_window.c +267 -74
- data/ext/ca_op_ipower.c +4 -4
- data/ext/ca_sort_kernels.h +6 -3
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +214 -75
- data/ext/carray_access.c +200 -99
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +113 -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 +375 -96
- data/ext/carray_cast_func.rb +90 -20
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +18 -9
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +150 -55
- data/ext/carray_count.c +56 -20
- data/ext/carray_element.c +81 -33
- data/ext/carray_factorize.c +138 -84
- data/ext/carray_generate.c +199 -52
- data/ext/carray_histogram.c +63 -18
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +348 -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 +10897 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +220 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +337 -94
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +129 -52
- data/ext/carray_order.c +604 -77
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +85 -31
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +87 -45
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +123 -37
- data/ext/carray_sort.c +259 -51
- data/ext/carray_sort_kernel.c +5 -7
- data/ext/carray_struct.c +54 -61
- data/ext/carray_test.c +26 -5
- data/ext/carray_time_text.c +4 -2
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +309 -66
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +403 -350
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +139 -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 +105 -17
- 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 +195 -59
- data/lib/carray/categorical_iterator.rb +132 -29
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +24 -5
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +9 -1
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +48 -3
- data/lib/carray/frame/column_verbs.rb +71 -0
- data/lib/carray/frame/concat.rb +17 -3
- 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 +252 -28
- data/lib/carray/frame/group.rb +603 -101
- data/lib/carray/frame/io.rb +117 -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 +42 -6
- 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 +217 -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 +61 -37
- 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 +323 -88
- data/lib/carray/serialize.rb +45 -14
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/stack.rb +15 -12
- data/lib/carray/string.rb +113 -5
- data/lib/carray/string_operation_extension.rb +21 -6
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +24 -11
- data/lib/carray/time.rb +819 -158
- 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_transpose.rb +5 -4
- data/yard-stubs/ca_obj_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +3 -6
- data/yard-stubs/carray_cast.rb +12 -0
- data/yard-stubs/carray_conversion.rb +7 -2
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +17 -10
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +32 -3
- data/yard-stubs/carray_math.rb +41 -5
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +129 -22
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +17 -10
- 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);
|
|
78
|
-
}
|
|
79
|
-
if ( cursor->data_type != CA_INT64 || cursor->elements != k ) {
|
|
80
|
-
rb_raise(rb_eArgError, "__categorical_scatter__: cursor must be int64[k]");
|
|
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");
|
|
81
67
|
}
|
|
82
|
-
if (
|
|
83
|
-
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);
|
|
84
71
|
}
|
|
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; \
|
|
176
|
+
} \
|
|
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; } } \
|
|
172
242
|
} \
|
|
173
|
-
cnt
|
|
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
|
|
|
@@ -383,20 +457,23 @@ rb_ca_reduceat_percentile (VALUE self, VALUE roffsets, VALUE rp, VALUE rout)
|
|
|
383
457
|
|
|
384
458
|
/* ---------------------------------------------------------------------------
|
|
385
459
|
|
|
386
|
-
__reduceat_variance__ — centred two-pass
|
|
387
|
-
The means (from the cached moments: sum/count)
|
|
388
|
-
accumulates the per-segment centred sum of
|
|
389
|
-
Centred (not the one-pass
|
|
390
|
-
one-pass formula cancels
|
|
391
|
-
|
|
392
|
-
SS / (count-
|
|
460
|
+
__reduceat_variance__ — centred two-pass variance reduceat, sample (ddof=1)
|
|
461
|
+
or population (ddof=0). The means (from the cached moments: sum/count)
|
|
462
|
+
drive a second walk that accumulates the per-segment centred sum of
|
|
463
|
+
squares; variance = SS / (n - ddof). Centred (not the one-pass
|
|
464
|
+
sum-of-squares) so the ε-close contract holds — a one-pass formula cancels
|
|
465
|
+
catastrophically. Matches CArray#variance / #variancep per group: count
|
|
466
|
+
<= ddof (or 0) -> masked, otherwise SS / (count - ddof), divided once as
|
|
467
|
+
the core does.
|
|
393
468
|
|
|
394
|
-
Surface (private):
|
|
469
|
+
Surface (private):
|
|
470
|
+
grouped.__reduceat_variance__(offsets, means, counts, out, ddof)
|
|
395
471
|
self = grouped (numeric value data type, may carry a mask)
|
|
396
472
|
offsets = int64[k] segment STARTS
|
|
397
473
|
means = float64[k] per-segment mean (ignored where count < 2)
|
|
398
474
|
counts = int64[k] per-segment present count
|
|
399
|
-
out = float64[k] output: variance; count
|
|
475
|
+
out = float64[k] output: variance; count <= ddof masked
|
|
476
|
+
ddof = 1 (sample) or 0 (population)
|
|
400
477
|
|
|
401
478
|
--------------------------------------------------------------------------- */
|
|
402
479
|
|
|
@@ -405,7 +482,7 @@ rb_ca_reduceat_percentile (VALUE self, VALUE roffsets, VALUE rp, VALUE rout)
|
|
|
405
482
|
const T *gp = (const T *) grouped->ptr; \
|
|
406
483
|
for ( c = 0; c < k; c++ ) { \
|
|
407
484
|
int64_t cnt = countp[c]; \
|
|
408
|
-
if ( cnt <
|
|
485
|
+
if ( cnt <= ddof || cnt < 1 ) { outp[c] = 0.0; outm[c] = 1; continue; } \
|
|
409
486
|
{ double mean = meanp[c], ss = 0.0; \
|
|
410
487
|
ca_size_t lo = (ca_size_t) offs[c]; \
|
|
411
488
|
ca_size_t hi = (c + 1 < k) ? (ca_size_t) offs[c+1] : n, j; \
|
|
@@ -420,14 +497,15 @@ rb_ca_reduceat_percentile (VALUE self, VALUE roffsets, VALUE rp, VALUE rout)
|
|
|
420
497
|
double d = (double) gp[j] - mean; ss += d * d; \
|
|
421
498
|
} \
|
|
422
499
|
} \
|
|
423
|
-
outp[c] = ss / (double) (cnt -
|
|
500
|
+
outp[c] = ss / (double) (cnt - ddof); } \
|
|
424
501
|
} \
|
|
425
502
|
} while (0)
|
|
426
503
|
|
|
427
504
|
static VALUE
|
|
428
505
|
rb_ca_reduceat_variance (VALUE self, VALUE roffsets, VALUE rmeans,
|
|
429
|
-
VALUE rcounts, VALUE rout)
|
|
506
|
+
VALUE rcounts, VALUE rout, VALUE rddof)
|
|
430
507
|
{
|
|
508
|
+
int64_t ddof = NUM2LL(rddof);
|
|
431
509
|
CArray *grouped, *offsets, *means, *counts, *out;
|
|
432
510
|
int64_t k, *offs, *countp;
|
|
433
511
|
ca_size_t n, c;
|
|
@@ -444,8 +522,9 @@ rb_ca_reduceat_variance (VALUE self, VALUE roffsets, VALUE rmeans,
|
|
|
444
522
|
n = grouped->elements;
|
|
445
523
|
if ( offsets->data_type != CA_INT64 || counts->data_type != CA_INT64 ||
|
|
446
524
|
means->data_type != CA_FLOAT64 || out->data_type != CA_FLOAT64 ||
|
|
447
|
-
means->elements != k || counts->elements != k || out->elements != k
|
|
448
|
-
|
|
525
|
+
means->elements != k || counts->elements != k || out->elements != k ||
|
|
526
|
+
( ddof != 0 && ddof != 1 ) ) {
|
|
527
|
+
rb_raise(rb_eArgError, "__reduceat_variance__: offsets/counts int64, means/out float64[k], ddof 0 or 1");
|
|
449
528
|
}
|
|
450
529
|
|
|
451
530
|
offs = (int64_t *) offsets->ptr;
|
|
@@ -693,19 +772,16 @@ cmp_double (const void *a, const void *b)
|
|
|
693
772
|
scratch[m++] = (double) gp[jj]; \
|
|
694
773
|
} \
|
|
695
774
|
if ( m == 0 ) { for ( t = 0; t < 5; t++ ) { outp[t][c] = 0.0; outm[t][c] = 1; } continue; } \
|
|
775
|
+
/* NaN sorts last, as in the core's sort, so a position or an upper \
|
|
776
|
+
neighbour in the tail is NaN, as the core answers. */ \
|
|
696
777
|
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
778
|
for ( t = 0; t < 5; t++ ) { \
|
|
700
779
|
double f = (double) (m - 1) * P[t] / 100.0; \
|
|
701
780
|
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
|
-
} } \
|
|
781
|
+
double vhi = (ki + 1 < m) ? scratch[ki+1] : scratch[ki]; \
|
|
782
|
+
outp[t][c] = ca_percentile_linear(scratch[ki], vhi, f - (double) ki, \
|
|
783
|
+
ki, m); \
|
|
784
|
+
} \
|
|
709
785
|
} \
|
|
710
786
|
} while (0)
|
|
711
787
|
|
|
@@ -857,7 +933,7 @@ rb_ca_reduceat_wsum_wmean (VALUE self, VALUE roffsets, VALUE rwg,
|
|
|
857
933
|
|
|
858
934
|
Not aligned kernel_iterator: output position depends on the codes value
|
|
859
935
|
(data-dependent scatter), so ca_attach materialises the inputs into
|
|
860
|
-
contiguous flat buffers — same pattern as sibling
|
|
936
|
+
contiguous flat buffers — same pattern as sibling addresses_by_category.
|
|
861
937
|
|
|
862
938
|
Surface (private):
|
|
863
939
|
h.__fiber_scatter_moments__(codes, axis, K, counts_out, sums_out)
|
|
@@ -1033,8 +1109,13 @@ rb_ca_fiber_scatter_moments (VALUE self, VALUE rcodes, VALUE raxis, VALUE rk,
|
|
|
1033
1109
|
h->data_type);
|
|
1034
1110
|
}
|
|
1035
1111
|
|
|
1112
|
+
ca_detach(h);
|
|
1113
|
+
ca_detach(codes);
|
|
1114
|
+
|
|
1036
1115
|
/* Mask empty (count == 0) cells in mins/maxs: value slot is 0 but meaningless.
|
|
1037
|
-
Matches __reduceat_moments__ contract for empty segments.
|
|
1116
|
+
Matches __reduceat_moments__ contract for empty segments. After the
|
|
1117
|
+
detach: creating a mask allocates, and a raise must not leave h and
|
|
1118
|
+
codes attached. */
|
|
1038
1119
|
ca_create_mask(mins);
|
|
1039
1120
|
ca_create_mask(maxs);
|
|
1040
1121
|
minm = (boolean8_t *) mins->mask->ptr;
|
|
@@ -1042,9 +1123,6 @@ rb_ca_fiber_scatter_moments (VALUE self, VALUE rcodes, VALUE raxis, VALUE rk,
|
|
|
1042
1123
|
for ( cell = 0; cell < total; cell++ ) {
|
|
1043
1124
|
if ( countp[cell] == 0 ) { minm[cell] = 1; maxm[cell] = 1; }
|
|
1044
1125
|
}
|
|
1045
|
-
|
|
1046
|
-
ca_detach(h);
|
|
1047
|
-
ca_detach(codes);
|
|
1048
1126
|
return Qnil;
|
|
1049
1127
|
}
|
|
1050
1128
|
|
|
@@ -1397,8 +1475,8 @@ rb_ca_fiber_scatter_wsum_wmean (VALUE self, VALUE rcodes, VALUE rweights,
|
|
|
1397
1475
|
void
|
|
1398
1476
|
Init_ca_categorical_iterator (void)
|
|
1399
1477
|
{
|
|
1400
|
-
rb_define_private_method(rb_cCArray, "
|
|
1401
|
-
|
|
1478
|
+
rb_define_private_method(rb_cCArray, "addresses_by_category",
|
|
1479
|
+
rb_ca_addresses_by_category, 3);
|
|
1402
1480
|
rb_define_private_method(rb_cCArray, "__fiber_scatter_moments__",
|
|
1403
1481
|
rb_ca_fiber_scatter_moments, 7);
|
|
1404
1482
|
rb_define_private_method(rb_cCArray, "__fiber_scatter_prod__",
|
|
@@ -1410,7 +1488,7 @@ Init_ca_categorical_iterator (void)
|
|
|
1410
1488
|
rb_define_private_method(rb_cCArray, "__reduceat_percentile__",
|
|
1411
1489
|
rb_ca_reduceat_percentile, 3);
|
|
1412
1490
|
rb_define_private_method(rb_cCArray, "__reduceat_variance__",
|
|
1413
|
-
rb_ca_reduceat_variance,
|
|
1491
|
+
rb_ca_reduceat_variance, 5);
|
|
1414
1492
|
rb_define_private_method(rb_cCArray, "__reduceat_prod__",
|
|
1415
1493
|
rb_ca_reduceat_prod, 2);
|
|
1416
1494
|
rb_define_private_method(rb_cCArray, "__reduceat_argminmax__",
|
data/ext/ca_compare.c
CHANGED
|
@@ -14,32 +14,28 @@
|
|
|
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) \
|
|
21
21
|
static int \
|
|
22
22
|
elem_cmp_## type (const void *va, const void *vb) \
|
|
23
23
|
{ \
|
|
24
|
-
const type *a = (const type *) va;
|
|
25
|
-
const type *b = (const type *) vb;
|
|
24
|
+
const CA_U(type) *a = (const CA_U(type) *) va; \
|
|
25
|
+
const CA_U(type) *b = (const CA_U(type) *) vb; \
|
|
26
26
|
if ( *a > *b ) return 1; \
|
|
27
27
|
if ( *a < *b ) return -1; \
|
|
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 CA_U(type) *) va; \
|
|
37
|
+
const type b = *(const CA_U(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_composite_dispatch.c
CHANGED
|
@@ -32,29 +32,29 @@ ca_fill_typed (char *dst, const char *val, ca_size_t bytes, ca_size_t n)
|
|
|
32
32
|
break;
|
|
33
33
|
}
|
|
34
34
|
case 2: {
|
|
35
|
-
uint16_t v = *(const
|
|
36
|
-
|
|
35
|
+
uint16_t v = *(const ca_u_uint16_t *)val;
|
|
36
|
+
ca_u_uint16_t *p = (ca_u_uint16_t *)dst;
|
|
37
37
|
for ( i = 0; i < n; i++ ) p[i] = v;
|
|
38
38
|
break;
|
|
39
39
|
}
|
|
40
40
|
case 4: {
|
|
41
|
-
uint32_t v = *(const
|
|
42
|
-
|
|
41
|
+
uint32_t v = *(const ca_u_uint32_t *)val;
|
|
42
|
+
ca_u_uint32_t *p = (ca_u_uint32_t *)dst;
|
|
43
43
|
for ( i = 0; i < n; i++ ) p[i] = v;
|
|
44
44
|
break;
|
|
45
45
|
}
|
|
46
46
|
case 8: {
|
|
47
|
-
uint64_t v = *(const
|
|
48
|
-
|
|
47
|
+
uint64_t v = *(const ca_u_uint64_t *)val;
|
|
48
|
+
ca_u_uint64_t *p = (ca_u_uint64_t *)dst;
|
|
49
49
|
for ( i = 0; i < n; i++ ) p[i] = v;
|
|
50
50
|
break;
|
|
51
51
|
}
|
|
52
52
|
case 16: {
|
|
53
53
|
/* complex128 etc. Two uint64_t stores per element. Compiler
|
|
54
54
|
pairs them into a NEON 128-bit or SSE2 store. */
|
|
55
|
-
uint64_t v0 = ((const
|
|
56
|
-
uint64_t v1 = ((const
|
|
57
|
-
|
|
55
|
+
uint64_t v0 = ((const ca_u_uint64_t *)val)[0];
|
|
56
|
+
uint64_t v1 = ((const ca_u_uint64_t *)val)[1];
|
|
57
|
+
ca_u_uint64_t *p = (ca_u_uint64_t *)dst;
|
|
58
58
|
for ( i = 0; i < n; i++ ) {
|
|
59
59
|
p[2*i] = v0;
|
|
60
60
|
p[2*i + 1] = v1;
|