carray 2.0.0 → 3.0.0
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 +5 -25
- data/CHANGELOG.md +16 -0
- data/LICENSE +1 -1
- data/NEWS.md +3 -0
- data/README.md +128 -44
- data/carray.gemspec +22 -24
- data/ext/ca_array_pool.c +91 -0
- data/ext/ca_axis_descriptor.h +186 -0
- data/ext/ca_axis_dispatch.c +924 -0
- data/ext/ca_axis_group.c +1208 -0
- data/ext/ca_bincmp_dispatch.c +76 -0
- data/ext/ca_bincmp_dispatch.h +85 -0
- data/ext/ca_binop_dispatch.c +125 -0
- data/ext/ca_binop_dispatch.h +159 -0
- data/ext/ca_categorical_iterator.c +1375 -0
- data/ext/ca_compare.c +94 -0
- data/ext/ca_compare.h +26 -0
- data/ext/ca_composite_dispatch.c +414 -0
- data/ext/ca_composite_dispatch.h +116 -0
- data/ext/ca_for_buffer.h +96 -0
- data/ext/ca_for_each_element.h +241 -0
- data/ext/ca_group_iter.c +304 -0
- data/ext/ca_iter_substrate.h +325 -0
- data/ext/ca_kernel_iterator.c +4321 -0
- data/ext/ca_kernel_iterator.h +2603 -0
- data/ext/ca_moncmp_dispatch.c +37 -0
- data/ext/ca_moncmp_dispatch.h +62 -0
- data/ext/ca_monop_dispatch.c +200 -0
- data/ext/ca_monop_dispatch.h +235 -0
- data/ext/ca_obj_array.c +355 -359
- data/ext/ca_obj_bincmp.c +809 -0
- data/ext/ca_obj_binop.c +892 -0
- data/ext/ca_obj_bitarray.c +369 -164
- data/ext/ca_obj_bitfield.c +294 -234
- data/ext/ca_obj_block.c +189 -711
- data/ext/ca_obj_byte_swap.c +766 -0
- data/ext/ca_obj_const_string.c +965 -0
- data/ext/ca_obj_face.c +670 -0
- data/ext/ca_obj_face.h +247 -0
- data/ext/ca_obj_fake.c +228 -100
- data/ext/ca_obj_farray.c +54 -441
- data/ext/ca_obj_field.c +82 -529
- data/ext/ca_obj_fixlen_string.c +306 -0
- data/ext/ca_obj_grid.c +858 -440
- data/ext/ca_obj_meld.c +1034 -0
- data/ext/ca_obj_moncmp.c +569 -0
- data/ext/ca_obj_monop.c +1111 -0
- data/ext/ca_obj_object.c +774 -298
- data/ext/ca_obj_record.c +468 -0
- data/ext/ca_obj_reduce.c +97 -82
- data/ext/ca_obj_refer.c +569 -459
- data/ext/ca_obj_remap.c +475 -0
- data/ext/ca_obj_repeat.c +92 -477
- data/ext/ca_obj_roll.c +616 -0
- data/ext/ca_obj_select.c +344 -296
- data/ext/ca_obj_select_axis.c +1296 -0
- data/ext/ca_obj_shift.c +230 -792
- data/ext/ca_obj_source.c +78 -0
- data/ext/ca_obj_stack.c +1173 -0
- data/ext/ca_obj_stride.c +2501 -0
- data/ext/ca_obj_string.c +268 -0
- data/ext/ca_obj_tile.c +614 -0
- data/ext/ca_obj_time.c +546 -0
- data/ext/ca_obj_timedelta.c +435 -0
- data/ext/ca_obj_transpose.c +62 -516
- data/ext/ca_obj_triop.c +746 -0
- data/ext/ca_obj_unbound_repeat.c +208 -241
- data/ext/ca_obj_window.c +1131 -563
- data/ext/ca_op_byte_swap.c +175 -0
- data/ext/ca_op_ipower.c +319 -0
- data/ext/ca_op_powi.h +88 -0
- data/ext/ca_sort_kernels.h +132 -0
- data/ext/ca_sweep_engine.c +430 -0
- data/ext/ca_sweep_engine.h +157 -0
- data/ext/ca_transform_common.c +228 -0
- data/ext/ca_triop_dispatch.c +55 -0
- data/ext/ca_triop_dispatch.h +62 -0
- data/ext/carray.h +795 -402
- data/ext/carray_access.c +831 -711
- data/ext/carray_attribute.c +98 -330
- data/ext/carray_bincount.c +255 -0
- data/ext/carray_broadcast.c +283 -0
- data/ext/carray_call_cfunc.c +1360 -828
- data/ext/carray_call_cfunc.h +160 -0
- data/ext/carray_cast.c +1212 -301
- data/ext/carray_cast_func.rb +81 -40
- data/ext/carray_class.c +53 -63
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +350 -346
- data/ext/carray_copy.c +156 -268
- data/ext/carray_core.c +1342 -199
- data/ext/carray_count.c +312 -0
- data/ext/carray_data_type.c +43 -19
- data/ext/carray_element.c +585 -213
- data/ext/carray_factorize.c +2542 -0
- data/ext/carray_generate.c +230 -559
- data/ext/carray_histogram.c +490 -0
- data/ext/carray_hold.c +228 -0
- data/ext/carray_index_classifier.c +1035 -0
- data/ext/carray_index_classifier.h +27 -0
- data/ext/carray_internal.h +120 -0
- data/ext/carray_kernels_bincmp.c +4445 -0
- data/ext/carray_kernels_binop.c +10979 -0
- data/ext/carray_kernels_init.c +36 -0
- data/ext/carray_kernels_map.c +3466 -0
- data/ext/carray_kernels_moncmp.c +2096 -0
- data/ext/carray_kernels_monop.c +18312 -0
- data/ext/carray_kernels_reduce_aggregate.c +25836 -0
- data/ext/carray_kernels_reduce_boolean.c +329 -0
- data/ext/carray_kernels_reduce_cumulative.c +14592 -0
- data/ext/carray_kernels_reduce_extreme.c +16947 -0
- data/ext/carray_kernels_reduce_variance.c +3909 -0
- data/ext/carray_kernels_scan.c +3692 -0
- data/ext/carray_kernels_search.c +32137 -0
- data/ext/carray_kernels_sort.c +10625 -0
- data/ext/carray_kernels_triop.c +1391 -0
- data/ext/carray_lazy.c +567 -0
- data/ext/carray_loop.c +88 -200
- data/ext/carray_mask.c +848 -154
- data/ext/carray_math_kernel.h +120 -0
- data/ext/carray_mathfunc.c +10 -241
- data/ext/carray_median_percentile.c +1257 -0
- data/ext/carray_memory_view.c +1625 -0
- data/ext/carray_operator.c +1526 -318
- data/ext/carray_order.c +664 -1394
- data/ext/carray_partition.c +416 -0
- data/ext/carray_random.c +518 -0
- data/ext/carray_scatter.c +357 -0
- data/ext/carray_slab.c +1219 -0
- data/ext/carray_slab.h +84 -0
- data/ext/carray_sort.c +829 -0
- data/ext/carray_sort_kernel.c +620 -0
- data/ext/carray_struct.c +695 -0
- data/ext/carray_test.c +343 -229
- data/ext/carray_undef.c +34 -17
- data/ext/carray_utils.c +175 -74
- data/ext/extconf.rb +216 -55
- data/ext/mk_call_cfunc.rb +480 -0
- data/ext/mkkernel.rb +8842 -0
- data/ext/ruby_carray.c +202 -101
- data/ext/version.h +4 -14
- data/ext/version.rb +5 -13
- data/lib/carray/arrow_tensor.rb +401 -0
- data/lib/carray/attribute.rb +166 -0
- data/lib/carray/autoload_carray.rb +220 -0
- data/lib/carray/autoload_method_extension.rb +44 -0
- data/lib/carray/axis_group.rb +711 -0
- data/lib/carray/basics.rb +481 -0
- data/lib/carray/bincount_nd.rb +358 -0
- data/lib/carray/block_iterator.rb +604 -0
- data/lib/carray/boolean_reduce.rb +109 -0
- data/lib/carray/categorical.rb +561 -0
- data/lib/carray/categorical_iterator.rb +1062 -0
- data/lib/carray/complex.rb +150 -0
- data/lib/carray/conditional.rb +216 -0
- data/lib/carray/const_string.rb +228 -0
- data/lib/carray/construct.rb +139 -328
- data/lib/carray/core_extensions.rb +240 -0
- data/lib/carray/data_type_extension.rb +233 -0
- data/lib/carray/fixlen_string.rb +95 -0
- data/lib/carray/frame/concat.rb +132 -0
- data/lib/carray/frame/convert.rb +95 -0
- data/lib/carray/frame/csv_parser.rb +211 -0
- data/lib/carray/frame/frame.rb +649 -0
- data/lib/carray/frame/group.rb +186 -0
- data/lib/carray/frame/io.rb +164 -0
- data/lib/carray/frame/join.rb +248 -0
- data/lib/carray/frame/records.rb +99 -0
- data/lib/carray/frame/sort.rb +113 -0
- data/lib/carray/frame/verbs.rb +299 -0
- data/lib/carray/frame.rb +16 -0
- data/lib/carray/histogram.rb +512 -0
- data/lib/carray/inspect.rb +37 -20
- data/lib/carray/iterator.rb +57 -349
- data/lib/carray/lazy.rb +889 -0
- data/lib/carray/mask_gap_fill.rb +200 -0
- data/lib/carray/math.rb +78 -342
- data/lib/carray/meld_reduce.rb +289 -0
- data/lib/carray/methods/align_addr.rb +116 -0
- data/lib/carray/methods/bin.rb +128 -0
- data/lib/carray/methods/bincount.rb +87 -0
- data/lib/carray/methods/bit_string.rb +92 -0
- data/lib/carray/methods/broadcast.rb +63 -0
- data/lib/carray/methods/choose.rb +39 -0
- data/lib/carray/methods/composition.rb +280 -0
- data/lib/carray/methods/gather_nd.rb +206 -0
- data/lib/carray/methods/index.rb +39 -0
- data/lib/carray/methods/insert_block.rb +99 -0
- data/lib/carray/methods/is_in.rb +141 -0
- data/lib/carray/methods/join.rb +90 -0
- data/lib/carray/methods/locate_addr.rb +47 -0
- data/lib/carray/methods/mask_duplicates.rb +41 -0
- data/lib/carray/methods/meshgrid.rb +91 -0
- data/lib/carray/methods/mode.rb +126 -0
- data/lib/carray/methods/nunique.rb +46 -0
- data/lib/carray/methods/resize.rb +56 -0
- data/lib/carray/methods/snap.rb +156 -0
- data/lib/carray/methods/string_format.rb +57 -0
- data/lib/carray/methods/unique.rb +47 -0
- data/lib/carray/methods/value_counts.rb +71 -0
- data/lib/carray/mkmf.rb +124 -101
- data/lib/carray/runtime.rb +108 -0
- data/lib/carray/serialize.rb +478 -167
- data/lib/carray/slab_iterator.rb +292 -0
- data/lib/carray/stack.rb +291 -0
- data/lib/carray/string.rb +56 -180
- data/lib/carray/string_operation_extension.rb +289 -0
- data/lib/carray/struct.rb +335 -323
- data/lib/carray/struct_builder.rb +697 -0
- data/lib/carray/table.rb +41 -2
- data/lib/carray/time.rb +2255 -38
- data/lib/carray/window_iterator.rb +655 -0
- data/lib/carray.rb +55 -57
- metadata +163 -130
- data/Rakefile +0 -51
- data/TODO.md +0 -18
- data/ext/ca_iter_block.c +0 -257
- data/ext/ca_iter_dimension.c +0 -299
- data/ext/ca_iter_window.c +0 -214
- data/ext/ca_obj_mapping.c +0 -644
- data/ext/carray_iterator.c +0 -641
- data/ext/carray_math.rb +0 -850
- data/ext/carray_numeric.c +0 -259
- data/ext/carray_sort_addr.c +0 -254
- data/ext/carray_stat.c +0 -2100
- data/ext/carray_stat_proc.rb +0 -1999
- data/ext/mkmath.rb +0 -741
- data/ext/ruby_ccomplex.c +0 -509
- data/ext/ruby_float_func.c +0 -86
- data/lib/carray/array.rb +0 -8
- data/lib/carray/autoload/autoload_base.rb +0 -19
- data/lib/carray/autoload/autoload_gem_cairo.rb +0 -9
- data/lib/carray/autoload/autoload_gem_ffi.rb +0 -9
- data/lib/carray/autoload/autoload_gem_gnuplot.rb +0 -2
- data/lib/carray/autoload/autoload_gem_io_csv.rb +0 -14
- data/lib/carray/autoload/autoload_gem_io_pg.rb +0 -6
- data/lib/carray/autoload/autoload_gem_io_sqlite3.rb +0 -12
- data/lib/carray/autoload/autoload_gem_narray.rb +0 -10
- data/lib/carray/autoload/autoload_gem_numo_narray.rb +0 -15
- data/lib/carray/autoload/autoload_gem_opencv.rb +0 -16
- data/lib/carray/autoload/autoload_gem_random.rb +0 -8
- data/lib/carray/autoload/autoload_gem_rmagick.rb +0 -23
- data/lib/carray/autoload/autoload_gem_zimg.rb +0 -3
- data/lib/carray/autoload/autoload_io_imagemagick.rb +0 -6
- data/lib/carray/autoload/autoload_math_histogram.rb +0 -5
- data/lib/carray/autoload/autoload_math_recurrence.rb +0 -6
- data/lib/carray/autoload/autoload_object_iterator.rb +0 -1
- data/lib/carray/autoload/autoload_object_link.rb +0 -1
- data/lib/carray/autoload/autoload_object_pack.rb +0 -2
- data/lib/carray/autoload.rb +0 -141
- data/lib/carray/basic.rb +0 -191
- data/lib/carray/broadcast.rb +0 -101
- data/lib/carray/compose.rb +0 -315
- data/lib/carray/convert.rb +0 -115
- data/lib/carray/info.rb +0 -110
- data/lib/carray/io/imagemagick.rb +0 -235
- data/lib/carray/mask.rb +0 -102
- data/lib/carray/math/histogram.rb +0 -177
- data/lib/carray/math/recurrence.rb +0 -93
- data/lib/carray/object/ca_obj_iterator.rb +0 -50
- data/lib/carray/object/ca_obj_link.rb +0 -50
- data/lib/carray/object/ca_obj_pack.rb +0 -99
- data/lib/carray/obsolete.rb +0 -256
- data/lib/carray/ordering.rb +0 -181
- data/lib/carray/testing.rb +0 -51
- data/lib/carray/transform.rb +0 -109
- data/misc/Methods.ja.md +0 -182
- data/misc/NOTE +0 -51
- data/spec/Classes/CABitfield_spec.rb +0 -58
- data/spec/Classes/CABlockIterator_spec.rb +0 -114
- data/spec/Classes/CABlock_spec.rb +0 -205
- data/spec/Classes/CAField_spec.rb +0 -39
- data/spec/Classes/CAGrid_spec.rb +0 -75
- data/spec/Classes/CAMap_spec.rb +0 -0
- data/spec/Classes/CAMapping_spec.rb +0 -105
- data/spec/Classes/CAObject_attribute_spec.rb +0 -33
- data/spec/Classes/CAObject_spec.rb +0 -33
- data/spec/Classes/CARefer_spec.rb +0 -93
- data/spec/Classes/CARepeat_spec.rb +0 -65
- data/spec/Classes/CASelect_spec.rb +0 -22
- data/spec/Classes/CAShift_spec.rb +0 -16
- data/spec/Classes/CAStruct_spec.rb +0 -71
- data/spec/Classes/CATranspose_spec.rb +0 -60
- data/spec/Classes/CAUnboudRepeat_spec.rb +0 -102
- data/spec/Classes/CAWindow_spec.rb +0 -54
- data/spec/Classes/CAWrap_spec.rb +0 -8
- data/spec/Classes/CArray_spec.rb +0 -184
- data/spec/Classes/CScalar_spec.rb +0 -55
- data/spec/Classes/ex1.rb +0 -46
- data/spec/Features/feature_130_spec.rb +0 -19
- data/spec/Features/feature_attributes_spec.rb +0 -280
- data/spec/Features/feature_boolean_spec.rb +0 -98
- data/spec/Features/feature_broadcast.rb +0 -116
- data/spec/Features/feature_cast_function.rb +0 -19
- data/spec/Features/feature_cast_spec.rb +0 -33
- data/spec/Features/feature_class_spec.rb +0 -84
- data/spec/Features/feature_complex_spec.rb +0 -42
- data/spec/Features/feature_composite_spec.rb +0 -124
- data/spec/Features/feature_convert_spec.rb +0 -46
- data/spec/Features/feature_copy_spec.rb +0 -123
- data/spec/Features/feature_creation_spec.rb +0 -84
- data/spec/Features/feature_element_spec.rb +0 -144
- data/spec/Features/feature_extream_spec.rb +0 -54
- data/spec/Features/feature_generate_spec.rb +0 -74
- data/spec/Features/feature_index_spec.rb +0 -69
- data/spec/Features/feature_mask_spec.rb +0 -580
- data/spec/Features/feature_math_spec.rb +0 -97
- data/spec/Features/feature_order_spec.rb +0 -146
- data/spec/Features/feature_ref_store_spec.rb +0 -209
- data/spec/Features/feature_serialization_spec.rb +0 -125
- data/spec/Features/feature_stat_spec.rb +0 -397
- data/spec/Features/feature_virtual_spec.rb +0 -48
- data/spec/Features/method_eq_spec.rb +0 -81
- data/spec/Features/method_is_nan_spec.rb +0 -12
- data/spec/Features/method_map_spec.rb +0 -54
- data/spec/Features/method_max_with.rb +0 -20
- data/spec/Features/method_min_with.rb +0 -19
- data/spec/Features/method_ne_spec.rb +0 -18
- data/spec/Features/method_project_spec.rb +0 -188
- data/spec/Features/method_ref_spec.rb +0 -27
- data/spec/Features/method_round_spec.rb +0 -11
- data/spec/Features/method_s_linspace_spec.rb +0 -48
- data/spec/Features/method_s_span_spec.rb +0 -14
- data/spec/Features/method_seq_spec.rb +0 -47
- data/spec/Features/method_sort_with.rb +0 -43
- data/spec/Features/method_sorted_with.rb +0 -29
- data/spec/Features/method_span_spec.rb +0 -42
- data/spec/Features/method_wrap_readonly_spec.rb +0 -43
- data/spec/UnitTest/test_CAVirtual.rb +0 -214
- data/spec/spec_all.rb +0 -10
- data/utils/ca_ase.rb +0 -21
- data/utils/ca_methods.rb +0 -15
- data/utils/cast_checker.rb +0 -30
- data/utils/convert_test.rb +0 -73
- data/utils/extract_yard.rb +0 -22
- data/utils/guess_shape.rb +0 -76
- data/utils/monkey_patch_methods.rb +0 -62
- data/utils/remove_resource_fork.sh +0 -5
data/ext/ca_obj_grid.c
CHANGED
|
@@ -1,15 +1,41 @@
|
|
|
1
1
|
/* ---------------------------------------------------------------------------
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
CAGrid -- a coordinate-selected view: each axis independently picks a
|
|
4
|
+
set of parent indices (whole axis, a contiguous range, or an arbitrary
|
|
5
|
+
index list) and the view is their Cartesian product.
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
Gather / scatter / fill_value all go through the shared per-axis
|
|
8
|
+
descriptor engine in ca_axis_dispatch.c; this file emits the per-axis
|
|
9
|
+
descriptor (ca_grid_describe_axes) and holds the region-delivery
|
|
10
|
+
(xfer_stride / xfer_addrs) and fold_stride paths. Sibling of
|
|
11
|
+
ca_obj_select_axis.c (CASelectAxis), which rb_ca_grid routes to for the
|
|
12
|
+
single-boolean-axis slab-copy fast path.
|
|
8
13
|
|
|
9
14
|
---------------------------------------------------------------------------- */
|
|
10
15
|
|
|
11
16
|
#include "carray.h"
|
|
12
17
|
|
|
18
|
+
/* Per-axis tagged kind. Each axis is either STRIDE (start/step/count,
|
|
19
|
+
no allocation) or INDEX (an owned ca_size_t index snapshot). A Range
|
|
20
|
+
argument is detected at rb_ca_grid and stored as STRIDE, so its
|
|
21
|
+
arithmetic-progression structure is available to axis-merge; a nil-arg
|
|
22
|
+
axis is STRIDE(0, dim, 1) and allocates nothing. */
|
|
23
|
+
typedef enum {
|
|
24
|
+
CAG_AXIS_STRIDE = 0,
|
|
25
|
+
CAG_AXIS_INDEX = 1
|
|
26
|
+
} cag_axis_kind_t;
|
|
27
|
+
|
|
28
|
+
typedef struct {
|
|
29
|
+
cag_axis_kind_t kind;
|
|
30
|
+
ca_size_t count; /* = ca->dim[k] (view's output size along axis) */
|
|
31
|
+
/* STRIDE-only */
|
|
32
|
+
ca_size_t start;
|
|
33
|
+
ca_size_t step;
|
|
34
|
+
/* INDEX-only. Owned in the non-share case (xfree'd by free_ca_grid),
|
|
35
|
+
aliased in the share case (parent owns; CA_FLAG_SHARE_INDEX). */
|
|
36
|
+
ca_size_t *indices;
|
|
37
|
+
} cag_axis_t;
|
|
38
|
+
|
|
13
39
|
typedef struct {
|
|
14
40
|
int16_t obj_type;
|
|
15
41
|
int8_t data_type;
|
|
@@ -20,21 +46,60 @@ typedef struct {
|
|
|
20
46
|
ca_size_t *dim;
|
|
21
47
|
char *ptr;
|
|
22
48
|
CArray *mask;
|
|
49
|
+
char *_pool; /* framework-managed pool buffer (NULL = legacy ALLOC_N path). */
|
|
23
50
|
CArray *parent;
|
|
24
51
|
uint32_t attach;
|
|
25
52
|
uint8_t nosync;
|
|
26
53
|
/* -------------*/
|
|
27
|
-
|
|
28
|
-
int8_t *contig;
|
|
54
|
+
cag_axis_t *axes; /* [ndim], owned (non-share) or aliased (share) */
|
|
29
55
|
} CAGrid;
|
|
30
56
|
|
|
57
|
+
static size_t
|
|
58
|
+
ca_grid_dsize (const void *ap)
|
|
59
|
+
{
|
|
60
|
+
const CAGrid *ca = (const CAGrid *) ap;
|
|
61
|
+
size_t total = sizeof(CAGrid)
|
|
62
|
+
+ ca->ndim * sizeof(ca_size_t) /* dim */
|
|
63
|
+
+ ca->ndim * sizeof(cag_axis_t); /* axes */
|
|
64
|
+
/* indices for INDEX axes (variable per-axis count; STRIDE axes
|
|
65
|
+
contribute 0 — the big win vs. the legacy identity-allocation
|
|
66
|
+
pattern). */
|
|
67
|
+
int8_t k;
|
|
68
|
+
for (k = 0; k < ca->ndim; k++) {
|
|
69
|
+
if (ca->axes[k].kind == CAG_AXIS_INDEX && ca->axes[k].indices) {
|
|
70
|
+
total += ca->axes[k].count * sizeof(ca_size_t);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return total;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* Pool framework hooks: CAGrid owns dim (ndim ca_size_t), axes (ndim
|
|
77
|
+
cag_axis_t), and per-INDEX-axis indices buffers. Only `dim` is always
|
|
78
|
+
owned and ndim-sized, so only dim moves into the _pool; `axes` is
|
|
79
|
+
sometimes aliased (CA_FLAG_SHARE_INDEX) and the per-axis `indices`
|
|
80
|
+
buffers are variable-size, so both stay on their own ALLOC_N path
|
|
81
|
+
(cf. CAWindow's fill). */
|
|
82
|
+
static size_t
|
|
83
|
+
ca_grid_pool_bytes (int8_t ndim)
|
|
84
|
+
{
|
|
85
|
+
ca_size_t n = (ndim > 0) ? ndim : 1;
|
|
86
|
+
return (size_t) n * sizeof(ca_size_t);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
static void
|
|
90
|
+
ca_grid_pool_init (void *ap, int8_t ndim)
|
|
91
|
+
{
|
|
92
|
+
CAGrid *ca = (CAGrid *) ap;
|
|
93
|
+
ca->dim = (ca_size_t *) ca->_pool;
|
|
94
|
+
}
|
|
95
|
+
|
|
31
96
|
const rb_data_type_t cagrid_data_type = {
|
|
32
|
-
.parent = &
|
|
97
|
+
.parent = &caview_data_type,
|
|
33
98
|
.wrap_struct_name = "CAGrid",
|
|
34
99
|
.function = {
|
|
35
100
|
.dmark = ca_mark,
|
|
36
101
|
.dfree = ca_free,
|
|
37
|
-
.dsize =
|
|
102
|
+
.dsize = ca_grid_dsize,
|
|
38
103
|
.dcompact = NULL
|
|
39
104
|
},
|
|
40
105
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
@@ -46,7 +111,7 @@ const rb_data_type_t cagrid_mask_data_type = {
|
|
|
46
111
|
.function = {
|
|
47
112
|
.dmark = NULL,
|
|
48
113
|
.dfree = ca_free_nop,
|
|
49
|
-
.dsize =
|
|
114
|
+
.dsize = ca_grid_dsize,
|
|
50
115
|
.dcompact = NULL
|
|
51
116
|
},
|
|
52
117
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
@@ -55,40 +120,47 @@ const rb_data_type_t cagrid_mask_data_type = {
|
|
|
55
120
|
static VALUE rb_cCAGrid;
|
|
56
121
|
static VALUE rb_cCAGridMask;
|
|
57
122
|
|
|
58
|
-
/* yard:
|
|
59
|
-
class CAGrid < CAVirtual # :nodoc:
|
|
60
|
-
end
|
|
61
|
-
*/
|
|
62
|
-
|
|
63
123
|
static int8_t CA_OBJ_GRID;
|
|
64
124
|
|
|
125
|
+
/* Setup: caller passes ndim + per-axis protos (cag_axis_t). Copies the
|
|
126
|
+
fields and, for INDEX axes, snapshots the indices into an owned buffer.
|
|
127
|
+
The share path (share=1, from initialize_copy and create_mask) aliases
|
|
128
|
+
the caller's protos buffer instead, tying its lifetime to the source
|
|
129
|
+
CAGrid (free_ca_grid skips the xfree under CA_FLAG_SHARE_INDEX). */
|
|
65
130
|
int
|
|
66
|
-
ca_grid_setup (CAGrid *ca, CArray *parent,
|
|
67
|
-
|
|
131
|
+
ca_grid_setup (CAGrid *ca, CArray *parent, int8_t ndim,
|
|
132
|
+
cag_axis_t *protos, int share)
|
|
68
133
|
{
|
|
69
|
-
int8_t
|
|
70
|
-
|
|
134
|
+
int8_t k;
|
|
135
|
+
int8_t data_type;
|
|
71
136
|
ca_size_t elements, bytes;
|
|
72
|
-
ca_size_t j, k;
|
|
73
137
|
double length;
|
|
74
|
-
|
|
138
|
+
ca_size_t *dim0;
|
|
75
139
|
|
|
140
|
+
CA_ASSUME(ndim >= 0 && ndim <= CA_RANK_MAX); /* bound loops/allocs over [CA_RANK_MAX] arrays */
|
|
76
141
|
data_type = parent->data_type;
|
|
77
|
-
ndim = parent->ndim;
|
|
78
142
|
bytes = parent->bytes;
|
|
79
143
|
dim0 = parent->dim;
|
|
80
144
|
|
|
145
|
+
/* parent->ndim should equal ndim (= number of axes provided).
|
|
146
|
+
rb_ca_grid pads with nil when fewer args are given, so by the
|
|
147
|
+
time we get here ndim == parent->ndim. */
|
|
148
|
+
if ( ndim != parent->ndim ) {
|
|
149
|
+
rb_raise(rb_eArgError,
|
|
150
|
+
"CAGrid: ndim mismatch (%d args vs parent->ndim %d)",
|
|
151
|
+
(int) ndim, (int) parent->ndim);
|
|
152
|
+
}
|
|
153
|
+
|
|
81
154
|
elements = 1;
|
|
82
155
|
length = bytes;
|
|
83
|
-
for (
|
|
84
|
-
if (
|
|
85
|
-
rb_raise(rb_eRuntimeError, "negative size for %
|
|
156
|
+
for (k = 0; k < ndim; k++) {
|
|
157
|
+
if (protos[k].count < 0) {
|
|
158
|
+
rb_raise(rb_eRuntimeError, "negative size for %d-th dimension", k);
|
|
86
159
|
}
|
|
87
|
-
elements *=
|
|
88
|
-
length *=
|
|
160
|
+
elements *= protos[k].count;
|
|
161
|
+
length *= protos[k].count;
|
|
89
162
|
}
|
|
90
|
-
|
|
91
|
-
if ( length > CA_LENGTH_MAX ) {
|
|
163
|
+
if (length > CA_LENGTH_MAX) {
|
|
92
164
|
rb_raise(rb_eRuntimeError, "too large byte length");
|
|
93
165
|
}
|
|
94
166
|
|
|
@@ -100,87 +172,72 @@ ca_grid_setup (CAGrid *ca, CArray *parent, ca_size_t *dim,
|
|
|
100
172
|
ca->elements = elements;
|
|
101
173
|
ca->ptr = NULL;
|
|
102
174
|
ca->mask = NULL;
|
|
103
|
-
ca->
|
|
104
|
-
|
|
175
|
+
if ( ! ca->_pool ) {
|
|
176
|
+
ca->dim = ALLOC_N(ca_size_t, ndim);
|
|
177
|
+
}
|
|
105
178
|
ca->parent = parent;
|
|
106
179
|
ca->attach = 0;
|
|
107
180
|
ca->nosync = 0;
|
|
108
181
|
|
|
182
|
+
for (k = 0; k < ndim; k++) ca->dim[k] = protos[k].count;
|
|
183
|
+
|
|
109
184
|
if ( share ) {
|
|
185
|
+
/* Alias the protos buffer; lifetime tied to the source CAGrid
|
|
186
|
+
(initialize_copy and create_mask call sites). free_ca_grid
|
|
187
|
+
skips the axes / indices xfree under SHARE_INDEX. */
|
|
110
188
|
ca_set_flag(ca, CA_FLAG_SHARE_INDEX);
|
|
111
|
-
ca->
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
ca_size_t n;
|
|
128
|
-
ca->grid[i] = carray_new(CA_SIZE, 1, &gsize, 0, NULL);
|
|
129
|
-
m = (boolean8_t *)grid[i]->mask->ptr;
|
|
130
|
-
n = 0;
|
|
131
|
-
for (j=0; j<grid[i]->elements; j++) {
|
|
132
|
-
if ( ! *m ) {
|
|
133
|
-
k = ((ca_size_t*)grid[i]->ptr)[j];
|
|
134
|
-
CA_CHECK_INDEX(k, dim0[i]);
|
|
135
|
-
((ca_size_t*)ca->grid[i]->ptr)[n] = k;
|
|
136
|
-
n++;
|
|
137
|
-
}
|
|
138
|
-
m++;
|
|
139
|
-
}
|
|
140
|
-
ca->contig[i] = 0;
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
ca->grid[i] = ca_template(grid[i]);
|
|
144
|
-
for (j=0; j<grid[i]->elements; j++) {
|
|
145
|
-
k = ((ca_size_t*)grid[i]->ptr)[j];
|
|
146
|
-
CA_CHECK_INDEX(k, dim0[i]);
|
|
147
|
-
((ca_size_t*)ca->grid[i]->ptr)[j] = k;
|
|
148
|
-
}
|
|
149
|
-
ca->contig[i] = 0;
|
|
189
|
+
ca->axes = protos;
|
|
190
|
+
} else {
|
|
191
|
+
ca->axes = ALLOC_N(cag_axis_t, ndim);
|
|
192
|
+
for (k = 0; k < ndim; k++) {
|
|
193
|
+
ca->axes[k].kind = protos[k].kind;
|
|
194
|
+
ca->axes[k].count = protos[k].count;
|
|
195
|
+
if (protos[k].kind == CAG_AXIS_STRIDE) {
|
|
196
|
+
ca->axes[k].start = protos[k].start;
|
|
197
|
+
ca->axes[k].step = protos[k].step;
|
|
198
|
+
ca->axes[k].indices = NULL;
|
|
199
|
+
/* Bounds check: first and last parent index must be in range. */
|
|
200
|
+
if (protos[k].count > 0) {
|
|
201
|
+
ca_size_t first = protos[k].start;
|
|
202
|
+
ca_size_t last = first + (protos[k].count - 1) * protos[k].step;
|
|
203
|
+
CA_CHECK_INDEX(first, dim0[k]);
|
|
204
|
+
if (protos[k].count > 1) CA_CHECK_INDEX(last, dim0[k]);
|
|
150
205
|
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
ca->
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
206
|
+
} else {
|
|
207
|
+
ca->axes[k].start = 0;
|
|
208
|
+
ca->axes[k].step = 0;
|
|
209
|
+
ca->axes[k].indices = ALLOC_N(ca_size_t,
|
|
210
|
+
protos[k].count > 0 ? protos[k].count : 1);
|
|
211
|
+
ca_size_t j;
|
|
212
|
+
for (j = 0; j < protos[k].count; j++) {
|
|
213
|
+
ca_size_t v = protos[k].indices[j];
|
|
214
|
+
CA_CHECK_INDEX(v, dim0[k]);
|
|
215
|
+
ca->axes[k].indices[j] = v;
|
|
158
216
|
}
|
|
159
|
-
ca->contig[i] = 1;
|
|
160
217
|
}
|
|
161
218
|
}
|
|
162
219
|
}
|
|
163
220
|
|
|
164
|
-
if (
|
|
165
|
-
|
|
221
|
+
if ( ca_has_mask(parent) ) {
|
|
222
|
+
ca_create_mask(ca);
|
|
166
223
|
}
|
|
167
224
|
|
|
168
225
|
return 0;
|
|
169
226
|
}
|
|
170
227
|
|
|
171
228
|
CAGrid *
|
|
172
|
-
ca_grid_new (CArray *parent,
|
|
229
|
+
ca_grid_new (CArray *parent, int8_t ndim, cag_axis_t *protos)
|
|
173
230
|
{
|
|
174
|
-
CAGrid *ca =
|
|
175
|
-
ca_grid_setup(ca, parent,
|
|
231
|
+
CAGrid *ca = (CAGrid *) ca_array_alloc(CA_OBJ_GRID, ndim);
|
|
232
|
+
ca_grid_setup(ca, parent, ndim, protos, 0);
|
|
176
233
|
return ca;
|
|
177
234
|
}
|
|
178
235
|
|
|
179
236
|
CAGrid *
|
|
180
|
-
ca_grid_new_share (CArray *parent,
|
|
237
|
+
ca_grid_new_share (CArray *parent, int8_t ndim, cag_axis_t *protos)
|
|
181
238
|
{
|
|
182
|
-
CAGrid *ca =
|
|
183
|
-
ca_grid_setup(ca, parent,
|
|
239
|
+
CAGrid *ca = (CAGrid *) ca_array_alloc(CA_OBJ_GRID, ndim);
|
|
240
|
+
ca_grid_setup(ca, parent, ndim, protos, 1);
|
|
184
241
|
return ca;
|
|
185
242
|
}
|
|
186
243
|
|
|
@@ -188,99 +245,375 @@ static void
|
|
|
188
245
|
free_ca_grid (void *ap)
|
|
189
246
|
{
|
|
190
247
|
CAGrid *ca = (CAGrid *) ap;
|
|
191
|
-
ca_size_t i;
|
|
192
248
|
if ( ca != NULL ) {
|
|
193
249
|
ca_free(ca->mask);
|
|
194
|
-
if ( ! (ca->flags & CA_FLAG_SHARE_INDEX)) {
|
|
195
|
-
|
|
196
|
-
for (
|
|
197
|
-
|
|
250
|
+
if ( ! (ca->flags & CA_FLAG_SHARE_INDEX) ) {
|
|
251
|
+
int8_t k;
|
|
252
|
+
for (k = 0; k < ca->ndim; k++) {
|
|
253
|
+
if ( ca->axes[k].kind == CAG_AXIS_INDEX && ca->axes[k].indices ) {
|
|
254
|
+
xfree(ca->axes[k].indices);
|
|
255
|
+
}
|
|
198
256
|
}
|
|
199
|
-
xfree(ca->
|
|
257
|
+
xfree(ca->axes);
|
|
258
|
+
}
|
|
259
|
+
/* dim is the only field in the pool; axes/indices freed above. */
|
|
260
|
+
if ( ca->_pool ) {
|
|
261
|
+
ca_array_free(ca); /* dim + struct */
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
xfree(ca->dim);
|
|
265
|
+
xfree(ca);
|
|
200
266
|
}
|
|
201
|
-
xfree(ca->dim);
|
|
202
|
-
xfree(ca);
|
|
203
267
|
}
|
|
204
268
|
}
|
|
205
269
|
|
|
206
270
|
/* ------------------------------------------------------------------- */
|
|
207
271
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
272
|
+
/* gather, scatter, and broadcast-fill all run through the shared
|
|
273
|
+
descriptor engine in ca_axis_dispatch.c via the func_* dispatchers
|
|
274
|
+
below; this file only translates CAGrid state into the descriptor
|
|
275
|
+
(ca_grid_describe_axes). */
|
|
211
276
|
|
|
212
277
|
static void *
|
|
213
278
|
ca_grid_func_clone (void *ap)
|
|
214
279
|
{
|
|
215
280
|
CAGrid *ca = (CAGrid *) ap;
|
|
216
|
-
return ca_grid_new_share(ca->parent, ca->
|
|
281
|
+
return ca_grid_new_share(ca->parent, ca->ndim, ca->axes);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/* Per-axis parent-index lookup. STRIDE = one multiply, INDEX = one
|
|
285
|
+
indirect load. */
|
|
286
|
+
static inline ca_size_t
|
|
287
|
+
cag_parent_index_for (const cag_axis_t *ax, ca_size_t i)
|
|
288
|
+
{
|
|
289
|
+
if (ax->kind == CAG_AXIS_STRIDE) {
|
|
290
|
+
return ax->start + i * ax->step;
|
|
291
|
+
}
|
|
292
|
+
return ax->indices[i];
|
|
217
293
|
}
|
|
218
294
|
|
|
219
|
-
|
|
220
|
-
|
|
295
|
+
/* per-cell logic lives in ca_grid_func_xfer_index; forward-declared for
|
|
296
|
+
the region-delivery paths below. */
|
|
297
|
+
static void ca_grid_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir);
|
|
298
|
+
|
|
299
|
+
/* dir-unified per-cell: translate per-axis idx via the grid descriptors,
|
|
300
|
+
then re-delegate to the parent's xfer_index. */
|
|
301
|
+
static void
|
|
302
|
+
ca_grid_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
221
303
|
{
|
|
222
304
|
CAGrid *ca = (CAGrid *) ap;
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
305
|
+
ca_size_t idx0[CA_RANK_MAX];
|
|
306
|
+
int8_t i;
|
|
307
|
+
for (i = 0; i < ca->ndim; i++) {
|
|
308
|
+
idx0[i] = cag_parent_index_for(&ca->axes[i], idx[i]);
|
|
309
|
+
}
|
|
310
|
+
ca_xfer_index(ca->parent, idx0, data, dir);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/* Batched address gather/scatter. Per-axis index remap
|
|
314
|
+
(cag_parent_index_for), always in-bounds; duplicate parent addrs
|
|
315
|
+
(duplicate grid indices) scatter last-write-wins. ONE parent
|
|
316
|
+
ca_xfer_addrs call -- no whole-view attach.
|
|
317
|
+
|
|
318
|
+
Fast path: when addrs form the whole-view sequential run
|
|
319
|
+
[0..elements-1] and parent.ptr is present, rebuild the full sub_axes
|
|
320
|
+
descriptor via ca_grid_describe_axes and dispatch through
|
|
321
|
+
ca_axis_dispatch_gather/_scatter directly, skipping the per-cell remap
|
|
322
|
+
loop. */
|
|
323
|
+
static void
|
|
324
|
+
ca_grid_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
325
|
+
void *data, int dir)
|
|
326
|
+
{
|
|
327
|
+
CAGrid *ca = (CAGrid *) ap;
|
|
328
|
+
CArray *parent = ca->parent;
|
|
329
|
+
ca_size_t *paddrs;
|
|
330
|
+
ca_size_t i, base;
|
|
331
|
+
int8_t k;
|
|
332
|
+
volatile VALUE holder;
|
|
333
|
+
|
|
334
|
+
/* Opportunistic fast path. ca_resolve_attached_root_via_identity lifts
|
|
335
|
+
parent->ptr through an identity CAStride compose-fold (handles a
|
|
336
|
+
flatten[idx].reshape(*) chain etc.). */
|
|
337
|
+
if ( n == ca->elements
|
|
338
|
+
&& ca_xfer_addrs_is_sequential_run(n, addrs, &base) && base == 0 ) {
|
|
339
|
+
CArray *eff_parent = ca_resolve_attached_root_via_identity(parent);
|
|
340
|
+
if ( eff_parent->ptr ) {
|
|
341
|
+
ca_axis_desc_t sub_axes[CA_RANK_MAX];
|
|
342
|
+
ca_size_t parent_axis_dims[CA_RANK_MAX];
|
|
343
|
+
ca_grid_describe_axes(ca, sub_axes, parent_axis_dims);
|
|
344
|
+
if ( dir == CA_XFER_GET ) {
|
|
345
|
+
ca_axis_dispatch_gather(eff_parent, parent_axis_dims, sub_axes, ca->ndim,
|
|
346
|
+
ca->bytes, ca->elements, NULL, (char *) data);
|
|
347
|
+
} else {
|
|
348
|
+
ca_axis_dispatch_scatter(eff_parent, parent_axis_dims, sub_axes, ca->ndim,
|
|
349
|
+
ca->bytes, ca->elements, (char *) data);
|
|
350
|
+
}
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
227
353
|
}
|
|
228
|
-
|
|
229
|
-
|
|
354
|
+
|
|
355
|
+
/* Per-cell remap fallback (arbitrary addrs, view parent, partial). */
|
|
356
|
+
paddrs = ALLOCV_N(ca_size_t, holder, n);
|
|
357
|
+
for (i = 0; i < n; i++) {
|
|
358
|
+
ca_size_t vidx[CA_RANK_MAX], pidx[CA_RANK_MAX];
|
|
359
|
+
ca_addr2index((CArray *) ca, addrs[i], vidx);
|
|
360
|
+
for (k = 0; k < ca->ndim; k++) pidx[k] = cag_parent_index_for(&ca->axes[k], vidx[k]);
|
|
361
|
+
paddrs[i] = ca_index2addr(ca->parent, pidx);
|
|
230
362
|
}
|
|
363
|
+
ca_xfer_addrs(ca->parent, n, paddrs, data, dir);
|
|
364
|
+
ALLOCV_END(holder);
|
|
231
365
|
}
|
|
232
366
|
|
|
233
|
-
|
|
234
|
-
|
|
367
|
+
/* fold_stride: a CAGrid folds into the stride chain when every axis is
|
|
368
|
+
STRIDE or singleton-INDEX (count == 1). STRIDE axis k contributes
|
|
369
|
+
stride step_k*pstride_k and base start_k*pstride_k; a singleton INDEX
|
|
370
|
+
axis bakes indices_k[0]*pstride_k into the base (count 1 -> no stride).
|
|
371
|
+
A multi-element INDEX axis is a true gather -> decline (the grid
|
|
372
|
+
becomes the fold boundary, delivered by the descriptor engine).
|
|
373
|
+
Synthesises a CAStride over grid->parent and composes f through it. */
|
|
374
|
+
static int
|
|
375
|
+
ca_grid_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
235
376
|
{
|
|
236
|
-
CAGrid
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
377
|
+
CAGrid *g = (CAGrid *) ap;
|
|
378
|
+
CArray *parent = g->parent;
|
|
379
|
+
ca_size_t pstride[CA_RANK_MAX];
|
|
380
|
+
ca_size_t synth_strides[CA_RANK_MAX];
|
|
381
|
+
ca_size_t synth_base = 0;
|
|
382
|
+
ca_size_t next_strides[CA_RANK_MAX];
|
|
383
|
+
ca_size_t next_base;
|
|
384
|
+
ca_size_t s;
|
|
385
|
+
CAStride tmp, synth;
|
|
386
|
+
int8_t k;
|
|
387
|
+
|
|
388
|
+
for (k = 0; k < g->ndim; k++) {
|
|
389
|
+
if (g->axes[k].kind == CAG_AXIS_INDEX && g->axes[k].count != 1) {
|
|
390
|
+
return 0; /* multi-INDEX axis -> true gather, decline */
|
|
246
391
|
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/* parent row-major byte strides (g->bytes == parent->bytes) */
|
|
395
|
+
s = g->bytes;
|
|
396
|
+
for (k = g->ndim - 1; k >= 0; k--) {
|
|
397
|
+
pstride[k] = s;
|
|
398
|
+
s *= parent->dim[k];
|
|
399
|
+
}
|
|
247
400
|
|
|
248
|
-
|
|
249
|
-
|
|
401
|
+
for (k = 0; k < g->ndim; k++) {
|
|
402
|
+
if (g->axes[k].kind == CAG_AXIS_STRIDE) {
|
|
403
|
+
synth_strides[k] = g->axes[k].step * pstride[k];
|
|
404
|
+
synth_base += g->axes[k].start * pstride[k];
|
|
250
405
|
}
|
|
251
|
-
else {
|
|
252
|
-
|
|
406
|
+
else { /* singleton INDEX: count == 1, position baked into base */
|
|
407
|
+
synth_strides[k] = 0;
|
|
408
|
+
synth_base += g->axes[k].indices[0] * pstride[k];
|
|
253
409
|
}
|
|
254
410
|
}
|
|
255
|
-
|
|
256
|
-
|
|
411
|
+
|
|
412
|
+
tmp.ndim = f->ndim;
|
|
413
|
+
tmp.bytes = g->bytes;
|
|
414
|
+
tmp.dim = f->counts;
|
|
415
|
+
tmp.strides = f->strides;
|
|
416
|
+
tmp.base_offset = f->base;
|
|
417
|
+
|
|
418
|
+
synth.ndim = g->ndim;
|
|
419
|
+
synth.bytes = g->bytes;
|
|
420
|
+
synth.dim = g->dim;
|
|
421
|
+
synth.strides = synth_strides;
|
|
422
|
+
synth.base_offset = synth_base;
|
|
423
|
+
|
|
424
|
+
if (!ca_stride_compose_through(&tmp, &synth, next_strides, &next_base)) {
|
|
425
|
+
return 0;
|
|
257
426
|
}
|
|
427
|
+
|
|
428
|
+
for (k = 0; k < f->ndim; k++) f->strides[k] = next_strides[k];
|
|
429
|
+
f->base = next_base;
|
|
430
|
+
*next_parent = parent;
|
|
431
|
+
return 1;
|
|
258
432
|
}
|
|
259
433
|
|
|
434
|
+
/* xfer_stride: structural region delivery when CAGrid is the (declining)
|
|
435
|
+
fold boundary -- a multi-element INDEX axis. Instead of materialising
|
|
436
|
+
the whole grid, deliver only the requested region using the per-axis
|
|
437
|
+
kind:
|
|
438
|
+
|
|
439
|
+
- iterate the OUTER axes [0..ndim-2] with an odometer, computing the parent
|
|
440
|
+
byte base and the contiguous data offset for each combination;
|
|
441
|
+
- deliver the INNERMOST axis as one batched run into the contiguous data
|
|
442
|
+
sub-block at data+offset:
|
|
443
|
+
* STRIDE inner axis -> parent.xfer_stride (one strided run; entity
|
|
444
|
+
parent delivers a contiguous/strided memcpy);
|
|
445
|
+
* INDEX inner axis -> parent.xfer_addrs (gather the selected cells).
|
|
446
|
+
|
|
447
|
+
strides[] = src access byte strides into the grid (semantics b); data is
|
|
448
|
+
contiguous row-major over counts. g->bytes == parent->bytes (no reinterpret).
|
|
449
|
+
No whole-view attach -- only the requested cells touch the parent. */
|
|
260
450
|
static void
|
|
261
|
-
|
|
451
|
+
ca_grid_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
452
|
+
ca_size_t *strides, void *data, int dir)
|
|
262
453
|
{
|
|
263
|
-
CAGrid
|
|
264
|
-
CArray
|
|
265
|
-
|
|
266
|
-
int8_t
|
|
267
|
-
|
|
268
|
-
|
|
454
|
+
CAGrid *g = (CAGrid *) ap;
|
|
455
|
+
CArray *parent = g->parent;
|
|
456
|
+
int8_t ndim = g->ndim;
|
|
457
|
+
int8_t inner = ndim - 1;
|
|
458
|
+
ca_size_t pnative[CA_RANK_MAX]; /* parent row-major byte strides */
|
|
459
|
+
ca_size_t gnative[CA_RANK_MAX]; /* grid row-major byte strides */
|
|
460
|
+
ca_size_t dstride[CA_RANK_MAX]; /* data row-major byte strides over counts */
|
|
461
|
+
ca_size_t src_step[CA_RANK_MAX]; /* element step into grid per axis (request) */
|
|
462
|
+
ca_size_t o[CA_RANK_MAX]; /* odometer over outer axes */
|
|
463
|
+
ca_size_t s;
|
|
464
|
+
int8_t k;
|
|
465
|
+
int aligned = 1;
|
|
466
|
+
char *d = (char *) data;
|
|
467
|
+
|
|
468
|
+
s = parent->bytes;
|
|
469
|
+
for (k = ndim - 1; k >= 0; k--) { pnative[k] = s; s *= parent->dim[k]; }
|
|
470
|
+
s = g->bytes;
|
|
471
|
+
for (k = ndim - 1; k >= 0; k--) { gnative[k] = s; s *= g->dim[k]; }
|
|
472
|
+
s = g->bytes;
|
|
473
|
+
for (k = ndim - 1; k >= 0; k--) { dstride[k] = s; s *= counts[k]; }
|
|
474
|
+
|
|
475
|
+
/* The structural decomposition assumes the request is axis-aligned: each
|
|
476
|
+
axis k is accessed by a stride that is a whole multiple of the grid's own
|
|
477
|
+
axis-k stride (src_step[k] = strides[k]/gnative[k]). A reshaped or
|
|
478
|
+
transposed leaf breaks this (cross-axis / non-multiple strides); fall back
|
|
479
|
+
to per-cell delivery (correct, still no whole-view attach). The wiring
|
|
480
|
+
guards ndim == grid->ndim, so counts/strides have ndim entries here. */
|
|
481
|
+
for (k = 0; k < ndim; k++) {
|
|
482
|
+
if (strides[k] % gnative[k] != 0) { aligned = 0; break; }
|
|
483
|
+
src_step[k] = strides[k] / gnative[k];
|
|
269
484
|
}
|
|
270
|
-
ca_fetch_index(ca->parent, idx0, ptr);
|
|
271
|
-
}
|
|
272
485
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
486
|
+
if (!aligned) {
|
|
487
|
+
ca_size_t idx[CA_RANK_MAX], doff = 0, base = 0;
|
|
488
|
+
for (k = 0; k < ndim; k++) base += starts[k] * gnative[k];
|
|
489
|
+
for (k = 0; k < ndim; k++) idx[k] = 0;
|
|
490
|
+
while (1) {
|
|
491
|
+
ca_size_t goff = base, gidx[CA_RANK_MAX];
|
|
492
|
+
for (k = 0; k < ndim; k++) goff += idx[k] * strides[k];
|
|
493
|
+
ca_addr2index((CArray *) g, goff / g->bytes, gidx);
|
|
494
|
+
ca_grid_func_xfer_index(g, gidx, d + doff, dir);
|
|
495
|
+
doff += g->bytes;
|
|
496
|
+
k = ndim - 1;
|
|
497
|
+
while (k >= 0) { if (++idx[k] < counts[k]) break; idx[k] = 0; k--; }
|
|
498
|
+
if (k < 0) break;
|
|
499
|
+
}
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/* Fast path: when parent is attached (ptr != NULL), translate the
|
|
504
|
+
sub-region request (starts/counts/src_step) into a transient
|
|
505
|
+
ca_axis_desc_t[] sub-descriptor and call
|
|
506
|
+
ca_axis_dispatch_gather/_scatter directly. This is the same engine
|
|
507
|
+
entry that ca_grid_func_xfer_all uses (minus the ca_attach(parent)
|
|
508
|
+
call, which per-region functions must not do). Collapses N
|
|
509
|
+
outer-row dispatch calls into 1.
|
|
510
|
+
|
|
511
|
+
INDEX axis with src_step==1: zero-copy pointer offset into
|
|
512
|
+
g->axes[k].indices. INDEX axis with src_step!=1: materialise a
|
|
513
|
+
sub-indices array via ALLOCV (per-call, not per-row). STRIDE axis:
|
|
514
|
+
trivially fold starts/src_step into start/step.
|
|
515
|
+
|
|
516
|
+
Parent unattached falls through to the legacy per-row outer loop. */
|
|
517
|
+
if (parent->ptr) {
|
|
518
|
+
ca_axis_desc_t sub_axes[CA_RANK_MAX];
|
|
519
|
+
ca_size_t parent_axis_dims[CA_RANK_MAX];
|
|
520
|
+
ca_size_t *index_bufs[CA_RANK_MAX];
|
|
521
|
+
volatile VALUE holders[CA_RANK_MAX];
|
|
522
|
+
ca_size_t total_elements = 1;
|
|
523
|
+
ca_size_t j;
|
|
524
|
+
int8_t have_alloc = 0;
|
|
525
|
+
|
|
526
|
+
for (k = 0; k < ndim; k++) { index_bufs[k] = NULL; holders[k] = Qnil; }
|
|
527
|
+
|
|
528
|
+
for (k = 0; k < ndim; k++) {
|
|
529
|
+
parent_axis_dims[k] = parent->dim[k];
|
|
530
|
+
total_elements *= counts[k];
|
|
531
|
+
if (g->axes[k].kind == CAG_AXIS_STRIDE) {
|
|
532
|
+
sub_axes[k].kind = CA_AXIS_KIND_STRIDE;
|
|
533
|
+
sub_axes[k].count = counts[k];
|
|
534
|
+
sub_axes[k].start = g->axes[k].start + starts[k] * g->axes[k].step;
|
|
535
|
+
sub_axes[k].step = g->axes[k].step * src_step[k];
|
|
536
|
+
sub_axes[k].indices = NULL;
|
|
537
|
+
} else {
|
|
538
|
+
sub_axes[k].kind = CA_AXIS_KIND_INDEX;
|
|
539
|
+
sub_axes[k].count = counts[k];
|
|
540
|
+
sub_axes[k].start = 0;
|
|
541
|
+
sub_axes[k].step = 0;
|
|
542
|
+
if (src_step[k] == 1) {
|
|
543
|
+
/* zero-copy: pointer offset into the original indices */
|
|
544
|
+
sub_axes[k].indices = g->axes[k].indices + starts[k];
|
|
545
|
+
} else {
|
|
546
|
+
/* sub-sampled or reversed: materialise sub-indices */
|
|
547
|
+
index_bufs[k] = ALLOCV_N(ca_size_t, holders[k], counts[k]);
|
|
548
|
+
for (j = 0; j < counts[k]; j++) {
|
|
549
|
+
index_bufs[k][j] =
|
|
550
|
+
g->axes[k].indices[starts[k] + j * src_step[k]];
|
|
551
|
+
}
|
|
552
|
+
sub_axes[k].indices = index_bufs[k];
|
|
553
|
+
have_alloc = 1;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
if (dir == CA_XFER_GET) {
|
|
559
|
+
ca_axis_dispatch_gather(parent, parent_axis_dims, sub_axes, ndim,
|
|
560
|
+
g->bytes, total_elements, NULL, d);
|
|
561
|
+
} else {
|
|
562
|
+
ca_axis_dispatch_scatter(parent, parent_axis_dims, sub_axes, ndim,
|
|
563
|
+
g->bytes, total_elements, d);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
if (have_alloc) {
|
|
567
|
+
for (k = 0; k < ndim; k++) {
|
|
568
|
+
if (index_bufs[k] != NULL) ALLOCV_END(holders[k]);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/* Fallback (parent unattached): per-row outer loop + per-row
|
|
575
|
+
ca_xfer_stride/ca_xfer_addrs. */
|
|
576
|
+
for (k = 0; k < ndim; k++) o[k] = 0;
|
|
577
|
+
|
|
578
|
+
while (1) {
|
|
579
|
+
ca_size_t pbase = 0, doff = 0;
|
|
580
|
+
for (k = 0; k < inner; k++) {
|
|
581
|
+
ca_size_t gpos = starts[k] + o[k] * src_step[k];
|
|
582
|
+
ca_size_t ppos = (g->axes[k].kind == CAG_AXIS_STRIDE)
|
|
583
|
+
? (g->axes[k].start + gpos * g->axes[k].step)
|
|
584
|
+
: g->axes[k].indices[gpos];
|
|
585
|
+
pbase += ppos * pnative[k];
|
|
586
|
+
doff += o[k] * dstride[k];
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
if (g->axes[inner].kind == CAG_AXIS_STRIDE) {
|
|
590
|
+
ca_size_t pstarts[CA_RANK_MAX], pcounts[CA_RANK_MAX], pstrides[CA_RANK_MAX];
|
|
591
|
+
ca_size_t inner_pbase =
|
|
592
|
+
(g->axes[inner].start + starts[inner] * g->axes[inner].step) * pnative[inner];
|
|
593
|
+
ca_addr2index((CArray *) parent, (pbase + inner_pbase) / parent->bytes, pstarts);
|
|
594
|
+
for (k = 0; k < ndim; k++) { pcounts[k] = 1; pstrides[k] = 0; }
|
|
595
|
+
pcounts[inner] = counts[inner];
|
|
596
|
+
pstrides[inner] = src_step[inner] * g->axes[inner].step * pnative[inner];
|
|
597
|
+
ca_xfer_stride(parent, pstarts, pcounts, pstrides, d + doff, dir);
|
|
598
|
+
}
|
|
599
|
+
else {
|
|
600
|
+
ca_size_t *addrs;
|
|
601
|
+
ca_size_t j, n = counts[inner];
|
|
602
|
+
volatile VALUE holder;
|
|
603
|
+
addrs = ALLOCV_N(ca_size_t, holder, n);
|
|
604
|
+
for (j = 0; j < n; j++) {
|
|
605
|
+
ca_size_t gpos = starts[inner] + j * src_step[inner];
|
|
606
|
+
ca_size_t ppos = g->axes[inner].indices[gpos];
|
|
607
|
+
addrs[j] = (pbase + ppos * pnative[inner]) / parent->bytes;
|
|
608
|
+
}
|
|
609
|
+
ca_xfer_addrs(parent, n, addrs, d + doff, dir);
|
|
610
|
+
ALLOCV_END(holder);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
k = inner - 1;
|
|
614
|
+
while (k >= 0) { if (++o[k] < counts[k]) break; o[k] = 0; k--; }
|
|
615
|
+
if (k < 0) break;
|
|
282
616
|
}
|
|
283
|
-
ca_store_index(ca->parent, idx0, ptr);
|
|
284
617
|
}
|
|
285
618
|
|
|
286
619
|
static void
|
|
@@ -288,27 +621,34 @@ ca_grid_func_allocate (void *ap)
|
|
|
288
621
|
{
|
|
289
622
|
CAGrid *ca = (CAGrid *) ap;
|
|
290
623
|
ca_attach(ca->parent);
|
|
291
|
-
|
|
292
|
-
ca->ptr = malloc_with_check(ca_length(ca));
|
|
624
|
+
ca->ptr = xmalloc(ca_length(ca));
|
|
293
625
|
}
|
|
294
626
|
|
|
627
|
+
/* attach / sync / copy_data / sync_data / fill_data all go through the
|
|
628
|
+
descriptor engine (ca_axis_dispatch.c). This file supplies only
|
|
629
|
+
describe_axes; the engine does the rest. */
|
|
630
|
+
|
|
295
631
|
static void
|
|
296
632
|
ca_grid_func_attach (void *ap)
|
|
297
633
|
{
|
|
298
|
-
void ca_grid_attach (CAGrid *cb);
|
|
299
|
-
|
|
300
634
|
CAGrid *ca = (CAGrid *) ap;
|
|
635
|
+
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
636
|
+
ca_size_t pdims[CA_RANK_MAX];
|
|
301
637
|
ca_attach(ca->parent);
|
|
302
|
-
|
|
303
|
-
ca->ptr =
|
|
304
|
-
|
|
638
|
+
ca_grid_describe_axes(ca, desc, pdims);
|
|
639
|
+
ca->ptr = ca_axis_dispatch_attach(ca->parent, pdims, desc, ca->ndim,
|
|
640
|
+
ca->bytes, ca->elements, NULL);
|
|
305
641
|
}
|
|
306
642
|
|
|
307
643
|
static void
|
|
308
644
|
ca_grid_func_sync (void *ap)
|
|
309
645
|
{
|
|
310
646
|
CAGrid *ca = (CAGrid *) ap;
|
|
311
|
-
|
|
647
|
+
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
648
|
+
ca_size_t pdims[CA_RANK_MAX];
|
|
649
|
+
ca_grid_describe_axes(ca, desc, pdims);
|
|
650
|
+
ca_axis_dispatch_scatter(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
651
|
+
ca->elements, ca->ptr);
|
|
312
652
|
ca_sync(ca->parent);
|
|
313
653
|
}
|
|
314
654
|
|
|
@@ -316,42 +656,79 @@ static void
|
|
|
316
656
|
ca_grid_func_detach (void *ap)
|
|
317
657
|
{
|
|
318
658
|
CAGrid *ca = (CAGrid *) ap;
|
|
319
|
-
|
|
659
|
+
xfree(ca->ptr);
|
|
320
660
|
ca->ptr = NULL;
|
|
321
661
|
ca_detach(ca->parent);
|
|
322
662
|
}
|
|
323
663
|
|
|
664
|
+
/* xfer_all: fast path on parent->ptr, with no silent transitive attach
|
|
665
|
+
of the parent. A cold parent uses a proper 2-pass -- materialise the
|
|
666
|
+
parent into scratch via ca_xfer_all, temporarily expose it as
|
|
667
|
+
parent->ptr, run the fast path, then (for PUT) write scratch back. */
|
|
324
668
|
static void
|
|
325
|
-
|
|
669
|
+
ca_grid_func_run_fast_path (CAGrid *ca, char *data, int dir)
|
|
326
670
|
{
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
671
|
+
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
672
|
+
ca_size_t pdims[CA_RANK_MAX];
|
|
673
|
+
ca_grid_describe_axes(ca, desc, pdims);
|
|
674
|
+
if ( dir == CA_XFER_GET ) {
|
|
675
|
+
ca_axis_dispatch_gather(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
676
|
+
ca->elements, NULL, data);
|
|
677
|
+
} else {
|
|
678
|
+
ca_axis_dispatch_scatter(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
679
|
+
ca->elements, data);
|
|
680
|
+
}
|
|
334
681
|
}
|
|
335
682
|
|
|
336
683
|
static void
|
|
337
|
-
|
|
684
|
+
ca_grid_func_xfer_all (void *ap, void *data, int dir)
|
|
338
685
|
{
|
|
339
686
|
CAGrid *ca = (CAGrid *) ap;
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
687
|
+
if ( ca->parent->ptr ) {
|
|
688
|
+
ca_grid_func_run_fast_path(ca, (char *) data, dir);
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
/* Proper 2-pass cold fallback. */
|
|
692
|
+
{
|
|
693
|
+
volatile VALUE holder;
|
|
694
|
+
CArray *parent = ca->parent;
|
|
695
|
+
ca_size_t plen = parent->elements * parent->bytes;
|
|
696
|
+
char *parent_scratch = ALLOCV_N(char, holder, plen);
|
|
697
|
+
char *parent_ptr_saved = parent->ptr;
|
|
698
|
+
ca_xfer_all(parent, parent_scratch, CA_XFER_GET);
|
|
699
|
+
parent->ptr = parent_scratch;
|
|
700
|
+
ca_grid_func_run_fast_path(ca, (char *) data, dir);
|
|
701
|
+
if ( dir == CA_XFER_PUT ) {
|
|
702
|
+
ca_xfer_all(parent, parent_scratch, CA_XFER_PUT);
|
|
703
|
+
}
|
|
704
|
+
parent->ptr = parent_ptr_saved;
|
|
705
|
+
ALLOCV_END(holder);
|
|
706
|
+
}
|
|
347
707
|
}
|
|
348
708
|
|
|
349
709
|
static void
|
|
350
710
|
ca_grid_func_fill_data (void *ap, void *ptr)
|
|
351
711
|
{
|
|
352
712
|
CAGrid *ca = (CAGrid *) ap;
|
|
713
|
+
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
714
|
+
ca_size_t pdims[CA_RANK_MAX];
|
|
715
|
+
|
|
716
|
+
ca_grid_describe_axes(ca, desc, pdims);
|
|
717
|
+
|
|
718
|
+
/* Writing the selected cells used to go through a whole-parent attach and
|
|
719
|
+
sync. Where that attach is a gather rather than an alias, the cells this
|
|
720
|
+
view did not select make the round trip for nothing -- and through a
|
|
721
|
+
lossy layer they do not come back the same. Hand each slab to the parent
|
|
722
|
+
as a region instead. (PROPOSAL_PARTIAL_FILL_WHOLE_ROOT_WRITEBACK.md) */
|
|
723
|
+
if ( !ca_is_attached(ca->parent) && !ca_attach_is_alias(ca->parent) ) {
|
|
724
|
+
ca_axis_dispatch_fill_value_via_parent(ca->parent, pdims, desc, ca->ndim,
|
|
725
|
+
ca->bytes, ca->elements, ptr);
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
|
|
353
729
|
ca_attach(ca->parent);
|
|
354
|
-
|
|
730
|
+
ca_axis_dispatch_fill_value(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
731
|
+
ca->elements, ptr);
|
|
355
732
|
ca_sync(ca->parent);
|
|
356
733
|
ca_detach(ca->parent);
|
|
357
734
|
}
|
|
@@ -367,271 +744,77 @@ ca_grid_func_create_mask (void *ap)
|
|
|
367
744
|
}
|
|
368
745
|
|
|
369
746
|
ca->mask = (CArray *) ca_grid_new_share(ca->parent->mask,
|
|
370
|
-
ca->
|
|
747
|
+
ca->ndim, ca->axes);
|
|
371
748
|
}
|
|
372
749
|
|
|
373
750
|
ca_operation_function_t ca_grid_func = {
|
|
374
751
|
-1, /* CA_OBJ_GRID */
|
|
375
|
-
|
|
752
|
+
CA_VIEW_ARRAY,
|
|
376
753
|
free_ca_grid,
|
|
377
754
|
ca_grid_func_clone,
|
|
378
|
-
ca_grid_func_ptr_at_addr,
|
|
379
|
-
ca_grid_func_ptr_at_index,
|
|
380
|
-
NULL,
|
|
381
|
-
ca_grid_func_fetch_index,
|
|
382
|
-
NULL,
|
|
383
|
-
ca_grid_func_store_index,
|
|
384
755
|
ca_grid_func_allocate,
|
|
385
756
|
ca_grid_func_attach,
|
|
386
757
|
ca_grid_func_sync,
|
|
387
758
|
ca_grid_func_detach,
|
|
388
|
-
ca_grid_func_copy_data,
|
|
389
|
-
ca_grid_func_sync_data,
|
|
390
759
|
ca_grid_func_fill_data,
|
|
391
760
|
ca_grid_func_create_mask,
|
|
761
|
+
ca_grid_func_xfer_index,
|
|
762
|
+
ca_grid_func_xfer_addrs,
|
|
763
|
+
ca_grid_func_fold_stride,
|
|
764
|
+
ca_grid_func_xfer_stride,
|
|
765
|
+
ca_grid_func_xfer_all,
|
|
392
766
|
};
|
|
393
767
|
|
|
394
768
|
/* ------------------------------------------------------------------- */
|
|
395
769
|
|
|
396
|
-
#define proc_grid_attach(type) \
|
|
397
|
-
{ \
|
|
398
|
-
ca_size_t *pi = (ca_size_t*) ca_ptr_at_addr(grid[level], 0); \
|
|
399
|
-
type *p = (type*) ca_ptr_at_index(ca, idx); \
|
|
400
|
-
type *q = (type*) ca_ptr_at_index(ca->parent, idx0); \
|
|
401
|
-
for (i=0; i<ca->dim[level]; i++, pi++, p++) { \
|
|
402
|
-
k = *pi; \
|
|
403
|
-
*p = *(q+k); \
|
|
404
|
-
} \
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
static void
|
|
408
|
-
ca_grid_attach_loop (CAGrid *ca, int16_t level, ca_size_t *idx, ca_size_t *idx0)
|
|
409
|
-
{
|
|
410
|
-
CArray **grid = ca->grid;
|
|
411
|
-
ca_size_t i, k;
|
|
412
|
-
|
|
413
|
-
if ( level == ca->ndim - 1 ) {
|
|
414
|
-
idx[level] = 0;
|
|
415
|
-
idx0[level] = 0;
|
|
416
|
-
if ( ca->contig[level] ) {
|
|
417
|
-
memcpy(ca_ptr_at_index(ca, idx), ca_ptr_at_index(ca->parent, idx0),
|
|
418
|
-
ca->bytes * ca->dim[level]);
|
|
419
|
-
}
|
|
420
|
-
else {
|
|
421
|
-
switch ( ca->bytes ) {
|
|
422
|
-
case 1: proc_grid_attach(int8_t); break;
|
|
423
|
-
case 2: proc_grid_attach(int16_t); break;
|
|
424
|
-
case 4: proc_grid_attach(int32_t); break;
|
|
425
|
-
case 8: proc_grid_attach(float64_t); break;
|
|
426
|
-
default:
|
|
427
|
-
{
|
|
428
|
-
ca_size_t *pi = (ca_size_t*) ca_ptr_at_addr(grid[level], 0);
|
|
429
|
-
char *p = ca_ptr_at_index(ca, idx);
|
|
430
|
-
char *q;
|
|
431
|
-
idx0[level] = 0;
|
|
432
|
-
q = ca_ptr_at_index(ca->parent, idx0);
|
|
433
|
-
for (i=0; i<ca->dim[level]; i++, pi++, p+=ca->bytes) {
|
|
434
|
-
k = *pi;
|
|
435
|
-
memcpy(p, q + ca->bytes * k, ca->bytes);
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
else {
|
|
442
|
-
if ( ca->contig[level] ) {
|
|
443
|
-
for (i=0; i<ca->dim[level]; i++) {
|
|
444
|
-
idx[level] = i;
|
|
445
|
-
idx0[level] = i;
|
|
446
|
-
ca_grid_attach_loop(ca, level+1, idx, idx0);
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
else {
|
|
450
|
-
ca_size_t *pi;
|
|
451
|
-
pi = (ca_size_t*) ca_ptr_at_addr(grid[level], 0);
|
|
452
|
-
for (i=0; i<ca->dim[level]; i++, pi++) {
|
|
453
|
-
k = *pi;
|
|
454
|
-
idx[level] = i;
|
|
455
|
-
idx0[level] = k;
|
|
456
|
-
ca_grid_attach_loop(ca, level+1, idx, idx0);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
static void
|
|
463
|
-
ca_grid_attach (CAGrid *ca)
|
|
464
|
-
{
|
|
465
|
-
ca_size_t idx[CA_RANK_MAX];
|
|
466
|
-
ca_size_t idx0[CA_RANK_MAX];
|
|
467
|
-
ca_grid_attach_loop(ca, (int16_t) 0, idx, idx0);
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
#define proc_grid_sync(type) \
|
|
471
|
-
{ \
|
|
472
|
-
ca_size_t *pi = (ca_size_t*) ca_ptr_at_addr(grid[level], 0); \
|
|
473
|
-
type *p = (type*) ca_ptr_at_index(ca, idx); \
|
|
474
|
-
type *q = (type*) ca_ptr_at_index(ca->parent, idx0); \
|
|
475
|
-
for (i=0; i<ca->dim[level]; i++, pi++, p++) { \
|
|
476
|
-
k = *pi; \
|
|
477
|
-
*(q+k) = *p; \
|
|
478
|
-
} \
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
static void
|
|
482
|
-
ca_grid_sync_loop (CAGrid *ca, int16_t level, ca_size_t *idx, ca_size_t *idx0)
|
|
483
|
-
{
|
|
484
|
-
CArray **grid = ca->grid;
|
|
485
|
-
ca_size_t i, k;
|
|
486
|
-
|
|
487
|
-
if ( level == ca->ndim - 1 ) {
|
|
488
|
-
idx[level] = 0;
|
|
489
|
-
idx0[level] = 0;
|
|
490
|
-
if ( ca->contig[level] ) {
|
|
491
|
-
memcpy(ca_ptr_at_index(ca->parent, idx0), ca_ptr_at_index(ca, idx),
|
|
492
|
-
ca->bytes * ca->dim[level]);
|
|
493
|
-
}
|
|
494
|
-
else {
|
|
495
|
-
switch ( ca->bytes ) {
|
|
496
|
-
case 1: proc_grid_sync(int8_t); break;
|
|
497
|
-
case 2: proc_grid_sync(int16_t); break;
|
|
498
|
-
case 4: proc_grid_sync(int32_t); break;
|
|
499
|
-
case 8: proc_grid_sync(float64_t); break;
|
|
500
|
-
default:
|
|
501
|
-
{
|
|
502
|
-
ca_size_t *pi = (ca_size_t*) ca_ptr_at_addr(grid[level], 0);
|
|
503
|
-
char *p = ca_ptr_at_index(ca, idx);
|
|
504
|
-
char *q;
|
|
505
|
-
idx0[level] = 0;
|
|
506
|
-
q = ca_ptr_at_index(ca->parent, idx0);
|
|
507
|
-
for (i=0; i<ca->dim[level]; i++, pi++, p+=ca->bytes) {
|
|
508
|
-
k = *pi;
|
|
509
|
-
memcpy(q + ca->bytes * k, p, ca->bytes);
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
else {
|
|
516
|
-
if ( ca->contig[level] ) {
|
|
517
|
-
for (i=0; i<ca->dim[level]; i++) {
|
|
518
|
-
idx[level] = i;
|
|
519
|
-
idx0[level] = i;
|
|
520
|
-
ca_grid_sync_loop(ca, level+1, idx, idx0);
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
else {
|
|
524
|
-
for (i=0; i<ca->dim[level]; i++) {
|
|
525
|
-
k = *(ca_size_t*) ca_ptr_at_addr(grid[level], i);
|
|
526
|
-
idx[level] = i;
|
|
527
|
-
idx0[level] = k;
|
|
528
|
-
ca_grid_sync_loop(ca, level+1, idx, idx0);
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
static void
|
|
535
|
-
ca_grid_sync (CAGrid *ca)
|
|
536
|
-
{
|
|
537
|
-
ca_size_t idx[CA_RANK_MAX];
|
|
538
|
-
ca_size_t idx0[CA_RANK_MAX];
|
|
539
|
-
ca_grid_sync_loop(ca, (int16_t) 0, idx, idx0);
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
#define proc_grid_fill(type) \
|
|
543
|
-
{ \
|
|
544
|
-
ca_size_t *pi = (ca_size_t*) ca_ptr_at_addr(grid[level], 0); \
|
|
545
|
-
type fval = *(type*)ptr; \
|
|
546
|
-
type *q = (type*) ca_ptr_at_index(ca->parent, idx0); \
|
|
547
|
-
for (i=0; i<ca->dim[level]; i++, pi++) { \
|
|
548
|
-
k = *pi; \
|
|
549
|
-
*(q+k) = fval; \
|
|
550
|
-
} \
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
static void
|
|
554
|
-
ca_grid_fill_loop (CAGrid *ca, char *ptr,
|
|
555
|
-
int16_t level, ca_size_t *idx0)
|
|
556
|
-
{
|
|
557
|
-
CArray **grid = ca->grid;
|
|
558
|
-
ca_size_t i, k;
|
|
559
|
-
if ( level == ca->ndim - 1 ) {
|
|
560
|
-
idx0[level] = 0;
|
|
561
|
-
if ( ca->contig[level] ) {
|
|
562
|
-
char *p = ca_ptr_at_index(ca->parent, idx0);
|
|
563
|
-
for (i=0; i<ca->dim[level]; i++) {
|
|
564
|
-
memcpy(p, ptr, ca->bytes);
|
|
565
|
-
p += ca->bytes;
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
else {
|
|
569
|
-
switch ( ca->bytes ) {
|
|
570
|
-
case 1: proc_grid_fill(int8_t); break;
|
|
571
|
-
case 2: proc_grid_fill(int16_t); break;
|
|
572
|
-
case 4: proc_grid_fill(int32_t); break;
|
|
573
|
-
case 8: proc_grid_fill(float64_t); break;
|
|
574
|
-
default:
|
|
575
|
-
{
|
|
576
|
-
ca_size_t *pi = (ca_size_t*) ca_ptr_at_addr(grid[level], 0);
|
|
577
|
-
char *q;
|
|
578
|
-
idx0[level] = 0;
|
|
579
|
-
q = ca_ptr_at_index(ca->parent, idx0);
|
|
580
|
-
for (i=0; i<ca->dim[level]; i++, pi++) {
|
|
581
|
-
k = *pi;
|
|
582
|
-
memcpy(q + ca->bytes * k, ptr, ca->bytes);
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
else {
|
|
589
|
-
if ( ca->contig[level] ) {
|
|
590
|
-
for (i=0; i<ca->dim[level]; i++) {
|
|
591
|
-
idx0[level] = i;
|
|
592
|
-
ca_grid_fill_loop(ca, ptr, level+1, idx0);
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
else {
|
|
596
|
-
for (i=0; i<ca->dim[level]; i++) {
|
|
597
|
-
k = *(ca_size_t*) ca_ptr_at_addr(grid[level], i);
|
|
598
|
-
idx0[level] = k;
|
|
599
|
-
ca_grid_fill_loop(ca, ptr, level+1, idx0);
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
static void
|
|
606
|
-
ca_grid_fill (CAGrid *ca, char *ptr)
|
|
607
|
-
{
|
|
608
|
-
ca_size_t idx0[CA_RANK_MAX];
|
|
609
|
-
ca_grid_fill_loop(ca, ptr, (int16_t) 0, idx0);
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
/* ------------------------------------------------------------------- */
|
|
613
|
-
|
|
614
770
|
VALUE
|
|
615
|
-
rb_ca_grid_new (VALUE cary,
|
|
771
|
+
rb_ca_grid_new (VALUE cary, int8_t ndim, cag_axis_t *protos)
|
|
616
772
|
{
|
|
617
773
|
volatile VALUE obj;
|
|
618
774
|
CArray *parent;
|
|
619
775
|
CAGrid *ca;
|
|
620
776
|
rb_check_carray_object(cary);
|
|
621
777
|
TypedData_Get_Struct(cary, CArray, &carray_data_type, parent);
|
|
622
|
-
ca = ca_grid_new(parent,
|
|
778
|
+
ca = ca_grid_new(parent, ndim, protos);
|
|
623
779
|
obj = ca_wrap_struct(ca);
|
|
624
780
|
rb_ca_set_parent(obj, cary);
|
|
625
|
-
rb_ca_data_type_inherit(obj, cary);
|
|
626
781
|
return obj;
|
|
627
782
|
}
|
|
628
783
|
|
|
629
|
-
/*
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
784
|
+
/* Detect a plain Ruby Range (Integer first/last, exclude_end?, step=1
|
|
785
|
+
implicit) and convert it to STRIDE (start, count, step=1).
|
|
786
|
+
Returns 1 on success (fills *out_start, *out_count), 0 on fallback
|
|
787
|
+
(caller should materialise to INDEX). Negative endpoints are
|
|
788
|
+
normalised against dim_size like everywhere else in CArray. */
|
|
789
|
+
static int
|
|
790
|
+
cag_range_to_stride (VALUE range, ca_size_t dim_size,
|
|
791
|
+
ca_size_t *out_start, ca_size_t *out_count)
|
|
792
|
+
{
|
|
793
|
+
VALUE rb_first, rb_last;
|
|
794
|
+
ca_size_t first, last, count;
|
|
795
|
+
int exclude_end;
|
|
796
|
+
|
|
797
|
+
if ( ! rb_obj_is_kind_of(range, rb_cRange) ) return 0;
|
|
798
|
+
rb_first = rb_funcall(range, rb_intern("first"), 0);
|
|
799
|
+
rb_last = rb_funcall(range, rb_intern("last"), 0);
|
|
800
|
+
if ( ! FIXNUM_P(rb_first) || ! FIXNUM_P(rb_last) ) return 0;
|
|
801
|
+
exclude_end = RTEST(rb_funcall(range, rb_intern("exclude_end?"), 0));
|
|
802
|
+
|
|
803
|
+
first = NUM2SIZE(rb_first);
|
|
804
|
+
last = NUM2SIZE(rb_last);
|
|
805
|
+
if (first < 0) first += dim_size;
|
|
806
|
+
if (last < 0) last += dim_size;
|
|
807
|
+
if (exclude_end) last -= 1;
|
|
808
|
+
|
|
809
|
+
if (first < 0 || first >= dim_size) return 0;
|
|
810
|
+
if (last < first - 1) return 0; /* empty range */
|
|
811
|
+
if (last >= dim_size) return 0;
|
|
812
|
+
count = last - first + 1;
|
|
813
|
+
|
|
814
|
+
*out_start = first;
|
|
815
|
+
*out_count = count;
|
|
816
|
+
return 1;
|
|
817
|
+
}
|
|
635
818
|
|
|
636
819
|
VALUE
|
|
637
820
|
rb_ca_grid (int argc, VALUE *argv, VALUE self)
|
|
@@ -639,12 +822,23 @@ rb_ca_grid (int argc, VALUE *argv, VALUE self)
|
|
|
639
822
|
volatile VALUE obj, ridx, rval;
|
|
640
823
|
volatile VALUE list = rb_ary_new();
|
|
641
824
|
CArray *ca;
|
|
642
|
-
CArray *ci[CA_RANK_MAX];
|
|
643
|
-
|
|
644
|
-
CArray *grid[CA_RANK_MAX];
|
|
825
|
+
CArray *ci[CA_RANK_MAX]; /* CAWrap holders for INDEX axes; NULL for STRIDE */
|
|
826
|
+
cag_axis_t protos[CA_RANK_MAX];
|
|
645
827
|
ca_size_t i;
|
|
646
828
|
|
|
647
|
-
|
|
829
|
+
/* Dispatch hook: route mixed AP + single boolean to CASelectAxis
|
|
830
|
+
(slab-copy optimised path). Falls through to per-cell CAGrid gather
|
|
831
|
+
when not eligible (integer index, multiple INDIRECT axes, indirect
|
|
832
|
+
not on axis 0). Inline argv[0] type check avoids the function call
|
|
833
|
+
when axis 0 is nil/Integer (most patterns with INDIRECT on inner axes). */
|
|
834
|
+
extern int ca_csa_dispatch_bypass;
|
|
835
|
+
if ( ! ca_csa_dispatch_bypass && argc > 0 && TYPE(argv[0]) == T_DATA ) {
|
|
836
|
+
if ( rb_ca_select_axis_eligible_p(argc, argv, self) ) {
|
|
837
|
+
return rb_ca_select_axis(argc, argv, self);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
648
842
|
|
|
649
843
|
ridx = rb_ary_new4(argc, argv);
|
|
650
844
|
|
|
@@ -679,43 +873,82 @@ rb_ca_grid (int argc, VALUE *argv, VALUE self)
|
|
|
679
873
|
return rb_ca_grid(argc, argv, ref);
|
|
680
874
|
}
|
|
681
875
|
|
|
682
|
-
|
|
876
|
+
/* Build per-axis protos:
|
|
877
|
+
nil -> STRIDE(0, parent.dim, 1), no CArray
|
|
878
|
+
Range -> STRIDE if plain integer Range, else fall through to INDEX
|
|
879
|
+
CArray -> INDEX with indices = (ca_size_t*)ca_wrap_readonly(...)->ptr */
|
|
880
|
+
for (i = 0; i < ca->ndim; i++) {
|
|
881
|
+
ca_size_t dim_size = ca->dim[i];
|
|
683
882
|
rval = rb_ary_entry(ridx, i);
|
|
883
|
+
ci[i] = NULL;
|
|
684
884
|
if ( NIL_P(rval) ) {
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
885
|
+
protos[i].kind = CAG_AXIS_STRIDE;
|
|
886
|
+
protos[i].count = dim_size;
|
|
887
|
+
protos[i].start = 0;
|
|
888
|
+
protos[i].step = 1;
|
|
889
|
+
protos[i].indices = NULL;
|
|
890
|
+
continue;
|
|
688
891
|
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
892
|
+
if ( rb_obj_is_kind_of(rval, rb_cRange) ) {
|
|
893
|
+
ca_size_t start, count;
|
|
894
|
+
if ( cag_range_to_stride(rval, dim_size, &start, &count) ) {
|
|
895
|
+
protos[i].kind = CAG_AXIS_STRIDE;
|
|
896
|
+
protos[i].count = count;
|
|
897
|
+
protos[i].start = start;
|
|
898
|
+
protos[i].step = 1;
|
|
899
|
+
protos[i].indices = NULL;
|
|
900
|
+
continue;
|
|
694
901
|
}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
902
|
+
/* fallback: materialise to integer array */
|
|
903
|
+
rval = rb_funcall(rb_mKernel, rb_intern("CA_SIZE"), 1, rval);
|
|
904
|
+
}
|
|
905
|
+
else if ( rb_obj_is_carray(rval) ) {
|
|
906
|
+
if ( rb_ca_is_boolean_type(rval) ) {
|
|
907
|
+
rval = rb_ca_where(rval);
|
|
700
908
|
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
909
|
+
}
|
|
910
|
+
else if ( TYPE(rval) == T_ARRAY ) {
|
|
911
|
+
rb_raise(rb_eRuntimeError, "not implemented for this index");
|
|
912
|
+
}
|
|
704
913
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
914
|
+
/* INDEX axis */
|
|
915
|
+
ci[i] = ca_wrap_readonly(rval, CA_SIZE);
|
|
916
|
+
rb_ary_push(list, rval);
|
|
917
|
+
ca_attach(ci[i]);
|
|
918
|
+
|
|
919
|
+
protos[i].kind = CAG_AXIS_INDEX;
|
|
920
|
+
if ( ca_is_any_masked(ci[i]) ) {
|
|
921
|
+
/* mask-filtered snapshot: skip masked cells. We point protos[i]
|
|
922
|
+
.indices at a temp buffer alloc'd here and freed after setup
|
|
923
|
+
copies it (setup snapshots into its own ALLOC). Caller-side
|
|
924
|
+
lifetime: the temp lives until ca_grid_new returns. */
|
|
925
|
+
ca_size_t gsize = ci[i]->elements - ca_count_masked(ci[i]);
|
|
926
|
+
ca_size_t *src = (ca_size_t *) ci[i]->ptr;
|
|
927
|
+
boolean8_t *m = (boolean8_t *) ci[i]->mask->ptr;
|
|
928
|
+
ca_size_t *tmp = ALLOC_N(ca_size_t, gsize > 0 ? gsize : 1);
|
|
929
|
+
ca_size_t j, n = 0;
|
|
930
|
+
for (j = 0; j < ci[i]->elements; j++) {
|
|
931
|
+
if ( ! m[j] ) tmp[n++] = src[j];
|
|
710
932
|
}
|
|
711
|
-
|
|
933
|
+
protos[i].count = gsize;
|
|
934
|
+
protos[i].indices = tmp;
|
|
935
|
+
} else {
|
|
936
|
+
protos[i].count = ci[i]->elements;
|
|
937
|
+
protos[i].indices = (ca_size_t *) ci[i]->ptr;
|
|
712
938
|
}
|
|
939
|
+
protos[i].start = 0;
|
|
940
|
+
protos[i].step = 0;
|
|
713
941
|
}
|
|
714
942
|
|
|
715
|
-
obj = rb_ca_grid_new(self,
|
|
943
|
+
obj = rb_ca_grid_new(self, ca->ndim, protos);
|
|
716
944
|
|
|
717
|
-
|
|
945
|
+
/* Cleanup: detach CAWraps + free temp masked-snapshot buffers (setup
|
|
946
|
+
has already copied indices into its own ALLOC). */
|
|
947
|
+
for (i = 0; i < ca->ndim; i++) {
|
|
718
948
|
if ( ci[i] ) {
|
|
949
|
+
if ( ca_is_any_masked(ci[i]) ) {
|
|
950
|
+
xfree(protos[i].indices);
|
|
951
|
+
}
|
|
719
952
|
ca_detach(ci[i]);
|
|
720
953
|
}
|
|
721
954
|
}
|
|
@@ -738,24 +971,197 @@ rb_ca_grid_initialize_copy (VALUE self, VALUE other)
|
|
|
738
971
|
TypedData_Get_Struct(self, CAGrid, &cagrid_data_type, ca);
|
|
739
972
|
TypedData_Get_Struct(other, CAGrid, &cagrid_data_type, cs);
|
|
740
973
|
|
|
741
|
-
|
|
742
|
-
|
|
974
|
+
if ( ca_func[CA_OBJ_GRID].pool_init ) {
|
|
975
|
+
ca_array_pool_alloc(ca, CA_OBJ_GRID, cs->ndim);
|
|
976
|
+
}
|
|
977
|
+
/* Share the source's axes buffer (CA_FLAG_SHARE_INDEX semantics:
|
|
978
|
+
source CAGrid owns the lifetime; clone aliases it). */
|
|
979
|
+
ca_grid_setup(ca, cs->parent, cs->ndim, cs->axes, 1);
|
|
743
980
|
|
|
744
981
|
return self;
|
|
745
982
|
}
|
|
746
983
|
|
|
747
984
|
|
|
748
985
|
|
|
986
|
+
/* ------------------------------------------------------------------- */
|
|
987
|
+
/* Producer interface: emit the per-axis descriptor array -- a 1:1
|
|
988
|
+
mechanical mapping from CAGrid's internal tagged storage to the
|
|
989
|
+
framework descriptor.
|
|
990
|
+
|
|
991
|
+
STRIDE axes (= nil-arg or arithmetic-progression Range) carry their
|
|
992
|
+
actual start/step, so axis-merge can fire on these axes when they
|
|
993
|
+
neighbour other STRIDE axes. INDEX axes borrow the owned
|
|
994
|
+
ca->axes[k].indices snapshot. */
|
|
995
|
+
|
|
996
|
+
void
|
|
997
|
+
ca_grid_describe_axes (void *ap, ca_axis_desc_t *out,
|
|
998
|
+
ca_size_t *out_parent_dims)
|
|
999
|
+
{
|
|
1000
|
+
CAGrid *ca = (CAGrid *) ap;
|
|
1001
|
+
int8_t k;
|
|
1002
|
+
for ( k = 0; k < ca->ndim; k++ ) {
|
|
1003
|
+
out_parent_dims[k] = ca->parent->dim[k];
|
|
1004
|
+
if ( ca->axes[k].kind == CAG_AXIS_STRIDE ) {
|
|
1005
|
+
out[k].kind = CA_AXIS_KIND_STRIDE;
|
|
1006
|
+
out[k].count = ca->axes[k].count;
|
|
1007
|
+
out[k].start = ca->axes[k].start;
|
|
1008
|
+
out[k].step = ca->axes[k].step;
|
|
1009
|
+
out[k].indices = NULL;
|
|
1010
|
+
} else {
|
|
1011
|
+
out[k].kind = CA_AXIS_KIND_INDEX;
|
|
1012
|
+
out[k].count = ca->axes[k].count;
|
|
1013
|
+
out[k].start = 0;
|
|
1014
|
+
out[k].step = 0;
|
|
1015
|
+
out[k].indices = ca->axes[k].indices;
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
#ifdef CARRAY_DEV_BUILD
|
|
1021
|
+
/* ============================================================
|
|
1022
|
+
* Debug accessors (dev-only, stripped in release)
|
|
1023
|
+
*
|
|
1024
|
+
* Gated by CARRAY_DEV_BUILD (enabled via `extconf.rb --enable-dev-build`
|
|
1025
|
+
* or `CARRAY_DEV=1 rake build_ext`). They expose the per-axis descriptor
|
|
1026
|
+
* and the engine's raw output to Ruby so spec_ai can pin them; nothing in
|
|
1027
|
+
* lib/ or the rest of ext/ consumes them. CASelectAxis carries the same
|
|
1028
|
+
* four under the same fence.
|
|
1029
|
+
* ============================================================ */
|
|
1030
|
+
|
|
1031
|
+
/* Returns the per-axis descriptor as an Array, one entry per axis:
|
|
1032
|
+
[:stride, count, start, step] or [:index, count, indices]. */
|
|
1033
|
+
static VALUE
|
|
1034
|
+
rb_ca_grid_describe_axes (VALUE self)
|
|
1035
|
+
{
|
|
1036
|
+
CAGrid *ca;
|
|
1037
|
+
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
1038
|
+
VALUE arr, entry, idx_ary;
|
|
1039
|
+
int8_t k;
|
|
1040
|
+
ca_size_t i;
|
|
1041
|
+
|
|
1042
|
+
ca_size_t pdims[CA_RANK_MAX];
|
|
1043
|
+
TypedData_Get_Struct(self, CAGrid, &cagrid_data_type, ca);
|
|
1044
|
+
ca_grid_describe_axes(ca, desc, pdims);
|
|
1045
|
+
|
|
1046
|
+
arr = rb_ary_new_capa(ca->ndim);
|
|
1047
|
+
for ( k = 0; k < ca->ndim; k++ ) {
|
|
1048
|
+
if ( desc[k].kind == CA_AXIS_KIND_STRIDE ) {
|
|
1049
|
+
entry = rb_ary_new_capa(4);
|
|
1050
|
+
rb_ary_push(entry, ID2SYM(rb_intern("stride")));
|
|
1051
|
+
rb_ary_push(entry, SIZE2NUM(desc[k].count));
|
|
1052
|
+
rb_ary_push(entry, SIZE2NUM(desc[k].start));
|
|
1053
|
+
rb_ary_push(entry, SIZE2NUM(desc[k].step));
|
|
1054
|
+
} else {
|
|
1055
|
+
entry = rb_ary_new_capa(3);
|
|
1056
|
+
rb_ary_push(entry, ID2SYM(rb_intern("index")));
|
|
1057
|
+
rb_ary_push(entry, SIZE2NUM(desc[k].count));
|
|
1058
|
+
idx_ary = rb_ary_new_capa(desc[k].count);
|
|
1059
|
+
for ( i = 0; i < desc[k].count; i++ ) {
|
|
1060
|
+
rb_ary_push(idx_ary, SIZE2NUM(desc[k].indices[i]));
|
|
1061
|
+
}
|
|
1062
|
+
rb_ary_push(entry, idx_ary);
|
|
1063
|
+
}
|
|
1064
|
+
rb_ary_push(arr, entry);
|
|
1065
|
+
}
|
|
1066
|
+
return arr;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
/* Returns the attach engine's gathered buffer as a String. */
|
|
1070
|
+
static VALUE
|
|
1071
|
+
rb_ca_grid_dispatch_attach_debug (VALUE self)
|
|
1072
|
+
{
|
|
1073
|
+
CAGrid *ca;
|
|
1074
|
+
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
1075
|
+
char *buf;
|
|
1076
|
+
VALUE str;
|
|
1077
|
+
|
|
1078
|
+
ca_size_t pdims[CA_RANK_MAX];
|
|
1079
|
+
TypedData_Get_Struct(self, CAGrid, &cagrid_data_type, ca);
|
|
1080
|
+
ca_grid_describe_axes(ca, desc, pdims);
|
|
1081
|
+
|
|
1082
|
+
ca_attach(ca->parent);
|
|
1083
|
+
buf = ca_axis_dispatch_attach(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
1084
|
+
ca->elements, NULL);
|
|
1085
|
+
ca_detach(ca->parent);
|
|
1086
|
+
|
|
1087
|
+
str = rb_str_new(buf, ca->elements * ca->bytes);
|
|
1088
|
+
xfree(buf);
|
|
1089
|
+
return str;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
/* Drives the scatter engine with a view-shaped input String. */
|
|
1093
|
+
static VALUE
|
|
1094
|
+
rb_ca_grid_dispatch_scatter_debug (VALUE self, VALUE in_str)
|
|
1095
|
+
{
|
|
1096
|
+
CAGrid *ca;
|
|
1097
|
+
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
1098
|
+
ca_size_t expected;
|
|
1099
|
+
|
|
1100
|
+
Check_Type(in_str, T_STRING);
|
|
1101
|
+
TypedData_Get_Struct(self, CAGrid, &cagrid_data_type, ca);
|
|
1102
|
+
|
|
1103
|
+
expected = ca->elements * ca->bytes;
|
|
1104
|
+
if ( (ca_size_t) RSTRING_LEN(in_str) != expected ) {
|
|
1105
|
+
rb_raise(rb_eArgError,
|
|
1106
|
+
"CAGrid#_dispatch_scatter_debug: input string length %lld "
|
|
1107
|
+
"!= expected %lld",
|
|
1108
|
+
(long long) RSTRING_LEN(in_str), (long long) expected);
|
|
1109
|
+
}
|
|
1110
|
+
ca_size_t pdims[CA_RANK_MAX];
|
|
1111
|
+
ca_grid_describe_axes(ca, desc, pdims);
|
|
1112
|
+
|
|
1113
|
+
ca_attach(ca->parent);
|
|
1114
|
+
ca_axis_dispatch_scatter(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
1115
|
+
ca->elements, RSTRING_PTR(in_str));
|
|
1116
|
+
ca_sync(ca->parent);
|
|
1117
|
+
ca_detach(ca->parent);
|
|
1118
|
+
return Qnil;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
/* Drives the fill_value engine with a one-element String. */
|
|
1122
|
+
static VALUE
|
|
1123
|
+
rb_ca_grid_dispatch_fill_value_debug (VALUE self, VALUE val_str)
|
|
1124
|
+
{
|
|
1125
|
+
CAGrid *ca;
|
|
1126
|
+
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
1127
|
+
|
|
1128
|
+
Check_Type(val_str, T_STRING);
|
|
1129
|
+
TypedData_Get_Struct(self, CAGrid, &cagrid_data_type, ca);
|
|
1130
|
+
|
|
1131
|
+
if ( (ca_size_t) RSTRING_LEN(val_str) != ca->bytes ) {
|
|
1132
|
+
rb_raise(rb_eArgError,
|
|
1133
|
+
"CAGrid#_dispatch_fill_value_debug: value string length %lld "
|
|
1134
|
+
"!= bytes %lld",
|
|
1135
|
+
(long long) RSTRING_LEN(val_str), (long long) ca->bytes);
|
|
1136
|
+
}
|
|
1137
|
+
ca_size_t pdims[CA_RANK_MAX];
|
|
1138
|
+
ca_grid_describe_axes(ca, desc, pdims);
|
|
1139
|
+
|
|
1140
|
+
ca_attach(ca->parent);
|
|
1141
|
+
ca_axis_dispatch_fill_value(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
1142
|
+
ca->elements, RSTRING_PTR(val_str));
|
|
1143
|
+
ca_sync(ca->parent);
|
|
1144
|
+
ca_detach(ca->parent);
|
|
1145
|
+
return Qnil;
|
|
1146
|
+
}
|
|
1147
|
+
#endif /* CARRAY_DEV_BUILD */
|
|
1148
|
+
|
|
1149
|
+
/* ------------------------------------------------------------------- */
|
|
1150
|
+
|
|
749
1151
|
void
|
|
750
|
-
Init_ca_obj_grid ()
|
|
1152
|
+
Init_ca_obj_grid (void)
|
|
751
1153
|
{
|
|
752
|
-
rb_cCAGrid = rb_define_class("CAGrid",
|
|
1154
|
+
rb_cCAGrid = rb_define_class("CAGrid", rb_cCAView);
|
|
753
1155
|
rb_cCAGridMask = rb_define_class("CAGridMask", rb_cCAGrid);
|
|
754
1156
|
|
|
755
|
-
|
|
1157
|
+
ca_grid_func.struct_size = sizeof(CAGrid);
|
|
1158
|
+
ca_grid_func.pool_bytes = ca_grid_pool_bytes;
|
|
1159
|
+
ca_grid_func.pool_init = ca_grid_pool_init;
|
|
1160
|
+
|
|
1161
|
+
CA_OBJ_GRID = ca_install_obj_type(rb_cCAGrid,
|
|
756
1162
|
&cagrid_data_type,
|
|
757
1163
|
rb_cCAGridMask,
|
|
758
|
-
&cagrid_mask_data_type, ca_grid_func);
|
|
1164
|
+
&cagrid_mask_data_type, &ca_grid_func, sizeof(ca_grid_func));
|
|
759
1165
|
rb_define_const(rb_cObject, "CA_OBJ_GRID", INT2NUM(CA_OBJ_GRID));
|
|
760
1166
|
|
|
761
1167
|
rb_define_method(rb_cCArray, "grid", rb_ca_grid, -1);
|
|
@@ -763,5 +1169,17 @@ Init_ca_obj_grid ()
|
|
|
763
1169
|
rb_define_alloc_func(rb_cCAGrid, rb_ca_grid_s_allocate);
|
|
764
1170
|
rb_define_method(rb_cCAGrid, "initialize_copy",
|
|
765
1171
|
rb_ca_grid_initialize_copy, 1);
|
|
1172
|
+
|
|
1173
|
+
#ifdef CARRAY_DEV_BUILD
|
|
1174
|
+
/* debug accessors (dev-only, stripped in release) */
|
|
1175
|
+
rb_define_method(rb_cCAGrid, "_describe_axes",
|
|
1176
|
+
rb_ca_grid_describe_axes, 0);
|
|
1177
|
+
rb_define_method(rb_cCAGrid, "_dispatch_attach_debug",
|
|
1178
|
+
rb_ca_grid_dispatch_attach_debug, 0);
|
|
1179
|
+
rb_define_method(rb_cCAGrid, "_dispatch_scatter_debug",
|
|
1180
|
+
rb_ca_grid_dispatch_scatter_debug, 1);
|
|
1181
|
+
rb_define_method(rb_cCAGrid, "_dispatch_fill_value_debug",
|
|
1182
|
+
rb_ca_grid_dispatch_fill_value_debug, 1);
|
|
1183
|
+
#endif
|
|
766
1184
|
}
|
|
767
1185
|
|