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
data/ext/carray_generate.c
CHANGED
|
@@ -9,14 +9,16 @@
|
|
|
9
9
|
|
|
10
10
|
#include "ruby.h"
|
|
11
11
|
#include "carray.h"
|
|
12
|
-
#include "carray_internal.h" /* ca_attach_window,
|
|
12
|
+
#include "carray_internal.h" /* ca_attach_window, ca_normalize_axis_arg */
|
|
13
|
+
#include "ca_obj_face.h" /* ca_face_element_to_storage */
|
|
13
14
|
|
|
14
15
|
/* ----------------------------------------------------------------- */
|
|
15
16
|
|
|
16
17
|
/* CArray#where -- collect the flat addresses of all non-zero (or
|
|
17
|
-
true) cells in self into a fresh 1-D CA_SIZE array.
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
true) cells in self into a fresh 1-D CA_SIZE array. An integer,
|
|
19
|
+
float or complex array selects its non-zero cells (NaN is non-zero);
|
|
20
|
+
any other non-boolean array is cast to boolean, which takes only
|
|
21
|
+
0 / 1 / true / false. Masked cells are excluded.
|
|
20
22
|
|
|
21
23
|
Also used internally by ext/ca_obj_grid.c when it needs to extract
|
|
22
24
|
the addresses of true cells from a boolean axis selector. */
|
|
@@ -27,28 +29,44 @@ rb_ca_where (VALUE self)
|
|
|
27
29
|
CArray *ca, *co;
|
|
28
30
|
boolean8_t *p, *m;
|
|
29
31
|
ca_size_t *q;
|
|
30
|
-
ca_size_t i, count;
|
|
32
|
+
ca_size_t i, j, n, last, count;
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
35
|
+
if ( ca_is_boolean_type(ca) ) {
|
|
36
|
+
bool0 = self;
|
|
37
|
+
}
|
|
38
|
+
else if ( ! ca_is_face(ca) &&
|
|
39
|
+
( ca_is_integer_type(ca) || ca_is_float_type(ca) ||
|
|
40
|
+
ca_is_complex_type(ca) ) ) {
|
|
41
|
+
bool0 = rb_funcall(self, rb_intern("ne"), 1, INT2FIX(0));
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
bool0 = rb_ca_to_boolean(self);
|
|
45
|
+
}
|
|
33
46
|
|
|
34
47
|
TypedData_Get_Struct(bool0, CArray, &carray_data_type, ca);
|
|
35
48
|
|
|
36
49
|
ca_attach(ca); /* window: nothing raises inside */
|
|
37
50
|
|
|
38
|
-
/* calculate elements of output array */
|
|
51
|
+
/* calculate elements of output array, and the last selected cell */
|
|
39
52
|
p = (boolean8_t *) ca->ptr;
|
|
40
53
|
m = ca_mask_ptr(ca);
|
|
54
|
+
n = ca->elements;
|
|
41
55
|
count = 0;
|
|
42
56
|
if ( m ) {
|
|
43
|
-
for (i=0; i<
|
|
44
|
-
|
|
45
|
-
m++; p++;
|
|
57
|
+
for (i=0; i<n; i++) {
|
|
58
|
+
count += ( ! m[i] ) & ( p[i] != 0 ); /* not-masked && true */
|
|
46
59
|
}
|
|
47
60
|
}
|
|
48
61
|
else {
|
|
49
|
-
for (i=0; i<
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
for (i=0; i<n; i++) {
|
|
63
|
+
count += ( p[i] != 0 ); /* true */
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
last = n - 1;
|
|
67
|
+
if ( count > 0 ) {
|
|
68
|
+
while ( m ? ( m[last] || ! p[last] ) : ! p[last] ) {
|
|
69
|
+
last--;
|
|
52
70
|
}
|
|
53
71
|
}
|
|
54
72
|
|
|
@@ -56,20 +74,25 @@ rb_ca_where (VALUE self)
|
|
|
56
74
|
obj = rb_carray_new(CA_SIZE, 1, &count, 0, NULL);
|
|
57
75
|
TypedData_Get_Struct(obj, CArray, &carray_data_type, co);
|
|
58
76
|
|
|
59
|
-
/*
|
|
60
|
-
|
|
77
|
+
/* Store the address of each selected cell. Every cell up to the last
|
|
78
|
+
selected one is written and the output position advances only on a
|
|
79
|
+
selected cell, so a selection with true and false mixed at random
|
|
80
|
+
does not mispredict a branch on most cells. Stopping at the last
|
|
81
|
+
selected cell keeps the writes inside the count slots. */
|
|
61
82
|
q = (ca_size_t *) co->ptr;
|
|
62
|
-
|
|
63
|
-
if (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
83
|
+
j = 0;
|
|
84
|
+
if ( count > 0 ) {
|
|
85
|
+
if ( m ) {
|
|
86
|
+
for (i=0; i<=last; i++) { /* not-masked && true */
|
|
87
|
+
q[j] = i;
|
|
88
|
+
j += ( ! m[i] ) & ( p[i] != 0 );
|
|
89
|
+
}
|
|
67
90
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
91
|
+
else { /* true */
|
|
92
|
+
for (i=0; i<=last; i++) {
|
|
93
|
+
q[j] = i;
|
|
94
|
+
j += ( p[i] != 0 );
|
|
95
|
+
}
|
|
73
96
|
}
|
|
74
97
|
}
|
|
75
98
|
|
|
@@ -80,6 +103,17 @@ rb_ca_where (VALUE self)
|
|
|
80
103
|
|
|
81
104
|
/* ----------------------------------------------------------------- */
|
|
82
105
|
|
|
106
|
+
/* A number that is not an Integer (a Float, a Rational, a BigDecimal) makes
|
|
107
|
+
the progression a real one: every cell is offset + step*i computed in
|
|
108
|
+
double, and an integer array takes it as a store takes a float (cut
|
|
109
|
+
toward zero; the run is checked to fit before anything is written). */
|
|
110
|
+
static int
|
|
111
|
+
ca_seq_is_real (VALUE v)
|
|
112
|
+
{
|
|
113
|
+
return ! NIL_P(v) && ! RB_INTEGER_TYPE_P(v) && ! RB_TYPE_P(v, T_COMPLEX)
|
|
114
|
+
&& RTEST(rb_obj_is_kind_of(v, rb_cNumeric));
|
|
115
|
+
}
|
|
116
|
+
|
|
83
117
|
/* Fill the whole array in row-major order with `step*i + offset`. */
|
|
84
118
|
#define proc_seq_bang(type, from, to) \
|
|
85
119
|
{ \
|
|
@@ -90,9 +124,8 @@ rb_ca_where (VALUE self)
|
|
|
90
124
|
*p++ = (type) to(i); \
|
|
91
125
|
} \
|
|
92
126
|
} \
|
|
93
|
-
else if (
|
|
94
|
-
|
|
95
|
-
type offset = (NIL_P(roffset)) ? (type) 0 : (type) from(roffset); \
|
|
127
|
+
else if ( ca_seq_is_real(rstep) || ca_seq_is_real(roffset) ) { \
|
|
128
|
+
double offset = (NIL_P(roffset)) ? 0 : NUM2DBL(roffset); \
|
|
96
129
|
double step = (NIL_P(rstep)) ? 1 : NUM2DBL(rstep); \
|
|
97
130
|
for (i=0; i<ca->elements; i++) { \
|
|
98
131
|
*p++ = (type) to(step*i+offset); \
|
|
@@ -118,9 +151,8 @@ rb_ca_where (VALUE self)
|
|
|
118
151
|
{ \
|
|
119
152
|
type *p = (type *)ca->ptr; \
|
|
120
153
|
ca_size_t o, k, in; \
|
|
121
|
-
if (
|
|
122
|
-
|
|
123
|
-
type offset = (NIL_P(roffset)) ? (type) 0 : (type) from(roffset); \
|
|
154
|
+
if ( ca_seq_is_real(rstep) || ca_seq_is_real(roffset) ) { \
|
|
155
|
+
double offset = (NIL_P(roffset)) ? 0 : NUM2DBL(roffset); \
|
|
124
156
|
double step = (NIL_P(rstep)) ? 1 : NUM2DBL(rstep); \
|
|
125
157
|
for (o=0; o<outer_size; o++) { \
|
|
126
158
|
for (k=0; k<len; k++) { \
|
|
@@ -183,7 +215,7 @@ ca_seq_resolve_axis (CArray *ca, VALUE raxis)
|
|
|
183
215
|
"%s: axis must be a single Integer (a seq over several axes is not supported)",
|
|
184
216
|
ca_calling_method_name());
|
|
185
217
|
}
|
|
186
|
-
axis =
|
|
218
|
+
axis = ca_normalize_axis_arg(raxis, ca->ndim, NULL);
|
|
187
219
|
return axis;
|
|
188
220
|
}
|
|
189
221
|
|
|
@@ -209,6 +241,7 @@ ca_seq_geometry (CArray *ca, int axis,
|
|
|
209
241
|
left as they were, as they would for an entity. */
|
|
210
242
|
|
|
211
243
|
typedef struct {
|
|
244
|
+
VALUE self;
|
|
212
245
|
CArray *ca;
|
|
213
246
|
VALUE roffset;
|
|
214
247
|
VALUE rstep;
|
|
@@ -216,6 +249,14 @@ typedef struct {
|
|
|
216
249
|
int axis;
|
|
217
250
|
} ca_seq_ctx_t;
|
|
218
251
|
|
|
252
|
+
/* A value of the progression as it goes into a cell: a Face receiver (a
|
|
253
|
+
CAString) checks it as it checks any value stored into it. */
|
|
254
|
+
static VALUE
|
|
255
|
+
ca_seq_cell (ca_seq_ctx_t *c, VALUE v)
|
|
256
|
+
{
|
|
257
|
+
return ca_face_element_to_storage(c->self, c->ca, v);
|
|
258
|
+
}
|
|
259
|
+
|
|
219
260
|
static VALUE
|
|
220
261
|
ca_seq_bang_object_body (VALUE arg)
|
|
221
262
|
{
|
|
@@ -227,10 +268,6 @@ ca_seq_bang_object_body (VALUE arg)
|
|
|
227
268
|
VALUE *p;
|
|
228
269
|
ca_size_t i;
|
|
229
270
|
|
|
230
|
-
if ( ca_has_mask(ca) ) {
|
|
231
|
-
ca_clear_mask(ca); /* clear all mask */
|
|
232
|
-
}
|
|
233
|
-
|
|
234
271
|
if ( axis < 0 ) { /* flat fill */
|
|
235
272
|
p = (VALUE *)ca->ptr;
|
|
236
273
|
if ( rb_obj_is_kind_of(roffset, rb_cFloat) ||
|
|
@@ -238,7 +275,7 @@ ca_seq_bang_object_body (VALUE arg)
|
|
|
238
275
|
double offset = ( NIL_P(roffset) ) ? 0 : NUM2DBL(roffset);
|
|
239
276
|
double step = ( NIL_P(rstep) ) ? 1 : NUM2DBL(rstep);
|
|
240
277
|
for (i=0; i<ca->elements; i++) {
|
|
241
|
-
*p++ = rb_float_new(step*i+offset);
|
|
278
|
+
*p++ = ca_seq_cell(c, rb_float_new(step*i+offset));
|
|
242
279
|
}
|
|
243
280
|
}
|
|
244
281
|
else if ( NIL_P(roffset) ) {
|
|
@@ -247,22 +284,22 @@ ca_seq_bang_object_body (VALUE arg)
|
|
|
247
284
|
"nil is invalid as offset for seq([offset[,step])");
|
|
248
285
|
}
|
|
249
286
|
for (i=0; i<ca->elements; i++) { /* a.seq() */
|
|
250
|
-
*p++ = LL2NUM(i);
|
|
287
|
+
*p++ = ca_seq_cell(c, LL2NUM(i));
|
|
251
288
|
}
|
|
252
289
|
}
|
|
253
290
|
else if ( ! NIL_P(rmethod) ) { /* a.seq(obj, :method) */
|
|
254
291
|
ID id_method = SYM2ID(rmethod);
|
|
255
|
-
*p++ = rval = roffset;
|
|
292
|
+
*p++ = ca_seq_cell(c, rval = roffset);
|
|
256
293
|
for (i=1; i<ca->elements; i++) {
|
|
257
|
-
*p++ = rval = rb_funcall(rval, id_method, 0);
|
|
294
|
+
*p++ = ca_seq_cell(c, rval = rb_funcall(rval, id_method, 0));
|
|
258
295
|
}
|
|
259
296
|
}
|
|
260
297
|
else { /* a.seq(obj, step) */
|
|
261
298
|
ID id_plus = rb_intern("+");
|
|
262
299
|
rstep = ( NIL_P(rstep) ) ? INT2NUM(1) : rstep;
|
|
263
|
-
*p++ = rval = roffset;
|
|
300
|
+
*p++ = ca_seq_cell(c, rval = roffset);
|
|
264
301
|
for (i=1; i<ca->elements; i++) {
|
|
265
|
-
*p++ = rval = rb_funcall(rval, id_plus, 1, rstep);
|
|
302
|
+
*p++ = ca_seq_cell(c, rval = rb_funcall(rval, id_plus, 1, rstep));
|
|
266
303
|
}
|
|
267
304
|
}
|
|
268
305
|
}
|
|
@@ -280,7 +317,7 @@ ca_seq_bang_object_body (VALUE arg)
|
|
|
280
317
|
double offset = ( NIL_P(roffset) ) ? 0 : NUM2DBL(roffset);
|
|
281
318
|
double step = ( NIL_P(rstep) ) ? 1 : NUM2DBL(rstep);
|
|
282
319
|
for (k=0; k<len; k++) {
|
|
283
|
-
rb_ary_push(vtbl, rb_float_new(step*k+offset));
|
|
320
|
+
rb_ary_push(vtbl, ca_seq_cell(c, rb_float_new(step*k+offset)));
|
|
284
321
|
}
|
|
285
322
|
}
|
|
286
323
|
else if ( NIL_P(roffset) ) {
|
|
@@ -289,26 +326,26 @@ ca_seq_bang_object_body (VALUE arg)
|
|
|
289
326
|
"nil is invalid as offset for seq([offset[,step])");
|
|
290
327
|
}
|
|
291
328
|
for (k=0; k<len; k++) {
|
|
292
|
-
rb_ary_push(vtbl, LL2NUM(k));
|
|
329
|
+
rb_ary_push(vtbl, ca_seq_cell(c, LL2NUM(k)));
|
|
293
330
|
}
|
|
294
331
|
}
|
|
295
332
|
else if ( ! NIL_P(rmethod) ) {
|
|
296
333
|
ID id_method = SYM2ID(rmethod);
|
|
297
334
|
rval = roffset;
|
|
298
|
-
rb_ary_push(vtbl, rval);
|
|
335
|
+
rb_ary_push(vtbl, ca_seq_cell(c, rval));
|
|
299
336
|
for (k=1; k<len; k++) {
|
|
300
337
|
rval = rb_funcall(rval, id_method, 0);
|
|
301
|
-
rb_ary_push(vtbl, rval);
|
|
338
|
+
rb_ary_push(vtbl, ca_seq_cell(c, rval));
|
|
302
339
|
}
|
|
303
340
|
}
|
|
304
341
|
else {
|
|
305
342
|
ID id_plus = rb_intern("+");
|
|
306
343
|
rstep = ( NIL_P(rstep) ) ? INT2NUM(1) : rstep;
|
|
307
344
|
rval = roffset;
|
|
308
|
-
rb_ary_push(vtbl, rval);
|
|
345
|
+
rb_ary_push(vtbl, ca_seq_cell(c, rval));
|
|
309
346
|
for (k=1; k<len; k++) {
|
|
310
347
|
rval = rb_funcall(rval, id_plus, 1, rstep);
|
|
311
|
-
rb_ary_push(vtbl, rval);
|
|
348
|
+
rb_ary_push(vtbl, ca_seq_cell(c, rval));
|
|
312
349
|
}
|
|
313
350
|
}
|
|
314
351
|
p = (VALUE *)ca->ptr;
|
|
@@ -320,6 +357,10 @@ ca_seq_bang_object_body (VALUE arg)
|
|
|
320
357
|
}
|
|
321
358
|
}
|
|
322
359
|
|
|
360
|
+
/* Cleared last, so a fill that raises leaves the mask as it was. */
|
|
361
|
+
if ( ca_has_mask(ca) ) {
|
|
362
|
+
ca_clear_mask(ca);
|
|
363
|
+
}
|
|
323
364
|
return Qnil;
|
|
324
365
|
}
|
|
325
366
|
|
|
@@ -330,6 +371,7 @@ rb_ca_seq_bang_object (VALUE self, VALUE roffset, VALUE rstep, int axis)
|
|
|
330
371
|
|
|
331
372
|
TypedData_Get_Struct(self, CArray, &carray_data_type, c.ca);
|
|
332
373
|
|
|
374
|
+
c.self = self;
|
|
333
375
|
c.rmethod = Qnil;
|
|
334
376
|
if ( TYPE(rstep) == T_SYMBOL ) { /* e.g. a.seq("a", :succ) */
|
|
335
377
|
c.rmethod = rstep;
|
|
@@ -344,8 +386,9 @@ rb_ca_seq_bang_object (VALUE self, VALUE roffset, VALUE rstep, int axis)
|
|
|
344
386
|
return self;
|
|
345
387
|
}
|
|
346
388
|
|
|
347
|
-
/* The numeric fill
|
|
348
|
-
|
|
389
|
+
/* The numeric fill runs in an allocate window, which clears an entity's
|
|
390
|
+
mask as it opens (an entity has no separate buffer), so nothing in it may
|
|
391
|
+
raise: offset and step are checked to be numbers before it opens. */
|
|
349
392
|
static VALUE
|
|
350
393
|
ca_seq_bang_numeric_body (VALUE arg)
|
|
351
394
|
{
|
|
@@ -368,6 +411,76 @@ ca_seq_bang_numeric_body (VALUE arg)
|
|
|
368
411
|
return Qnil;
|
|
369
412
|
}
|
|
370
413
|
|
|
414
|
+
/* An integer array refuses a first value it cannot hold, as a store does,
|
|
415
|
+
and an Integer step whose size it cannot hold. An unsigned array takes
|
|
416
|
+
a negative step (a descending run). A run that passes the end of the
|
|
417
|
+
type wraps, as integer arithmetic does. */
|
|
418
|
+
static void
|
|
419
|
+
ca_seq_check_integer_args (CArray *ca, VALUE roffset, VALUE rstep)
|
|
420
|
+
{
|
|
421
|
+
int8_t dt = ca->data_type;
|
|
422
|
+
/* Only a number is checked here; anything else is left to the fill's
|
|
423
|
+
own conversion, which refuses it with TypeError. */
|
|
424
|
+
if ( RB_INTEGER_TYPE_P(roffset) || RB_FLOAT_TYPE_P(roffset) ) {
|
|
425
|
+
VALUE first = RB_INTEGER_TYPE_P(roffset) ? roffset : rb_Integer(roffset);
|
|
426
|
+
if ( ca_integer_range_side(first, dt) != 0 ) {
|
|
427
|
+
rb_raise(rb_eRangeError, "%s: first value %"PRIsVALUE" is out of range for %s",
|
|
428
|
+
ca_calling_method_name(), rb_inspect(roffset), ca_type_name[dt]);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
if ( RB_INTEGER_TYPE_P(rstep) ) {
|
|
432
|
+
int is_unsigned = ( dt == CA_UINT8 || dt == CA_UINT16 ||
|
|
433
|
+
dt == CA_UINT32 || dt == CA_UINT64 );
|
|
434
|
+
VALUE size = rstep;
|
|
435
|
+
if ( is_unsigned && RTEST(rb_funcall(rstep, rb_intern("negative?"), 0)) ) {
|
|
436
|
+
size = rb_funcall(rstep, rb_intern("-@"), 0);
|
|
437
|
+
}
|
|
438
|
+
if ( ca_integer_range_side(size, dt) != 0 ) {
|
|
439
|
+
rb_raise(rb_eRangeError, "%s: step %"PRIsVALUE" is out of range for %s",
|
|
440
|
+
ca_calling_method_name(), rb_inspect(rstep), ca_type_name[dt]);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/* A real progression on an integer array: each cell takes offset + step*i
|
|
446
|
+
cut toward zero, as a store takes a float, so the first and the last
|
|
447
|
+
value (the extremes of a linear run) must fit the type, and NaN raises
|
|
448
|
+
as it does in a store. Checked before the fill writes anything. */
|
|
449
|
+
static void
|
|
450
|
+
ca_seq_check_real_run (CArray *ca, VALUE roffset, VALUE rstep, ca_size_t n)
|
|
451
|
+
{
|
|
452
|
+
int8_t dt = ca->data_type;
|
|
453
|
+
double offset = NIL_P(roffset) ? 0.0 : NUM2DBL(roffset);
|
|
454
|
+
double step = NIL_P(rstep) ? 1.0 : NUM2DBL(rstep);
|
|
455
|
+
double ends[2];
|
|
456
|
+
double lo, hi_excl;
|
|
457
|
+
int k;
|
|
458
|
+
if ( n == 0 ) return;
|
|
459
|
+
ends[0] = offset;
|
|
460
|
+
ends[1] = step * (double) (n - 1) + offset;
|
|
461
|
+
switch ( dt ) {
|
|
462
|
+
case CA_INT8: lo = INT8_MIN; hi_excl = (double) INT8_MAX + 1; break;
|
|
463
|
+
case CA_UINT8: lo = 0; hi_excl = (double) UINT8_MAX + 1; break;
|
|
464
|
+
case CA_INT16: lo = INT16_MIN; hi_excl = (double) INT16_MAX + 1; break;
|
|
465
|
+
case CA_UINT16: lo = 0; hi_excl = (double) UINT16_MAX + 1; break;
|
|
466
|
+
case CA_INT32: lo = INT32_MIN; hi_excl = (double) INT32_MAX + 1; break;
|
|
467
|
+
case CA_UINT32: lo = 0; hi_excl = (double) UINT32_MAX + 1; break;
|
|
468
|
+
case CA_INT64: lo = -ldexp(1.0, 63); hi_excl = ldexp(1.0, 63); break;
|
|
469
|
+
default: lo = 0; hi_excl = ldexp(1.0, 64); break;
|
|
470
|
+
}
|
|
471
|
+
for (k = 0; k < 2; k++) {
|
|
472
|
+
double t = trunc(ends[k]);
|
|
473
|
+
if ( isnan(ends[k]) || ( step != 0.0 && isnan(step) ) ) {
|
|
474
|
+
rb_raise(rb_eFloatDomainError, "%s: the run has NaN",
|
|
475
|
+
ca_calling_method_name());
|
|
476
|
+
}
|
|
477
|
+
if ( ! ( t >= lo && t < hi_excl ) ) {
|
|
478
|
+
rb_raise(rb_eRangeError, "%s: value %g is out of range for %s",
|
|
479
|
+
ca_calling_method_name(), ends[k], ca_type_name[dt]);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
371
484
|
/* CArray#seq!(init_val=0, step=1, axis: nil) -- arithmetic-progression
|
|
372
485
|
fill, in place. Without `axis:` the fill runs in row-major order
|
|
373
486
|
over the whole array; with `axis: k` the progression runs along axis
|
|
@@ -397,6 +510,34 @@ rb_ca_seq_bang_method (int argc, VALUE *argv, VALUE self)
|
|
|
397
510
|
return rb_ca_seq_bang_object(self, roffset, rstep, axis);
|
|
398
511
|
}
|
|
399
512
|
|
|
513
|
+
{
|
|
514
|
+
VALUE args[2];
|
|
515
|
+
const char *names[2] = { "offset", "step" };
|
|
516
|
+
int k;
|
|
517
|
+
args[0] = roffset;
|
|
518
|
+
args[1] = rstep;
|
|
519
|
+
for (k = 0; k < 2; k++) {
|
|
520
|
+
VALUE v = args[k];
|
|
521
|
+
if ( NIL_P(v) ) continue;
|
|
522
|
+
if ( ! RTEST(rb_obj_is_kind_of(v, rb_cNumeric)) ||
|
|
523
|
+
( RB_TYPE_P(v, T_COMPLEX) && ! ca_is_complex_type(ca) ) ) {
|
|
524
|
+
rb_raise(rb_eTypeError, "%s: %s must be a %snumber (got %"PRIsVALUE")",
|
|
525
|
+
ca_calling_method_name(), names[k],
|
|
526
|
+
ca_is_complex_type(ca) ? "" : "real ", rb_inspect(v));
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
if ( ca_is_integer_type(ca) ) {
|
|
532
|
+
if ( ca_seq_is_real(roffset) || ca_seq_is_real(rstep) ) {
|
|
533
|
+
ca_seq_check_real_run(ca, roffset, rstep,
|
|
534
|
+
axis < 0 ? ca->elements : ca->dim[axis]);
|
|
535
|
+
}
|
|
536
|
+
else {
|
|
537
|
+
ca_seq_check_integer_args(ca, roffset, rstep);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
400
541
|
{
|
|
401
542
|
ca_seq_ctx_t c;
|
|
402
543
|
c.ca = ca;
|
data/ext/carray_histogram.c
CHANGED
|
@@ -26,11 +26,38 @@
|
|
|
26
26
|
#include "carray_internal.h" /* ca_attach_window */
|
|
27
27
|
#include <math.h>
|
|
28
28
|
|
|
29
|
-
/*
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
/* Edges are the bin boundaries and must read as such: no masked edge (its
|
|
30
|
+
stored value is no boundary), no NaN, and no edge below the one before
|
|
31
|
+
it. Equal edges (a bin of zero width) and infinite ones are kept. */
|
|
32
|
+
static void
|
|
33
|
+
histbin_check_edge_mask (CArray *ce, const char *name)
|
|
34
|
+
{
|
|
35
|
+
if ( ca_has_mask(ce) && ca_is_any_masked(ce) ) {
|
|
36
|
+
rb_raise(rb_eArgError, "%s: edges has a masked value", name);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static void
|
|
41
|
+
histbin_check_edge_order (const double *ep, ca_size_t n, const char *name)
|
|
42
|
+
{
|
|
43
|
+
ca_size_t i;
|
|
44
|
+
for (i = 0; i < n; i++) {
|
|
45
|
+
if ( isnan(ep[i]) ) {
|
|
46
|
+
rb_raise(rb_eArgError, "%s: edges has NaN at %lld", name, (long long) i);
|
|
47
|
+
}
|
|
48
|
+
if ( i > 0 && ep[i] < ep[i-1] ) {
|
|
49
|
+
rb_raise(rb_eArgError, "%s: edges must not decrease "
|
|
50
|
+
"(%g at %lld after %g)", name, ep[i], (long long) i, ep[i-1]);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* Resolve `redges` to a 1-D float64 CArray of at least two edges, and
|
|
56
|
+
return it: it may be a view made here, which only the caller can keep
|
|
57
|
+
alive. The caller copies the edges out (ca_xfer_all into its own
|
|
58
|
+
buffer) rather than attaching them: the walk that follows reads the
|
|
59
|
+
caller's array, and a raise there must not leave the edges attached. */
|
|
60
|
+
static VALUE
|
|
34
61
|
histbin_resolve_edges (VALUE self, VALUE redges)
|
|
35
62
|
{
|
|
36
63
|
CArray *ce;
|
|
@@ -50,8 +77,9 @@ histbin_resolve_edges (VALUE self, VALUE redges)
|
|
|
50
77
|
if ( ce->elements < 2 ) {
|
|
51
78
|
rb_raise(rb_eArgError, "histbin_ki: edges needs at least 2 values");
|
|
52
79
|
}
|
|
80
|
+
histbin_check_edge_mask(ce, "bin_to");
|
|
53
81
|
|
|
54
|
-
return
|
|
82
|
+
return redges;
|
|
55
83
|
}
|
|
56
84
|
|
|
57
85
|
/* ---- shared binning helpers (used by histbin_ki + the fused kernel) ---- */
|
|
@@ -144,10 +172,13 @@ rb_ca_histbin_ki (VALUE self, VALUE redges, VALUE rinclude_max)
|
|
|
144
172
|
ca_type_name[ca->data_type]);
|
|
145
173
|
}
|
|
146
174
|
|
|
147
|
-
|
|
175
|
+
redges = histbin_resolve_edges(self, redges);
|
|
176
|
+
GetCArray(redges, ce);
|
|
148
177
|
ep = ALLOCV_N(double, hedges, ce->elements);
|
|
149
178
|
ca_xfer_all(ce, ep, CA_XFER_GET);
|
|
179
|
+
histbin_check_edge_order(ep, ce->elements, "bin_to");
|
|
150
180
|
histbin_axis_setup(&ax, ep, ce->elements, RTEST(rinclude_max));
|
|
181
|
+
RB_GC_GUARD(redges); /* a view made by histbin_resolve_edges is read through ce */
|
|
151
182
|
|
|
152
183
|
/* output: fresh contiguous int64, same shape as self. */
|
|
153
184
|
vout = rb_carray_new(CA_INT64, ca->ndim, ca->dim, 0, NULL);
|
|
@@ -314,6 +345,10 @@ histogram_scatter_edges (VALUE arg)
|
|
|
314
345
|
{
|
|
315
346
|
histogram_scatter_t *c = (histogram_scatter_t *) arg;
|
|
316
347
|
long k;
|
|
348
|
+
for ( k = 0; k < c->M; k++ ) {
|
|
349
|
+
histbin_check_edge_order((const double *) c->edge_ca[k]->ptr,
|
|
350
|
+
c->edge_ca[k]->elements, "histogram");
|
|
351
|
+
}
|
|
317
352
|
for ( k = 0; k < c->M; k++ ) {
|
|
318
353
|
histbin_axis_setup(&c->axes[k], (const double *) c->edge_ca[k]->ptr,
|
|
319
354
|
c->edge_ca[k]->elements,
|
|
@@ -382,6 +417,7 @@ rb_ca_histogram_scatter_ki (VALUE self, VALUE rcounts, VALUE redges,
|
|
|
382
417
|
for ( k = 0; k < M; k++ ) {
|
|
383
418
|
VALUE e = RARRAY_AREF(redges, k);
|
|
384
419
|
GetCArray(e, edge_ca[k]);
|
|
420
|
+
histbin_check_edge_mask(edge_ca[k], "histogram");
|
|
385
421
|
}
|
|
386
422
|
|
|
387
423
|
/* ext strides (row-major within the trailing M bin axes of counts). */
|
|
@@ -428,7 +464,16 @@ rb_ca_histogram_scatter_ki (VALUE self, VALUE rcounts, VALUE redges,
|
|
|
428
464
|
weights = nil OR float64 [fiber..., A] (second iterator in lockstep).
|
|
429
465
|
=========================================================================== */
|
|
430
466
|
|
|
431
|
-
|
|
467
|
+
/* A label at or above the last bin lands in the overflow cell. An unsigned
|
|
468
|
+
64-bit label above INT64_MAX must be clamped before it becomes an int64,
|
|
469
|
+
or it turns negative and indexes before the counts. */
|
|
470
|
+
static inline int64_t
|
|
471
|
+
bincount_nd_label_u64 (uint64_t x)
|
|
472
|
+
{
|
|
473
|
+
return ( x > (uint64_t) INT64_MAX ) ? INT64_MAX : (int64_t) x;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
#define BINCOUNT_ND_BODY(LABEL_T, TO_INT64) \
|
|
432
477
|
do { \
|
|
433
478
|
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) { \
|
|
434
479
|
ca_size_t fiber_base = 0, A, a, kk, ss, cs, sms, cms, ws = 0, wms = 0; \
|
|
@@ -441,7 +486,7 @@ rb_ca_histogram_scatter_ki (VALUE self, VALUE rcounts, VALUE redges,
|
|
|
441
486
|
for ( a = 0; a < A; a++ ) { \
|
|
442
487
|
ca_size_t off = fiber_base; int masked = 0; \
|
|
443
488
|
for ( kk = 0; kk < (ca_size_t) M; kk++ ) { \
|
|
444
|
-
int64_t v = (
|
|
489
|
+
int64_t v = TO_INT64(*(const LABEL_T *)(p + a * ss + kk * cs)); \
|
|
445
490
|
if ( m && m[a * sms + kk * cms] ) { masked = 1; break; } \
|
|
446
491
|
if ( v >= ext_dim[kk] - 1 ) v = ext_dim[kk] - 1; \
|
|
447
492
|
off += (ca_size_t) v * ext_stride[kk]; \
|
|
@@ -515,14 +560,14 @@ rb_ca_bincount_nd_count_ki (VALUE self, VALUE rcounts, VALUE rweights)
|
|
|
515
560
|
for ( mm = 0; mm < st.outer_ndim; mm++ ) cur_outer_idx[mm] = 0;
|
|
516
561
|
|
|
517
562
|
switch ( ca->data_type ) {
|
|
518
|
-
case CA_INT8: BINCOUNT_ND_BODY(int8_t); break;
|
|
519
|
-
case CA_UINT8: BINCOUNT_ND_BODY(uint8_t); break;
|
|
520
|
-
case CA_INT16: BINCOUNT_ND_BODY(int16_t); break;
|
|
521
|
-
case CA_UINT16: BINCOUNT_ND_BODY(uint16_t); break;
|
|
522
|
-
case CA_INT32: BINCOUNT_ND_BODY(int32_t); break;
|
|
523
|
-
case CA_UINT32: BINCOUNT_ND_BODY(uint32_t); break;
|
|
524
|
-
case CA_INT64: BINCOUNT_ND_BODY(int64_t); break;
|
|
525
|
-
case CA_UINT64: BINCOUNT_ND_BODY(uint64_t); break;
|
|
563
|
+
case CA_INT8: BINCOUNT_ND_BODY(int8_t, (int64_t)); break;
|
|
564
|
+
case CA_UINT8: BINCOUNT_ND_BODY(uint8_t, (int64_t)); break;
|
|
565
|
+
case CA_INT16: BINCOUNT_ND_BODY(int16_t, (int64_t)); break;
|
|
566
|
+
case CA_UINT16: BINCOUNT_ND_BODY(uint16_t, (int64_t)); break;
|
|
567
|
+
case CA_INT32: BINCOUNT_ND_BODY(int32_t, (int64_t)); break;
|
|
568
|
+
case CA_UINT32: BINCOUNT_ND_BODY(uint32_t, (int64_t)); break;
|
|
569
|
+
case CA_INT64: BINCOUNT_ND_BODY(int64_t, (int64_t)); break;
|
|
570
|
+
case CA_UINT64: BINCOUNT_ND_BODY(uint64_t, bincount_nd_label_u64); break;
|
|
526
571
|
default:
|
|
527
572
|
ca_iter_state_finish(&st);
|
|
528
573
|
if ( weighted ) ca_iter_state_finish(&stw);
|
data/ext/carray_hold.c
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
#include "carray.h"
|
|
21
21
|
#include "ca_kernel_iterator.h"
|
|
22
22
|
#include "ca_obj_face.h"
|
|
23
|
+
#include "carray_internal.h" /* ca_normalize_axis_arg */
|
|
23
24
|
|
|
24
25
|
/* Forward hold along `axis`. Per fiber along the scan axis:
|
|
25
26
|
- present cell -> output = cell value, becomes the held value;
|
|
@@ -47,22 +48,24 @@ rb_ca_hold_forward (VALUE self, int axis)
|
|
|
47
48
|
ca_iter_state st_in, st_out;
|
|
48
49
|
int rc = ca_iter_state_init_l2(&st_in, ca, CA_SLAB_AXES, slab_axes, 1, 0);
|
|
49
50
|
if ( rc != CA_ITER_OK ) {
|
|
50
|
-
rb_raise(rb_eRuntimeError, "
|
|
51
|
+
rb_raise(rb_eRuntimeError, "hold_forward: input init failed rc=%d", rc);
|
|
51
52
|
}
|
|
52
53
|
rc = ca_iter_state_init_l2_paired(&st_out, &st_in, co, CA_SLAB_AXES,
|
|
53
54
|
slab_axes, 1,
|
|
54
55
|
CA_KERNEL_WRITE);
|
|
55
56
|
if ( rc != CA_ITER_OK ) {
|
|
56
57
|
ca_iter_state_finish(&st_in);
|
|
57
|
-
rb_raise(rb_eRuntimeError, "
|
|
58
|
+
rb_raise(rb_eRuntimeError, "hold_forward: output init failed rc=%d", rc);
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
/* Output mask allocated lazily on the first leading-masked (UNDEF) cell:
|
|
61
62
|
a fiber can only go UNDEF on a leading masked run, so a fully filled
|
|
62
|
-
result carries no mask at all.
|
|
63
|
-
|
|
63
|
+
result carries no mask at all. The output is a fresh row-major entity
|
|
64
|
+
and the walk cuts its slabs from a buffer laid out the same way (the
|
|
65
|
+
output's memory, or the walk's scratch when it delivers by transfer),
|
|
66
|
+
so a slab's offset from st_out.alias_ptr is its offset in co, which
|
|
67
|
+
op_mask parallels. */
|
|
64
68
|
boolean8_t *op_mask = NULL;
|
|
65
|
-
char *co_root = (char *) co->ptr;
|
|
66
69
|
|
|
67
70
|
char *pi, *po;
|
|
68
71
|
boolean8_t *mi, *mo;
|
|
@@ -73,7 +76,7 @@ rb_ca_hold_forward (VALUE self, int axis)
|
|
|
73
76
|
ca_size_t oS = st_out.slab_strides[0]; /* output data byte stride */
|
|
74
77
|
ca_size_t iMS = st_in.slab_mask_strides[0]; /* input mask element stride */
|
|
75
78
|
ca_size_t oMStep = oS / K; /* output mask element step */
|
|
76
|
-
ca_size_t oMBase = (ca_size_t)(po -
|
|
79
|
+
ca_size_t oMBase = (ca_size_t)(po - st_out.alias_ptr) / K;
|
|
77
80
|
const char *held = NULL; /* last valid cell (points into input slab) */
|
|
78
81
|
|
|
79
82
|
for ( ca_size_t j = 0; j < N; j++ ) {
|
|
@@ -104,7 +107,7 @@ rb_ca_hold_forward (VALUE self, int axis)
|
|
|
104
107
|
return vout;
|
|
105
108
|
}
|
|
106
109
|
|
|
107
|
-
/*
|
|
110
|
+
/* hold_forward(axis): private forward-hold primitive. axis is a required
|
|
108
111
|
Integer (negative counts from the end). The Ruby wrapper composes
|
|
109
112
|
backward / flatten / linear on top of this. */
|
|
110
113
|
static VALUE
|
|
@@ -112,13 +115,7 @@ rb_ca_hold_method (VALUE self, VALUE raxis)
|
|
|
112
115
|
{
|
|
113
116
|
CArray *ca;
|
|
114
117
|
GetCArray(self, ca);
|
|
115
|
-
|
|
116
|
-
if ( axis < 0 ) axis += ca->ndim;
|
|
117
|
-
if ( axis < 0 || axis >= ca->ndim ) {
|
|
118
|
-
rb_raise(rb_eArgError, "__hold__: axis %d out of range for ndim %d",
|
|
119
|
-
NUM2INT(raxis), ca->ndim);
|
|
120
|
-
}
|
|
121
|
-
return rb_ca_hold_forward(self, axis);
|
|
118
|
+
return rb_ca_hold_forward(self, ca_normalize_axis_arg(raxis, ca->ndim, NULL));
|
|
122
119
|
}
|
|
123
120
|
|
|
124
121
|
/* first / last: the reduction sibling of hold. Reduce each fiber to its
|
|
@@ -223,7 +220,7 @@ rb_ca_last (int argc, VALUE *argv, VALUE self)
|
|
|
223
220
|
void
|
|
224
221
|
Init_carray_hold (void)
|
|
225
222
|
{
|
|
226
|
-
rb_define_private_method(rb_cCArray, "
|
|
223
|
+
rb_define_private_method(rb_cCArray, "hold_forward", rb_ca_hold_method, 1);
|
|
227
224
|
rb_define_method(rb_cCArray, "first", rb_ca_first, -1);
|
|
228
225
|
rb_define_method(rb_cCArray, "last", rb_ca_last, -1);
|
|
229
226
|
}
|