carray 3.0.2 → 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 +568 -0
- data/README.md +6 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +220 -0
- data/ext/ca_axis_group.c +201 -123
- data/ext/ca_binop_dispatch.c +46 -52
- data/ext/ca_binop_dispatch.h +1 -1
- data/ext/ca_categorical_iterator.c +249 -183
- data/ext/ca_compare.c +7 -12
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +38 -23
- data/ext/ca_kernel_iterator.c +1765 -2076
- data/ext/ca_kernel_iterator.h +584 -566
- data/ext/ca_monop_dispatch.c +86 -63
- data/ext/ca_monop_dispatch.h +5 -0
- data/ext/ca_obj_array.c +223 -56
- data/ext/ca_obj_bincmp.c +172 -138
- data/ext/ca_obj_binop.c +116 -230
- data/ext/ca_obj_bitarray.c +40 -26
- data/ext/ca_obj_bitfield.c +100 -68
- data/ext/ca_obj_block.c +19 -9
- data/ext/ca_obj_byte_swap.c +45 -46
- data/ext/ca_obj_const_string.c +269 -44
- data/ext/ca_obj_face.c +612 -89
- data/ext/ca_obj_face.h +111 -47
- data/ext/ca_obj_fake.c +36 -79
- data/ext/ca_obj_farray.c +7 -3
- data/ext/ca_obj_field.c +33 -8
- data/ext/ca_obj_fixlen_string.c +23 -24
- data/ext/ca_obj_grid.c +541 -210
- data/ext/ca_obj_meld.c +331 -111
- data/ext/ca_obj_moncmp.c +80 -65
- data/ext/ca_obj_monop.c +177 -149
- data/ext/ca_obj_object.c +664 -248
- data/ext/ca_obj_record.c +63 -23
- data/ext/ca_obj_reduce.c +18 -16
- data/ext/ca_obj_refer.c +140 -58
- data/ext/ca_obj_remap.c +85 -24
- data/ext/ca_obj_repeat.c +24 -9
- data/ext/ca_obj_roll.c +121 -16
- data/ext/ca_obj_select.c +61 -58
- data/ext/ca_obj_select_axis.c +73 -107
- data/ext/ca_obj_shift.c +32 -102
- data/ext/ca_obj_stack.c +372 -122
- data/ext/ca_obj_stride.c +348 -140
- data/ext/ca_obj_string.c +88 -22
- data/ext/ca_obj_tile.c +38 -21
- data/ext/ca_obj_time.c +45 -31
- data/ext/ca_obj_timedelta.c +43 -29
- data/ext/ca_obj_transpose.c +17 -6
- data/ext/ca_obj_triop.c +125 -141
- data/ext/ca_obj_window.c +330 -44
- data/ext/ca_op_ipower.c +24 -11
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +104 -81
- data/ext/ca_sweep_engine.h +7 -20
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +542 -0
- data/ext/carray.h +241 -92
- data/ext/carray_access.c +608 -276
- data/ext/carray_address_basis.c +494 -97
- data/ext/carray_attribute.c +129 -4
- data/ext/carray_bincount.c +39 -7
- data/ext/carray_broadcast.c +56 -19
- data/ext/carray_build_flags.h +1 -1
- data/ext/carray_call_cfunc.c +108 -28
- data/ext/carray_cast.c +1576 -223
- data/ext/carray_cast_func.rb +77 -24
- data/ext/carray_class.c +4 -3
- data/ext/carray_conversion.c +208 -75
- data/ext/carray_copy.c +82 -24
- data/ext/carray_core.c +646 -162
- data/ext/carray_count.c +171 -88
- data/ext/carray_element.c +94 -60
- data/ext/carray_factorize.c +670 -324
- data/ext/carray_generate.c +260 -83
- data/ext/carray_histogram.c +209 -106
- data/ext/carray_hold.c +14 -16
- data/ext/carray_index_classifier.c +422 -243
- data/ext/carray_internal.h +692 -3
- data/ext/carray_kernels_bincmp.c +7 -0
- data/ext/carray_kernels_binop.c +487 -120
- data/ext/carray_kernels_init.c +653 -50
- data/ext/carray_kernels_moncmp.c +15 -8
- data/ext/carray_kernels_monop.c +99 -43
- data/ext/carray_kernels_reduce_aggregate.c +3925 -6112
- data/ext/carray_kernels_reduce_boolean.c +112 -36
- data/ext/carray_kernels_reduce_cumulative.c +2127 -6903
- data/ext/carray_kernels_reduce_extreme.c +3032 -2892
- data/ext/carray_kernels_reduce_variance.c +439 -500
- data/ext/carray_kernels_scan.c +1097 -488
- data/ext/carray_kernels_search.c +3787 -2176
- data/ext/carray_kernels_sort.c +1200 -920
- data/ext/carray_kernels_triop.c +479 -7
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +967 -153
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +910 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +299 -100
- data/ext/carray_memory_view.c +872 -758
- data/ext/carray_operator.c +1171 -364
- data/ext/carray_order.c +505 -133
- data/ext/carray_partition.c +112 -65
- data/ext/carray_random.c +327 -239
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +346 -78
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +249 -86
- data/ext/carray_sort.c +224 -227
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +118 -39
- data/ext/carray_test.c +193 -69
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +579 -113
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +19 -4
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1202 -1014
- data/ext/ruby_carray.c +17 -5
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +160 -17
- data/lib/carray/autoload_carray.rb +23 -27
- data/lib/carray/autoload_method_extension.rb +20 -5
- data/lib/carray/axis_group.rb +360 -63
- data/lib/carray/basics.rb +162 -28
- data/lib/carray/bincount_nd.rb +18 -2
- data/lib/carray/block_iterator.rb +231 -58
- data/lib/carray/boolean_reduce.rb +34 -42
- data/lib/carray/categorical.rb +242 -52
- data/lib/carray/categorical_iterator.rb +437 -827
- data/lib/carray/complex.rb +41 -34
- data/lib/carray/conditional.rb +150 -14
- data/lib/carray/const_string.rb +59 -4
- 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/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +82 -7
- data/lib/carray/frame/csv_parser.rb +688 -87
- data/lib/carray/frame/describe.rb +80 -0
- data/lib/carray/frame/frame.rb +369 -45
- data/lib/carray/frame/group.rb +631 -90
- data/lib/carray/frame/io.rb +506 -79
- data/lib/carray/frame/join.rb +411 -62
- data/lib/carray/frame/records.rb +116 -19
- data/lib/carray/frame/reshape.rb +455 -0
- data/lib/carray/frame/sort.rb +30 -18
- data/lib/carray/frame/verbs.rb +868 -61
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +4 -0
- data/lib/carray/fuse_source.rb +118 -2
- data/lib/carray/fusion.rb +257 -42
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +54 -13
- data/lib/carray/iterator.rb +99 -9
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +216 -193
- data/lib/carray/mask_gap_fill.rb +112 -92
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +52 -21
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +18 -2
- data/lib/carray/methods/bit_string.rb +15 -4
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +18 -10
- data/lib/carray/methods/factorize.rb +2 -2
- data/lib/carray/methods/gather_nd.rb +25 -5
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +140 -10
- data/lib/carray/methods/join.rb +2 -7
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +182 -45
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/repeat.rb +1 -20
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +11 -2
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +65 -17
- data/lib/carray/segment_iterator.rb +1221 -0
- data/lib/carray/serialize.rb +214 -30
- data/lib/carray/slab_iterator.rb +101 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +12 -4
- data/lib/carray/struct.rb +137 -58
- data/lib/carray/struct_builder.rb +124 -17
- data/lib/carray/time.rb +1222 -186
- data/lib/carray/window_iterator.rb +242 -81
- data/lib/carray.rb +9 -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_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +5 -1
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +5 -4
- data/yard-stubs/ca_obj_roll.rb +2 -3
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +9 -5
- data/yard-stubs/carray_access.rb +11 -5
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_broadcast.rb +1 -1
- data/yard-stubs/carray_cast.rb +88 -43
- data/yard-stubs/carray_conversion.rb +15 -2
- data/yard-stubs/carray_copy.rb +12 -5
- data/yard-stubs/carray_core.rb +3 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +60 -12
- data/yard-stubs/carray_math.rb +52 -14
- data/yard-stubs/carray_median_percentile.rb +15 -8
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +61 -29
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +21 -9
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +10 -2
- data/yard-stubs/carray_sort.rb +49 -8
- data/yard-stubs/carray_test.rb +15 -3
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -5
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_kernels_map.c +0 -3467
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/ext/ca_obj_stride.c
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
---------------------------------------------------------------------------- */
|
|
21
21
|
|
|
22
22
|
#include "carray.h"
|
|
23
|
+
#include "carray_internal.h" /* ca_normalize_axis_arg */
|
|
23
24
|
#include "ca_iter_substrate.h"
|
|
24
25
|
#include "ca_obj_face.h" /* ca_is_face, used by the compose-fold walk */
|
|
25
26
|
|
|
@@ -93,24 +94,27 @@ int8_t CA_OBJ_STRIDE; /* assigned at Init time via ca_install_obj_type */
|
|
|
93
94
|
override pattern and makes the C-level dispatch wire up correctly
|
|
94
95
|
on the first try. */
|
|
95
96
|
int
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
ca_stride_setup_view (CAStride *ca, int8_t obj_type, CArray *parent,
|
|
98
|
+
int8_t data_type, ca_size_t bytes,
|
|
99
|
+
int8_t ndim, ca_size_t *dim,
|
|
100
|
+
ca_size_t *strides, ca_size_t base_offset)
|
|
100
101
|
{
|
|
101
102
|
ca_size_t elements;
|
|
102
103
|
int i;
|
|
103
104
|
|
|
104
|
-
|
|
105
|
-
rb_raise(rb_eArgError, "invalid ndim %d", (int) ndim);
|
|
106
|
-
}
|
|
107
|
-
elements = 1;
|
|
105
|
+
ca_check_rank_fits(ndim, NULL);
|
|
108
106
|
for (i = 0; i < ndim; i++) {
|
|
109
107
|
if (dim[i] < 0) {
|
|
110
108
|
rb_raise(rb_eIndexError,
|
|
111
109
|
"invalid size for %i-th dimension (negative)", i);
|
|
112
110
|
}
|
|
113
|
-
|
|
111
|
+
}
|
|
112
|
+
elements = ca_shape_elements(ndim, dim, bytes);
|
|
113
|
+
|
|
114
|
+
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
115
|
+
run them before it allocates. */
|
|
116
|
+
if ( ca == NULL ) {
|
|
117
|
+
return 0;
|
|
114
118
|
}
|
|
115
119
|
|
|
116
120
|
ca->obj_type = obj_type;
|
|
@@ -138,10 +142,23 @@ ca_stride_setup (CAStride *ca, int8_t obj_type, CArray *parent,
|
|
|
138
142
|
ca->strides[i] = strides[i];
|
|
139
143
|
}
|
|
140
144
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
145
|
+
return 0;
|
|
146
|
+
}
|
|
144
147
|
|
|
148
|
+
/* The public form also takes the parent's mask. A struct that no Ruby
|
|
149
|
+
object owns yet is lost if the parent's answer raises; the in-tree
|
|
150
|
+
constructors use ca_stride_setup_view and ca_view_inherit_mask. */
|
|
151
|
+
int
|
|
152
|
+
ca_stride_setup (CAStride *ca, int8_t obj_type, CArray *parent,
|
|
153
|
+
int8_t data_type, ca_size_t bytes,
|
|
154
|
+
int8_t ndim, ca_size_t *dim,
|
|
155
|
+
ca_size_t *strides, ca_size_t base_offset)
|
|
156
|
+
{
|
|
157
|
+
ca_stride_setup_view(ca, obj_type, parent, data_type, bytes,
|
|
158
|
+
ndim, dim, strides, base_offset);
|
|
159
|
+
if ( ca != NULL ) {
|
|
160
|
+
ca_view_inherit_mask((VALUE) ca);
|
|
161
|
+
}
|
|
145
162
|
return 0;
|
|
146
163
|
}
|
|
147
164
|
|
|
@@ -151,9 +168,13 @@ ca_stride_new (int8_t obj_type, CArray *parent,
|
|
|
151
168
|
int8_t ndim, ca_size_t *dim,
|
|
152
169
|
ca_size_t *strides, ca_size_t base_offset)
|
|
153
170
|
{
|
|
154
|
-
CAStride *ca
|
|
155
|
-
|
|
156
|
-
|
|
171
|
+
CAStride *ca;
|
|
172
|
+
ca_stride_setup_view(NULL, obj_type, parent,
|
|
173
|
+
data_type, bytes, ndim, dim, strides, base_offset);
|
|
174
|
+
ca = (CAStride *) ca_array_alloc(obj_type, ndim);
|
|
175
|
+
ca_stride_setup_view(ca, obj_type, parent,
|
|
176
|
+
data_type, bytes, ndim, dim, strides, base_offset);
|
|
177
|
+
ca_fill_or_free((CArray *) ca, ca_view_inherit_mask, (VALUE) ca);
|
|
157
178
|
return ca;
|
|
158
179
|
}
|
|
159
180
|
|
|
@@ -292,6 +313,38 @@ ca_stride_compose_through (CAStride *leaf, CAStride *parent,
|
|
|
292
313
|
out_strides[k] = composed;
|
|
293
314
|
}
|
|
294
315
|
|
|
316
|
+
/* A leaf cell wider than the remainder of its first parent element
|
|
317
|
+
(CARefer reinterpreting two float64 as one complex128) covers several
|
|
318
|
+
consecutive parent elements, and the folded access reads the cell as
|
|
319
|
+
one run of bytes from out_base. That is only true when those parent
|
|
320
|
+
elements are adjacent in parent->parent's memory as well: every cell
|
|
321
|
+
must fit inside the parent's trailing row-major contiguous block.
|
|
322
|
+
Cell starts are flat0 + sum idx[k]*advance[k], so their residues
|
|
323
|
+
modulo the block size C step by g = gcd(C, advance...); every cell
|
|
324
|
+
fits when (flat0 mod g) + span <= g. */
|
|
325
|
+
if ( sub_byte + leaf->bytes > parent->bytes ) {
|
|
326
|
+
ca_size_t span = (sub_byte + leaf->bytes + parent->bytes - 1)
|
|
327
|
+
/ parent->bytes;
|
|
328
|
+
ca_size_t block = 1;
|
|
329
|
+
ca_size_t g, flat0 = leaf->base_offset / parent->bytes;
|
|
330
|
+
if ( parent->ndim > 0
|
|
331
|
+
&& parent->strides[parent->ndim - 1] == parent->bytes ) {
|
|
332
|
+
block = parent->dim[parent->ndim - 1];
|
|
333
|
+
for (m = parent->ndim - 2; m >= 0; m--) {
|
|
334
|
+
if ( parent->strides[m] != parent->strides[m + 1] * parent->dim[m + 1] )
|
|
335
|
+
break;
|
|
336
|
+
block *= parent->dim[m];
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
g = block;
|
|
340
|
+
for (k = 0; k < leaf->ndim; k++) {
|
|
341
|
+
ca_size_t a = leaf->strides[k] / parent->bytes;
|
|
342
|
+
if ( a < 0 ) a = -a;
|
|
343
|
+
while ( a != 0 ) { ca_size_t r = g % a; g = a; a = r; }
|
|
344
|
+
}
|
|
345
|
+
if ( g == 0 || (flat0 % g) + span > g ) return 0;
|
|
346
|
+
}
|
|
347
|
+
|
|
295
348
|
return 1;
|
|
296
349
|
}
|
|
297
350
|
|
|
@@ -402,6 +455,8 @@ ca_stride_compose_to_root (CAStride *leaf,
|
|
|
402
455
|
|
|
403
456
|
"Identity compose-fold" semantics:
|
|
404
457
|
- cand->bytes == root->bytes (no byte reinterpret)
|
|
458
|
+
- cand->data_type == root->data_type (no type reinterpret: a caller
|
|
459
|
+
may read the root's cells as typed values)
|
|
405
460
|
- composed_base == 0
|
|
406
461
|
- composed_strides[k] match row-major over cand->dim with cand->bytes
|
|
407
462
|
|
|
@@ -430,6 +485,7 @@ ca_resolve_attached_root_via_identity (CArray *cand)
|
|
|
430
485
|
ca_stride_compose_to_root(cs, &root, composed_strides, &composed_base);
|
|
431
486
|
if ( !root->ptr ) return cand;
|
|
432
487
|
if ( cs->bytes != root->bytes ) return cand;
|
|
488
|
+
if ( cs->data_type != root->data_type ) return cand;
|
|
433
489
|
if ( composed_base != 0 ) return cand;
|
|
434
490
|
|
|
435
491
|
s = root->bytes;
|
|
@@ -512,19 +568,32 @@ ca_stride_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
512
568
|
ca_xfer_index(ca->parent, pidx, data, dir);
|
|
513
569
|
}
|
|
514
570
|
else {
|
|
515
|
-
|
|
516
|
-
|
|
571
|
+
/* Byte-mismatched reinterpret. The cell covers the parent elements
|
|
572
|
+
from off / pbytes through the one holding its last byte: one for a
|
|
573
|
+
narrower cell (CAField .real / .imag), several for a wider one
|
|
574
|
+
(CARefer reading two float64 as one complex128). Read all of
|
|
575
|
+
them; a store writes back all of them.
|
|
576
|
+
ALLOCV: the parent's fetch/store can raise (a CAObject parent runs
|
|
577
|
+
Ruby), and a raise must not leak the scratch. */
|
|
578
|
+
volatile VALUE holder;
|
|
579
|
+
ca_size_t addr = off / pbytes;
|
|
580
|
+
ca_size_t sub = off % pbytes;
|
|
581
|
+
ca_size_t span = (sub + ca->bytes + pbytes - 1) / pbytes;
|
|
582
|
+
ca_size_t i;
|
|
583
|
+
char *scratch = ALLOCV_N(char, holder, span * pbytes);
|
|
584
|
+
for (i = 0; i < span; i++) {
|
|
585
|
+
ca_fetch_addr(ca->parent, addr + i, scratch + i * pbytes);
|
|
586
|
+
}
|
|
517
587
|
if (dir == CA_XFER_GET) {
|
|
518
|
-
|
|
519
|
-
memcpy(data, scratch + (off % pbytes), ca->bytes);
|
|
588
|
+
memcpy(data, scratch + sub, ca->bytes);
|
|
520
589
|
}
|
|
521
590
|
else {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
591
|
+
memcpy(scratch + sub, data, ca->bytes);
|
|
592
|
+
for (i = 0; i < span; i++) {
|
|
593
|
+
ca_store_addr(ca->parent, addr + i, scratch + i * pbytes);
|
|
594
|
+
}
|
|
526
595
|
}
|
|
527
|
-
|
|
596
|
+
ALLOCV_END(holder);
|
|
528
597
|
}
|
|
529
598
|
}
|
|
530
599
|
}
|
|
@@ -556,7 +625,7 @@ ca_stride_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
556
625
|
ca_size_t composed_base;
|
|
557
626
|
ca_size_t rbytes;
|
|
558
627
|
ca_size_t *paddrs;
|
|
559
|
-
ca_size_t i
|
|
628
|
+
ca_size_t i;
|
|
560
629
|
int8_t k;
|
|
561
630
|
int all_aligned = 1;
|
|
562
631
|
volatile VALUE holder;
|
|
@@ -565,18 +634,12 @@ ca_stride_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
565
634
|
ca_stride_compose_to_root(ca, &root, composed_strides, &composed_base);
|
|
566
635
|
rbytes = root->bytes;
|
|
567
636
|
|
|
568
|
-
/*
|
|
569
|
-
|
|
570
|
-
root
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
simple reshape so addrs pass through, then CAGrid Y.1.b fast path
|
|
575
|
-
triggers on the recursive call, then inner CARefer simple reshape
|
|
576
|
-
pass-through to entity. Detection is O(ndim) + O(n). */
|
|
577
|
-
if ( n == ca->elements
|
|
578
|
-
&& ca->bytes == rbytes && composed_base == 0
|
|
579
|
-
&& ca_xfer_addrs_is_sequential_run(n, addrs, &base) && base == 0 ) {
|
|
637
|
+
/* Identity: same cell size, no offset, row-major composed strides (a
|
|
638
|
+
simple reshape / flatten of the root). A view address is then the
|
|
639
|
+
root address, whatever the addresses are, so the list goes through
|
|
640
|
+
as-is. Cascades through chains such as a[idx_2d] (outer reshape ->
|
|
641
|
+
CAGrid -> inner reshape -> entity). */
|
|
642
|
+
if ( ca->bytes == rbytes && composed_base == 0 ) {
|
|
580
643
|
ca_size_t s = rbytes;
|
|
581
644
|
int is_identity = 1;
|
|
582
645
|
for ( k = ca->ndim - 1; k >= 0; k-- ) {
|
|
@@ -589,36 +652,51 @@ ca_stride_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
589
652
|
}
|
|
590
653
|
}
|
|
591
654
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
ca_size_t idx[CA_RANK_MAX];
|
|
595
|
-
ca_size_t off = composed_base;
|
|
596
|
-
ca_addr2index((CArray *) ca, addrs[i], idx);
|
|
655
|
+
/* Whole-cell strides: translate in cell units, with no per-cell division. */
|
|
656
|
+
if ( ca->bytes == rbytes && composed_base % rbytes == 0 ) {
|
|
597
657
|
for ( k = 0; k < ca->ndim; k++ ) {
|
|
598
|
-
|
|
599
|
-
}
|
|
600
|
-
if ( ca->bytes == rbytes && off % rbytes == 0 ) {
|
|
601
|
-
paddrs[i] = off / rbytes;
|
|
602
|
-
}
|
|
603
|
-
else {
|
|
604
|
-
all_aligned = 0;
|
|
605
|
-
break;
|
|
658
|
+
if ( composed_strides[k] % rbytes != 0 ) { all_aligned = 0; break; }
|
|
606
659
|
}
|
|
607
660
|
}
|
|
661
|
+
else {
|
|
662
|
+
all_aligned = 0;
|
|
663
|
+
}
|
|
608
664
|
|
|
609
665
|
if ( all_aligned ) {
|
|
666
|
+
ca_size_t esteps[CA_RANK_MAX];
|
|
667
|
+
ca_size_t ebase = composed_base / rbytes;
|
|
668
|
+
for ( k = 0; k < ca->ndim; k++ ) {
|
|
669
|
+
esteps[k] = composed_strides[k] / rbytes;
|
|
670
|
+
}
|
|
671
|
+
paddrs = ALLOCV_N(ca_size_t, holder, n);
|
|
672
|
+
if ( ca->ndim == 1 ) {
|
|
673
|
+
for ( i = 0; i < n; i++ ) {
|
|
674
|
+
paddrs[i] = ebase + addrs[i] * esteps[0];
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
for ( i = 0; i < n; i++ ) {
|
|
679
|
+
ca_size_t idx[CA_RANK_MAX];
|
|
680
|
+
ca_size_t off = ebase;
|
|
681
|
+
ca_addr2index((CArray *) ca, addrs[i], idx);
|
|
682
|
+
for ( k = 0; k < ca->ndim; k++ ) {
|
|
683
|
+
off += idx[k] * esteps[k];
|
|
684
|
+
}
|
|
685
|
+
paddrs[i] = off;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
610
688
|
ca_xfer_addrs(root, n, paddrs, data, dir);
|
|
689
|
+
ALLOCV_END(holder);
|
|
690
|
+
return;
|
|
611
691
|
}
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
}
|
|
692
|
+
|
|
693
|
+
/* Byte-mismatched reinterpret: deliver cell by cell via xfer_index
|
|
694
|
+
(still no whole-view attach -- delegates one cell at a time). */
|
|
695
|
+
for ( i = 0; i < n; i++ ) {
|
|
696
|
+
ca_size_t idx[CA_RANK_MAX];
|
|
697
|
+
ca_addr2index((CArray *) ca, addrs[i], idx);
|
|
698
|
+
ca_stride_func_xfer_index(ca, idx, d + i * ca->bytes, dir);
|
|
620
699
|
}
|
|
621
|
-
ALLOCV_END(holder);
|
|
622
700
|
}
|
|
623
701
|
|
|
624
702
|
/* Optimised region delivery. Reached when ca->ptr == NULL (the central dispatcher handles the alias / attached case).
|
|
@@ -656,6 +734,7 @@ static void
|
|
|
656
734
|
ca_stride_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
657
735
|
ca_size_t *strides, void *data, int dir)
|
|
658
736
|
{
|
|
737
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
659
738
|
CAStride *ca = (CAStride *) ap;
|
|
660
739
|
CArray *root;
|
|
661
740
|
ca_size_t composed_strides[CA_RANK_MAX];
|
|
@@ -736,16 +815,49 @@ ca_stride_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
736
815
|
}
|
|
737
816
|
}
|
|
738
817
|
|
|
818
|
+
/* A reshape over a 1-D cold root (ndim != root->ndim): the request has no
|
|
819
|
+
box in the root's single axis, but the root cells it touches lie in one
|
|
820
|
+
flat span. Ask the root for that span once and walk the request over
|
|
821
|
+
it, as xfer_all does for the whole view. A PUT reads the span first so
|
|
822
|
+
the cells between the requested ones go back unchanged. */
|
|
823
|
+
if (aligned && !root->ptr && ca_func[root->obj_type].xfer_stride
|
|
824
|
+
&& ca->bytes == root->bytes && root->ndim == 1
|
|
825
|
+
&& root_base % root->bytes == 0) {
|
|
826
|
+
ca_size_t span_lo = root_base;
|
|
827
|
+
ca_size_t span_hi = root_base + ca->bytes;
|
|
828
|
+
for (k = 0; k < ndim; k++) {
|
|
829
|
+
ca_size_t ext = (counts[k] - 1) * root_stride[k];
|
|
830
|
+
if ( root_stride[k] >= 0 ) span_hi += ext;
|
|
831
|
+
else span_lo += ext;
|
|
832
|
+
}
|
|
833
|
+
if ( span_lo >= 0 && span_hi <= root->elements * root->bytes ) {
|
|
834
|
+
volatile VALUE holder;
|
|
835
|
+
ca_size_t rlo = span_lo / root->bytes;
|
|
836
|
+
ca_size_t rcount = (span_hi - span_lo) / root->bytes;
|
|
837
|
+
ca_size_t rstep = root->bytes;
|
|
838
|
+
char *scratch = ALLOCV_N(char, holder, rcount * root->bytes);
|
|
839
|
+
ca_xfer_stride(root, &rlo, &rcount, &rstep, scratch, CA_XFER_GET);
|
|
840
|
+
ca_xfer_strided_walk(scratch + (root_base - span_lo), ca->bytes, ndim,
|
|
841
|
+
counts, root_stride, d, dir);
|
|
842
|
+
if ( dir == CA_XFER_PUT ) {
|
|
843
|
+
ca_xfer_stride(root, &rlo, &rcount, &rstep, scratch, CA_XFER_PUT);
|
|
844
|
+
}
|
|
845
|
+
ALLOCV_END(holder);
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
|
|
739
850
|
/* Per-cell fallback (correct, no whole-view attach): byte-mismatch
|
|
740
851
|
reinterpret (CAField), a region that is not a box over our axes (a
|
|
741
852
|
transposed request onto a degenerate axis, a flat index over several
|
|
742
|
-
axes), or a cold non-entity root the
|
|
743
|
-
region to (
|
|
744
|
-
|
|
745
|
-
|
|
853
|
+
axes), or a cold non-entity root the branches above could not hand a
|
|
854
|
+
region to (a reshape over a root of two or more axes, or one with no
|
|
855
|
+
region slot). ca_stride_func_xfer_index composes one hop and
|
|
856
|
+
delegates to the parent. */
|
|
746
857
|
if (!aligned || !root->ptr) {
|
|
747
858
|
ca_size_t idx[CA_RANK_MAX], doff = 0;
|
|
748
859
|
for (k = 0; k < ndim; k++) idx[k] = 0;
|
|
860
|
+
/* empty: the slot returns on an empty region at its entry */
|
|
749
861
|
while (1) {
|
|
750
862
|
ca_size_t off = base_addr, vmidx[CA_RANK_MAX];
|
|
751
863
|
for (k = 0; k < ndim; k++) off += idx[k] * strides[k];
|
|
@@ -942,6 +1054,8 @@ ca_stride_func_fill_stride (void *ap, ca_size_t base, int8_t ndim,
|
|
|
942
1054
|
}
|
|
943
1055
|
|
|
944
1056
|
extern int ca_stride_is_contiguous (CAStride *ca); /* defined below; non-static for Tier A */
|
|
1057
|
+
static int ca_layout_is_contiguous (int8_t ndim, const ca_size_t *dim,
|
|
1058
|
+
const ca_size_t *strides, ca_size_t bytes);
|
|
945
1059
|
|
|
946
1060
|
/* Alias fast path:
|
|
947
1061
|
When the view's strides describe a contiguous row-major run, the
|
|
@@ -996,8 +1110,9 @@ extern int ca_stride_is_contiguous (CAStride *ca); /* defined below; non-stati
|
|
|
996
1110
|
composes a source down to its root.
|
|
997
1111
|
|
|
998
1112
|
Entities hold their own buffer. A CAStride-family root is one the fold
|
|
999
|
-
declined to walk through (a
|
|
1000
|
-
onward
|
|
1113
|
+
declined to walk through (a reshape over a transpose); its own attach
|
|
1114
|
+
folds onward from itself, so the answer is the one for the root it folds
|
|
1115
|
+
to. What is left is the
|
|
1001
1116
|
boundary views that compute or fetch their contents -- CAObject, the lazy
|
|
1002
1117
|
per-element transforms, whatever a companion gem installed -- and of those,
|
|
1003
1118
|
only the ones with an xfer_stride slot can answer a region request at all.
|
|
@@ -1009,10 +1124,41 @@ ca_root_lends_no_memory (void *ap)
|
|
|
1009
1124
|
CArray *root = (CArray *) ap;
|
|
1010
1125
|
|
|
1011
1126
|
if ( ca_is_entity(root) ) return 0;
|
|
1012
|
-
if ( ca_func[root->obj_type].attach == ca_stride_func.attach )
|
|
1127
|
+
if ( ca_func[root->obj_type].attach == ca_stride_func.attach ) {
|
|
1128
|
+
/* The fold stopped at a CAStride (a reshape over a transpose). Its
|
|
1129
|
+
own attach folds onward from itself, so it lends memory exactly when
|
|
1130
|
+
the root it folds to does: over a computed root, attaching it
|
|
1131
|
+
produces all of it. */
|
|
1132
|
+
CArray *below;
|
|
1133
|
+
ca_size_t cs[CA_RANK_MAX];
|
|
1134
|
+
ca_size_t base;
|
|
1135
|
+
ca_stride_compose_to_root((CAStride *) root, &below, cs, &base);
|
|
1136
|
+
return ca_root_lends_no_memory(below);
|
|
1137
|
+
}
|
|
1013
1138
|
return ca_func[root->obj_type].xfer_stride != NULL;
|
|
1014
1139
|
}
|
|
1015
1140
|
|
|
1141
|
+
/* The same question for the parent of a view that is not itself in the
|
|
1142
|
+
CAStride family (CAGrid, ...): whether the array its cells come from --
|
|
1143
|
+
the parent, or the root a CAStride parent folds to -- has no memory to
|
|
1144
|
+
lend. Like ca_root_lends_no_memory it asks only what those arrays are,
|
|
1145
|
+
so the lifecycle slots can rely on getting the same answer from attach
|
|
1146
|
+
to detach. */
|
|
1147
|
+
int
|
|
1148
|
+
ca_parent_lends_no_memory (void *ap)
|
|
1149
|
+
{
|
|
1150
|
+
CArray *parent = (CArray *) ap;
|
|
1151
|
+
|
|
1152
|
+
if ( ca_is_stride_family(parent) ) {
|
|
1153
|
+
CArray *root;
|
|
1154
|
+
ca_size_t cs[CA_RANK_MAX];
|
|
1155
|
+
ca_size_t base;
|
|
1156
|
+
ca_stride_compose_to_root((CAStride *) parent, &root, cs, &base);
|
|
1157
|
+
return ca_root_lends_no_memory(root);
|
|
1158
|
+
}
|
|
1159
|
+
return ca_root_lends_no_memory(parent);
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1016
1162
|
/* ca_attach_is_alias asks the same question from carray_core.c: a view whose
|
|
1017
1163
|
attach owns its buffer does not alias its parent, so writes through
|
|
1018
1164
|
ca->ptr need a ca_sync and callers must not assume otherwise. */
|
|
@@ -1032,7 +1178,16 @@ ca_stride_attach_aliases_root (CAStride *ca)
|
|
|
1032
1178
|
return 1;
|
|
1033
1179
|
}
|
|
1034
1180
|
ca_stride_compose_to_root(ca, &root, composed_strides, &composed_base);
|
|
1035
|
-
|
|
1181
|
+
/* The same test ca_stride_func_attach makes, and then the same question of
|
|
1182
|
+
the fold boundary. The leaf's own strides are in its parent's address
|
|
1183
|
+
space -- a block over a flip is contiguous there and not in the root --
|
|
1184
|
+
and a boundary that is itself a CAStride (a reshape over a transpose
|
|
1185
|
+
stops the fold) is one whose attach may build a buffer of its own, which
|
|
1186
|
+
this view would then alias without reaching the memory below it. */
|
|
1187
|
+
return !ca_root_lends_no_memory(root)
|
|
1188
|
+
&& ca_layout_is_contiguous(ca->ndim, ca->dim, composed_strides,
|
|
1189
|
+
ca->bytes)
|
|
1190
|
+
&& ca_attach_is_alias(root);
|
|
1036
1191
|
}
|
|
1037
1192
|
|
|
1038
1193
|
static void
|
|
@@ -1045,14 +1200,14 @@ ca_stride_func_allocate (void *ap)
|
|
|
1045
1200
|
|
|
1046
1201
|
ca_stride_compose_to_root(ca, &root, composed_strides, &composed_base);
|
|
1047
1202
|
if (ca_root_lends_no_memory(root)) {
|
|
1048
|
-
ca->ptr =
|
|
1203
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
1049
1204
|
return;
|
|
1050
1205
|
}
|
|
1051
1206
|
ca_attach(root);
|
|
1052
1207
|
if (ca_layout_is_contiguous(ca->ndim, ca->dim, composed_strides, ca->bytes)) {
|
|
1053
1208
|
ca->ptr = root->ptr + composed_base;
|
|
1054
1209
|
} else {
|
|
1055
|
-
ca->ptr =
|
|
1210
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
1056
1211
|
}
|
|
1057
1212
|
}
|
|
1058
1213
|
|
|
@@ -1081,14 +1236,9 @@ ca_stride_func_attach (void *ap)
|
|
|
1081
1236
|
transfer slots. */
|
|
1082
1237
|
char *buf = xmalloc(ca_length(ca));
|
|
1083
1238
|
void *args[2];
|
|
1084
|
-
int tag = 0;
|
|
1085
1239
|
args[0] = ca;
|
|
1086
1240
|
args[1] = buf;
|
|
1087
|
-
|
|
1088
|
-
if (tag) {
|
|
1089
|
-
xfree(buf);
|
|
1090
|
-
rb_jump_tag(tag);
|
|
1091
|
-
}
|
|
1241
|
+
ca_fill_or_xfree(buf, ca_stride_cold_fill, (VALUE) args); /* root stays cold */
|
|
1092
1242
|
ca->ptr = buf;
|
|
1093
1243
|
return;
|
|
1094
1244
|
}
|
|
@@ -1096,7 +1246,7 @@ ca_stride_func_attach (void *ap)
|
|
|
1096
1246
|
if (ca_layout_is_contiguous(ca->ndim, ca->dim, composed_strides, ca->bytes)) {
|
|
1097
1247
|
ca->ptr = root->ptr + composed_base;
|
|
1098
1248
|
} else {
|
|
1099
|
-
ca->ptr =
|
|
1249
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
1100
1250
|
ca_stride_xfer_with_layout(ca, 0, root->ptr + composed_base, composed_strides);
|
|
1101
1251
|
}
|
|
1102
1252
|
}
|
|
@@ -1223,6 +1373,8 @@ ca_stride_func_xfer_all (void *ap, void *data, int dir)
|
|
|
1223
1373
|
char *ptr0 = ca->ptr;
|
|
1224
1374
|
char *ptr = (char *) data;
|
|
1225
1375
|
|
|
1376
|
+
if ( ca->elements == 0 ) return;
|
|
1377
|
+
|
|
1226
1378
|
ca_stride_compose_to_root(ca, &root, composed_strides, &composed_base);
|
|
1227
1379
|
|
|
1228
1380
|
/* Partial materialise: when the fold stops at a cold boundary view that knows how to deliver a region (has an
|
|
@@ -1324,6 +1476,81 @@ ca_stride_func_xfer_all (void *ap, void *data, int dir)
|
|
|
1324
1476
|
return;
|
|
1325
1477
|
}
|
|
1326
1478
|
|
|
1479
|
+
/* A request the bridges above could not express as a region goes to the
|
|
1480
|
+
root as the list of its cells. A write never makes a round trip of
|
|
1481
|
+
the whole root: a root that repeats its cells (CATile) would have the
|
|
1482
|
+
stale copies the caller never wrote land after the written ones, and a
|
|
1483
|
+
root that converts on the way would bring the unwritten cells back
|
|
1484
|
+
changed. A read does not make the root produce cells it was not asked
|
|
1485
|
+
for, unless it is asked for as many as it has. The root's addresses
|
|
1486
|
+
are whole elements here, as in the region hand-off above. */
|
|
1487
|
+
if ( ( dir == CA_XFER_PUT || ca->elements < root->elements )
|
|
1488
|
+
&& ca->bytes == root->bytes && composed_base % root->bytes == 0 ) {
|
|
1489
|
+
volatile VALUE holder;
|
|
1490
|
+
ca_size_t *addrs = ALLOCV_N(ca_size_t, holder, ca->elements);
|
|
1491
|
+
ca_size_t idx[CA_RANK_MAX], n = 0;
|
|
1492
|
+
int8_t k;
|
|
1493
|
+
for (k = 0; k < ca->ndim; k++) idx[k] = 0;
|
|
1494
|
+
/* empty: the slot returns on an empty view at its entry */
|
|
1495
|
+
while (1) {
|
|
1496
|
+
ca_size_t off = composed_base;
|
|
1497
|
+
for (k = 0; k < ca->ndim; k++) off += idx[k] * composed_strides[k];
|
|
1498
|
+
addrs[n++] = off / root->bytes;
|
|
1499
|
+
k = ca->ndim - 1;
|
|
1500
|
+
while (k >= 0) { if (++idx[k] < ca->dim[k]) break; idx[k] = 0; k--; }
|
|
1501
|
+
if (k < 0) break;
|
|
1502
|
+
}
|
|
1503
|
+
ca_xfer_addrs(root, n, addrs, ptr, dir);
|
|
1504
|
+
ALLOCV_END(holder);
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
/* A read through a byte reinterpret (CAField, a refer to another width)
|
|
1509
|
+
over a cold root: the root's addresses are not this view's cells, but
|
|
1510
|
+
each cell lies in a run of whole root elements. Ask the root for those
|
|
1511
|
+
elements and cut the cell's bytes out of them. A write keeps the
|
|
1512
|
+
whole-root round trip below: two cells can share a root element, and
|
|
1513
|
+
writing back each one's copy of it would drop the other's bytes. */
|
|
1514
|
+
if ( dir == CA_XFER_GET && ca->elements > 0 && ca->bytes != root->bytes
|
|
1515
|
+
&& ca_func[root->obj_type].xfer_stride ) {
|
|
1516
|
+
volatile VALUE ah = 0, sh = 0;
|
|
1517
|
+
ca_size_t rb = root->bytes, cb = ca->bytes;
|
|
1518
|
+
ca_size_t per = (cb + rb - 1) / rb + 1;
|
|
1519
|
+
ca_size_t *addrs = ALLOCV_N(ca_size_t, ah, ca->elements * per);
|
|
1520
|
+
char *scratch;
|
|
1521
|
+
ca_size_t idx[CA_RANK_MAX], n = 0, i;
|
|
1522
|
+
ca_size_t *first = ALLOCV_N(ca_size_t, sh, ca->elements);
|
|
1523
|
+
int8_t k;
|
|
1524
|
+
int ok = 1;
|
|
1525
|
+
for (k = 0; k < ca->ndim; k++) idx[k] = 0;
|
|
1526
|
+
for (i = 0; ok; i++) {
|
|
1527
|
+
ca_size_t off = composed_base, e, e_end;
|
|
1528
|
+
for (k = 0; k < ca->ndim; k++) off += idx[k] * composed_strides[k];
|
|
1529
|
+
if ( off < 0 || off + cb > root->elements * rb ) { ok = 0; break; }
|
|
1530
|
+
first[i] = n * rb + off % rb;
|
|
1531
|
+
for (e = off / rb, e_end = (off + cb - 1) / rb; e <= e_end; e++) {
|
|
1532
|
+
addrs[n++] = e;
|
|
1533
|
+
}
|
|
1534
|
+
k = ca->ndim - 1;
|
|
1535
|
+
while (k >= 0) { if (++idx[k] < ca->dim[k]) break; idx[k] = 0; k--; }
|
|
1536
|
+
if (k < 0) break;
|
|
1537
|
+
}
|
|
1538
|
+
if ( ok && n < root->elements ) {
|
|
1539
|
+
volatile VALUE dh = 0;
|
|
1540
|
+
scratch = ALLOCV_N(char, dh, n * rb);
|
|
1541
|
+
ca_xfer_addrs(root, n, addrs, scratch, CA_XFER_GET);
|
|
1542
|
+
for (i = 0; i < ca->elements; i++) {
|
|
1543
|
+
memcpy(ptr + i * cb, scratch + first[i], cb);
|
|
1544
|
+
}
|
|
1545
|
+
ALLOCV_END(dh);
|
|
1546
|
+
ALLOCV_END(sh);
|
|
1547
|
+
ALLOCV_END(ah);
|
|
1548
|
+
return;
|
|
1549
|
+
}
|
|
1550
|
+
ALLOCV_END(sh);
|
|
1551
|
+
ALLOCV_END(ah);
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1327
1554
|
/* Cold root without an xfer_stride slot, or an ndim mismatch the bridges
|
|
1328
1555
|
above could not express: materialise the root into scratch via
|
|
1329
1556
|
ca_xfer_all and run the direct strided gather/scatter against that.
|
|
@@ -1342,11 +1569,14 @@ ca_stride_func_xfer_all (void *ap, void *data, int dir)
|
|
|
1342
1569
|
ca_stride_xfer_with_layout(ca, (dir == CA_XFER_PUT) ? 1 : 0,
|
|
1343
1570
|
root->ptr + composed_base, composed_strides);
|
|
1344
1571
|
ca->ptr = ptr0;
|
|
1572
|
+
/* Put root->ptr back before the PUT: the PUT can raise (a lazy
|
|
1573
|
+
backing's sync failing), and the scratch is gone once this frame
|
|
1574
|
+
is. */
|
|
1575
|
+
root->ptr = root_ptr_saved;
|
|
1345
1576
|
if ( dir == CA_XFER_PUT ) {
|
|
1346
1577
|
/* Push back scratch (modified by scatter) to root. */
|
|
1347
1578
|
ca_xfer_all(root, root_scratch, CA_XFER_PUT);
|
|
1348
1579
|
}
|
|
1349
|
-
root->ptr = root_ptr_saved;
|
|
1350
1580
|
ALLOCV_END(holder);
|
|
1351
1581
|
}
|
|
1352
1582
|
}
|
|
@@ -1849,6 +2079,7 @@ rb_cs_initialize_copy (VALUE self, VALUE other)
|
|
|
1849
2079
|
{
|
|
1850
2080
|
CAStride *ca, *cs;
|
|
1851
2081
|
TypedData_Get_Struct(self, CAStride, &castride_data_type, ca);
|
|
2082
|
+
ca_check_uninitialized(ca);
|
|
1852
2083
|
TypedData_Get_Struct(other, CAStride, &castride_data_type, cs);
|
|
1853
2084
|
/* Pool framework: self was created by rb_cs_s_allocate (= TypedData_Make_Struct),
|
|
1854
2085
|
so ca->_pool is NULL. Wire up the pool before ca_stride_setup so the
|
|
@@ -1927,9 +2158,10 @@ rb_ca_as_strided (int argc, VALUE *argv, VALUE self)
|
|
|
1927
2158
|
"shape (%ld) and strides (%ld) length mismatch",
|
|
1928
2159
|
len, RARRAY_LEN(rstrides));
|
|
1929
2160
|
}
|
|
1930
|
-
if (len <= 0
|
|
2161
|
+
if (len <= 0) {
|
|
1931
2162
|
rb_raise(rb_eArgError, "invalid ndim %ld", len);
|
|
1932
2163
|
}
|
|
2164
|
+
ca_check_rank_fits(len, NULL);
|
|
1933
2165
|
ndim = (int8_t) len;
|
|
1934
2166
|
for (i = 0; i < len; i++) {
|
|
1935
2167
|
shape[i] = NUM2SIZE(RARRAY_AREF(rshape, i));
|
|
@@ -1939,8 +2171,10 @@ rb_ca_as_strided (int argc, VALUE *argv, VALUE self)
|
|
|
1939
2171
|
base_offset = NUM2SIZE(roffset);
|
|
1940
2172
|
}
|
|
1941
2173
|
|
|
1942
|
-
|
|
1943
|
-
|
|
2174
|
+
VALUE obj = rb_ca_stride_new(self, parent->data_type, parent->bytes,
|
|
2175
|
+
ndim, shape, strides, base_offset);
|
|
2176
|
+
CA_WRAPPER_LIFT(obj, self, parent);
|
|
2177
|
+
return obj;
|
|
1944
2178
|
}
|
|
1945
2179
|
|
|
1946
2180
|
/* sliding_windows(*window, step: nil) -- overlapping-window view over every
|
|
@@ -1965,11 +2199,7 @@ rb_ca_sliding_windows (int argc, VALUE *argv, VALUE self)
|
|
|
1965
2199
|
TypedData_Get_Struct(self, CArray, &carray_data_type, parent);
|
|
1966
2200
|
|
|
1967
2201
|
ndim = parent->ndim;
|
|
1968
|
-
|
|
1969
|
-
rb_raise(rb_eArgError,
|
|
1970
|
-
"sliding_windows: result rank %d exceeds CA_RANK_MAX (%d)",
|
|
1971
|
-
2 * (int) ndim, CA_RANK_MAX);
|
|
1972
|
-
}
|
|
2202
|
+
ca_check_rank_fits(2 * (long) ndim, "sliding_windows");
|
|
1973
2203
|
|
|
1974
2204
|
rb_scan_args(argc, argv, "*:", (VALUE *) &rposary, (VALUE *) &ropt);
|
|
1975
2205
|
if (! NIL_P(ropt)) {
|
|
@@ -2051,8 +2281,10 @@ rb_ca_sliding_windows (int argc, VALUE *argv, VALUE self)
|
|
|
2051
2281
|
outstrides[ndim + i] = parent_byte_stride[i];
|
|
2052
2282
|
}
|
|
2053
2283
|
|
|
2054
|
-
|
|
2055
|
-
|
|
2284
|
+
VALUE obj = rb_ca_stride_new(self, parent->data_type, parent->bytes,
|
|
2285
|
+
(int8_t)(2 * ndim), outdim, outstrides, 0);
|
|
2286
|
+
CA_WRAPPER_LIFT(obj, self, parent);
|
|
2287
|
+
return obj;
|
|
2056
2288
|
}
|
|
2057
2289
|
|
|
2058
2290
|
/* unfold(*window, step: nil) -- sliding_windows over the leading `S` axes
|
|
@@ -2111,11 +2343,7 @@ rb_ca_unfold (int argc, VALUE *argv, VALUE self)
|
|
|
2111
2343
|
|
|
2112
2344
|
ntrail = ndim - nspatial;
|
|
2113
2345
|
outrank = (int) ndim + (int) nspatial;
|
|
2114
|
-
|
|
2115
|
-
rb_raise(rb_eArgError,
|
|
2116
|
-
"unfold: result rank %d exceeds CA_RANK_MAX (%d)",
|
|
2117
|
-
outrank, CA_RANK_MAX);
|
|
2118
|
-
}
|
|
2346
|
+
ca_check_rank_fits(outrank, "unfold");
|
|
2119
2347
|
|
|
2120
2348
|
if (NIL_P(rstep)) {
|
|
2121
2349
|
for (i = 0; i < nspatial; i++) step[i] = 1;
|
|
@@ -2173,8 +2401,10 @@ rb_ca_unfold (int argc, VALUE *argv, VALUE self)
|
|
|
2173
2401
|
outstrides[2 * nspatial + i] = parent_byte_stride[nspatial + i];
|
|
2174
2402
|
}
|
|
2175
2403
|
|
|
2176
|
-
|
|
2177
|
-
|
|
2404
|
+
VALUE obj = rb_ca_stride_new(self, parent->data_type, parent->bytes,
|
|
2405
|
+
(int8_t) outrank, outdim, outstrides, 0);
|
|
2406
|
+
CA_WRAPPER_LIFT(obj, self, parent);
|
|
2407
|
+
return obj;
|
|
2178
2408
|
}
|
|
2179
2409
|
|
|
2180
2410
|
/* block_view(*block) -- non-overlapping tile view. Parent [d0..dN-1]
|
|
@@ -2197,11 +2427,7 @@ rb_ca_block_view (int argc, VALUE *argv, VALUE self)
|
|
|
2197
2427
|
TypedData_Get_Struct(self, CArray, &carray_data_type, parent);
|
|
2198
2428
|
|
|
2199
2429
|
ndim = parent->ndim;
|
|
2200
|
-
|
|
2201
|
-
rb_raise(rb_eArgError,
|
|
2202
|
-
"block_view: result rank %d exceeds CA_RANK_MAX (%d)",
|
|
2203
|
-
2 * (int) ndim, CA_RANK_MAX);
|
|
2204
|
-
}
|
|
2430
|
+
ca_check_rank_fits(2 * (long) ndim, "block_view");
|
|
2205
2431
|
|
|
2206
2432
|
rb_scan_args(argc, argv, "*:", (VALUE *) &rposary, (VALUE *) &ropt);
|
|
2207
2433
|
rb_reject_options(ropt);
|
|
@@ -2258,8 +2484,12 @@ rb_ca_block_view (int argc, VALUE *argv, VALUE self)
|
|
|
2258
2484
|
outstrides[ndim + i] = parent_byte_stride[i];
|
|
2259
2485
|
}
|
|
2260
2486
|
|
|
2261
|
-
|
|
2262
|
-
|
|
2487
|
+
VALUE obj = rb_ca_stride_new(self, parent->data_type, parent->bytes,
|
|
2488
|
+
(int8_t)(2 * ndim), outdim, outstrides, 0);
|
|
2489
|
+
/* The Face stays on top, as for every view: a tile reduction over a
|
|
2490
|
+
bare block_view compared the Face's surface bytes. */
|
|
2491
|
+
CA_WRAPPER_LIFT(obj, self, parent);
|
|
2492
|
+
return obj;
|
|
2263
2493
|
}
|
|
2264
2494
|
|
|
2265
2495
|
/* defined in ca_obj_transpose.c */
|
|
@@ -2300,7 +2530,7 @@ rb_ca_dim_view (int argc, VALUE *argv, VALUE self)
|
|
|
2300
2530
|
(int) n_iter, (int) ndim);
|
|
2301
2531
|
}
|
|
2302
2532
|
for (i = 0; i < n_iter; i++) {
|
|
2303
|
-
iter_axes[i] =
|
|
2533
|
+
iter_axes[i] = ca_normalize_axis_arg(RARRAY_AREF(aary, i), ndim, NULL);
|
|
2304
2534
|
}
|
|
2305
2535
|
}
|
|
2306
2536
|
else if (nargs >= 1) {
|
|
@@ -2311,7 +2541,7 @@ rb_ca_dim_view (int argc, VALUE *argv, VALUE self)
|
|
|
2311
2541
|
}
|
|
2312
2542
|
n_iter = (int8_t) nargs;
|
|
2313
2543
|
for (i = 0; i < n_iter; i++) {
|
|
2314
|
-
iter_axes[i] =
|
|
2544
|
+
iter_axes[i] = ca_normalize_axis_arg(RARRAY_AREF(rposary, i), ndim, NULL);
|
|
2315
2545
|
}
|
|
2316
2546
|
}
|
|
2317
2547
|
else {
|
|
@@ -2319,23 +2549,16 @@ rb_ca_dim_view (int argc, VALUE *argv, VALUE self)
|
|
|
2319
2549
|
"dim_view: at least one iteration axis required");
|
|
2320
2550
|
}
|
|
2321
2551
|
|
|
2322
|
-
/*
|
|
2552
|
+
/* The axes are normalized as they are read; check distinctness. */
|
|
2323
2553
|
for (i = 0; i < ndim; i++) seen[i] = 0;
|
|
2324
2554
|
for (i = 0; i < n_iter; i++) {
|
|
2325
2555
|
ca_size_t a = iter_axes[i];
|
|
2326
|
-
if (a < 0) a += ndim;
|
|
2327
|
-
if (a < 0 || a >= ndim) {
|
|
2328
|
-
rb_raise(rb_eArgError,
|
|
2329
|
-
"dim_view: axis %lld out of range for ndim %d",
|
|
2330
|
-
(long long) iter_axes[i], (int) ndim);
|
|
2331
|
-
}
|
|
2332
2556
|
if (seen[a]) {
|
|
2333
2557
|
rb_raise(rb_eArgError,
|
|
2334
2558
|
"dim_view: duplicate iteration axis %lld",
|
|
2335
2559
|
(long long) a);
|
|
2336
2560
|
}
|
|
2337
2561
|
seen[a] = 1;
|
|
2338
|
-
iter_axes[i] = a;
|
|
2339
2562
|
}
|
|
2340
2563
|
|
|
2341
2564
|
/* imap: iter axes first (in given order), then remaining axes
|
|
@@ -2407,12 +2630,8 @@ rb_ca_flip_axis (VALUE self, long axis)
|
|
|
2407
2630
|
rb_check_carray_object(self);
|
|
2408
2631
|
TypedData_Get_Struct(self, CArray, &carray_data_type, parent);
|
|
2409
2632
|
int8_t ndim = parent->ndim;
|
|
2410
|
-
long a = (axis
|
|
2411
|
-
|
|
2412
|
-
rb_raise(rb_eArgError,
|
|
2413
|
-
"flip_axis: axis %ld out of range for ndim %d",
|
|
2414
|
-
axis, (int) ndim);
|
|
2415
|
-
}
|
|
2633
|
+
long a = rb_ca_normalize_axis_for_ndim(axis, ndim, /* axis-check: a long from a C caller */
|
|
2634
|
+
"flip_axis");
|
|
2416
2635
|
int8_t flip[CA_RANK_MAX] = {0};
|
|
2417
2636
|
flip[a] = 1;
|
|
2418
2637
|
return rb_ca_flip_build_view(self, parent, flip);
|
|
@@ -2439,8 +2658,8 @@ rb_ca_flip (int argc, VALUE *argv, VALUE self)
|
|
|
2439
2658
|
|
|
2440
2659
|
for (i = 0; i < ndim; i++) flip[i] = 0;
|
|
2441
2660
|
|
|
2442
|
-
if (nargs == 0) {
|
|
2443
|
-
/* No args: flip every axis. */
|
|
2661
|
+
if (nargs == 0 || (nargs == 1 && NIL_P(RARRAY_AREF(rposary, 0)))) {
|
|
2662
|
+
/* No args, or a lone nil: flip every axis. */
|
|
2444
2663
|
for (i = 0; i < ndim; i++) flip[i] = 1;
|
|
2445
2664
|
n_axes = ndim;
|
|
2446
2665
|
}
|
|
@@ -2454,7 +2673,7 @@ rb_ca_flip (int argc, VALUE *argv, VALUE self)
|
|
|
2454
2673
|
(int) n_axes, (int) ndim);
|
|
2455
2674
|
}
|
|
2456
2675
|
for (i = 0; i < n_axes; i++) {
|
|
2457
|
-
axes[i] =
|
|
2676
|
+
axes[i] = ca_normalize_axis_arg(RARRAY_AREF(aary, i), ndim, NULL);
|
|
2458
2677
|
}
|
|
2459
2678
|
}
|
|
2460
2679
|
else {
|
|
@@ -2465,18 +2684,12 @@ rb_ca_flip (int argc, VALUE *argv, VALUE self)
|
|
|
2465
2684
|
}
|
|
2466
2685
|
n_axes = (int8_t) nargs;
|
|
2467
2686
|
for (i = 0; i < n_axes; i++) {
|
|
2468
|
-
axes[i] =
|
|
2687
|
+
axes[i] = ca_normalize_axis_arg(RARRAY_AREF(rposary, i), ndim, NULL);
|
|
2469
2688
|
}
|
|
2470
2689
|
}
|
|
2471
2690
|
|
|
2472
2691
|
for (i = 0; i < n_axes; i++) {
|
|
2473
2692
|
ca_size_t a = axes[i];
|
|
2474
|
-
if (a < 0) a += ndim;
|
|
2475
|
-
if (a < 0 || a >= ndim) {
|
|
2476
|
-
rb_raise(rb_eArgError,
|
|
2477
|
-
"flip: axis %lld out of range for ndim %d",
|
|
2478
|
-
(long long) axes[i], (int) ndim);
|
|
2479
|
-
}
|
|
2480
2693
|
if (flip[a]) {
|
|
2481
2694
|
rb_raise(rb_eArgError,
|
|
2482
2695
|
"flip: duplicate axis %lld",
|
|
@@ -2550,18 +2763,8 @@ rb_ca_diagonal (int argc, VALUE *argv, VALUE self)
|
|
|
2550
2763
|
rb_raise(rb_eArgError,
|
|
2551
2764
|
"diagonal: axis: must be an Array of 2 integers");
|
|
2552
2765
|
}
|
|
2553
|
-
ai =
|
|
2554
|
-
aj =
|
|
2555
|
-
if (ai < 0) ai += ndim;
|
|
2556
|
-
if (aj < 0) aj += ndim;
|
|
2557
|
-
if (ai < 0 || ai >= ndim) {
|
|
2558
|
-
rb_raise(rb_eArgError, "diagonal: axis[0] out of range for ndim %d",
|
|
2559
|
-
(int) ndim);
|
|
2560
|
-
}
|
|
2561
|
-
if (aj < 0 || aj >= ndim) {
|
|
2562
|
-
rb_raise(rb_eArgError, "diagonal: axis[1] out of range for ndim %d",
|
|
2563
|
-
(int) ndim);
|
|
2564
|
-
}
|
|
2766
|
+
ai = ca_normalize_axis_arg(RARRAY_AREF(raxis, 0), ndim, NULL);
|
|
2767
|
+
aj = ca_normalize_axis_arg(RARRAY_AREF(raxis, 1), ndim, NULL);
|
|
2565
2768
|
if (ai == aj) {
|
|
2566
2769
|
rb_raise(rb_eArgError, "diagonal: axis[0] and axis[1] must be distinct");
|
|
2567
2770
|
}
|
|
@@ -2589,7 +2792,9 @@ rb_ca_diagonal (int argc, VALUE *argv, VALUE self)
|
|
|
2589
2792
|
base_offset = offset * parent_byte_stride[aj];
|
|
2590
2793
|
}
|
|
2591
2794
|
else {
|
|
2592
|
-
|
|
2795
|
+
/* compare before negating: -offset overflows for the most negative
|
|
2796
|
+
offset */
|
|
2797
|
+
ca_size_t neg = ( offset <= -parent->dim[ai] ) ? parent->dim[ai] : -offset;
|
|
2593
2798
|
if (neg >= parent->dim[ai]) {
|
|
2594
2799
|
diag_len = 0;
|
|
2595
2800
|
}
|
|
@@ -2600,6 +2805,9 @@ rb_ca_diagonal (int argc, VALUE *argv, VALUE self)
|
|
|
2600
2805
|
}
|
|
2601
2806
|
base_offset = neg * parent_byte_stride[ai];
|
|
2602
2807
|
}
|
|
2808
|
+
if (diag_len == 0) {
|
|
2809
|
+
base_offset = 0; /* an offset past the edge can overflow the product */
|
|
2810
|
+
}
|
|
2603
2811
|
|
|
2604
2812
|
/* build output: kept axes (in original order), then diagonal axis */
|
|
2605
2813
|
out_k = 0;
|