carray 3.0.0 → 3.0.1
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/.yardopts +2 -1
- data/CHANGELOG.md +325 -3
- data/{NEWS.md → CHANGELOG.v1.md} +1 -1
- data/README.md +32 -32
- data/carray.gemspec +12 -8
- data/ext/ca_axis_group.c +55 -19
- data/ext/ca_binop_dispatch.c +5 -6
- data/ext/ca_binop_dispatch.h +0 -7
- data/ext/ca_categorical_iterator.c +13 -13
- data/ext/ca_for_each_element.h +6 -8
- data/ext/ca_group_iter.c +1 -1
- data/ext/ca_kernel_iterator.c +69 -23
- data/ext/ca_kernel_iterator.h +3 -10
- data/ext/ca_obj_bincmp.c +57 -27
- data/ext/ca_obj_binop.c +86 -30
- data/ext/ca_obj_const_string.c +3 -1
- data/ext/ca_obj_face.c +80 -0
- data/ext/ca_obj_face.h +33 -1
- data/ext/ca_obj_fake.c +11 -0
- data/ext/ca_obj_fixlen_string.c +3 -1
- data/ext/ca_obj_grid.c +11 -3
- data/ext/ca_obj_meld.c +13 -8
- data/ext/ca_obj_moncmp.c +33 -14
- data/ext/ca_obj_monop.c +19 -7
- data/ext/ca_obj_object.c +99 -4
- data/ext/ca_obj_record.c +3 -1
- data/ext/ca_obj_refer.c +30 -6
- data/ext/ca_obj_roll.c +13 -5
- data/ext/ca_obj_select_axis.c +16 -6
- data/ext/ca_obj_shift.c +3 -3
- data/ext/ca_obj_stride.c +106 -23
- data/ext/ca_obj_string.c +3 -1
- data/ext/ca_obj_tile.c +13 -5
- data/ext/ca_obj_time.c +3 -1
- data/ext/ca_obj_timedelta.c +3 -1
- data/ext/ca_obj_transpose.c +1 -1
- data/ext/ca_obj_triop.c +62 -23
- data/ext/ca_obj_window.c +86 -17
- data/ext/ca_op_cmplx64.h +123 -0
- data/ext/ca_op_ipower.c +0 -3
- data/ext/ca_sort_kernels.h +5 -5
- data/ext/ca_sweep_engine.c +78 -35
- data/ext/ca_sweep_engine.h +13 -4
- data/ext/ca_transform_common.c +7 -0
- data/ext/carray.h +127 -130
- data/ext/carray_access.c +56 -34
- data/ext/carray_bincount.c +8 -8
- data/ext/carray_broadcast.c +99 -6
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +1491 -0
- data/ext/carray_call_cfunc.h +153 -0
- data/ext/carray_cast.c +69 -31
- data/ext/carray_conversion.c +22 -22
- data/ext/carray_copy.c +12 -2
- data/ext/carray_core.c +57 -10
- data/ext/carray_count.c +1 -1
- data/ext/carray_element.c +7 -7
- data/ext/carray_factorize.c +28 -28
- data/ext/carray_hold.c +1 -1
- data/ext/carray_index_classifier.c +7 -21
- data/ext/carray_internal.h +19 -3
- data/ext/carray_kernels_bincmp.c +1 -0
- data/ext/carray_kernels_binop.c +320 -298
- data/ext/carray_kernels_init.c +1095 -0
- data/ext/carray_kernels_map.c +1 -0
- data/ext/carray_kernels_moncmp.c +1 -0
- data/ext/carray_kernels_monop.c +412 -411
- data/ext/carray_kernels_reduce_aggregate.c +88 -87
- data/ext/carray_kernels_reduce_boolean.c +1 -0
- data/ext/carray_kernels_reduce_cumulative.c +54 -53
- data/ext/carray_kernels_reduce_extreme.c +51 -50
- data/ext/carray_kernels_reduce_variance.c +1 -0
- data/ext/carray_kernels_scan.c +1 -0
- data/ext/carray_kernels_search.c +93 -92
- data/ext/carray_kernels_sort.c +1 -0
- data/ext/carray_kernels_triop.c +1 -0
- data/ext/carray_lazy.c +175 -5
- data/ext/carray_mask.c +6 -5
- data/ext/carray_median_percentile.c +1 -1
- data/ext/carray_memory_view.c +46 -21
- data/ext/carray_operator.c +46 -49
- data/ext/carray_partition.c +4 -4
- data/ext/carray_random.c +7 -7
- data/ext/carray_scatter.c +1 -1
- data/ext/carray_sort.c +3 -3
- data/ext/carray_sort_kernel.c +10 -10
- data/ext/carray_test.c +1 -1
- data/ext/extconf.rb +18 -0
- data/ext/mk_call_cfunc.rb +243 -52
- data/ext/mkkernel.rb +354 -100
- data/ext/ruby_carray.c +18 -16
- data/ext/version.h +4 -4
- data/lib/carray/autoload_carray.rb +19 -0
- data/lib/carray/autoload_method_extension.rb +2 -1
- data/lib/carray/axis_group.rb +7 -7
- data/lib/carray/basics.rb +59 -59
- data/lib/carray/bincount_nd.rb +12 -12
- data/lib/carray/block_iterator.rb +24 -14
- data/lib/carray/categorical.rb +4 -4
- data/lib/carray/categorical_iterator.rb +98 -76
- data/lib/carray/conditional.rb +14 -14
- data/lib/carray/construct.rb +21 -0
- data/lib/carray/core_extensions.rb +62 -5
- data/lib/carray/data_type_extension.rb +18 -1
- data/lib/carray/frame/concat.rb +3 -3
- data/lib/carray/frame/convert.rb +1 -1
- data/lib/carray/frame/frame.rb +4 -11
- data/lib/carray/frame/io.rb +159 -2
- data/lib/carray/frame/sort.rb +1 -1
- data/lib/carray/frame/verbs.rb +18 -1
- data/lib/carray/fuse_source.rb +123 -0
- data/lib/carray/fusion.rb +218 -0
- data/lib/carray/histogram.rb +16 -16
- data/lib/carray/inspect.rb +1 -7
- data/lib/carray/iterator.rb +4 -3
- data/lib/carray/lazy.rb +125 -73
- data/lib/carray/meld_reduce.rb +2 -2
- data/lib/carray/methods/align_addr.rb +1 -1
- data/lib/carray/methods/composition.rb +1 -1
- data/lib/carray/methods/is_in.rb +12 -12
- data/lib/carray/methods/locate_addr.rb +6 -1
- data/lib/carray/methods/mask_duplicates.rb +1 -1
- data/lib/carray/methods/meshgrid.rb +4 -5
- data/lib/carray/methods/mode.rb +2 -2
- data/lib/carray/methods/nunique.rb +1 -1
- data/lib/carray/methods/snap.rb +7 -2
- data/lib/carray/methods/unique.rb +3 -3
- data/lib/carray/methods/value_counts.rb +2 -2
- data/lib/carray/runtime.rb +0 -19
- data/lib/carray/slab_iterator.rb +20 -7
- data/lib/carray/string_operation_extension.rb +5 -5
- data/lib/carray/time.rb +890 -491
- data/lib/carray/window_iterator.rb +285 -13
- data/lib/carray.rb +5 -5
- data/yard-stubs/ca_obj_array.rb +385 -0
- data/yard-stubs/ca_obj_bitarray.rb +38 -0
- data/yard-stubs/ca_obj_bitfield.rb +43 -0
- data/yard-stubs/ca_obj_block.rb +73 -0
- data/yard-stubs/ca_obj_byte_swap.rb +56 -0
- data/yard-stubs/ca_obj_fake.rb +31 -0
- data/yard-stubs/ca_obj_farray.rb +32 -0
- data/yard-stubs/ca_obj_field.rb +45 -0
- data/yard-stubs/ca_obj_grid.rb +35 -0
- data/yard-stubs/ca_obj_refer.rb +72 -0
- data/yard-stubs/ca_obj_roll.rb +45 -0
- data/yard-stubs/ca_obj_shift.rb +43 -0
- data/yard-stubs/ca_obj_stride.rb +181 -0
- data/yard-stubs/ca_obj_tile.rb +29 -0
- data/yard-stubs/ca_obj_transpose.rb +40 -0
- data/yard-stubs/ca_obj_window.rb +49 -0
- data/yard-stubs/carray_access.rb +131 -0
- data/yard-stubs/carray_attribute.rb +246 -0
- data/yard-stubs/carray_broadcast.rb +37 -0
- data/yard-stubs/carray_cast.rb +489 -0
- data/yard-stubs/carray_class.rb +65 -0
- data/yard-stubs/carray_conversion.rb +76 -0
- data/yard-stubs/carray_copy.rb +79 -0
- data/yard-stubs/carray_core.rb +114 -0
- data/yard-stubs/carray_count.rb +79 -0
- data/yard-stubs/carray_element.rb +108 -0
- data/yard-stubs/carray_generate.rb +66 -0
- data/yard-stubs/carray_lazy.rb +23 -0
- data/yard-stubs/carray_loop.rb +140 -0
- data/yard-stubs/carray_mask.rb +259 -0
- data/yard-stubs/carray_math.rb +132 -0
- data/yard-stubs/carray_mathfunc.rb +45 -0
- data/yard-stubs/carray_median_percentile.rb +89 -0
- data/yard-stubs/carray_memory_view.rb +163 -0
- data/yard-stubs/carray_order.rb +312 -0
- data/yard-stubs/carray_random.rb +89 -0
- data/yard-stubs/carray_scatter.rb +106 -0
- data/yard-stubs/carray_slab.rb +57 -0
- data/yard-stubs/carray_sort.rb +163 -0
- data/yard-stubs/carray_test.rb +85 -0
- data/yard-stubs/carray_undef.rb +64 -0
- data/yard-stubs/carray_utils.rb +97 -0
- data/yard-stubs/ruby_carray.rb +193 -0
- metadata +59 -10
- data/ext/ca_obj_unbound_repeat.c +0 -496
data/ext/ca_obj_moncmp.c
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
CAMonCmp — lazy monadic element-wise comparison view: is_nan /
|
|
4
4
|
is_inf / is_finite / is_invalid / signbit. Output data_type =
|
|
5
|
-
CA_BOOLEAN (1 byte); operand keeps its native data_type (per-
|
|
5
|
+
CA_BOOLEAN (1 byte); operand keeps its native data_type (per-type
|
|
6
6
|
kernels cover integer as well, so is_nan / is_inf on integer parents
|
|
7
7
|
return const-false and is_finite const-true without a cast layer).
|
|
8
8
|
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
Peak scratch: 1 operand-data_type slab.
|
|
21
21
|
|
|
22
22
|
Mask propagation:
|
|
23
|
-
Per-
|
|
23
|
+
Per-type moncmp kernels write only at non-masked positions, so
|
|
24
24
|
the standard create_mask = parent.mask machinery carries mask bits
|
|
25
25
|
to the caller-visible result. No in-flight mask handling in
|
|
26
26
|
xfer_stride.
|
|
@@ -121,9 +121,8 @@ ca_moncmp_setup (CAMonCmp *ca, CArray *parent, uint16_t op_id)
|
|
|
121
121
|
|
|
122
122
|
memcpy(ca->dim, parent->dim, parent->ndim * sizeof(ca_size_t));
|
|
123
123
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
124
|
+
/* The mask is NOT built here: ca_has_mask creates a view's mask on
|
|
125
|
+
demand from its parent's. */
|
|
127
126
|
if ( ca_is_scalar(parent) ) {
|
|
128
127
|
ca_set_flag(ca, CA_FLAG_SCALAR);
|
|
129
128
|
}
|
|
@@ -252,6 +251,8 @@ ca_moncmp_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
252
251
|
int8_t k;
|
|
253
252
|
void *scratch;
|
|
254
253
|
ca_size_t operand_bytes;
|
|
254
|
+
ca_size_t operand_strides[CA_RANK_MAX];
|
|
255
|
+
int is_contig;
|
|
255
256
|
|
|
256
257
|
if ( dir != CA_XFER_GET ) {
|
|
257
258
|
rb_raise(rb_eRuntimeError, "CAMonCmp is read-only (xfer_stride PUT)");
|
|
@@ -263,26 +264,44 @@ ca_moncmp_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
263
264
|
|
|
264
265
|
operand_bytes = mc->parent->bytes;
|
|
265
266
|
|
|
267
|
+
/* The operand's cell is operand_bytes wide where this view's is one byte
|
|
268
|
+
(CA_BOOLEAN), so the caller's strides have to be restated at the
|
|
269
|
+
operand's cell size before the pull; strides[k] / bytes is the index
|
|
270
|
+
step, which is what the two spaces share.
|
|
271
|
+
|
|
272
|
+
is_contig says the caller asked for the row-major slab that xfer_all
|
|
273
|
+
and attach send. Only then does the parent's own buffer hold the
|
|
274
|
+
wanted cells in the packed order the kernel reads them in, so it is
|
|
275
|
+
also the only case the leaf in-place path is good for. */
|
|
276
|
+
{
|
|
277
|
+
ca_size_t native = mc->bytes;
|
|
278
|
+
is_contig = 1;
|
|
279
|
+
for ( k = mc->ndim - 1; k >= 0; k-- ) {
|
|
280
|
+
operand_strides[k] = strides[k] / mc->bytes * operand_bytes;
|
|
281
|
+
if ( strides[k] != native ) {
|
|
282
|
+
is_contig = 0;
|
|
283
|
+
}
|
|
284
|
+
native *= mc->dim[k];
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
266
288
|
/* === 1. pull parent (leaf-opt or scratch) === */
|
|
267
289
|
int scratch_is_inplace = 0;
|
|
268
290
|
{
|
|
269
291
|
char *inplace = NULL;
|
|
270
|
-
if (
|
|
292
|
+
if ( is_contig &&
|
|
293
|
+
ca_moncmp_try_leaf_inplace(mc->parent, starts, counts,
|
|
271
294
|
operand_bytes, &inplace) ) {
|
|
272
295
|
scratch = inplace;
|
|
273
296
|
scratch_is_inplace = 1;
|
|
274
297
|
ca_moncmp_leaf_inplace_count++;
|
|
275
298
|
}
|
|
276
299
|
else {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
scratch_strides[k] = s;
|
|
281
|
-
s *= counts[k];
|
|
282
|
-
}
|
|
283
|
-
scratch = ca_lazy_arena_acquire(slab_n * operand_bytes);
|
|
300
|
+
scratch = ( mc->parent->data_type == CA_OBJECT )
|
|
301
|
+
? ca_lazy_arena_acquire_object(slab_n)
|
|
302
|
+
: ca_lazy_arena_acquire(slab_n * operand_bytes);
|
|
284
303
|
ca_moncmp_scratch_acquire_count++;
|
|
285
|
-
ca_xfer_stride(mc->parent, starts, counts,
|
|
304
|
+
ca_xfer_stride(mc->parent, starts, counts, operand_strides, scratch,
|
|
286
305
|
CA_XFER_GET);
|
|
287
306
|
}
|
|
288
307
|
}
|
data/ext/ca_obj_monop.c
CHANGED
|
@@ -207,9 +207,9 @@ ca_monop_setup (CAMonOp *ca, CArray *parent, uint16_t op_id)
|
|
|
207
207
|
|
|
208
208
|
memcpy(ca->dim, parent->dim, parent->ndim * sizeof(ca_size_t));
|
|
209
209
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
210
|
+
/* The mask is NOT built here: ca_has_mask creates a view's mask on
|
|
211
|
+
demand from its parent's, so an expression whose mask nobody reads
|
|
212
|
+
never allocates one. */
|
|
213
213
|
|
|
214
214
|
if ( ca_is_scalar(parent) ) {
|
|
215
215
|
ca_set_flag(ca, CA_FLAG_SCALAR);
|
|
@@ -380,8 +380,8 @@ ca_size_t ca_monop_materialise_call_count = 0;
|
|
|
380
380
|
but they are unobservable: the output mask is built separately via
|
|
381
381
|
the attach lifecycle (ca_monop_func_create_mask + parent.mask
|
|
382
382
|
CARefer), so reads of masked cells return UNDEF regardless of byte
|
|
383
|
-
contents.
|
|
384
|
-
|
|
383
|
+
contents. The mask marks cells as undefined; it does not guard their
|
|
384
|
+
bytes, so writing garbage into a masked cell is licensed.
|
|
385
385
|
|
|
386
386
|
A "partial mask slow path" (= a cell-wise branch to skip masked-cell
|
|
387
387
|
compute) is a possible future micro-optimisation; it is not done
|
|
@@ -461,7 +461,9 @@ pull_leaf_with_optional_cast (CArray *leaf, uint16_t innermost_op,
|
|
|
461
461
|
}
|
|
462
462
|
}
|
|
463
463
|
(void) holder;
|
|
464
|
-
scratch =
|
|
464
|
+
scratch = ( leaf->data_type == CA_OBJECT )
|
|
465
|
+
? ca_lazy_arena_acquire_object(slab_n)
|
|
466
|
+
: ca_lazy_arena_acquire(total_bytes);
|
|
465
467
|
ca_monop_scratch_acquire_count++;
|
|
466
468
|
ca_xfer_stride(leaf, starts, counts, parent_strides, scratch, CA_XFER_GET);
|
|
467
469
|
|
|
@@ -615,7 +617,9 @@ ca_monop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
615
617
|
→ data (in target data_type). Required because in-place cast
|
|
616
618
|
would overlap source/dest reads when target_bytes > src_bytes
|
|
617
619
|
(forward-walk reads cells past their own write boundary). */
|
|
618
|
-
scratch =
|
|
620
|
+
scratch = ( cur_dt == CA_OBJECT )
|
|
621
|
+
? ca_lazy_arena_acquire_object(slab_n)
|
|
622
|
+
: ca_lazy_arena_acquire(total_bytes);
|
|
619
623
|
ca_monop_scratch_acquire_count++;
|
|
620
624
|
memcpy(scratch, data, total_bytes);
|
|
621
625
|
ca_cast_block(slab_n, &src_stub, scratch, &dst_stub, data);
|
|
@@ -728,6 +732,14 @@ ca_monop_func_attach (void *ap)
|
|
|
728
732
|
s = ca->bytes;
|
|
729
733
|
for ( k = ca->ndim - 1; k >= 0; k-- ) { native[k] = s; s *= ca->dim[k]; }
|
|
730
734
|
for ( k = 0; k < ca->ndim; k++ ) starts[k] = 0;
|
|
735
|
+
/* CA_OBJECT cells are VALUEs and this buffer is about to be marked as
|
|
736
|
+
soon as the view is, so it must not be handed to the GC as raw
|
|
737
|
+
xmalloc garbage. */
|
|
738
|
+
if ( ca->data_type == CA_OBJECT ) {
|
|
739
|
+
VALUE *p = (VALUE *) ca->ptr;
|
|
740
|
+
ca_size_t i;
|
|
741
|
+
for ( i = 0; i < ca->elements; i++ ) *p++ = Qnil;
|
|
742
|
+
}
|
|
731
743
|
ca_monop_func_xfer_stride(ca, starts, ca->dim, native, ca->ptr, CA_XFER_GET);
|
|
732
744
|
}
|
|
733
745
|
|
data/ext/ca_obj_object.c
CHANGED
|
@@ -352,8 +352,11 @@ ca_objmask_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
352
352
|
if ( n == 0 ) return;
|
|
353
353
|
|
|
354
354
|
if ( rb_obj_respond_to(ca->array, mid_block, Qtrue) ) {
|
|
355
|
-
|
|
356
|
-
|
|
355
|
+
/* The request is over the view's addresses, so a transposed / flat
|
|
356
|
+
request is legal; the per-axis copy_block dispatch below would
|
|
357
|
+
misread it. See ca_xfer_stride_request_is_axis_box (carray.h). */
|
|
358
|
+
int aligned = ca_xfer_stride_request_is_axis_box(ca, starts, counts, strides);
|
|
359
|
+
for ( k = 0; aligned && k < ndim; k++ ) {
|
|
357
360
|
if ( strides[k] <= 0 || strides[k] % native[k] != 0 ) { aligned = 0; break; }
|
|
358
361
|
steps[k] = strides[k] / native[k];
|
|
359
362
|
}
|
|
@@ -937,8 +940,11 @@ ca_object_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
937
940
|
before the % check
|
|
938
941
|
- given %==0 + >0, strides/native >= 1 holds automatically */
|
|
939
942
|
if ( rb_obj_respond_to(ca->self, mid_block, Qtrue) ) {
|
|
940
|
-
|
|
941
|
-
|
|
943
|
+
/* The request is over the view's addresses, so a transposed / flat
|
|
944
|
+
request is legal; the per-axis copy_block dispatch below would
|
|
945
|
+
misread it. See ca_xfer_stride_request_is_axis_box (carray.h). */
|
|
946
|
+
int aligned = ca_xfer_stride_request_is_axis_box(ca, starts, counts, strides);
|
|
947
|
+
for ( k = 0; aligned && k < ndim; k++ ) {
|
|
942
948
|
if ( strides[k] <= 0 || strides[k] % native[k] != 0 ) { aligned = 0; break; }
|
|
943
949
|
steps[k] = strides[k] / native[k]; /* >= 1 by construction */
|
|
944
950
|
}
|
|
@@ -1001,6 +1007,93 @@ ca_object_func_fill_data (void *ap, void *ptr)
|
|
|
1001
1007
|
ca_object_dispatch_fill((CAObject *) ap, ptr);
|
|
1002
1008
|
}
|
|
1003
1009
|
|
|
1010
|
+
/* Partial fill. fill_data carries no region and can only say "fill
|
|
1011
|
+
everything I cover", so before these two slots existed the only way to
|
|
1012
|
+
fill part of a CAObject was the per-cell default -- one store_addr per
|
|
1013
|
+
cell. The region arrives in the view's own address space. With
|
|
1014
|
+
`fill_block` defined (and the region an axis-aligned forward sub-box of
|
|
1015
|
+
self) it becomes one call; with `fill_addrs` defined it becomes one call
|
|
1016
|
+
per address window. With neither defined the behaviour is exactly the
|
|
1017
|
+
old default, so an existing subclass sees no change. */
|
|
1018
|
+
static void
|
|
1019
|
+
ca_object_func_fill_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *ptr)
|
|
1020
|
+
{
|
|
1021
|
+
CAObject *ca = (CAObject *) ap;
|
|
1022
|
+
ID mid = rb_intern("fill_addrs");
|
|
1023
|
+
|
|
1024
|
+
if ( ca_is_face(ca) ) {
|
|
1025
|
+
ca_face_fill_addrs(ap, n, addrs, ptr);
|
|
1026
|
+
return;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
if ( n > 0 && rb_obj_respond_to(ca->self, mid, Qtrue) ) {
|
|
1030
|
+
volatile VALUE raddrs, rval;
|
|
1031
|
+
ca_size_t dim1[1] = { n };
|
|
1032
|
+
raddrs = ca_object_wrap_transient(CA_SIZE, sizeof(ca_size_t),
|
|
1033
|
+
1, dim1, addrs, CA_XFER_PUT);
|
|
1034
|
+
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
1035
|
+
rb_funcall(ca->self, mid, 2, raddrs, rval);
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
ca_fill_addrs_default(ap, n, addrs, ptr);
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
/* Gate: one region axis per view axis, forward, and a whole number of
|
|
1043
|
+
elements per step. native is strictly decreasing, so steps[k] =
|
|
1044
|
+
m_k * native[k] with m_k >= 1 admits only the identity permutation --
|
|
1045
|
+
transpose, negative and zero (broadcast) steps, sub-element steps and
|
|
1046
|
+
dimension-dropping regions all fail it and take the addrs route. The
|
|
1047
|
+
bound check then confirms the decomposed box lies inside self. */
|
|
1048
|
+
static void
|
|
1049
|
+
ca_object_func_fill_stride (void *ap, ca_size_t base, int8_t ndim,
|
|
1050
|
+
ca_size_t *counts, ca_size_t *steps, void *ptr)
|
|
1051
|
+
{
|
|
1052
|
+
CAObject *ca = (CAObject *) ap;
|
|
1053
|
+
ca_size_t native[CA_RANK_MAX], istep[CA_RANK_MAX], start[CA_RANK_MAX];
|
|
1054
|
+
ca_size_t s;
|
|
1055
|
+
int8_t k;
|
|
1056
|
+
ID mid = rb_intern("fill_block");
|
|
1057
|
+
|
|
1058
|
+
if ( ca_is_face(ca) ) {
|
|
1059
|
+
ca_face_fill_stride(ap, base, ndim, counts, steps, ptr);
|
|
1060
|
+
return;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
if ( ndim == ca->ndim && rb_obj_respond_to(ca->self, mid, Qtrue) ) {
|
|
1064
|
+
int aligned = 1;
|
|
1065
|
+
s = 1;
|
|
1066
|
+
for ( k = ca->ndim - 1; k >= 0; k-- ) { native[k] = s; s *= ca->dim[k]; }
|
|
1067
|
+
for ( k = 0; k < ndim; k++ ) {
|
|
1068
|
+
if ( steps[k] <= 0 || steps[k] % native[k] != 0 ) { aligned = 0; break; }
|
|
1069
|
+
istep[k] = steps[k] / native[k];
|
|
1070
|
+
start[k] = ( base / native[k] ) % ca->dim[k];
|
|
1071
|
+
if ( start[k] + ( counts[k] - 1 ) * istep[k] >= ca->dim[k] ) {
|
|
1072
|
+
aligned = 0;
|
|
1073
|
+
break;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
if ( aligned ) {
|
|
1077
|
+
volatile VALUE rstarts, rcounts, rsteps, rval;
|
|
1078
|
+
rstarts = rb_ary_new_capa(ndim);
|
|
1079
|
+
rcounts = rb_ary_new_capa(ndim);
|
|
1080
|
+
rsteps = rb_ary_new_capa(ndim);
|
|
1081
|
+
for ( k = 0; k < ndim; k++ ) {
|
|
1082
|
+
rb_ary_push(rstarts, SIZE2NUM(start[k]));
|
|
1083
|
+
rb_ary_push(rcounts, SIZE2NUM(counts[k]));
|
|
1084
|
+
rb_ary_push(rsteps, SIZE2NUM(istep[k]));
|
|
1085
|
+
}
|
|
1086
|
+
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
1087
|
+
rb_funcall(ca->self, mid, 4, rstarts, rcounts, rsteps, rval);
|
|
1088
|
+
return;
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
/* addrs route: address windows -> ca_fill_addrs -> `fill_addrs` when the
|
|
1093
|
+
author defined it, else the per-cell default. */
|
|
1094
|
+
ca_fill_stride_via_addrs(ap, base, ndim, counts, steps, ptr);
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1004
1097
|
static void
|
|
1005
1098
|
ca_object_func_create_mask (void *ap)
|
|
1006
1099
|
{
|
|
@@ -1050,6 +1143,8 @@ ca_operation_function_t ca_object_func = {
|
|
|
1050
1143
|
NULL, /* fold_stride: never-fold (callback boundary) */
|
|
1051
1144
|
ca_object_func_xfer_stride,
|
|
1052
1145
|
ca_object_func_xfer_all,
|
|
1146
|
+
.fill_addrs = ca_object_func_fill_addrs,
|
|
1147
|
+
.fill_stride = ca_object_func_fill_stride,
|
|
1053
1148
|
};
|
|
1054
1149
|
|
|
1055
1150
|
/* ------------------------------------------------------------------- */
|
data/ext/ca_obj_record.c
CHANGED
|
@@ -202,7 +202,9 @@ ca_operation_function_t ca_record_func = {
|
|
|
202
202
|
ca_face_xfer_addrs,
|
|
203
203
|
NULL, /* fold_stride: identity Face is not foldable */
|
|
204
204
|
ca_face_xfer_stride,
|
|
205
|
-
ca_face_xfer_all
|
|
205
|
+
ca_face_xfer_all,
|
|
206
|
+
.fill_addrs = ca_face_fill_addrs,
|
|
207
|
+
.fill_stride = ca_face_fill_stride,
|
|
206
208
|
};
|
|
207
209
|
|
|
208
210
|
/* ------------------------------------------------------------------- */
|
data/ext/ca_obj_refer.c
CHANGED
|
@@ -454,7 +454,7 @@ rb_ca_refer (int argc, VALUE *argv, VALUE self)
|
|
|
454
454
|
return obj;
|
|
455
455
|
}
|
|
456
456
|
}
|
|
457
|
-
|
|
457
|
+
CA_WRAPPER_LIFT(obj, self, ca);
|
|
458
458
|
return obj;
|
|
459
459
|
}
|
|
460
460
|
|
|
@@ -482,7 +482,31 @@ rb_ca_refer_new (VALUE self,
|
|
|
482
482
|
rb_set_options(ropt, "bytes,offset", SIZE2NUM(bytes), SIZE2NUM(offset));
|
|
483
483
|
rb_ary_store(list, 2, ropt);
|
|
484
484
|
|
|
485
|
-
|
|
485
|
+
{
|
|
486
|
+
volatile VALUE obj = rb_ca_refer(3, (VALUE *) RARRAY_CONST_PTR(list), self);
|
|
487
|
+
CArray *co;
|
|
488
|
+
|
|
489
|
+
/* CAREFUL: this is the internal builder -- some fifteen call sites want
|
|
490
|
+
the refer itself, not a wrapper on top of it. The public `refer` it
|
|
491
|
+
delegates to lifts a CALazyMarker, so strip that here.
|
|
492
|
+
|
|
493
|
+
Two things go wrong otherwise. rb_ca_value_array strips the mask off
|
|
494
|
+
what it gets back and marks the level it is handed; with a marker in
|
|
495
|
+
the way the refer underneath keeps its mask and never gets
|
|
496
|
+
CA_FLAG_VALUE_ARRAY, so the values read back as UNDEF. And builders
|
|
497
|
+
that stack further views on the result -- fancy indexing goes refer,
|
|
498
|
+
grid, refer -- end up with a marker buried in the middle of the
|
|
499
|
+
chain, which is the redundant-middle-wrapper that CAFace.md section
|
|
500
|
+
8.3 exists to prevent.
|
|
501
|
+
|
|
502
|
+
Faces stay lifted: rb_ca_value_array depends on that and says so
|
|
503
|
+
where it marks the storage level. */
|
|
504
|
+
TypedData_Get_Struct(obj, CArray, &carray_data_type, co);
|
|
505
|
+
if ( ca_is_lazy_marker(co) ) {
|
|
506
|
+
obj = rb_ca_parent(obj);
|
|
507
|
+
}
|
|
508
|
+
return obj;
|
|
509
|
+
}
|
|
486
510
|
}
|
|
487
511
|
|
|
488
512
|
/* CArray#reshape(*newdim) — returns a view of self with the new
|
|
@@ -605,7 +629,7 @@ rb_ca_reshape (int argc, VALUE *argv, VALUE self)
|
|
|
605
629
|
out_strides, out_base);
|
|
606
630
|
obj = ca_wrap_struct(cs);
|
|
607
631
|
rb_ca_set_parent(obj, self);
|
|
608
|
-
|
|
632
|
+
CA_WRAPPER_LIFT(obj, self, ca);
|
|
609
633
|
return obj;
|
|
610
634
|
}
|
|
611
635
|
}
|
|
@@ -614,7 +638,7 @@ rb_ca_reshape (int argc, VALUE *argv, VALUE self)
|
|
|
614
638
|
new_dim, ca->bytes, 0);
|
|
615
639
|
obj = ca_wrap_struct(cr);
|
|
616
640
|
rb_ca_set_parent(obj, self);
|
|
617
|
-
|
|
641
|
+
CA_WRAPPER_LIFT(obj, self, ca);
|
|
618
642
|
return obj;
|
|
619
643
|
}
|
|
620
644
|
|
|
@@ -642,7 +666,7 @@ rb_ca_flatten (VALUE self)
|
|
|
642
666
|
1, dim, out_strides, out_base);
|
|
643
667
|
obj = ca_wrap_struct(cs);
|
|
644
668
|
rb_ca_set_parent(obj, self);
|
|
645
|
-
|
|
669
|
+
CA_WRAPPER_LIFT(obj, self, ca);
|
|
646
670
|
return obj;
|
|
647
671
|
}
|
|
648
672
|
}
|
|
@@ -650,7 +674,7 @@ rb_ca_flatten (VALUE self)
|
|
|
650
674
|
cr = ca_refer_new(ca, ca->data_type, 1, dim, ca->bytes, 0);
|
|
651
675
|
obj = ca_wrap_struct(cr);
|
|
652
676
|
rb_ca_set_parent(obj, self);
|
|
653
|
-
|
|
677
|
+
CA_WRAPPER_LIFT(obj, self, ca);
|
|
654
678
|
return obj;
|
|
655
679
|
}
|
|
656
680
|
|
data/ext/ca_obj_roll.c
CHANGED
|
@@ -232,10 +232,18 @@ ca_roll_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
232
232
|
s = ca->bytes;
|
|
233
233
|
for (k = ndim - 1; k >= 0; k--) { dstride[k] = s; s *= counts[k]; }
|
|
234
234
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
235
|
+
/* The request is over the view's addresses, so a transposed / flat request
|
|
236
|
+
is legal and must not be composed axis-by-axis; see
|
|
237
|
+
ca_xfer_stride_request_is_axis_box (carray.h). */
|
|
238
|
+
if ( ! ca_xfer_stride_request_is_axis_box(ca, starts, counts, strides) ) {
|
|
239
|
+
structural = 0;
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
for (k = 0; k < ndim; k++) {
|
|
243
|
+
if (strides[k] % rnative[k] != 0 || strides[k] / rnative[k] != 1) {
|
|
244
|
+
structural = 0;
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
239
247
|
}
|
|
240
248
|
}
|
|
241
249
|
|
|
@@ -529,7 +537,7 @@ rb_ca_roll (int argc, VALUE *argv, VALUE self)
|
|
|
529
537
|
}
|
|
530
538
|
{
|
|
531
539
|
VALUE obj = rb_ca_roll_new(self, shift);
|
|
532
|
-
|
|
540
|
+
CA_WRAPPER_LIFT(obj, self, ca);
|
|
533
541
|
return obj;
|
|
534
542
|
}
|
|
535
543
|
}
|
data/ext/ca_obj_select_axis.c
CHANGED
|
@@ -571,9 +571,17 @@ ca_select_axis_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
571
571
|
s = ca->bytes;
|
|
572
572
|
for (k = ndim - 1; k >= 0; k--) { dstride[k] = s; s *= counts[k]; }
|
|
573
573
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
574
|
+
/* The request is over the view's addresses, so a transposed / flat request
|
|
575
|
+
is legal and must not be composed axis-by-axis; see
|
|
576
|
+
ca_xfer_stride_request_is_axis_box (carray.h). */
|
|
577
|
+
if ( ! ca_xfer_stride_request_is_axis_box(ca, starts, counts, strides) ) {
|
|
578
|
+
aligned = 0;
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
for (k = 0; k < ndim; k++) {
|
|
582
|
+
if (strides[k] % cnative[k] != 0) { aligned = 0; break; }
|
|
583
|
+
src_step[k] = strides[k] / cnative[k];
|
|
584
|
+
}
|
|
577
585
|
}
|
|
578
586
|
|
|
579
587
|
if (!aligned) {
|
|
@@ -925,7 +933,7 @@ rb_ca_select_axis_s_new_debug (VALUE klass, VALUE rparent, VALUE rindirect,
|
|
|
925
933
|
obj = TypedData_Make_Struct(klass, CASelectAxis, &caselectaxis_data_type, ca);
|
|
926
934
|
ca_select_axis_setup(ca, parent, indirect_axis, selector,
|
|
927
935
|
ap_start_buf, ap_count_buf, ap_step_buf);
|
|
928
|
-
|
|
936
|
+
rb_ca_set_parent(obj, rparent);
|
|
929
937
|
rb_ivar_set(obj, rb_intern("_selector"), rselector);
|
|
930
938
|
return obj;
|
|
931
939
|
}
|
|
@@ -1066,8 +1074,10 @@ rb_ca_select_axis (int argc, VALUE *argv, VALUE self)
|
|
|
1066
1074
|
ca_select_axis_setup(ca, parent, indirect_axis, selector,
|
|
1067
1075
|
ap_start, ap_count, ap_step);
|
|
1068
1076
|
|
|
1069
|
-
/* Keep Ruby objects alive (parent and selector references).
|
|
1070
|
-
|
|
1077
|
+
/* Keep Ruby objects alive (parent and selector references). The parent
|
|
1078
|
+
goes through rb_ca_set_parent so #parent, #root_array and #ancestors
|
|
1079
|
+
read the same link here as they do through every other view. */
|
|
1080
|
+
rb_ca_set_parent(obj, self);
|
|
1071
1081
|
rb_ivar_set(obj, rb_intern("_selector"), rselector_keep);
|
|
1072
1082
|
return obj;
|
|
1073
1083
|
}
|
data/ext/ca_obj_shift.c
CHANGED
|
@@ -264,7 +264,7 @@ rb_ca_shift_new (VALUE cary, ca_size_t *shift, char *fill, int8_t *roll,
|
|
|
264
264
|
VALUE
|
|
265
265
|
rb_ca_shift (int argc, VALUE *argv, VALUE self)
|
|
266
266
|
{
|
|
267
|
-
volatile VALUE obj, ropt, rfval =
|
|
267
|
+
volatile VALUE obj, ropt, rfval = CA_UNSPECIFIED, rroll = Qnil, rcs;
|
|
268
268
|
CArray *ca;
|
|
269
269
|
CScalar *cs;
|
|
270
270
|
ca_size_t shift[CA_RANK_MAX];
|
|
@@ -301,7 +301,7 @@ rb_ca_shift (int argc, VALUE *argv, VALUE self)
|
|
|
301
301
|
"use fill_value: kwarg (e.g. shift(1, fill_value: -2))");
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
-
if ( rfval ==
|
|
304
|
+
if ( rfval == CA_UNSPECIFIED ) {
|
|
305
305
|
/* Default fill value = 0 (or INT2NUM(0) for OBJECT type) */
|
|
306
306
|
rcs = rb_cscalar_new(ca->data_type, ca->bytes, NULL);
|
|
307
307
|
TypedData_Get_Struct(rcs, CScalar, &cscalar_data_type, cs);
|
|
@@ -343,7 +343,7 @@ rb_ca_shift (int argc, VALUE *argv, VALUE self)
|
|
|
343
343
|
|
|
344
344
|
obj = rb_ca_shift_new(self, shift, fill, roll, fill_mask);
|
|
345
345
|
|
|
346
|
-
|
|
346
|
+
CA_WRAPPER_LIFT(obj, self, ca);
|
|
347
347
|
return obj;
|
|
348
348
|
}
|
|
349
349
|
|
data/ext/ca_obj_stride.c
CHANGED
|
@@ -192,6 +192,19 @@ void ca_xfer_stride_tiled_transpose_2d (char *src_base, ca_size_t bytes,
|
|
|
192
192
|
ca_size_t *counts, ca_size_t *strides,
|
|
193
193
|
char *data, int dir);
|
|
194
194
|
|
|
195
|
+
/* Public form of the family test the fold walk below uses inline. The
|
|
196
|
+
family is defined by the operation table, not by a class or an
|
|
197
|
+
obj_type list: every member was installed with a copy of
|
|
198
|
+
ca_stride_func, so an externally installed view that shares the
|
|
199
|
+
table answers true as well. See carray.h for what membership does
|
|
200
|
+
and does not promise. */
|
|
201
|
+
int
|
|
202
|
+
ca_is_stride_family (const void *ap)
|
|
203
|
+
{
|
|
204
|
+
const CArray *ca = (const CArray *) ap;
|
|
205
|
+
return ( ca_func[ca->obj_type].attach == ca_stride_func.attach );
|
|
206
|
+
}
|
|
207
|
+
|
|
195
208
|
/* Compose `leaf->strides` and `leaf->base_offset` (which live in `parent`'s
|
|
196
209
|
own logical row-major contig byte space) into `out_strides` and
|
|
197
210
|
`out_base` expressed in `parent->parent`'s byte space.
|
|
@@ -616,9 +629,29 @@ ca_stride_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
616
629
|
hand the whole region to the root in a SINGLE ca_xfer_stride (entity -> ptr
|
|
617
630
|
memcpy; boundary view -> one recursion).
|
|
618
631
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
632
|
+
CAREFUL: the request is given over this view's linear ADDRESSES (carray.h
|
|
633
|
+
xfer_stride contract), so request axis k does NOT have to be view axis k.
|
|
634
|
+
A caller is free to hand over a transposed region -- counts/strides in one
|
|
635
|
+
order, the packed destination in another -- which is exactly what a
|
|
636
|
+
column-major backend (carray-linalg's Fortran-LAPACK gather) does. Matching
|
|
637
|
+
request axis k to view axis k by dividing strides[k] by the axis-k native
|
|
638
|
+
step looks right and is wrong: an (n, 1) view has the same native step on
|
|
639
|
+
both axes, so a transposed request divides cleanly and then composes the
|
|
640
|
+
n-cell walk onto the length-1 axis, whose parent stride is 0 -- delivering
|
|
641
|
+
the first cell n times, with no error anywhere. Ask ca_stride_region_axes
|
|
642
|
+
which view axis each request axis really moves (the same question
|
|
643
|
+
fill_stride asks), and fall back to the per-cell walk when the region is
|
|
644
|
+
not a box over our axes.
|
|
645
|
+
|
|
646
|
+
Byte-matching requests only; the byte-mismatch reinterpret (CAField
|
|
647
|
+
.real/.imag) and non-box access fall back to per-cell xfer_index (which
|
|
648
|
+
handles the sub-byte case). */
|
|
649
|
+
|
|
650
|
+
static int ca_stride_region_axes (CAStride *ca, ca_size_t base, int8_t ndim,
|
|
651
|
+
ca_size_t *counts, ca_size_t *steps,
|
|
652
|
+
ca_size_t *base_idx, int8_t *axis_of,
|
|
653
|
+
ca_size_t *mult);
|
|
654
|
+
|
|
622
655
|
static void
|
|
623
656
|
ca_stride_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
624
657
|
ca_size_t *strides, void *data, int dir)
|
|
@@ -629,7 +662,12 @@ ca_stride_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
629
662
|
ca_size_t composed_base;
|
|
630
663
|
ca_size_t view_native[CA_RANK_MAX];
|
|
631
664
|
ca_size_t root_stride[CA_RANK_MAX];
|
|
665
|
+
ca_size_t steps[CA_RANK_MAX];
|
|
666
|
+
ca_size_t base_idx[CA_RANK_MAX];
|
|
667
|
+
ca_size_t mult[CA_RANK_MAX];
|
|
668
|
+
int8_t axis_of[CA_RANK_MAX];
|
|
632
669
|
ca_size_t root_base;
|
|
670
|
+
ca_size_t base_addr = 0;
|
|
633
671
|
ca_size_t s;
|
|
634
672
|
int8_t ndim = ca->ndim, k;
|
|
635
673
|
int aligned = 1;
|
|
@@ -639,26 +677,77 @@ ca_stride_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
639
677
|
|
|
640
678
|
s = ca->bytes;
|
|
641
679
|
for (k = ndim - 1; k >= 0; k--) { view_native[k] = s; s *= ca->dim[k]; }
|
|
680
|
+
for (k = 0; k < ndim; k++) base_addr += starts[k] * view_native[k];
|
|
642
681
|
|
|
643
682
|
if (ca->bytes != root->bytes) {
|
|
644
683
|
aligned = 0;
|
|
645
684
|
}
|
|
646
685
|
else {
|
|
647
686
|
for (k = 0; k < ndim; k++) {
|
|
648
|
-
if (strides[k] %
|
|
687
|
+
if ( strides[k] % ca->bytes != 0 ) { aligned = 0; break; }
|
|
688
|
+
steps[k] = strides[k] / ca->bytes;
|
|
689
|
+
}
|
|
690
|
+
if ( aligned ) {
|
|
691
|
+
aligned = ca_stride_region_axes(ca, base_addr / ca->bytes, ndim,
|
|
692
|
+
counts, steps, base_idx, axis_of, mult);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
if ( aligned ) {
|
|
697
|
+
/* Each request axis now names the view axis it moves (axis_of) and by how
|
|
698
|
+
many of that axis' cells (mult); a count-1 axis moves nothing and gets
|
|
699
|
+
stride 0, which the walk never follows. */
|
|
700
|
+
root_base = composed_base;
|
|
701
|
+
for (k = 0; k < ca->ndim; k++) {
|
|
702
|
+
root_base += base_idx[k] * composed_strides[k];
|
|
703
|
+
}
|
|
704
|
+
for (k = 0; k < ndim; k++) {
|
|
705
|
+
root_stride[k] = ( axis_of[k] >= 0 )
|
|
706
|
+
? mult[k] * composed_strides[axis_of[k]]
|
|
707
|
+
: 0;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/* Cold root that answers regions: compose the request into its addresses
|
|
712
|
+
and hand it over whole, exactly as xfer_all does for the whole view. A
|
|
713
|
+
root with no memory to lend (a lazy transform, a CAObject over a file)
|
|
714
|
+
has no ptr to walk, but it can still produce a region on request -- and
|
|
715
|
+
asking it once beats asking it once per cell, which is what the per-cell
|
|
716
|
+
descent below would do. Chunked consumers (the binop / sweep drivers'
|
|
717
|
+
per-chunk gather) arrive here, so the difference is the whole cost of
|
|
718
|
+
the transfer, not a constant factor.
|
|
719
|
+
|
|
720
|
+
The gate is xfer_all's: the root must have the slot, share this view's
|
|
721
|
+
cell width (else the composed offsets are not whole root elements), and
|
|
722
|
+
carry the same ndim (else its index space cannot hold this request's
|
|
723
|
+
axes). Anything narrower keeps the per-cell descent, which is correct
|
|
724
|
+
for all of them. Direction is not part of the gate: a root that refuses
|
|
725
|
+
writes refuses them per cell as well. */
|
|
726
|
+
if (aligned && !root->ptr && ca_func[root->obj_type].xfer_stride
|
|
727
|
+
&& ca->bytes == root->bytes && ndim == root->ndim) {
|
|
728
|
+
ca_size_t rstarts[CA_RANK_MAX];
|
|
729
|
+
if ( root_base % root->bytes == 0 ) {
|
|
730
|
+
ca_size_t raddr = root_base / root->bytes;
|
|
731
|
+
if ( raddr >= 0 && raddr < root->elements ) {
|
|
732
|
+
ca_addr2index(root, raddr, rstarts);
|
|
733
|
+
ca_xfer_stride(root, rstarts, counts, root_stride, d, dir);
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
649
736
|
}
|
|
650
737
|
}
|
|
651
738
|
|
|
652
739
|
/* Per-cell fallback (correct, no whole-view attach): byte-mismatch
|
|
653
|
-
reinterpret (CAField),
|
|
654
|
-
|
|
655
|
-
|
|
740
|
+
reinterpret (CAField), a region that is not a box over our axes (a
|
|
741
|
+
transposed request onto a degenerate axis, a flat index over several
|
|
742
|
+
axes), or a cold non-entity root the branch above could not hand a
|
|
743
|
+
region to (its ndim differs from the view's -- e.g. a reshape over a
|
|
744
|
+
boundary -- or it has no region slot). ca_stride_func_xfer_index
|
|
745
|
+
composes one hop and delegates to the parent. */
|
|
656
746
|
if (!aligned || !root->ptr) {
|
|
657
|
-
ca_size_t idx[CA_RANK_MAX], doff = 0
|
|
658
|
-
for (k = 0; k < ndim; k++) base += starts[k] * view_native[k];
|
|
747
|
+
ca_size_t idx[CA_RANK_MAX], doff = 0;
|
|
659
748
|
for (k = 0; k < ndim; k++) idx[k] = 0;
|
|
660
749
|
while (1) {
|
|
661
|
-
ca_size_t off =
|
|
750
|
+
ca_size_t off = base_addr, vmidx[CA_RANK_MAX];
|
|
662
751
|
for (k = 0; k < ndim; k++) off += idx[k] * strides[k];
|
|
663
752
|
ca_addr2index((CArray *) ca, off / ca->bytes, vmidx);
|
|
664
753
|
ca_stride_func_xfer_index(ca, vmidx, d + doff, dir);
|
|
@@ -670,17 +759,11 @@ ca_stride_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
670
759
|
return;
|
|
671
760
|
}
|
|
672
761
|
|
|
673
|
-
/* Structural: root has a live ptr (entity / attached).
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
reshape view over a 1-D entity
|
|
677
|
-
|
|
678
|
-
for (k = 0; k < ndim; k++) {
|
|
679
|
-
ca_size_t req_step = strides[k] / view_native[k];
|
|
680
|
-
root_base += starts[k] * composed_strides[k];
|
|
681
|
-
root_stride[k] = req_step * composed_strides[k];
|
|
682
|
-
}
|
|
683
|
-
/* Slab-merge, tile-block and the general driver all live in the shared
|
|
762
|
+
/* Structural: root has a live ptr (entity / attached). The request is
|
|
763
|
+
already in root's BYTE space (root_base / root_stride above), so the walk
|
|
764
|
+
runs in the VIEW's ndim -- independent of root's own ndim, which is what
|
|
765
|
+
lets a reshape view over a 1-D entity through. compose happened once.
|
|
766
|
+
Slab-merge, tile-block and the general driver all live in the shared
|
|
684
767
|
walker, which the central dispatcher's structural path also uses. */
|
|
685
768
|
ca_xfer_strided_walk(root->ptr + root_base, ca->bytes, ndim,
|
|
686
769
|
counts, root_stride, d, dir);
|
|
@@ -2239,7 +2322,7 @@ rb_ca_flip_build_view (VALUE self, CArray *parent, const int8_t *flip)
|
|
|
2239
2322
|
|
|
2240
2323
|
VALUE obj = rb_ca_stride_new(self, parent->data_type, parent->bytes,
|
|
2241
2324
|
ndim, outdim, outstrides, base_offset);
|
|
2242
|
-
|
|
2325
|
+
CA_WRAPPER_LIFT(obj, self, parent);
|
|
2243
2326
|
return obj;
|
|
2244
2327
|
}
|
|
2245
2328
|
|
|
@@ -2462,7 +2545,7 @@ rb_ca_diagonal (int argc, VALUE *argv, VALUE self)
|
|
|
2462
2545
|
{
|
|
2463
2546
|
VALUE obj = rb_ca_stride_new(self, parent->data_type, parent->bytes,
|
|
2464
2547
|
out_k, outdim, outstrides, base_offset);
|
|
2465
|
-
|
|
2548
|
+
CA_WRAPPER_LIFT(obj, self, parent);
|
|
2466
2549
|
return obj;
|
|
2467
2550
|
}
|
|
2468
2551
|
}
|