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_scatter.c
CHANGED
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
(boolean / object / fixlen → CADataTypeError; the bang
|
|
15
15
|
cannot widen self, same rationale as fma! / fms!)
|
|
16
16
|
replace: numeric or boolean (assignment, no widening)
|
|
17
|
-
scalar
|
|
17
|
+
scalar any Numeric, true / false, or UNDEF; converted to self's
|
|
18
|
+
type as the indexer's store converts it (a value that does
|
|
19
|
+
not fit raises, as `self[i] = v` does)
|
|
18
20
|
|
|
19
21
|
--------------------------------------------------------------------------- */
|
|
20
22
|
|
|
@@ -44,12 +46,19 @@
|
|
|
44
46
|
#define OP_MIN_INT(qp, v) do { if ((v) < *(qp)) *(qp) = (v); } while (0)
|
|
45
47
|
#define OP_MAX_INT(qp, v) do { if ((v) > *(qp)) *(qp) = (v); } while (0)
|
|
46
48
|
|
|
47
|
-
/* The scalar operand
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
/* The scalar operand, already converted to self's type by rb_ca_obj2ptr
|
|
50
|
+
(the indexer's store conversion) and held as one cell in vcell. */
|
|
51
|
+
typedef union {
|
|
52
|
+
char bytes[16];
|
|
53
|
+
double d;
|
|
54
|
+
int64_t l;
|
|
55
|
+
#ifdef HAVE_COMPLEX_H
|
|
56
|
+
cmplx128_t z;
|
|
57
|
+
#endif
|
|
58
|
+
} ca_scatter_cell_t;
|
|
59
|
+
|
|
60
|
+
#define SCALAR_REAL(T) (*(const T *) vcell.bytes)
|
|
61
|
+
#define SCALAR_CMPLX(T) (*(const T *) vcell.bytes)
|
|
53
62
|
|
|
54
63
|
#define LOOP_SCALAR(T, APPLY) LOOP_SCALAR_V(T, APPLY, SCALAR_REAL(T))
|
|
55
64
|
|
|
@@ -105,8 +114,8 @@
|
|
|
105
114
|
both value and mask (indexer contract, `self[addrs] = vals`).
|
|
106
115
|
- masked vals[i] flips target to masked (writes UNDEF); valid
|
|
107
116
|
vals[i] writes value and clears the target's mask bit.
|
|
108
|
-
|
|
109
|
-
writes and clears target mask. */
|
|
117
|
+
A scalar UNDEF masks every target (self's mask exists by then); any
|
|
118
|
+
other scalar writes and clears the target's mask. */
|
|
110
119
|
|
|
111
120
|
#define LOOP_SCALAR_REPLACE(T) LOOP_SCALAR_REPLACE_V(T, SCALAR_REAL(T))
|
|
112
121
|
|
|
@@ -117,6 +126,10 @@
|
|
|
117
126
|
if ( maddrs && maddrs[i] ) continue; \
|
|
118
127
|
addr = p[i]; \
|
|
119
128
|
CA_CHECK_INDEX(addr, elements); \
|
|
129
|
+
if ( vals_undef ) { \
|
|
130
|
+
mself[addr] = 1; \
|
|
131
|
+
continue; \
|
|
132
|
+
} \
|
|
120
133
|
q[addr] = vs; \
|
|
121
134
|
if ( mself ) mself[addr] = 0; \
|
|
122
135
|
} \
|
|
@@ -204,11 +217,21 @@
|
|
|
204
217
|
} \
|
|
205
218
|
} while (0)
|
|
206
219
|
|
|
220
|
+
/* A value that is one cell for every address: a Numeric, true / false,
|
|
221
|
+
or UNDEF. Anything else (a CArray, an Array, ...) is coerced to an
|
|
222
|
+
array of values. */
|
|
223
|
+
static int
|
|
224
|
+
ca_scatter_is_scalar (VALUE v)
|
|
225
|
+
{
|
|
226
|
+
return v == CA_UNDEF || v == Qtrue || v == Qfalse
|
|
227
|
+
|| rb_obj_is_kind_of(v, rb_cNumeric);
|
|
228
|
+
}
|
|
229
|
+
|
|
207
230
|
/* Setup boilerplate: parse args and wrap addrs/vals.
|
|
208
231
|
|
|
209
232
|
Outputs into caller's locals:
|
|
210
233
|
ca, ci, cv (CArray*), n (ca_size_t),
|
|
211
|
-
vals_scalar (int),
|
|
234
|
+
vals_scalar, vals_undef (int), vcell (the scalar as one cell).
|
|
212
235
|
|
|
213
236
|
The kernel then runs through AT_RUN, and an address out of range
|
|
214
237
|
raising part way still leaves the cells already written.
|
|
@@ -218,9 +241,12 @@
|
|
|
218
241
|
*/
|
|
219
242
|
/* Body shared by arithmetic and replace setups. Caller precondition:
|
|
220
243
|
the data_type gate has already run (arithmetic = numeric only, replace
|
|
221
|
-
= numeric or boolean).
|
|
222
|
-
|
|
223
|
-
|
|
244
|
+
= numeric or boolean). A scalar is converted the way `self[i] = v`
|
|
245
|
+
converts it, so true / false reach only a boolean self and a value that
|
|
246
|
+
does not fit raises. A scalar UNDEF is a masked value: the arithmetic
|
|
247
|
+
family skips every pair, replace masks every target. */
|
|
248
|
+
#define AT_SETUP_BODY(name) \
|
|
249
|
+
ca_check_index_array(raddrs); \
|
|
224
250
|
raddrs = rb_ca_wrap_readonly(raddrs, INT2NUM(CA_SIZE)); \
|
|
225
251
|
TypedData_Get_Struct(raddrs, CArray, &carray_data_type, ci); \
|
|
226
252
|
if ( ca_shares_root(ci, ca) ) { \
|
|
@@ -229,20 +255,17 @@
|
|
|
229
255
|
} \
|
|
230
256
|
n = ci->elements; \
|
|
231
257
|
if ( n == 0 ) return self; \
|
|
232
|
-
vals_scalar = (
|
|
233
|
-
|| ((allow_bool_scalar) && (rvals == Qtrue || rvals == Qfalse)) \
|
|
234
|
-
|| (ca_is_complex_type(ca) && RB_TYPE_P(rvals, T_COMPLEX))); \
|
|
258
|
+
vals_scalar = ca_scatter_is_scalar(rvals); \
|
|
235
259
|
if ( vals_scalar ) { \
|
|
236
|
-
if (
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
260
|
+
if ( rvals == CA_UNDEF ) { \
|
|
261
|
+
vals_undef = 1; \
|
|
262
|
+
} \
|
|
263
|
+
else { \
|
|
264
|
+
rb_ca_obj2ptr(self, rvals, vcell.bytes); \
|
|
240
265
|
} \
|
|
241
|
-
else if ( RB_FLOAT_TYPE_P(rvals) ) { vd = RFLOAT_VALUE(rvals); v_is_float = 1; } \
|
|
242
|
-
else if ( FIXNUM_P(rvals) ) { vl = FIX2LONG(rvals); v_is_float = 0; } \
|
|
243
|
-
else { vl = (rvals == Qtrue) ? 1 : 0; v_is_float = 0; } \
|
|
244
266
|
} \
|
|
245
267
|
else { \
|
|
268
|
+
/* coerce: a store into the receiver */ \
|
|
246
269
|
rvals = rb_ca_wrap_readonly(rvals, INT2NUM(ca->data_type)); \
|
|
247
270
|
TypedData_Get_Struct(rvals, CArray, &carray_data_type, cv); \
|
|
248
271
|
if ( ca_shares_root(cv, ca) ) { \
|
|
@@ -259,8 +282,8 @@
|
|
|
259
282
|
#define AT_SETUP_LOCALS \
|
|
260
283
|
CArray *ca, *ci, *cv = NULL; \
|
|
261
284
|
ca_size_t n; \
|
|
262
|
-
int vals_scalar,
|
|
263
|
-
|
|
285
|
+
int vals_scalar, vals_undef = 0; \
|
|
286
|
+
ca_scatter_cell_t vcell = {{0}};
|
|
264
287
|
|
|
265
288
|
#define AT_SETUP_OR_RETURN(name, ordered) \
|
|
266
289
|
AT_SETUP_LOCALS \
|
|
@@ -273,7 +296,8 @@
|
|
|
273
296
|
rb_raise(rb_eCADataTypeError, \
|
|
274
297
|
name " requires a real array (complex values have no order)"); \
|
|
275
298
|
} \
|
|
276
|
-
AT_SETUP_BODY(name
|
|
299
|
+
AT_SETUP_BODY(name) \
|
|
300
|
+
if ( vals_undef ) return self;
|
|
277
301
|
|
|
278
302
|
/* replace variant: accepts boolean self (assignment, no widening) and
|
|
279
303
|
Ruby true / false as scalar vals. */
|
|
@@ -285,7 +309,8 @@
|
|
|
285
309
|
rb_raise(rb_eCADataTypeError, \
|
|
286
310
|
name " requires a numeric or boolean array"); \
|
|
287
311
|
} \
|
|
288
|
-
AT_SETUP_BODY(name
|
|
312
|
+
AT_SETUP_BODY(name) \
|
|
313
|
+
if ( vals_undef ) ca_create_mask(ca);
|
|
289
314
|
|
|
290
315
|
/* The kernel works either on self's own memory or on a compact region:
|
|
291
316
|
the distinct cells the addresses touch, read out of self and written
|
|
@@ -305,9 +330,8 @@ typedef struct {
|
|
|
305
330
|
typedef struct {
|
|
306
331
|
CArray *ca, *ci, *cv;
|
|
307
332
|
ca_size_t n;
|
|
308
|
-
int vals_scalar,
|
|
309
|
-
|
|
310
|
-
long vl;
|
|
333
|
+
int vals_scalar, vals_undef;
|
|
334
|
+
ca_scatter_cell_t vcell;
|
|
311
335
|
ca_scatter_region_t *region;
|
|
312
336
|
} ca_scatter_ctx_t;
|
|
313
337
|
|
|
@@ -330,10 +354,9 @@ fname (VALUE arg) \
|
|
|
330
354
|
boolean8_t *mvals = (cv && cv->mask) ? (boolean8_t *) cv->mask->ptr : NULL; \
|
|
331
355
|
boolean8_t *mself = rg_ ? rg_->mask \
|
|
332
356
|
: (ca->mask ? (boolean8_t *) ca->mask->ptr : NULL); \
|
|
333
|
-
int vals_scalar = c_->vals_scalar,
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
(void) cv; (void) mvals; (void) v_is_float; (void) vd; (void) vi; (void) vl; \
|
|
357
|
+
int vals_scalar = c_->vals_scalar, vals_undef = c_->vals_undef; \
|
|
358
|
+
ca_scatter_cell_t vcell = c_->vcell; \
|
|
359
|
+
(void) cv; (void) mvals; (void) vals_undef; (void) vcell; \
|
|
337
360
|
DISPATCH; \
|
|
338
361
|
return Qnil; \
|
|
339
362
|
}
|
|
@@ -460,8 +483,8 @@ ca_scatter_region_body (VALUE varg)
|
|
|
460
483
|
ca_scatter_ctx_t c_; \
|
|
461
484
|
CArray *list_[3]; \
|
|
462
485
|
c_.ca = ca; c_.ci = ci; c_.cv = cv; c_.n = n; \
|
|
463
|
-
c_.vals_scalar = vals_scalar; c_.
|
|
464
|
-
c_.
|
|
486
|
+
c_.vals_scalar = vals_scalar; c_.vals_undef = vals_undef; \
|
|
487
|
+
c_.vcell = vcell; \
|
|
465
488
|
c_.region = NULL; \
|
|
466
489
|
if ( ca_attach_is_alias(ca) ) { \
|
|
467
490
|
list_[0] = ca; list_[1] = ci; list_[2] = cv; \
|
|
@@ -474,6 +497,9 @@ ca_scatter_region_body (VALUE varg)
|
|
|
474
497
|
ca_attach_window(vals_scalar ? 1 : 2, list_, "rr", \
|
|
475
498
|
ca_scatter_region_body, (VALUE) &ra_); \
|
|
476
499
|
} \
|
|
500
|
+
/* the views AT_SETUP_BODY made are reached only through ci and cv */ \
|
|
501
|
+
RB_GC_GUARD(raddrs); \
|
|
502
|
+
RB_GC_GUARD(rvals); \
|
|
477
503
|
} while (0)
|
|
478
504
|
|
|
479
505
|
/* --------------------------------------------------------------- */
|
|
@@ -569,8 +595,7 @@ rb_ca_scatter_replace_bang (VALUE self, VALUE raddrs, VALUE rvals)
|
|
|
569
595
|
/* Pre-scan: if vals is a masked CArray and self isn't yet masked,
|
|
570
596
|
promote self so the kernel can flip target cells to masked (indexer
|
|
571
597
|
`self[addrs] = vals` establishes self.mask lazily the same way). */
|
|
572
|
-
if (
|
|
573
|
-
&& rb_obj_is_carray(rvals) ) {
|
|
598
|
+
if ( rb_obj_is_carray(rvals) ) {
|
|
574
599
|
CArray *cv_pre;
|
|
575
600
|
TypedData_Get_Struct(rvals, CArray, &carray_data_type, cv_pre);
|
|
576
601
|
if ( ca_has_mask(cv_pre) ) {
|
data/ext/carray_segment.c
CHANGED
|
@@ -228,7 +228,7 @@ rb_ca_s_segment_index (int argc, VALUE *argv, VALUE klass)
|
|
|
228
228
|
return rout;
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
/* CArray.
|
|
231
|
+
/* CArray.__segment_boundaries_from_lengths_or_offsets__(name, lengths: l | offsets: o) -> int64[k+1]
|
|
232
232
|
|
|
233
233
|
Internal: the validated boundaries, for a Ruby caller that takes the same
|
|
234
234
|
two keywords (CArray#segments). `name` heads the error messages. */
|
|
@@ -239,7 +239,7 @@ rb_ca_s_segment_bounds (int argc, VALUE *argv, VALUE klass)
|
|
|
239
239
|
ca_size_t k;
|
|
240
240
|
VALUE rname;
|
|
241
241
|
if ( argc < 1 ) {
|
|
242
|
-
rb_raise(rb_eArgError, "
|
|
242
|
+
rb_raise(rb_eArgError, "__segment_boundaries_from_lengths_or_offsets__: the caller's name is required");
|
|
243
243
|
}
|
|
244
244
|
rname = argv[0];
|
|
245
245
|
StringValue(rname);
|
|
@@ -253,5 +253,5 @@ Init_carray_segment (void)
|
|
|
253
253
|
id_offsets = rb_intern("offsets");
|
|
254
254
|
rb_define_singleton_method(rb_cCArray, "segment_offsets", rb_ca_s_segment_offsets, -1);
|
|
255
255
|
rb_define_singleton_method(rb_cCArray, "segment_index", rb_ca_s_segment_index, -1);
|
|
256
|
-
rb_define_singleton_method(rb_cCArray, "
|
|
256
|
+
rb_define_singleton_method(rb_cCArray, "__segment_boundaries_from_lengths_or_offsets__", rb_ca_s_segment_bounds, -1);
|
|
257
257
|
}
|
data/ext/carray_slab.c
CHANGED
|
@@ -28,8 +28,20 @@
|
|
|
28
28
|
--------------------------------------------------------------------------- */
|
|
29
29
|
|
|
30
30
|
#include "carray.h"
|
|
31
|
-
#include "carray_internal.h" /* ca_attach_window, ca_calling_method_name,
|
|
31
|
+
#include "carray_internal.h" /* ca_attach_window, ca_calling_method_name, ca_normalize_axis_arg */
|
|
32
32
|
#include "carray_slab.h"
|
|
33
|
+
#include "ca_obj_face.h"
|
|
34
|
+
|
|
35
|
+
/* Promise 8 of the kernel iterator: a slab may be lent to Ruby as a view
|
|
36
|
+
onto the source's own memory only when the source is an entity and the
|
|
37
|
+
walk reads that memory in place (alias_ptr is src->ptr, not a scratch or
|
|
38
|
+
a root it gathered from). Any other slab is a copy, and a view built on
|
|
39
|
+
it would read memory the walk frees or reuses. */
|
|
40
|
+
static int
|
|
41
|
+
ca_slab_walk_reads_src_in_place (const ca_iter_state *it, CArray *src)
|
|
42
|
+
{
|
|
43
|
+
return ca_is_entity(src) && it->alias_ptr == src->ptr;
|
|
44
|
+
}
|
|
33
45
|
|
|
34
46
|
/* Forward declarations: per-form loop bodies are defined later in this
|
|
35
47
|
file and take a state pointer directly. */
|
|
@@ -66,21 +78,14 @@ ca_slab_parse_axes (ca_slab_iter_state_t *st, VALUE axis_arg, int8_t src_ndim)
|
|
|
66
78
|
}
|
|
67
79
|
|
|
68
80
|
n = (int) RARRAY_LEN(arr);
|
|
69
|
-
if ( n < 1 || n > CA_RANK_MAX ) {
|
|
81
|
+
if ( n < 1 || n > CA_RANK_MAX ) { /* rank-check: a list of axes, no longer than the rank */
|
|
70
82
|
rb_raise(rb_eArgError,
|
|
71
83
|
"%s: axis count %d out of range [1..%d]",
|
|
72
84
|
ca_calling_method_name(), n, CA_RANK_MAX);
|
|
73
85
|
}
|
|
74
86
|
|
|
75
87
|
for ( i = 0; i < n; i++ ) {
|
|
76
|
-
int k = (
|
|
77
|
-
if ( k < 0 ) k += src_ndim;
|
|
78
|
-
if ( k < 0 || k >= src_ndim ) {
|
|
79
|
-
rb_raise(rb_eArgError,
|
|
80
|
-
"%s: axis %d out of range for ndim %d",
|
|
81
|
-
ca_calling_method_name(), NUM2INT(rb_ary_entry(arr, i)),
|
|
82
|
-
src_ndim);
|
|
83
|
-
}
|
|
88
|
+
int k = ca_normalize_axis_arg(rb_ary_entry(arr, i), src_ndim, NULL);
|
|
84
89
|
for ( j = 0; j < i; j++ ) {
|
|
85
90
|
if ( st->slab_axes[j] == (int8_t) k ) {
|
|
86
91
|
rb_raise(rb_eArgError,
|
|
@@ -370,12 +375,13 @@ ca_slab_setup_input_slab_view (ca_slab_iter_state_t *st, CArray *src,
|
|
|
370
375
|
p_in via slab_strides into the scratch, present slab_view as
|
|
371
376
|
a CAStride over the carrier with contig strides.
|
|
372
377
|
|
|
373
|
-
Path (a) needs p_in to lie in src's own buffer
|
|
374
|
-
|
|
375
|
-
|
|
378
|
+
Path (a) needs p_in to lie in src's own buffer: src is an entity
|
|
379
|
+
and the iterator walks that buffer (alias_ptr is src->ptr, not a
|
|
380
|
+
scratch it gathered into). Any other source -- a view, whose cells
|
|
381
|
+
the iterator hands out from the root, a parent or its own scratch --
|
|
376
382
|
takes path (b): the iterator describes every slab by p_in and
|
|
377
383
|
slab_strides, whatever its mode. */
|
|
378
|
-
int contig =
|
|
384
|
+
int contig = ca_slab_walk_reads_src_in_place(st->t1, src)
|
|
379
385
|
&& ca_slab_strides_are_row_major_contig(slab_ndim,
|
|
380
386
|
st->t1->slab_dims,
|
|
381
387
|
st->t1->slab_strides,
|
|
@@ -436,9 +442,10 @@ ca_slab_setup_input_slab_view (ca_slab_iter_state_t *st, CArray *src,
|
|
|
436
442
|
dim[0] = fiber_len;
|
|
437
443
|
strides[0] = src->bytes;
|
|
438
444
|
/* A window onto src only when the fiber lies in src's own buffer:
|
|
439
|
-
an entity whose fiber is contiguous.
|
|
440
|
-
the root or the iterator's scratch, so it
|
|
441
|
-
|
|
445
|
+
an entity the iterator walks in place, whose fiber is contiguous.
|
|
446
|
+
A view's fiber comes from the root or the iterator's scratch, so it
|
|
447
|
+
goes through a carrier. */
|
|
448
|
+
in_alias = ca_slab_walk_reads_src_in_place(st->t1, src) && (in_stride == src->bytes);
|
|
442
449
|
|
|
443
450
|
if ( in_alias ) {
|
|
444
451
|
/* ALIAS: parent = src. ca_stride_setup auto-creates slab_view->mask
|
|
@@ -494,8 +501,18 @@ ca_slab_advance_slab_view (ca_slab_iter_state_t *st,
|
|
|
494
501
|
slab_cs->base_offset = (ca_size_t) (p_in - src->ptr);
|
|
495
502
|
if ( slab_cs->mask != NULL ) {
|
|
496
503
|
CAStride *mask_cs = (CAStride *) slab_cs->mask;
|
|
497
|
-
|
|
498
|
-
|
|
504
|
+
if ( m_in != NULL ) {
|
|
505
|
+
mask_cs->ptr = (char *) m_in;
|
|
506
|
+
mask_cs->base_offset = (ca_size_t) ((char *) m_in - src->mask->ptr);
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
/* The walk was opened on a source without a mask and the block
|
|
510
|
+
has given it one since: there is no mask cursor, so the slab's
|
|
511
|
+
mask reads the source's mask at the cell the data starts on. */
|
|
512
|
+
mask_cs->ptr = NULL;
|
|
513
|
+
mask_cs->base_offset = (ca_size_t) ((p_in - src->ptr) / src->bytes)
|
|
514
|
+
* src->mask->bytes;
|
|
515
|
+
}
|
|
499
516
|
}
|
|
500
517
|
} else if ( st->own_data_scratch != NULL ) {
|
|
501
518
|
/* Non-contig multi-axis: K-D gather from src memory (via
|
|
@@ -515,7 +532,7 @@ ca_slab_advance_slab_view (ca_slab_iter_state_t *st,
|
|
|
515
532
|
both slab_view and carrier at the iter's delivered addr. */
|
|
516
533
|
slab_cs->ptr = p_in;
|
|
517
534
|
carrier_cw->ptr = p_in;
|
|
518
|
-
if ( slab_cs->mask != NULL ) {
|
|
535
|
+
if ( slab_cs->mask != NULL && m_in != NULL ) {
|
|
519
536
|
CAStride *mask_cs = (CAStride *) slab_cs->mask;
|
|
520
537
|
mask_cs->ptr = (char *) m_in;
|
|
521
538
|
carrier_cw->mask->ptr = (char *) m_in;
|
|
@@ -626,10 +643,26 @@ ca_map_slab_cast_body (VALUE arg)
|
|
|
626
643
|
return Qnil;
|
|
627
644
|
}
|
|
628
645
|
|
|
646
|
+
/* What the block sees of the slab: the slab view itself, or, over a Face,
|
|
647
|
+
the slab view under that Face, as `a[...]` would give it. The slab
|
|
648
|
+
view is moved per slab in place, and the Face reads through it, so one
|
|
649
|
+
is built per walk. */
|
|
650
|
+
static VALUE
|
|
651
|
+
ca_slab_piece (ca_slab_iter_state_t *st)
|
|
652
|
+
{
|
|
653
|
+
CArray *src;
|
|
654
|
+
TypedData_Get_Struct(st->self, CArray, &carray_data_type, src);
|
|
655
|
+
if ( ! ca_is_face(src) ) {
|
|
656
|
+
return st->slab_view;
|
|
657
|
+
}
|
|
658
|
+
return ca_face_lift(st->slab_view, st->self);
|
|
659
|
+
}
|
|
660
|
+
|
|
629
661
|
static VALUE
|
|
630
662
|
ca_slab_run_map (ca_slab_iter_state_t *st)
|
|
631
663
|
{
|
|
632
664
|
CArray *src;
|
|
665
|
+
volatile VALUE piece;
|
|
633
666
|
CArray *out;
|
|
634
667
|
uint32_t flags_in;
|
|
635
668
|
uint32_t flags_out;
|
|
@@ -715,6 +748,7 @@ ca_slab_run_map (ca_slab_iter_state_t *st)
|
|
|
715
748
|
TypedData_Get_Struct(st->output_slab_view, CAWrap,
|
|
716
749
|
&cawrap_data_type, out_slab_cw);
|
|
717
750
|
|
|
751
|
+
piece = ca_slab_piece(st);
|
|
718
752
|
while ( ca_iter_state_next_slab_axes(st->t1, &p_in, &m_in) &&
|
|
719
753
|
ca_iter_state_next_slab_axes(st->t1_out, &p_out, &m_out) ) {
|
|
720
754
|
VALUE result;
|
|
@@ -732,7 +766,7 @@ ca_slab_run_map (ca_slab_iter_state_t *st)
|
|
|
732
766
|
? st->own_out_scratch : p_out;
|
|
733
767
|
out_slab_cw->ptr = write_target;
|
|
734
768
|
|
|
735
|
-
result = rb_yield(
|
|
769
|
+
result = rb_yield(piece);
|
|
736
770
|
|
|
737
771
|
/* Strict shape check. */
|
|
738
772
|
if ( rb_obj_is_kind_of(result, rb_cCArray) ) {
|
|
@@ -898,10 +932,36 @@ ca_slab_reduce_setup (ca_slab_iter_state_t *st, CArray **out_src,
|
|
|
898
932
|
/* Per-slab block form: block receives the slab CArray, returns a
|
|
899
933
|
scalar; each scalar is cast into the corresponding output cell.
|
|
900
934
|
(`init:` absent ⇒ this path) */
|
|
935
|
+
/* Write one reduced value into the reduction output. UNDEF from the
|
|
936
|
+
block masks the cell, as storing UNDEF into an array does; obj2ptr
|
|
937
|
+
would read it as 0. */
|
|
938
|
+
static void
|
|
939
|
+
ca_slab_store_reduced (ca_slab_iter_state_t *st, CArray *out,
|
|
940
|
+
ca_size_t out_idx, VALUE value, char *scratch)
|
|
941
|
+
{
|
|
942
|
+
char *dst = out->ptr + out_idx * st->out_bytes;
|
|
943
|
+
if ( value == CA_UNDEF ) {
|
|
944
|
+
if ( out->mask == NULL ) {
|
|
945
|
+
ca_create_mask(out);
|
|
946
|
+
}
|
|
947
|
+
((boolean8_t *) out->mask->ptr)[out_idx] = 1;
|
|
948
|
+
if ( out->data_type == CA_OBJECT ) {
|
|
949
|
+
*(VALUE *) dst = INT2FIX(0);
|
|
950
|
+
}
|
|
951
|
+
else {
|
|
952
|
+
memset(dst, 0, st->out_bytes);
|
|
953
|
+
}
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
rb_ca_obj2ptr(st->output, value, scratch);
|
|
957
|
+
memcpy(dst, scratch, st->out_bytes);
|
|
958
|
+
}
|
|
959
|
+
|
|
901
960
|
static VALUE
|
|
902
961
|
ca_slab_run_reduce_slab (ca_slab_iter_state_t *st)
|
|
903
962
|
{
|
|
904
963
|
CArray *src;
|
|
964
|
+
volatile VALUE piece;
|
|
905
965
|
CArray *out;
|
|
906
966
|
ca_size_t fiber_len;
|
|
907
967
|
char *p_in;
|
|
@@ -927,13 +987,14 @@ ca_slab_run_reduce_slab (ca_slab_iter_state_t *st)
|
|
|
927
987
|
scratch = (st->out_bytes <= (ca_size_t) sizeof(buf))
|
|
928
988
|
? buf : ALLOCV_N(char, scratch_holder, st->out_bytes);
|
|
929
989
|
|
|
990
|
+
piece = ca_slab_piece(st);
|
|
930
991
|
while ( ca_iter_state_next_slab_axes(st->t1, &p_in, &m_in) ) {
|
|
931
992
|
VALUE result;
|
|
932
993
|
|
|
933
994
|
ca_slab_advance_slab_view(st, slab_cs, carrier_cw,
|
|
934
995
|
src, p_in, m_in, in_alias);
|
|
935
996
|
|
|
936
|
-
result = rb_yield(
|
|
997
|
+
result = rb_yield(piece);
|
|
937
998
|
|
|
938
999
|
/* Strict scalar contract: block must return a scalar Ruby value
|
|
939
1000
|
(Numeric / Object / etc.). A CArray is a
|
|
@@ -952,8 +1013,7 @@ ca_slab_run_reduce_slab (ca_slab_iter_state_t *st)
|
|
|
952
1013
|
res->elements == 1 ? "" : "s");
|
|
953
1014
|
}
|
|
954
1015
|
|
|
955
|
-
|
|
956
|
-
memcpy(out->ptr + out_idx * st->out_bytes, scratch, st->out_bytes);
|
|
1016
|
+
ca_slab_store_reduced(st, out, out_idx, result, scratch);
|
|
957
1017
|
out_idx++;
|
|
958
1018
|
}
|
|
959
1019
|
|
|
@@ -968,6 +1028,7 @@ static VALUE
|
|
|
968
1028
|
ca_slab_run_reduce_fiber (ca_slab_iter_state_t *st)
|
|
969
1029
|
{
|
|
970
1030
|
CArray *src;
|
|
1031
|
+
volatile VALUE piece;
|
|
971
1032
|
CArray *out;
|
|
972
1033
|
ca_size_t fiber_len;
|
|
973
1034
|
char *p_in;
|
|
@@ -993,6 +1054,7 @@ ca_slab_run_reduce_fiber (ca_slab_iter_state_t *st)
|
|
|
993
1054
|
scratch = (st->out_bytes <= (ca_size_t) sizeof(buf))
|
|
994
1055
|
? buf : ALLOCV_N(char, scratch_holder, st->out_bytes);
|
|
995
1056
|
|
|
1057
|
+
piece = ca_slab_piece(st);
|
|
996
1058
|
while ( ca_iter_state_next_slab_axes(st->t1, &p_in, &m_in) ) {
|
|
997
1059
|
VALUE acc;
|
|
998
1060
|
ca_size_t i;
|
|
@@ -1010,7 +1072,7 @@ ca_slab_run_reduce_fiber (ca_slab_iter_state_t *st)
|
|
|
1010
1072
|
ca_size_t total = st->t1->slab_elements;
|
|
1011
1073
|
for ( i = 0; i < total; i++ ) {
|
|
1012
1074
|
VALUE x;
|
|
1013
|
-
x = rb_ca_fetch_index(
|
|
1075
|
+
x = rb_ca_fetch_index(piece, kidx);
|
|
1014
1076
|
acc = rb_yield_values(2, acc, x);
|
|
1015
1077
|
/* Increment kidx[] row-major. */
|
|
1016
1078
|
for ( k = slab_cs->ndim - 1; k >= 0; k-- ) {
|
|
@@ -1021,8 +1083,7 @@ ca_slab_run_reduce_fiber (ca_slab_iter_state_t *st)
|
|
|
1021
1083
|
(void) fiber_len;
|
|
1022
1084
|
}
|
|
1023
1085
|
|
|
1024
|
-
|
|
1025
|
-
memcpy(out->ptr + out_idx * st->out_bytes, scratch, st->out_bytes);
|
|
1086
|
+
ca_slab_store_reduced(st, out, out_idx, acc, scratch);
|
|
1026
1087
|
out_idx++;
|
|
1027
1088
|
}
|
|
1028
1089
|
|
|
@@ -1049,6 +1110,7 @@ static VALUE
|
|
|
1049
1110
|
ca_slab_run_each (ca_slab_iter_state_t *st)
|
|
1050
1111
|
{
|
|
1051
1112
|
CArray *src;
|
|
1113
|
+
volatile VALUE piece;
|
|
1052
1114
|
char *p_in;
|
|
1053
1115
|
boolean8_t *m_in;
|
|
1054
1116
|
CAStride *slab_cs;
|
|
@@ -1082,10 +1144,11 @@ ca_slab_run_each (ca_slab_iter_state_t *st)
|
|
|
1082
1144
|
TypedData_Get_Struct(st->carrier, CAWrap, &cawrap_data_type, carrier_cw);
|
|
1083
1145
|
}
|
|
1084
1146
|
|
|
1147
|
+
piece = ca_slab_piece(st);
|
|
1085
1148
|
while ( ca_iter_state_next_slab_axes(st->t1, &p_in, &m_in) ) {
|
|
1086
1149
|
ca_slab_advance_slab_view(st, slab_cs, carrier_cw,
|
|
1087
1150
|
src, p_in, m_in, in_alias);
|
|
1088
|
-
rb_yield(
|
|
1151
|
+
rb_yield(piece); /* return value discarded */
|
|
1089
1152
|
}
|
|
1090
1153
|
|
|
1091
1154
|
return st->self;
|
data/ext/carray_sort.c
CHANGED
|
@@ -172,31 +172,10 @@ rb_ca_s_sort_addr_kw (int argc, VALUE *argv, VALUE ropt, VALUE self)
|
|
|
172
172
|
if ( elements != NUM2SIZE(rb_ca_elements(argv[j])) ) {
|
|
173
173
|
rb_raise(rb_eArgError, "elements mismatch");
|
|
174
174
|
}
|
|
175
|
-
/* Face gate: an ORDERABLE Face sorts by its storage, so it descends to
|
|
176
|
-
it (attach / comparator / template output then run on plain storage,
|
|
177
|
-
which also avoids a face-lifted NULL-ptr index output). A fixlen
|
|
178
|
-
storage that is not ORDERABLE (CAConstString's offsets, a record's
|
|
179
|
-
bytes) has no order in its bytes; the Face's own order stands in for
|
|
180
|
-
it, as a dense rank, so ties stay ties for the next key. A Face that
|
|
181
|
-
has no order (CARecord without order_by:) raises there. Any other
|
|
182
|
-
storage raises here. */
|
|
183
175
|
TypedData_Get_Struct(argv[j], CArray, &carray_data_type, ca_j);
|
|
184
176
|
if ( ca_is_face(ca_j) ) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
CArray *sc;
|
|
188
|
-
TypedData_Get_Struct(stripped, CArray, &carray_data_type, sc);
|
|
189
|
-
if ( sc->data_type == CA_FIXLEN && ! orderable ) {
|
|
190
|
-
VALUE opts = rb_hash_new();
|
|
191
|
-
rb_hash_aset(opts, ID2SYM(rb_intern("method")), ID2SYM(rb_intern("dense")));
|
|
192
|
-
argv[j] = rb_funcallv_kw(argv[j], rb_intern("order"), 1, &opts,
|
|
193
|
-
RB_PASS_KEYWORDS);
|
|
194
|
-
continue;
|
|
195
|
-
}
|
|
196
|
-
if ( ! orderable ) {
|
|
197
|
-
ca_face_refuse_order("sort_addr", argv[j], "order");
|
|
198
|
-
}
|
|
199
|
-
argv[j] = stripped;
|
|
177
|
+
argv[j] = ca_order_key(argv[j], "sort_addr");
|
|
178
|
+
continue;
|
|
200
179
|
}
|
|
201
180
|
{
|
|
202
181
|
CArray *k;
|
|
@@ -442,14 +421,9 @@ rb_ca_axis2addr_c (VALUE self, VALUE vindices, VALUE vaxis)
|
|
|
442
421
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
443
422
|
TypedData_Get_Struct(vindices, CArray, &carray_data_type, idx_ca);
|
|
444
423
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
int axis = (
|
|
448
|
-
if ( axis < 0 || axis >= ca->ndim ) {
|
|
449
|
-
rb_raise(rb_eArgError,
|
|
450
|
-
"%s: axis %d out of range for ndim %d",
|
|
451
|
-
ca_calling_method_name(), axis_raw, (int) ca->ndim);
|
|
452
|
-
}
|
|
424
|
+
long axis_l = ca_normalize_axis_arg(NIL_P(vaxis) ? INT2FIX(0) : vaxis,
|
|
425
|
+
(int) ca->ndim, NULL);
|
|
426
|
+
int axis = (int) axis_l;
|
|
453
427
|
|
|
454
428
|
/* Shape rule: indices.ndim == self.ndim, dims match except at axis. */
|
|
455
429
|
if ( idx_ca->ndim != ca->ndim ) {
|
|
@@ -470,10 +444,11 @@ rb_ca_axis2addr_c (VALUE self, VALUE vindices, VALUE vaxis)
|
|
|
470
444
|
|
|
471
445
|
/* indices data_type: integer kind accepted; cast to CA_SIZE if needed
|
|
472
446
|
(zero-copy when already CA_SIZE via to_type identity). */
|
|
447
|
+
ca_check_index_array(vindices);
|
|
473
448
|
if ( ! ca_is_integer_type(idx_ca) ) {
|
|
474
449
|
rb_raise(rb_eArgError,
|
|
475
|
-
"%s: indices data_type must be integer kind (got %
|
|
476
|
-
ca_calling_method_name(),
|
|
450
|
+
"%s: indices data_type must be integer kind (got %s)",
|
|
451
|
+
ca_calling_method_name(), ca_type_name[idx_ca->data_type]);
|
|
477
452
|
}
|
|
478
453
|
volatile VALUE vidx_cast = vindices;
|
|
479
454
|
CArray *idx_cast = idx_ca;
|
|
@@ -535,6 +510,31 @@ rb_ca_axis2addr (int argc, VALUE *argv, VALUE self)
|
|
|
535
510
|
}
|
|
536
511
|
|
|
537
512
|
|
|
513
|
+
/* The array the order of v is read from, for a method that orders v's
|
|
514
|
+
cells (a sort, a selection, a ranking, an extremum by key). A plain
|
|
515
|
+
array is its own key. An ORDERABLE Face orders by its storage, so the
|
|
516
|
+
key is the storage. A Face that is not ORDERABLE but defines its own
|
|
517
|
+
#order (CAConstString, whose cells are offsets; CARecord, whose bytes
|
|
518
|
+
are no order) is keyed by that order, as a dense rank, so ties stay ties
|
|
519
|
+
and a masked cell stays masked. A Face that has no order (a CARecord
|
|
520
|
+
without order_by:) raises in that order; any other Face raises here. */
|
|
521
|
+
VALUE
|
|
522
|
+
ca_order_key (VALUE v, const char *name)
|
|
523
|
+
{
|
|
524
|
+
CArray *ca;
|
|
525
|
+
TypedData_Get_Struct(v, CArray, &carray_data_type, ca);
|
|
526
|
+
if ( ! ca_is_face(ca) ) {
|
|
527
|
+
return v;
|
|
528
|
+
}
|
|
529
|
+
if ( ca_face_orders_by_itself(v) ) {
|
|
530
|
+
VALUE opts = rb_hash_new();
|
|
531
|
+
rb_hash_aset(opts, ID2SYM(rb_intern("method")), ID2SYM(rb_intern("dense")));
|
|
532
|
+
return rb_funcallv_kw(v, rb_intern("order"), 1, &opts, RB_PASS_KEYWORDS);
|
|
533
|
+
}
|
|
534
|
+
ca_face_require_orderable(v, name, "order");
|
|
535
|
+
return rb_ca_strip_face_value(v);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
538
|
/* ===== sort / sort_copy (value & view surface, sibling of the
|
|
539
539
|
sort_addr / axis2addr block above). =============== */
|
|
540
540
|
|
|
@@ -717,8 +717,7 @@ rb_ca_sort_copy (int argc, VALUE *argv, VALUE self)
|
|
|
717
717
|
TypedData_Get_Struct(target, CArray, &carray_data_type, cat);
|
|
718
718
|
|
|
719
719
|
/* Normalize axis (negative -> +ndim, range check). */
|
|
720
|
-
int axis =
|
|
721
|
-
cat->ndim, NULL);
|
|
720
|
+
int axis = ca_normalize_axis_arg(vaxis_use, cat->ndim, NULL);
|
|
722
721
|
|
|
723
722
|
/* Allocate output: same shape and data_type as target
|
|
724
723
|
(bytes=0 = preserve native bytes). */
|
|
@@ -805,6 +804,7 @@ rb_ca_sort_copy (int argc, VALUE *argv, VALUE self)
|
|
|
805
804
|
ALLOCV_END(aux_holder);
|
|
806
805
|
|
|
807
806
|
RB_GC_GUARD(target);
|
|
807
|
+
rb_ca_inherit_attr(vout, self);
|
|
808
808
|
return vout;
|
|
809
809
|
}
|
|
810
810
|
|