carray 3.0.1 → 3.0.3
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 +824 -0
- data/README.md +5 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +258 -4
- data/ext/ca_axis_group.c +368 -184
- data/ext/ca_binop_dispatch.c +54 -32
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +90 -41
- data/ext/ca_compare.c +8 -2
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +27 -11
- data/ext/ca_kernel_iterator.c +960 -245
- data/ext/ca_kernel_iterator.h +352 -181
- data/ext/ca_monop_dispatch.c +4 -4
- data/ext/ca_monop_dispatch.h +4 -0
- data/ext/ca_obj_array.c +194 -42
- data/ext/ca_obj_bincmp.c +152 -121
- data/ext/ca_obj_binop.c +107 -210
- data/ext/ca_obj_bitarray.c +37 -24
- data/ext/ca_obj_bitfield.c +95 -62
- data/ext/ca_obj_block.c +5 -4
- data/ext/ca_obj_byte_swap.c +40 -40
- data/ext/ca_obj_const_string.c +180 -50
- data/ext/ca_obj_face.c +428 -62
- data/ext/ca_obj_face.h +107 -47
- data/ext/ca_obj_fake.c +21 -50
- data/ext/ca_obj_farray.c +1 -0
- data/ext/ca_obj_field.c +16 -3
- data/ext/ca_obj_fixlen_string.c +39 -26
- data/ext/ca_obj_grid.c +181 -124
- data/ext/ca_obj_meld.c +235 -55
- data/ext/ca_obj_moncmp.c +61 -61
- data/ext/ca_obj_monop.c +125 -107
- data/ext/ca_obj_object.c +551 -233
- data/ext/ca_obj_record.c +51 -16
- data/ext/ca_obj_reduce.c +5 -8
- data/ext/ca_obj_refer.c +117 -33
- data/ext/ca_obj_remap.c +57 -17
- data/ext/ca_obj_repeat.c +21 -5
- data/ext/ca_obj_roll.c +115 -11
- data/ext/ca_obj_select.c +88 -75
- data/ext/ca_obj_select_axis.c +58 -60
- data/ext/ca_obj_shift.c +22 -102
- data/ext/ca_obj_stack.c +223 -123
- data/ext/ca_obj_stride.c +267 -35
- data/ext/ca_obj_string.c +25 -22
- data/ext/ca_obj_tile.c +32 -16
- data/ext/ca_obj_time.c +23 -25
- data/ext/ca_obj_timedelta.c +21 -23
- data/ext/ca_obj_transpose.c +12 -3
- data/ext/ca_obj_triop.c +110 -117
- data/ext/ca_obj_window.c +157 -29
- data/ext/ca_op_ipower.c +25 -13
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_rng_normal.h +42 -0
- data/ext/ca_rng_xoshiro256pp.h +105 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +385 -198
- data/ext/ca_sweep_engine.h +31 -23
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +463 -0
- data/ext/carray.h +90 -28
- data/ext/carray_access.c +487 -231
- data/ext/carray_address_basis.c +731 -0
- data/ext/carray_attribute.c +45 -3
- data/ext/carray_bincount.c +32 -2
- data/ext/carray_broadcast.c +49 -17
- data/ext/carray_call_cfunc.c +667 -511
- data/ext/carray_cast.c +1556 -247
- data/ext/carray_cast_func.rb +34 -21
- data/ext/carray_conversion.c +197 -73
- data/ext/carray_copy.c +84 -38
- data/ext/carray_core.c +591 -119
- data/ext/carray_count.c +148 -96
- data/ext/carray_element.c +18 -27
- data/ext/carray_factorize.c +604 -291
- data/ext/carray_generate.c +76 -40
- data/ext/carray_histogram.c +152 -94
- data/ext/carray_hold.c +2 -1
- data/ext/carray_index_classifier.c +63 -96
- data/ext/carray_internal.h +400 -1
- data/ext/carray_lazy.c +834 -79
- data/ext/carray_loop.c +88 -66
- data/ext/carray_mask.c +705 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +263 -63
- data/ext/carray_memory_view.c +254 -248
- data/ext/carray_operator.c +1093 -363
- data/ext/carray_order.c +133 -69
- data/ext/carray_partition.c +102 -56
- data/ext/carray_random.c +582 -204
- data/ext/carray_scatter.c +308 -65
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +183 -70
- data/ext/carray_sort.c +235 -240
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +99 -21
- data/ext/carray_test.c +167 -64
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_utils.c +363 -98
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +103 -118
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1349 -851
- data/ext/ruby_carray.c +17 -2
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +39 -0
- data/lib/carray/autoload_carray.rb +24 -3
- data/lib/carray/autoload_method_extension.rb +18 -0
- data/lib/carray/axis_group.rb +245 -20
- data/lib/carray/basics.rb +95 -25
- data/lib/carray/bincount_nd.rb +6 -0
- data/lib/carray/block_iterator.rb +200 -54
- data/lib/carray/boolean_reduce.rb +21 -29
- data/lib/carray/categorical.rb +244 -59
- data/lib/carray/categorical_iterator.rb +391 -757
- data/lib/carray/complex.rb +36 -29
- data/lib/carray/conditional.rb +94 -7
- data/lib/carray/const_string.rb +177 -27
- data/lib/carray/construct.rb +40 -0
- data/lib/carray/data_type_extension.rb +3 -0
- data/lib/carray/data_type_limits.rb +91 -0
- data/lib/carray/fixlen_string.rb +1 -1
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +13 -7
- data/lib/carray/frame/csv_parser.rb +590 -76
- data/lib/carray/frame/describe.rb +79 -0
- data/lib/carray/frame/frame.rb +205 -35
- data/lib/carray/frame/group.rb +199 -40
- data/lib/carray/frame/io.rb +452 -60
- data/lib/carray/frame/join.rb +134 -46
- data/lib/carray/frame/records.rb +54 -19
- data/lib/carray/frame/reshape.rb +448 -0
- data/lib/carray/frame/sort.rb +26 -2
- data/lib/carray/frame/verbs.rb +726 -56
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +111 -2
- data/lib/carray/fusion.rb +229 -38
- data/lib/carray/inspect.rb +71 -20
- data/lib/carray/iterator.rb +157 -2
- data/lib/carray/lazy.rb +54 -67
- data/lib/carray/mask_gap_fill.rb +66 -50
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +40 -7
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bincount.rb +2 -2
- data/lib/carray/methods/bit_string.rb +14 -3
- data/lib/carray/methods/composition.rb +16 -10
- data/lib/carray/methods/discovery_along.rb +74 -0
- data/lib/carray/methods/factorize.rb +50 -0
- data/lib/carray/methods/gather_nd.rb +13 -2
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_in.rb +130 -6
- data/lib/carray/methods/join.rb +1 -1
- data/lib/carray/methods/locate_addr.rb +235 -21
- data/lib/carray/methods/mask_duplicates.rb +35 -1
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +22 -1
- data/lib/carray/methods/repeat.rb +91 -0
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +52 -3
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +86 -0
- data/lib/carray/runtime.rb +14 -11
- data/lib/carray/segment_iterator.rb +990 -0
- data/lib/carray/serialize.rb +197 -27
- data/lib/carray/slab_iterator.rb +109 -40
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string_operation_extension.rb +9 -4
- data/lib/carray/struct.rb +142 -51
- data/lib/carray/struct_builder.rb +110 -14
- data/lib/carray/table.rb +2 -2
- data/lib/carray/time.rb +535 -105
- data/lib/carray/window_iterator.rb +259 -82
- data/lib/carray.rb +4 -2
- data/yard-stubs/ca_obj_array.rb +4 -4
- data/yard-stubs/ca_obj_bitarray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +23 -12
- data/yard-stubs/ca_obj_block.rb +2 -7
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +1 -1
- data/yard-stubs/ca_obj_refer.rb +3 -3
- data/yard-stubs/ca_obj_roll.rb +0 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +11 -4
- data/yard-stubs/carray_access.rb +6 -5
- data/yard-stubs/carray_broadcast.rb +2 -2
- data/yard-stubs/carray_cast.rb +78 -43
- data/yard-stubs/carray_conversion.rb +13 -1
- data/yard-stubs/carray_copy.rb +8 -3
- data/yard-stubs/carray_core.rb +3 -83
- data/yard-stubs/carray_count.rb +16 -2
- data/yard-stubs/carray_lazy.rb +210 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +34 -10
- data/yard-stubs/carray_math.rb +1499 -4
- data/yard-stubs/carray_median_percentile.rb +26 -8
- data/yard-stubs/carray_order.rb +43 -82
- data/yard-stubs/carray_scatter.rb +10 -3
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +11 -8
- data/yard-stubs/carray_sort.rb +50 -8
- data/yard-stubs/carray_test.rb +10 -0
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -19
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_build_flags.h +0 -3
- data/ext/carray_config.h +0 -28
- data/ext/carray_kernels_bincmp.c +0 -4446
- data/ext/carray_kernels_binop.c +0 -11001
- data/ext/carray_kernels_init.c +0 -1131
- data/ext/carray_kernels_map.c +0 -3467
- data/ext/carray_kernels_moncmp.c +0 -2097
- data/ext/carray_kernels_monop.c +0 -18313
- data/ext/carray_kernels_reduce_aggregate.c +0 -25837
- data/ext/carray_kernels_reduce_boolean.c +0 -330
- data/ext/carray_kernels_reduce_cumulative.c +0 -14593
- data/ext/carray_kernels_reduce_extreme.c +0 -16948
- data/ext/carray_kernels_reduce_variance.c +0 -3910
- data/ext/carray_kernels_scan.c +0 -3693
- data/ext/carray_kernels_search.c +0 -32138
- data/ext/carray_kernels_sort.c +0 -10626
- data/ext/carray_kernels_triop.c +0 -1392
data/ext/ca_obj_record.c
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
#include "carray.h"
|
|
22
22
|
#include "ca_obj_face.h"
|
|
23
|
+
#include "carray_internal.h"
|
|
23
24
|
|
|
24
25
|
typedef struct {
|
|
25
26
|
/* === CAView prefix === */
|
|
@@ -175,18 +176,6 @@ ca_record_func_allocate (void *ap)
|
|
|
175
176
|
ca->ptr = ca->parent->ptr;
|
|
176
177
|
}
|
|
177
178
|
|
|
178
|
-
static void
|
|
179
|
-
ca_record_func_create_mask (void *ap)
|
|
180
|
-
{
|
|
181
|
-
CARecord *ca = (CARecord *) ap;
|
|
182
|
-
ca_update_mask(ca->parent);
|
|
183
|
-
if ( ! ca->parent->mask ) {
|
|
184
|
-
ca_create_mask(ca->parent);
|
|
185
|
-
}
|
|
186
|
-
ca->mask = (CArray *) ca_refer_new(ca->parent->mask,
|
|
187
|
-
CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
179
|
ca_operation_function_t ca_record_func = {
|
|
191
180
|
-1, /* CA_OBJ_RECORD — filled by ca_install_obj_type */
|
|
192
181
|
CA_VIEW_ARRAY,
|
|
@@ -197,7 +186,7 @@ ca_operation_function_t ca_record_func = {
|
|
|
197
186
|
ca_face_sync,
|
|
198
187
|
ca_face_detach,
|
|
199
188
|
ca_face_fill_data,
|
|
200
|
-
|
|
189
|
+
ca_view_func_create_mask,
|
|
201
190
|
ca_face_xfer_index,
|
|
202
191
|
ca_face_xfer_addrs,
|
|
203
192
|
NULL, /* fold_stride: identity Face is not foldable */
|
|
@@ -230,6 +219,19 @@ ca_record_build (VALUE klass, VALUE data_class, VALUE parent_val)
|
|
|
230
219
|
"CARecord requires a CA_FIXLEN parent (got data_type=%d)",
|
|
231
220
|
parent_ca->data_type);
|
|
232
221
|
}
|
|
222
|
+
/* Each record is read and written at the data_class's member offsets,
|
|
223
|
+
so the parent's cells have to be exactly that size. */
|
|
224
|
+
{
|
|
225
|
+
ca_size_t record_bytes =
|
|
226
|
+
NUM2SIZE(rb_const_get(data_class, rb_intern("DATA_SIZE")));
|
|
227
|
+
if ( parent_ca->bytes != record_bytes ) {
|
|
228
|
+
rb_raise(rb_eArgError,
|
|
229
|
+
"CARecord: %"PRIsVALUE" records are %lld bytes, the array's "
|
|
230
|
+
"elements are %lld bytes",
|
|
231
|
+
data_class, (long long) record_bytes,
|
|
232
|
+
(long long) parent_ca->bytes);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
233
235
|
ca = ca_record_new(parent_ca, data_class);
|
|
234
236
|
obj = TypedData_Wrap_Struct(klass, &carecord_data_type, ca);
|
|
235
237
|
rb_ca_set_parent(obj, parent_val);
|
|
@@ -280,7 +282,9 @@ rb_ca_record_s_new (int argc, VALUE *argv, VALUE klass)
|
|
|
280
282
|
}
|
|
281
283
|
bytes = NUM2SIZE(rb_const_get(data_class, rb_intern("DATA_SIZE")));
|
|
282
284
|
|
|
283
|
-
|
|
285
|
+
/* Zero-filled, as CArray.new is: a new record holds zeros, not the bytes
|
|
286
|
+
the allocator last handed out. */
|
|
287
|
+
parent_val = rb_carray_new_safe(CA_FIXLEN, ndim, dim, bytes, NULL);
|
|
284
288
|
return ca_record_build(klass, data_class, parent_val);
|
|
285
289
|
}
|
|
286
290
|
|
|
@@ -328,7 +332,7 @@ rb_ca_record_s_data_class_dsl (int argc, VALUE *argv, VALUE klass)
|
|
|
328
332
|
}
|
|
329
333
|
rb_scan_args(argc, argv, "1", &given);
|
|
330
334
|
if ( ! NIL_P(current) ) {
|
|
331
|
-
rb_raise(
|
|
335
|
+
rb_raise(rb_eArgError,
|
|
332
336
|
"data_class already fixed to %"PRIsVALUE
|
|
333
337
|
"; CARecord subclass data_class is immutable once set",
|
|
334
338
|
current);
|
|
@@ -352,11 +356,16 @@ rb_ca_record_initialize_copy (VALUE self, VALUE other)
|
|
|
352
356
|
{
|
|
353
357
|
CARecord *ca, *cs;
|
|
354
358
|
TypedData_Get_Struct(self, CARecord, &carecord_data_type, ca);
|
|
359
|
+
ca_check_uninitialized(ca);
|
|
355
360
|
TypedData_Get_Struct(other, CARecord, &carecord_data_type, cs);
|
|
356
361
|
if ( ca_func[CA_OBJ_RECORD].pool_init ) {
|
|
357
362
|
ca_array_pool_alloc(ca, CA_OBJ_RECORD, cs->parent->ndim);
|
|
358
363
|
}
|
|
359
364
|
ca_record_setup(ca, cs->parent, cs->data_class);
|
|
365
|
+
/* Marshal loads into an empty instance through here without copying
|
|
366
|
+
ivars, so the parent pin is set from `other`, not inherited. */
|
|
367
|
+
rb_ca_set_parent(self, rb_ca_parent(other));
|
|
368
|
+
rb_ivar_set(self, rb_intern("member"), rb_hash_new());
|
|
360
369
|
return self;
|
|
361
370
|
}
|
|
362
371
|
|
|
@@ -401,7 +410,7 @@ ca_check_data_class (VALUE rtype)
|
|
|
401
410
|
{
|
|
402
411
|
if ( ! rb_obj_is_data_class(rtype) ) {
|
|
403
412
|
VALUE inspect = rb_inspect(rtype);
|
|
404
|
-
rb_raise(
|
|
413
|
+
rb_raise(rb_eTypeError,
|
|
405
414
|
"<%s> is not a data_class, which should has the features\n" \
|
|
406
415
|
" * constant data_class::DATA_SIZE -> integer\n" \
|
|
407
416
|
" * constant data_class::MEMBERS -> array of string\n" \
|
|
@@ -429,6 +438,26 @@ ca_record_state_compatible (CArray *a, CArray *b)
|
|
|
429
438
|
return (ra->data_class == rb->data_class) ? 1 : 0;
|
|
430
439
|
}
|
|
431
440
|
|
|
441
|
+
/* Write hook: a struct element becomes its bytes, on every store path (a
|
|
442
|
+
block or index store writes to the storage, below the Face, where the
|
|
443
|
+
element itself could not be cast). A struct of another data_class is
|
|
444
|
+
refused; anything else is left to the fixlen store (a String is bytes). */
|
|
445
|
+
static VALUE
|
|
446
|
+
ca_record_element_to_storage (VALUE self, VALUE obj)
|
|
447
|
+
{
|
|
448
|
+
volatile VALUE data_class = rb_ca_data_class(self);
|
|
449
|
+
if ( rb_obj_is_kind_of(obj, data_class) ) {
|
|
450
|
+
return rb_funcall(obj, rb_intern("encode"), 0);
|
|
451
|
+
}
|
|
452
|
+
if ( RB_TYPE_P(obj, T_OBJECT) && ! RB_TYPE_P(obj, T_STRING)
|
|
453
|
+
&& RTEST(rb_obj_is_data_class(rb_obj_class(obj))) ) {
|
|
454
|
+
rb_raise(rb_eTypeError,
|
|
455
|
+
"a %"PRIsVALUE" is not an element of a record array of %"PRIsVALUE,
|
|
456
|
+
rb_obj_class(obj), data_class);
|
|
457
|
+
}
|
|
458
|
+
return obj;
|
|
459
|
+
}
|
|
460
|
+
|
|
432
461
|
/* ------------------------------------------------------------------------- */
|
|
433
462
|
|
|
434
463
|
void
|
|
@@ -454,6 +483,12 @@ Init_ca_obj_record (void)
|
|
|
454
483
|
ca_face_register_state_compatible(CA_OBJ_RECORD,
|
|
455
484
|
ca_record_state_compatible);
|
|
456
485
|
|
|
486
|
+
/* The record's bytes are its members: a MemoryView consumer reads them
|
|
487
|
+
through the T{...} struct format built from the data_class. */
|
|
488
|
+
ca_face_register_memory_view(CA_OBJ_RECORD, 1);
|
|
489
|
+
ca_face_register_element_to_storage(CA_OBJ_RECORD,
|
|
490
|
+
ca_record_element_to_storage);
|
|
491
|
+
|
|
457
492
|
rb_define_alloc_func(rb_cCARecord, rb_ca_record_s_allocate);
|
|
458
493
|
rb_define_method(rb_cCARecord, "initialize_copy",
|
|
459
494
|
rb_ca_record_initialize_copy, 1);
|
data/ext/ca_obj_reduce.c
CHANGED
|
@@ -162,6 +162,7 @@ static void
|
|
|
162
162
|
ca_reduce_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
163
163
|
ca_size_t *strides, void *data, int dir)
|
|
164
164
|
{
|
|
165
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
165
166
|
CAReduce *ca = (CAReduce *) ap;
|
|
166
167
|
int8_t ndim = ca->ndim;
|
|
167
168
|
ca_size_t native[CA_RANK_MAX], idx[CA_RANK_MAX];
|
|
@@ -224,8 +225,7 @@ ca_reduce_func_sync (void *ap)
|
|
|
224
225
|
ca_reduce_func_xfer_addrs(ca, 1, &i, p, CA_XFER_PUT);
|
|
225
226
|
p++;
|
|
226
227
|
}
|
|
227
|
-
|
|
228
|
-
ca_detach(ca->parent);
|
|
228
|
+
ca_sync_detach(ca->parent);
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
static void
|
|
@@ -264,8 +264,7 @@ ca_reduce_func_fill_data (void *ap, void *ptr)
|
|
|
264
264
|
for (i=0; i<ca->elements; i++) {
|
|
265
265
|
ca_reduce_func_xfer_addrs(ca, 1, &i, ptr, CA_XFER_PUT);
|
|
266
266
|
}
|
|
267
|
-
|
|
268
|
-
ca_detach(ca->parent);
|
|
267
|
+
ca_sync_detach(ca->parent);
|
|
269
268
|
}
|
|
270
269
|
|
|
271
270
|
static void
|
|
@@ -273,10 +272,7 @@ ca_reduce_func_create_mask (void *ap)
|
|
|
273
272
|
{
|
|
274
273
|
CAReduce *ca = (CAReduce *) ap;
|
|
275
274
|
|
|
276
|
-
|
|
277
|
-
if ( ! ca->parent->mask ) {
|
|
278
|
-
ca_create_mask(ca->parent);
|
|
279
|
-
}
|
|
275
|
+
ca_create_mask(ca->parent);
|
|
280
276
|
|
|
281
277
|
ca->mask = (CArray *) ca_reduce_new(ca->parent->mask, ca->count, ca->offset);
|
|
282
278
|
}
|
|
@@ -314,6 +310,7 @@ rb_ca_reduce_initialize_copy (VALUE self, VALUE other)
|
|
|
314
310
|
CAReduce *ca, *cs;
|
|
315
311
|
|
|
316
312
|
TypedData_Get_Struct(self, CAReduce, &careduce_data_type, ca);
|
|
313
|
+
ca_check_uninitialized(ca);
|
|
317
314
|
TypedData_Get_Struct(other, CAReduce, &careduce_data_type, cs);
|
|
318
315
|
|
|
319
316
|
ca_reduce_setup(ca, cs->parent, cs->count, cs->offset);
|
data/ext/ca_obj_refer.c
CHANGED
|
@@ -79,29 +79,38 @@ ca_refer_setup (CARefer *ca, CArray *parent,
|
|
|
79
79
|
CA_CHECK_DIM(ndim, dim);
|
|
80
80
|
CA_CHECK_BYTES(data_type, bytes);
|
|
81
81
|
|
|
82
|
+
/* An object cell is a VALUE the GC marks: reading other bytes as one
|
|
83
|
+
marks garbage, and reading one as bytes exposes an address. */
|
|
82
84
|
if (ca_is_object_type(parent) && data_type != CA_OBJECT) {
|
|
83
|
-
rb_raise(
|
|
85
|
+
rb_raise(rb_eCADataTypeError,
|
|
84
86
|
"object array can't be referred by other data type");
|
|
85
87
|
}
|
|
88
|
+
if (! ca_is_object_type(parent) && data_type == CA_OBJECT) {
|
|
89
|
+
rb_raise(rb_eCADataTypeError,
|
|
90
|
+
"non-object array can't be referred as object data type");
|
|
91
|
+
}
|
|
86
92
|
if (parent->elements && bytes > parent_bytes * parent->elements) {
|
|
87
|
-
rb_raise(
|
|
93
|
+
rb_raise(rb_eArgError, "bytes exceeds the data size of referent");
|
|
88
94
|
}
|
|
89
95
|
if (bytes < parent_bytes && parent_bytes % bytes != 0) {
|
|
90
|
-
rb_raise(
|
|
96
|
+
rb_raise(rb_eArgError,
|
|
91
97
|
"bytes of reference array must be a multiple of that of referent");
|
|
92
98
|
}
|
|
93
99
|
if (bytes > parent_bytes && bytes % parent_bytes != 0) {
|
|
94
|
-
rb_raise(
|
|
100
|
+
rb_raise(rb_eArgError,
|
|
95
101
|
"bytes of reference array must be a multiple of that of referent");
|
|
96
102
|
}
|
|
97
103
|
if (offset < 0) {
|
|
98
|
-
rb_raise(
|
|
104
|
+
rb_raise(rb_eArgError, "negative offset is not permitted for CARefer");
|
|
105
|
+
}
|
|
106
|
+
elements = ca_shape_elements(ndim, dim, bytes);
|
|
107
|
+
if (offset > parent->elements) {
|
|
108
|
+
rb_raise(rb_eArgError,
|
|
109
|
+
"data size of reference array must not exceed that of referent");
|
|
99
110
|
}
|
|
100
|
-
elements = 1;
|
|
101
|
-
for (i = 0; i < ndim; i++) elements *= dim[i];
|
|
102
111
|
if ((bytes * elements + parent_bytes * offset) >
|
|
103
112
|
(parent_bytes * parent->elements)) {
|
|
104
|
-
rb_raise(
|
|
113
|
+
rb_raise(rb_eArgError,
|
|
105
114
|
"data size of reference array must not exceed that of referent");
|
|
106
115
|
}
|
|
107
116
|
|
|
@@ -114,6 +123,12 @@ ca_refer_setup (CARefer *ca, CArray *parent,
|
|
|
114
123
|
/* base_offset is in bytes: `offset` is in parent-element units. */
|
|
115
124
|
base_offset = offset * parent_bytes;
|
|
116
125
|
|
|
126
|
+
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
127
|
+
run them before it allocates. */
|
|
128
|
+
if ( ca == NULL ) {
|
|
129
|
+
return 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
117
132
|
/* CAREFUL: initialise mask0 before ca_stride_setup — the setup
|
|
118
133
|
may dispatch to ca_refer_func_create_mask, which writes to
|
|
119
134
|
mask0. Leaving it uninitialised risks freeing a garbage
|
|
@@ -134,7 +149,9 @@ ca_refer_new (CArray *parent,
|
|
|
134
149
|
int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes,
|
|
135
150
|
ca_size_t offset)
|
|
136
151
|
{
|
|
137
|
-
CARefer *ca
|
|
152
|
+
CARefer *ca;
|
|
153
|
+
ca_refer_setup(NULL, parent, data_type, ndim, dim, bytes, offset);
|
|
154
|
+
ca = (CARefer *) ca_array_alloc(CA_OBJ_REFER, ndim);
|
|
138
155
|
ca_refer_setup(ca, parent, data_type, ndim, dim, bytes, offset);
|
|
139
156
|
return ca;
|
|
140
157
|
}
|
|
@@ -172,10 +189,7 @@ ca_refer_func_create_mask (void *ap)
|
|
|
172
189
|
ca_size_t parent_bytes = ca->parent->bytes;
|
|
173
190
|
ca_size_t parent_offset;
|
|
174
191
|
|
|
175
|
-
|
|
176
|
-
if (! ca->parent->mask) {
|
|
177
|
-
ca_create_mask(ca->parent);
|
|
178
|
-
}
|
|
192
|
+
ca_create_mask(ca->parent);
|
|
179
193
|
|
|
180
194
|
parent_offset = ca->base_offset / parent_bytes;
|
|
181
195
|
|
|
@@ -200,9 +214,12 @@ ca_refer_func_create_mask (void *ap)
|
|
|
200
214
|
ca->mask0 =
|
|
201
215
|
(CArray *) ca_repeat_new(ca->parent->mask, ca->parent->ndim + 1, count);
|
|
202
216
|
ca_unset_flag(ca->mask0, CA_FLAG_READ_ONLY);
|
|
217
|
+
/* mask0 has ratio cells per parent element, so the offset is counted
|
|
218
|
+
in those. */
|
|
203
219
|
ca->mask =
|
|
204
220
|
(CArray *) ca_refer_new(ca->mask0,
|
|
205
|
-
CA_BOOLEAN, ca->ndim, ca->dim, 0,
|
|
221
|
+
CA_BOOLEAN, ca->ndim, ca->dim, 0,
|
|
222
|
+
parent_offset * ratio);
|
|
206
223
|
}
|
|
207
224
|
else {
|
|
208
225
|
/* Spanned reinterpret: ratio = bytes / parent_bytes parent
|
|
@@ -232,6 +249,7 @@ rb_ca_refer_initialize_copy (VALUE self, VALUE other)
|
|
|
232
249
|
{
|
|
233
250
|
CARefer *ca, *cs;
|
|
234
251
|
TypedData_Get_Struct(self, CARefer, &carefer_data_type, ca);
|
|
252
|
+
ca_check_uninitialized(ca);
|
|
235
253
|
TypedData_Get_Struct(other, CARefer, &carefer_data_type, cs);
|
|
236
254
|
if ( ca_func[CA_OBJ_REFER].pool_init ) {
|
|
237
255
|
ca_array_pool_alloc(ca, CA_OBJ_REFER, cs->ndim);
|
|
@@ -275,6 +293,34 @@ rb_ca_refer_initialize_copy (VALUE self, VALUE other)
|
|
|
275
293
|
* 2. Match ranges of parent axes to new axes so element products
|
|
276
294
|
* agree. Inside each matched range, root_strides must be
|
|
277
295
|
* inter-axis contiguous. */
|
|
296
|
+
/* Three properties of an array are answered by walking its C parent chain:
|
|
297
|
+
ca_is_value_array, ca_is_readonly and ca_is_mask_array. An array that is
|
|
298
|
+
built somewhere other than as a child of `src` -- a reshape that folds
|
|
299
|
+
onto the root, the copy that dup / clone makes -- does not have `src` on
|
|
300
|
+
that chain, so carry each property across from `src`. Without this a
|
|
301
|
+
reshape or a dup of x.value reads the mask of x again (and takes UNDEF
|
|
302
|
+
into it), and a reshape of a broadcast view becomes writable. */
|
|
303
|
+
void
|
|
304
|
+
ca_keep_chain_flags (CArray *view, CArray *src)
|
|
305
|
+
{
|
|
306
|
+
if ( ca_is_value_array(src) ) {
|
|
307
|
+
if ( view->mask ) {
|
|
308
|
+
ca_free(view->mask);
|
|
309
|
+
view->mask = NULL;
|
|
310
|
+
}
|
|
311
|
+
ca_set_flag(view, CA_FLAG_VALUE_ARRAY);
|
|
312
|
+
}
|
|
313
|
+
if ( ca_is_readonly(src) ) {
|
|
314
|
+
ca_set_flag(view, CA_FLAG_READ_ONLY);
|
|
315
|
+
if ( view->mask ) {
|
|
316
|
+
ca_set_flag(view->mask, CA_FLAG_READ_ONLY);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if ( ca_is_mask_array(src) ) {
|
|
320
|
+
ca_set_flag(view, CA_FLAG_MASK_ARRAY);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
278
324
|
static int
|
|
279
325
|
ca_reshape_try_strides (CArray *parent,
|
|
280
326
|
const ca_size_t *new_dim,
|
|
@@ -401,8 +447,11 @@ ca_reshape_try_strides (CArray *parent,
|
|
|
401
447
|
return 1;
|
|
402
448
|
}
|
|
403
449
|
|
|
450
|
+
/* `refer` with its options given apart from argv, for callers in C that
|
|
451
|
+
build the options themselves (a Hash at the end of argv is read as
|
|
452
|
+
options only when the Ruby caller passed keywords). */
|
|
404
453
|
static VALUE
|
|
405
|
-
|
|
454
|
+
rb_ca_refer_kw (int argc, VALUE *argv, VALUE ropt, VALUE self)
|
|
406
455
|
{
|
|
407
456
|
volatile VALUE obj = Qnil;
|
|
408
457
|
CArray *ca;
|
|
@@ -415,7 +464,7 @@ rb_ca_refer (int argc, VALUE *argv, VALUE self)
|
|
|
415
464
|
|
|
416
465
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
417
466
|
|
|
418
|
-
if (argc == 0) {
|
|
467
|
+
if (argc == 0 && NIL_P(ropt)) {
|
|
419
468
|
data_type = ca->data_type;
|
|
420
469
|
bytes = ca->bytes;
|
|
421
470
|
ndim = ca->ndim;
|
|
@@ -425,39 +474,57 @@ rb_ca_refer (int argc, VALUE *argv, VALUE self)
|
|
|
425
474
|
rb_ca_set_parent(obj, self);
|
|
426
475
|
}
|
|
427
476
|
else {
|
|
428
|
-
volatile VALUE rtype, rdim,
|
|
429
|
-
ropt = rb_pop_options(&argc, &argv);
|
|
477
|
+
volatile VALUE rtype, rdim, rbytes = Qnil, roffset = Qnil;
|
|
430
478
|
rb_scan_args(argc, argv, "11", (VALUE *) &rtype, (VALUE *) &rdim);
|
|
431
479
|
rb_scan_options(ropt, "bytes,offset", &rbytes, &roffset);
|
|
432
480
|
if (NIL_P(rbytes)) rbytes = rb_ca_bytes(self);
|
|
433
481
|
rb_ca_guess_type_and_bytes(rtype, rbytes, &data_type, &bytes);
|
|
434
482
|
if (NIL_P(rdim)) {
|
|
435
483
|
if (ca->bytes != bytes) {
|
|
436
|
-
rb_raise(
|
|
484
|
+
rb_raise(rb_eArgError,
|
|
437
485
|
"specify dimension shape for different byte size");
|
|
438
486
|
} else {
|
|
439
487
|
rdim = rb_ca_dim(self);
|
|
440
488
|
}
|
|
441
489
|
}
|
|
442
490
|
Check_Type(rdim, T_ARRAY);
|
|
491
|
+
CA_CHECK_RANK(RARRAY_LEN(rdim)); /* before dim[] is filled */
|
|
443
492
|
ndim = RARRAY_LEN(rdim);
|
|
444
493
|
for (i = 0; i < ndim; i++) dim[i] = NUM2SIZE(rb_ary_entry(rdim, i));
|
|
445
494
|
if (! NIL_P(roffset)) offset = NUM2SIZE(roffset);
|
|
495
|
+
/* When rtype is a data_class the result is a record array. It is
|
|
496
|
+
built on the storage, never on a Face, so that a Face stays on top
|
|
497
|
+
of the chain: re-reading a record array as its own data_class lifts
|
|
498
|
+
it (keeping its class), any other data_class wraps a new CARecord. */
|
|
499
|
+
if ( rb_obj_is_data_class(rtype) ) {
|
|
500
|
+
volatile VALUE base = rb_ca_strip_face_value(self);
|
|
501
|
+
CArray *base_ca;
|
|
502
|
+
TypedData_Get_Struct(base, CArray, &carray_data_type, base_ca);
|
|
503
|
+
cr = ca_refer_new(base_ca, data_type, ndim, dim, bytes, offset);
|
|
504
|
+
obj = ca_wrap_struct(cr);
|
|
505
|
+
rb_ca_set_parent(obj, base);
|
|
506
|
+
if ( ca->obj_type == CA_OBJ_RECORD
|
|
507
|
+
&& rb_ca_data_class(self) == rtype ) {
|
|
508
|
+
return ca_face_lift(obj, self);
|
|
509
|
+
}
|
|
510
|
+
return rb_funcall(rb_const_get(rb_cObject, rb_intern("CARecord")),
|
|
511
|
+
rb_intern("wrap"), 2, obj, rtype);
|
|
512
|
+
}
|
|
446
513
|
cr = ca_refer_new((CArray *) ca, data_type, ndim, dim, bytes, offset);
|
|
447
514
|
obj = ca_wrap_struct(cr);
|
|
448
515
|
rb_ca_set_parent(obj, self);
|
|
449
|
-
/* When rtype is a data_class, wrap the result in CARecord so
|
|
450
|
-
the data_class is carried even if self is not itself a Face. */
|
|
451
|
-
if ( rb_obj_is_data_class(rtype) ) {
|
|
452
|
-
obj = rb_funcall(rb_const_get(rb_cObject, rb_intern("CARecord")),
|
|
453
|
-
rb_intern("wrap"), 2, obj, rtype);
|
|
454
|
-
return obj;
|
|
455
|
-
}
|
|
456
516
|
}
|
|
457
517
|
CA_WRAPPER_LIFT(obj, self, ca);
|
|
458
518
|
return obj;
|
|
459
519
|
}
|
|
460
520
|
|
|
521
|
+
static VALUE
|
|
522
|
+
rb_ca_refer (int argc, VALUE *argv, VALUE self)
|
|
523
|
+
{
|
|
524
|
+
volatile VALUE ropt = rb_pop_options(&argc, &argv);
|
|
525
|
+
return rb_ca_refer_kw(argc, argv, ropt, self);
|
|
526
|
+
}
|
|
527
|
+
|
|
461
528
|
VALUE
|
|
462
529
|
rb_ca_refer_new (VALUE self,
|
|
463
530
|
int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes,
|
|
@@ -483,7 +550,7 @@ rb_ca_refer_new (VALUE self,
|
|
|
483
550
|
rb_ary_store(list, 2, ropt);
|
|
484
551
|
|
|
485
552
|
{
|
|
486
|
-
volatile VALUE obj =
|
|
553
|
+
volatile VALUE obj = rb_ca_refer_kw(2, (VALUE *) RARRAY_CONST_PTR(list), ropt, self);
|
|
487
554
|
CArray *co;
|
|
488
555
|
|
|
489
556
|
/* CAREFUL: this is the internal builder -- some fifteen call sites want
|
|
@@ -535,6 +602,7 @@ rb_ca_reshape (int argc, VALUE *argv, VALUE self)
|
|
|
535
602
|
CARefer *cr;
|
|
536
603
|
ca_size_t new_dim[CA_RANK_MAX];
|
|
537
604
|
ca_size_t prod = 1;
|
|
605
|
+
int overflow = 0, zero = 0;
|
|
538
606
|
int placeholder_idx = -1; /* axis with `-1` or `:~` infer placeholder */
|
|
539
607
|
int i;
|
|
540
608
|
volatile VALUE obj;
|
|
@@ -553,7 +621,7 @@ rb_ca_reshape (int argc, VALUE *argv, VALUE self)
|
|
|
553
621
|
if ( (FIXNUM_P(argv[i]) && FIX2LONG(argv[i]) == -1)
|
|
554
622
|
|| argv[i] == sym_tilde ) {
|
|
555
623
|
if (placeholder_idx >= 0) {
|
|
556
|
-
rb_raise(
|
|
624
|
+
rb_raise(rb_eArgError,
|
|
557
625
|
"reshape: only one auto-infer placeholder (-1 / :~) allowed");
|
|
558
626
|
}
|
|
559
627
|
placeholder_idx = i;
|
|
@@ -578,7 +646,7 @@ rb_ca_reshape (int argc, VALUE *argv, VALUE self)
|
|
|
578
646
|
src = (i < ca->ndim) ? i : ca->ndim - (argc - i);
|
|
579
647
|
}
|
|
580
648
|
if (src < 0 || src >= ca->ndim) {
|
|
581
|
-
rb_raise(
|
|
649
|
+
rb_raise(rb_eArgError,
|
|
582
650
|
"reshape: nil at axis %d has no source dim", i);
|
|
583
651
|
}
|
|
584
652
|
new_dim[i] = ca->dim[src];
|
|
@@ -586,13 +654,27 @@ rb_ca_reshape (int argc, VALUE *argv, VALUE self)
|
|
|
586
654
|
else {
|
|
587
655
|
new_dim[i] = NUM2SIZE(argv[i]);
|
|
588
656
|
}
|
|
589
|
-
|
|
657
|
+
/* A product too large to count cannot equal the element count; an
|
|
658
|
+
extent of zero anywhere makes it zero whatever it overflowed to. */
|
|
659
|
+
if ( __builtin_mul_overflow(prod, new_dim[i], &prod) ) {
|
|
660
|
+
overflow = 1;
|
|
661
|
+
}
|
|
662
|
+
if ( new_dim[i] == 0 ) {
|
|
663
|
+
zero = 1;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
if ( zero ) {
|
|
667
|
+
prod = 0;
|
|
668
|
+
}
|
|
669
|
+
else if ( overflow ) {
|
|
670
|
+
rb_raise(rb_eArgError,
|
|
671
|
+
"reshape: the shape has more elements than an array can hold");
|
|
590
672
|
}
|
|
591
673
|
|
|
592
674
|
/* Resolve placeholder dim from the leftover total. */
|
|
593
675
|
if (placeholder_idx >= 0) {
|
|
594
676
|
if (prod == 0 || ca->elements % prod != 0) {
|
|
595
|
-
rb_raise(
|
|
677
|
+
rb_raise(rb_eArgError,
|
|
596
678
|
"reshape: cannot infer dim for `-1` placeholder");
|
|
597
679
|
}
|
|
598
680
|
new_dim[placeholder_idx] = ca->elements / prod;
|
|
@@ -604,7 +686,7 @@ rb_ca_reshape (int argc, VALUE *argv, VALUE self)
|
|
|
604
686
|
a subset), and on non-contiguous parents the compose-fold
|
|
605
687
|
path corrupts data outright — hence the raise. */
|
|
606
688
|
if (prod != ca->elements) {
|
|
607
|
-
rb_raise(
|
|
689
|
+
rb_raise(rb_eArgError,
|
|
608
690
|
"reshape: cannot reshape array of %lld elements into a shape "
|
|
609
691
|
"of %lld elements (use -1 / :~ to infer a dim)",
|
|
610
692
|
(long long) ca->elements, (long long) prod);
|
|
@@ -627,6 +709,7 @@ rb_ca_reshape (int argc, VALUE *argv, VALUE self)
|
|
|
627
709
|
ca->data_type, ca->bytes,
|
|
628
710
|
(int8_t) argc, new_dim,
|
|
629
711
|
out_strides, out_base);
|
|
712
|
+
ca_keep_chain_flags((CArray *) cs, ca);
|
|
630
713
|
obj = ca_wrap_struct(cs);
|
|
631
714
|
rb_ca_set_parent(obj, self);
|
|
632
715
|
CA_WRAPPER_LIFT(obj, self, ca);
|
|
@@ -664,6 +747,7 @@ rb_ca_flatten (VALUE self)
|
|
|
664
747
|
CAStride *cs = ca_stride_new(CA_OBJ_STRIDE, out_root,
|
|
665
748
|
ca->data_type, ca->bytes,
|
|
666
749
|
1, dim, out_strides, out_base);
|
|
750
|
+
ca_keep_chain_flags((CArray *) cs, ca);
|
|
667
751
|
obj = ca_wrap_struct(cs);
|
|
668
752
|
rb_ca_set_parent(obj, self);
|
|
669
753
|
CA_WRAPPER_LIFT(obj, self, ca);
|
|
@@ -725,7 +809,7 @@ rb_ca_insert_axis (int argc, VALUE *argv, VALUE self)
|
|
|
725
809
|
gap_count[i] = 0;
|
|
726
810
|
}
|
|
727
811
|
for (i = 0; i < argc; i++) {
|
|
728
|
-
int raw =
|
|
812
|
+
int raw = (int) ca_axis_integer(argv[i], "insert_axis");
|
|
729
813
|
int g = (raw < 0) ? raw + ngap : raw;
|
|
730
814
|
if (g < 0 || g >= ngap) {
|
|
731
815
|
rb_raise(rb_eArgError,
|
data/ext/ca_obj_remap.c
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
Constraints:
|
|
8
8
|
- ref.dim == idx.dim (same shape, same ndim, per-axis dim match)
|
|
9
9
|
- idx.data_type == CA_SIZE (caller responsible)
|
|
10
|
-
- No public constructor — there is no `CArray#remap(idx)`
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
- No public constructor — there is no `CArray#remap(idx)` surface; a
|
|
11
|
+
view is built by internal helpers and the `ca[idx]` same-shape
|
|
12
|
+
indexer fast path. `dup` / `clone` copy an existing one.
|
|
13
13
|
- The CARemap Ruby class IS rb_define_class'd: visibility lets users
|
|
14
14
|
see "this view came from a same-shape gather" when they inspect
|
|
15
15
|
`.class`. CA_OBJ_REMAP integer remains unexported as a Ruby
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
---------------------------------------------------------------------------- */
|
|
19
19
|
|
|
20
20
|
#include "carray.h"
|
|
21
|
+
#include "carray_internal.h"
|
|
21
22
|
|
|
22
23
|
typedef struct {
|
|
23
24
|
int16_t obj_type;
|
|
@@ -216,9 +217,7 @@ ca_remap_func_allocate (void *ap)
|
|
|
216
217
|
static void
|
|
217
218
|
ca_remap_func_attach (void *ap)
|
|
218
219
|
{
|
|
219
|
-
|
|
220
|
-
ca->ptr = xmalloc(ca_length(ca));
|
|
221
|
-
ca_remap_func_xfer_all(ca, ca->ptr, CA_XFER_GET);
|
|
220
|
+
ca_axis_view_attach_owned(ap);
|
|
222
221
|
}
|
|
223
222
|
|
|
224
223
|
static void
|
|
@@ -265,10 +264,7 @@ static void
|
|
|
265
264
|
ca_remap_func_create_mask (void *ap)
|
|
266
265
|
{
|
|
267
266
|
CARemap *ca = (CARemap *) ap;
|
|
268
|
-
|
|
269
|
-
if ( ! ca->parent->mask ) {
|
|
270
|
-
ca_create_mask(ca->parent);
|
|
271
|
-
}
|
|
267
|
+
ca_create_mask(ca->parent);
|
|
272
268
|
/* Mask is a CARemap over (parent->mask, idx) — same shape, boolean. */
|
|
273
269
|
ca->mask = (CArray *) ca_remap_new(ca->parent->mask, ca->idx);
|
|
274
270
|
}
|
|
@@ -282,7 +278,7 @@ ca_remap_func_create_mask (void *ap)
|
|
|
282
278
|
2. ca_xfer_addrs(ca->idx, n, addrs, paddrs, GET) — one batched
|
|
283
279
|
read of the parent flat addresses through ca->idx's own
|
|
284
280
|
xfer_addrs dispatcher (entity, view, view chain — all
|
|
285
|
-
transparent).
|
|
281
|
+
transparent), each address then checked against the parent.
|
|
286
282
|
3. ca_xfer_addrs(ca->parent, n, paddrs, data, dir) — one batched
|
|
287
283
|
gather/scatter of the user payload against parent.
|
|
288
284
|
|
|
@@ -295,13 +291,20 @@ ca_remap_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
295
291
|
{
|
|
296
292
|
CARemap *ca = (CARemap *) ap;
|
|
297
293
|
ca_size_t *paddrs;
|
|
294
|
+
ca_size_t i;
|
|
298
295
|
volatile VALUE holder;
|
|
299
296
|
|
|
300
297
|
if ( n == 0 ) return;
|
|
301
298
|
|
|
302
299
|
paddrs = ALLOCV_N(ca_size_t, holder, n);
|
|
303
|
-
ca_xfer_addrs(ca->idx,
|
|
304
|
-
|
|
300
|
+
ca_xfer_addrs(ca->idx, n, addrs, paddrs, CA_XFER_GET);
|
|
301
|
+
/* idx is read live, so its values are checked here, not at
|
|
302
|
+
construction: negative counts from the end, out of range raises
|
|
303
|
+
before the parent is touched. */
|
|
304
|
+
for ( i = 0; i < n; i++ ) {
|
|
305
|
+
CA_CHECK_INDEX(paddrs[i], ca->parent->elements);
|
|
306
|
+
}
|
|
307
|
+
ca_xfer_addrs(ca->parent, n, paddrs, data, dir);
|
|
305
308
|
ALLOCV_END(holder);
|
|
306
309
|
}
|
|
307
310
|
|
|
@@ -329,6 +332,7 @@ static void
|
|
|
329
332
|
ca_remap_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
330
333
|
ca_size_t *strides, void *data, int dir)
|
|
331
334
|
{
|
|
335
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
332
336
|
CARemap *ca = (CARemap *) ap;
|
|
333
337
|
int8_t ndim = ca->ndim;
|
|
334
338
|
ca_size_t native[CA_RANK_MAX], idx[CA_RANK_MAX];
|
|
@@ -443,18 +447,54 @@ rb_ca_remap_mapper (VALUE self)
|
|
|
443
447
|
}
|
|
444
448
|
|
|
445
449
|
|
|
450
|
+
/* `dup` / `clone`. CARemap has no allocator (Ruby cannot build one), so
|
|
451
|
+
Object#dup cannot copy it; these build the copy the way the indexer
|
|
452
|
+
does: a new view over the same parent and the same index array. */
|
|
453
|
+
static VALUE
|
|
454
|
+
rb_ca_remap_dup (VALUE self)
|
|
455
|
+
{
|
|
456
|
+
return rb_ca_remap_new(rb_ca_parent(self),
|
|
457
|
+
rb_ivar_get(self, rb_intern("remap_idx")));
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
static VALUE
|
|
461
|
+
rb_ca_remap_clone (int argc, VALUE *argv, VALUE self)
|
|
462
|
+
{
|
|
463
|
+
VALUE opts = Qnil, vfreeze = Qnil;
|
|
464
|
+
volatile VALUE obj;
|
|
465
|
+
rb_scan_args(argc, argv, "0:", &opts);
|
|
466
|
+
if ( ! NIL_P(opts) ) {
|
|
467
|
+
/* rb_get_kwargs refuses any key but freeze:, as Kernel#clone does. */
|
|
468
|
+
ID kw[1];
|
|
469
|
+
VALUE val[1];
|
|
470
|
+
kw[0] = rb_intern("freeze");
|
|
471
|
+
rb_get_kwargs(opts, kw, 0, 1, val);
|
|
472
|
+
if ( val[0] != Qundef ) {
|
|
473
|
+
vfreeze = val[0];
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
obj = rb_ca_remap_dup(self);
|
|
477
|
+
if ( RTEST(vfreeze) || ( NIL_P(vfreeze) && OBJ_FROZEN(self) ) ) {
|
|
478
|
+
rb_obj_freeze(obj);
|
|
479
|
+
}
|
|
480
|
+
return obj;
|
|
481
|
+
}
|
|
482
|
+
|
|
446
483
|
void
|
|
447
484
|
Init_ca_obj_remap (void)
|
|
448
485
|
{
|
|
449
486
|
/* CARemap is a proper Ruby class so users can see "this view is a
|
|
450
|
-
per-element gather" on .class.
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
tag, not
|
|
487
|
+
per-element gather" on .class. A view is built from C only (the
|
|
488
|
+
indexer and sort / partition): there is no allocator, and `dup` /
|
|
489
|
+
`clone` are defined here instead of going through one. CA_OBJ_REMAP
|
|
490
|
+
integer remains unexported (it's an internal type tag, not
|
|
491
|
+
user-meaningful). */
|
|
454
492
|
rb_cCARemap = rb_define_class("CARemap", rb_cCAView);
|
|
455
493
|
rb_cCARemapMask = rb_define_class("CARemapMask", rb_cCARemap);
|
|
456
494
|
rb_undef_alloc_func(rb_cCARemap);
|
|
457
495
|
rb_undef_alloc_func(rb_cCARemapMask);
|
|
496
|
+
rb_define_method(rb_cCARemap, "dup", rb_ca_remap_dup, 0);
|
|
497
|
+
rb_define_method(rb_cCARemap, "clone", rb_ca_remap_clone, -1);
|
|
458
498
|
|
|
459
499
|
ca_remap_func.struct_size = sizeof(CARemap);
|
|
460
500
|
ca_remap_func.pool_bytes = ca_remap_pool_bytes;
|