carray 2.0.1 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +6 -25
- data/CHANGELOG.md +338 -0
- data/{NEWS.md → CHANGELOG.v1.md} +3 -0
- data/LICENSE +1 -1
- data/README.md +120 -36
- data/carray.gemspec +32 -30
- 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 +1244 -0
- data/ext/ca_bincmp_dispatch.c +76 -0
- data/ext/ca_bincmp_dispatch.h +85 -0
- data/ext/ca_binop_dispatch.c +124 -0
- data/ext/ca_binop_dispatch.h +152 -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 +239 -0
- data/ext/ca_group_iter.c +304 -0
- data/ext/ca_iter_substrate.h +325 -0
- data/ext/ca_kernel_iterator.c +4367 -0
- data/ext/ca_kernel_iterator.h +2596 -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 +839 -0
- data/ext/ca_obj_binop.c +948 -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 +967 -0
- data/ext/ca_obj_face.c +750 -0
- data/ext/ca_obj_face.h +279 -0
- data/ext/ca_obj_fake.c +239 -100
- data/ext/ca_obj_farray.c +54 -441
- data/ext/ca_obj_field.c +82 -529
- data/ext/ca_obj_fixlen_string.c +308 -0
- data/ext/ca_obj_grid.c +866 -440
- data/ext/ca_obj_meld.c +1039 -0
- data/ext/ca_obj_moncmp.c +588 -0
- data/ext/ca_obj_monop.c +1123 -0
- data/ext/ca_obj_object.c +866 -296
- data/ext/ca_obj_record.c +470 -0
- data/ext/ca_obj_reduce.c +97 -82
- data/ext/ca_obj_refer.c +593 -459
- data/ext/ca_obj_remap.c +475 -0
- data/ext/ca_obj_repeat.c +92 -477
- data/ext/ca_obj_roll.c +624 -0
- data/ext/ca_obj_select.c +344 -296
- data/ext/ca_obj_select_axis.c +1306 -0
- data/ext/ca_obj_shift.c +231 -793
- data/ext/ca_obj_source.c +78 -0
- data/ext/ca_obj_stack.c +1173 -0
- data/ext/ca_obj_stride.c +2584 -0
- data/ext/ca_obj_string.c +270 -0
- data/ext/ca_obj_tile.c +622 -0
- data/ext/ca_obj_time.c +548 -0
- data/ext/ca_obj_timedelta.c +437 -0
- data/ext/ca_obj_transpose.c +62 -516
- data/ext/ca_obj_triop.c +785 -0
- data/ext/ca_obj_window.c +1202 -565
- data/ext/ca_op_byte_swap.c +175 -0
- data/ext/ca_op_cmplx64.h +123 -0
- data/ext/ca_op_ipower.c +316 -0
- data/ext/ca_op_powi.h +88 -0
- data/ext/ca_sort_kernels.h +132 -0
- data/ext/ca_sweep_engine.c +473 -0
- data/ext/ca_sweep_engine.h +166 -0
- data/ext/ca_transform_common.c +235 -0
- data/ext/ca_triop_dispatch.c +55 -0
- data/ext/ca_triop_dispatch.h +62 -0
- data/ext/carray.h +810 -420
- data/ext/carray_access.c +873 -731
- data/ext/carray_attribute.c +98 -329
- data/ext/carray_bincount.c +255 -0
- data/ext/carray_broadcast.c +376 -0
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +2897 -874
- data/ext/carray_call_cfunc.h +313 -0
- data/ext/carray_cast.c +1264 -315
- 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 +168 -270
- data/ext/carray_core.c +1396 -206
- 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 +1021 -0
- data/ext/carray_index_classifier.h +27 -0
- data/ext/carray_internal.h +136 -0
- data/ext/carray_kernels_bincmp.c +4446 -0
- data/ext/carray_kernels_binop.c +11001 -0
- data/ext/carray_kernels_init.c +1131 -0
- data/ext/carray_kernels_map.c +3467 -0
- data/ext/carray_kernels_moncmp.c +2097 -0
- data/ext/carray_kernels_monop.c +18313 -0
- data/ext/carray_kernels_reduce_aggregate.c +25837 -0
- data/ext/carray_kernels_reduce_boolean.c +330 -0
- data/ext/carray_kernels_reduce_cumulative.c +14593 -0
- data/ext/carray_kernels_reduce_extreme.c +16948 -0
- data/ext/carray_kernels_reduce_variance.c +3910 -0
- data/ext/carray_kernels_scan.c +3693 -0
- data/ext/carray_kernels_search.c +32138 -0
- data/ext/carray_kernels_sort.c +10626 -0
- data/ext/carray_kernels_triop.c +1392 -0
- data/ext/carray_lazy.c +737 -0
- data/ext/carray_loop.c +88 -200
- data/ext/carray_mask.c +853 -158
- 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 +1650 -0
- data/ext/carray_operator.c +1525 -320
- 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 +234 -55
- data/ext/mk_call_cfunc.rb +671 -0
- data/ext/mkkernel.rb +9096 -0
- data/ext/ruby_carray.c +211 -108
- 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 +239 -0
- data/lib/carray/autoload_method_extension.rb +45 -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 +614 -0
- data/lib/carray/boolean_reduce.rb +109 -0
- data/lib/carray/categorical.rb +561 -0
- data/lib/carray/categorical_iterator.rb +1084 -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 +160 -328
- data/lib/carray/core_extensions.rb +297 -0
- data/lib/carray/data_type_extension.rb +250 -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 +642 -0
- data/lib/carray/frame/group.rb +186 -0
- data/lib/carray/frame/io.rb +321 -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 +316 -0
- data/lib/carray/frame.rb +16 -0
- data/lib/carray/fuse_source.rb +123 -0
- data/lib/carray/fusion.rb +218 -0
- data/lib/carray/histogram.rb +512 -0
- data/lib/carray/inspect.rb +37 -26
- data/lib/carray/iterator.rb +58 -349
- data/lib/carray/lazy.rb +941 -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 +52 -0
- data/lib/carray/methods/mask_duplicates.rb +41 -0
- data/lib/carray/methods/meshgrid.rb +90 -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 +161 -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 +89 -0
- data/lib/carray/serialize.rb +478 -167
- data/lib/carray/slab_iterator.rb +305 -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 +2654 -38
- data/lib/carray/window_iterator.rb +927 -0
- data/lib/carray.rb +55 -57
- data/yard-stubs/ca_obj_array.rb +385 -0
- data/yard-stubs/ca_obj_bitarray.rb +38 -0
- data/yard-stubs/ca_obj_bitfield.rb +43 -0
- data/yard-stubs/ca_obj_block.rb +73 -0
- data/yard-stubs/ca_obj_byte_swap.rb +56 -0
- data/yard-stubs/ca_obj_fake.rb +31 -0
- data/yard-stubs/ca_obj_farray.rb +32 -0
- data/yard-stubs/ca_obj_field.rb +45 -0
- data/yard-stubs/ca_obj_grid.rb +35 -0
- data/yard-stubs/ca_obj_refer.rb +72 -0
- data/yard-stubs/ca_obj_roll.rb +45 -0
- data/yard-stubs/ca_obj_shift.rb +43 -0
- data/yard-stubs/ca_obj_stride.rb +181 -0
- data/yard-stubs/ca_obj_tile.rb +29 -0
- data/yard-stubs/ca_obj_transpose.rb +40 -0
- data/yard-stubs/ca_obj_window.rb +49 -0
- data/yard-stubs/carray_access.rb +131 -0
- data/yard-stubs/carray_attribute.rb +246 -0
- data/yard-stubs/carray_broadcast.rb +37 -0
- data/yard-stubs/carray_cast.rb +489 -0
- data/yard-stubs/carray_class.rb +65 -0
- data/yard-stubs/carray_conversion.rb +76 -0
- data/yard-stubs/carray_copy.rb +79 -0
- data/yard-stubs/carray_core.rb +114 -0
- data/yard-stubs/carray_count.rb +79 -0
- data/yard-stubs/carray_element.rb +108 -0
- data/yard-stubs/carray_generate.rb +66 -0
- data/yard-stubs/carray_lazy.rb +23 -0
- data/yard-stubs/carray_loop.rb +140 -0
- data/yard-stubs/carray_mask.rb +259 -0
- data/yard-stubs/carray_math.rb +132 -0
- data/yard-stubs/carray_mathfunc.rb +45 -0
- data/yard-stubs/carray_median_percentile.rb +89 -0
- data/yard-stubs/carray_memory_view.rb +163 -0
- data/yard-stubs/carray_order.rb +312 -0
- data/yard-stubs/carray_random.rb +89 -0
- data/yard-stubs/carray_scatter.rb +106 -0
- data/yard-stubs/carray_slab.rb +57 -0
- data/yard-stubs/carray_sort.rb +163 -0
- data/yard-stubs/carray_test.rb +85 -0
- data/yard-stubs/carray_undef.rb +64 -0
- data/yard-stubs/carray_utils.rb +97 -0
- data/yard-stubs/ruby_carray.rb +193 -0
- metadata +220 -138
- 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/ca_obj_unbound_repeat.c +0 -529
- 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/mailmap +0 -1
- 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/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;
|
|
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]);
|
|
141
205
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
else {
|
|
153
|
-
ca_size_t *p;
|
|
154
|
-
ca->grid[i] = carray_new(CA_SIZE, 1, &dim[i], 0, NULL);
|
|
155
|
-
p = (ca_size_t *)ca->grid[i]->ptr;
|
|
156
|
-
for (j=0; j<dim[i]; j++) {
|
|
157
|
-
*p++ = j;
|
|
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,383 @@ 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);
|
|
217
282
|
}
|
|
218
283
|
|
|
219
|
-
|
|
220
|
-
|
|
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];
|
|
293
|
+
}
|
|
294
|
+
|
|
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]);
|
|
227
309
|
}
|
|
228
|
-
|
|
229
|
-
|
|
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
|
+
}
|
|
230
353
|
}
|
|
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);
|
|
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
|
+
}
|
|
247
393
|
|
|
248
|
-
|
|
249
|
-
|
|
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
|
+
}
|
|
400
|
+
|
|
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
|
+
/* The request is over the view's addresses, so a transposed / flat request
|
|
482
|
+
is legal and must not be composed axis-by-axis; see
|
|
483
|
+
ca_xfer_stride_request_is_axis_box (carray.h). */
|
|
484
|
+
if ( ! ca_xfer_stride_request_is_axis_box(g, starts, counts, strides) ) {
|
|
485
|
+
aligned = 0;
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
for (k = 0; k < ndim; k++) {
|
|
489
|
+
if (strides[k] % gnative[k] != 0) { aligned = 0; break; }
|
|
490
|
+
src_step[k] = strides[k] / gnative[k];
|
|
491
|
+
}
|
|
269
492
|
}
|
|
270
|
-
ca_fetch_index(ca->parent, idx0, ptr);
|
|
271
|
-
}
|
|
272
493
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
494
|
+
if (!aligned) {
|
|
495
|
+
ca_size_t idx[CA_RANK_MAX], doff = 0, base = 0;
|
|
496
|
+
for (k = 0; k < ndim; k++) base += starts[k] * gnative[k];
|
|
497
|
+
for (k = 0; k < ndim; k++) idx[k] = 0;
|
|
498
|
+
while (1) {
|
|
499
|
+
ca_size_t goff = base, gidx[CA_RANK_MAX];
|
|
500
|
+
for (k = 0; k < ndim; k++) goff += idx[k] * strides[k];
|
|
501
|
+
ca_addr2index((CArray *) g, goff / g->bytes, gidx);
|
|
502
|
+
ca_grid_func_xfer_index(g, gidx, d + doff, dir);
|
|
503
|
+
doff += g->bytes;
|
|
504
|
+
k = ndim - 1;
|
|
505
|
+
while (k >= 0) { if (++idx[k] < counts[k]) break; idx[k] = 0; k--; }
|
|
506
|
+
if (k < 0) break;
|
|
507
|
+
}
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/* Fast path: when parent is attached (ptr != NULL), translate the
|
|
512
|
+
sub-region request (starts/counts/src_step) into a transient
|
|
513
|
+
ca_axis_desc_t[] sub-descriptor and call
|
|
514
|
+
ca_axis_dispatch_gather/_scatter directly. This is the same engine
|
|
515
|
+
entry that ca_grid_func_xfer_all uses (minus the ca_attach(parent)
|
|
516
|
+
call, which per-region functions must not do). Collapses N
|
|
517
|
+
outer-row dispatch calls into 1.
|
|
518
|
+
|
|
519
|
+
INDEX axis with src_step==1: zero-copy pointer offset into
|
|
520
|
+
g->axes[k].indices. INDEX axis with src_step!=1: materialise a
|
|
521
|
+
sub-indices array via ALLOCV (per-call, not per-row). STRIDE axis:
|
|
522
|
+
trivially fold starts/src_step into start/step.
|
|
523
|
+
|
|
524
|
+
Parent unattached falls through to the legacy per-row outer loop. */
|
|
525
|
+
if (parent->ptr) {
|
|
526
|
+
ca_axis_desc_t sub_axes[CA_RANK_MAX];
|
|
527
|
+
ca_size_t parent_axis_dims[CA_RANK_MAX];
|
|
528
|
+
ca_size_t *index_bufs[CA_RANK_MAX];
|
|
529
|
+
volatile VALUE holders[CA_RANK_MAX];
|
|
530
|
+
ca_size_t total_elements = 1;
|
|
531
|
+
ca_size_t j;
|
|
532
|
+
int8_t have_alloc = 0;
|
|
533
|
+
|
|
534
|
+
for (k = 0; k < ndim; k++) { index_bufs[k] = NULL; holders[k] = Qnil; }
|
|
535
|
+
|
|
536
|
+
for (k = 0; k < ndim; k++) {
|
|
537
|
+
parent_axis_dims[k] = parent->dim[k];
|
|
538
|
+
total_elements *= counts[k];
|
|
539
|
+
if (g->axes[k].kind == CAG_AXIS_STRIDE) {
|
|
540
|
+
sub_axes[k].kind = CA_AXIS_KIND_STRIDE;
|
|
541
|
+
sub_axes[k].count = counts[k];
|
|
542
|
+
sub_axes[k].start = g->axes[k].start + starts[k] * g->axes[k].step;
|
|
543
|
+
sub_axes[k].step = g->axes[k].step * src_step[k];
|
|
544
|
+
sub_axes[k].indices = NULL;
|
|
545
|
+
} else {
|
|
546
|
+
sub_axes[k].kind = CA_AXIS_KIND_INDEX;
|
|
547
|
+
sub_axes[k].count = counts[k];
|
|
548
|
+
sub_axes[k].start = 0;
|
|
549
|
+
sub_axes[k].step = 0;
|
|
550
|
+
if (src_step[k] == 1) {
|
|
551
|
+
/* zero-copy: pointer offset into the original indices */
|
|
552
|
+
sub_axes[k].indices = g->axes[k].indices + starts[k];
|
|
553
|
+
} else {
|
|
554
|
+
/* sub-sampled or reversed: materialise sub-indices */
|
|
555
|
+
index_bufs[k] = ALLOCV_N(ca_size_t, holders[k], counts[k]);
|
|
556
|
+
for (j = 0; j < counts[k]; j++) {
|
|
557
|
+
index_bufs[k][j] =
|
|
558
|
+
g->axes[k].indices[starts[k] + j * src_step[k]];
|
|
559
|
+
}
|
|
560
|
+
sub_axes[k].indices = index_bufs[k];
|
|
561
|
+
have_alloc = 1;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
if (dir == CA_XFER_GET) {
|
|
567
|
+
ca_axis_dispatch_gather(parent, parent_axis_dims, sub_axes, ndim,
|
|
568
|
+
g->bytes, total_elements, NULL, d);
|
|
569
|
+
} else {
|
|
570
|
+
ca_axis_dispatch_scatter(parent, parent_axis_dims, sub_axes, ndim,
|
|
571
|
+
g->bytes, total_elements, d);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
if (have_alloc) {
|
|
575
|
+
for (k = 0; k < ndim; k++) {
|
|
576
|
+
if (index_bufs[k] != NULL) ALLOCV_END(holders[k]);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/* Fallback (parent unattached): per-row outer loop + per-row
|
|
583
|
+
ca_xfer_stride/ca_xfer_addrs. */
|
|
584
|
+
for (k = 0; k < ndim; k++) o[k] = 0;
|
|
585
|
+
|
|
586
|
+
while (1) {
|
|
587
|
+
ca_size_t pbase = 0, doff = 0;
|
|
588
|
+
for (k = 0; k < inner; k++) {
|
|
589
|
+
ca_size_t gpos = starts[k] + o[k] * src_step[k];
|
|
590
|
+
ca_size_t ppos = (g->axes[k].kind == CAG_AXIS_STRIDE)
|
|
591
|
+
? (g->axes[k].start + gpos * g->axes[k].step)
|
|
592
|
+
: g->axes[k].indices[gpos];
|
|
593
|
+
pbase += ppos * pnative[k];
|
|
594
|
+
doff += o[k] * dstride[k];
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
if (g->axes[inner].kind == CAG_AXIS_STRIDE) {
|
|
598
|
+
ca_size_t pstarts[CA_RANK_MAX], pcounts[CA_RANK_MAX], pstrides[CA_RANK_MAX];
|
|
599
|
+
ca_size_t inner_pbase =
|
|
600
|
+
(g->axes[inner].start + starts[inner] * g->axes[inner].step) * pnative[inner];
|
|
601
|
+
ca_addr2index((CArray *) parent, (pbase + inner_pbase) / parent->bytes, pstarts);
|
|
602
|
+
for (k = 0; k < ndim; k++) { pcounts[k] = 1; pstrides[k] = 0; }
|
|
603
|
+
pcounts[inner] = counts[inner];
|
|
604
|
+
pstrides[inner] = src_step[inner] * g->axes[inner].step * pnative[inner];
|
|
605
|
+
ca_xfer_stride(parent, pstarts, pcounts, pstrides, d + doff, dir);
|
|
606
|
+
}
|
|
607
|
+
else {
|
|
608
|
+
ca_size_t *addrs;
|
|
609
|
+
ca_size_t j, n = counts[inner];
|
|
610
|
+
volatile VALUE holder;
|
|
611
|
+
addrs = ALLOCV_N(ca_size_t, holder, n);
|
|
612
|
+
for (j = 0; j < n; j++) {
|
|
613
|
+
ca_size_t gpos = starts[inner] + j * src_step[inner];
|
|
614
|
+
ca_size_t ppos = g->axes[inner].indices[gpos];
|
|
615
|
+
addrs[j] = (pbase + ppos * pnative[inner]) / parent->bytes;
|
|
616
|
+
}
|
|
617
|
+
ca_xfer_addrs(parent, n, addrs, d + doff, dir);
|
|
618
|
+
ALLOCV_END(holder);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
k = inner - 1;
|
|
622
|
+
while (k >= 0) { if (++o[k] < counts[k]) break; o[k] = 0; k--; }
|
|
623
|
+
if (k < 0) break;
|
|
282
624
|
}
|
|
283
|
-
ca_store_index(ca->parent, idx0, ptr);
|
|
284
625
|
}
|
|
285
626
|
|
|
286
627
|
static void
|
|
@@ -288,27 +629,34 @@ ca_grid_func_allocate (void *ap)
|
|
|
288
629
|
{
|
|
289
630
|
CAGrid *ca = (CAGrid *) ap;
|
|
290
631
|
ca_attach(ca->parent);
|
|
291
|
-
|
|
292
|
-
ca->ptr = malloc_with_check(ca_length(ca));
|
|
632
|
+
ca->ptr = xmalloc(ca_length(ca));
|
|
293
633
|
}
|
|
294
634
|
|
|
635
|
+
/* attach / sync / copy_data / sync_data / fill_data all go through the
|
|
636
|
+
descriptor engine (ca_axis_dispatch.c). This file supplies only
|
|
637
|
+
describe_axes; the engine does the rest. */
|
|
638
|
+
|
|
295
639
|
static void
|
|
296
640
|
ca_grid_func_attach (void *ap)
|
|
297
641
|
{
|
|
298
|
-
void ca_grid_attach (CAGrid *cb);
|
|
299
|
-
|
|
300
642
|
CAGrid *ca = (CAGrid *) ap;
|
|
643
|
+
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
644
|
+
ca_size_t pdims[CA_RANK_MAX];
|
|
301
645
|
ca_attach(ca->parent);
|
|
302
|
-
|
|
303
|
-
ca->ptr =
|
|
304
|
-
|
|
646
|
+
ca_grid_describe_axes(ca, desc, pdims);
|
|
647
|
+
ca->ptr = ca_axis_dispatch_attach(ca->parent, pdims, desc, ca->ndim,
|
|
648
|
+
ca->bytes, ca->elements, NULL);
|
|
305
649
|
}
|
|
306
650
|
|
|
307
651
|
static void
|
|
308
652
|
ca_grid_func_sync (void *ap)
|
|
309
653
|
{
|
|
310
654
|
CAGrid *ca = (CAGrid *) ap;
|
|
311
|
-
|
|
655
|
+
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
656
|
+
ca_size_t pdims[CA_RANK_MAX];
|
|
657
|
+
ca_grid_describe_axes(ca, desc, pdims);
|
|
658
|
+
ca_axis_dispatch_scatter(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
659
|
+
ca->elements, ca->ptr);
|
|
312
660
|
ca_sync(ca->parent);
|
|
313
661
|
}
|
|
314
662
|
|
|
@@ -316,42 +664,79 @@ static void
|
|
|
316
664
|
ca_grid_func_detach (void *ap)
|
|
317
665
|
{
|
|
318
666
|
CAGrid *ca = (CAGrid *) ap;
|
|
319
|
-
|
|
667
|
+
xfree(ca->ptr);
|
|
320
668
|
ca->ptr = NULL;
|
|
321
669
|
ca_detach(ca->parent);
|
|
322
670
|
}
|
|
323
671
|
|
|
672
|
+
/* xfer_all: fast path on parent->ptr, with no silent transitive attach
|
|
673
|
+
of the parent. A cold parent uses a proper 2-pass -- materialise the
|
|
674
|
+
parent into scratch via ca_xfer_all, temporarily expose it as
|
|
675
|
+
parent->ptr, run the fast path, then (for PUT) write scratch back. */
|
|
324
676
|
static void
|
|
325
|
-
|
|
677
|
+
ca_grid_func_run_fast_path (CAGrid *ca, char *data, int dir)
|
|
326
678
|
{
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
679
|
+
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
680
|
+
ca_size_t pdims[CA_RANK_MAX];
|
|
681
|
+
ca_grid_describe_axes(ca, desc, pdims);
|
|
682
|
+
if ( dir == CA_XFER_GET ) {
|
|
683
|
+
ca_axis_dispatch_gather(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
684
|
+
ca->elements, NULL, data);
|
|
685
|
+
} else {
|
|
686
|
+
ca_axis_dispatch_scatter(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
687
|
+
ca->elements, data);
|
|
688
|
+
}
|
|
334
689
|
}
|
|
335
690
|
|
|
336
691
|
static void
|
|
337
|
-
|
|
692
|
+
ca_grid_func_xfer_all (void *ap, void *data, int dir)
|
|
338
693
|
{
|
|
339
694
|
CAGrid *ca = (CAGrid *) ap;
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
695
|
+
if ( ca->parent->ptr ) {
|
|
696
|
+
ca_grid_func_run_fast_path(ca, (char *) data, dir);
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
/* Proper 2-pass cold fallback. */
|
|
700
|
+
{
|
|
701
|
+
volatile VALUE holder;
|
|
702
|
+
CArray *parent = ca->parent;
|
|
703
|
+
ca_size_t plen = parent->elements * parent->bytes;
|
|
704
|
+
char *parent_scratch = ALLOCV_N(char, holder, plen);
|
|
705
|
+
char *parent_ptr_saved = parent->ptr;
|
|
706
|
+
ca_xfer_all(parent, parent_scratch, CA_XFER_GET);
|
|
707
|
+
parent->ptr = parent_scratch;
|
|
708
|
+
ca_grid_func_run_fast_path(ca, (char *) data, dir);
|
|
709
|
+
if ( dir == CA_XFER_PUT ) {
|
|
710
|
+
ca_xfer_all(parent, parent_scratch, CA_XFER_PUT);
|
|
711
|
+
}
|
|
712
|
+
parent->ptr = parent_ptr_saved;
|
|
713
|
+
ALLOCV_END(holder);
|
|
714
|
+
}
|
|
347
715
|
}
|
|
348
716
|
|
|
349
717
|
static void
|
|
350
718
|
ca_grid_func_fill_data (void *ap, void *ptr)
|
|
351
719
|
{
|
|
352
720
|
CAGrid *ca = (CAGrid *) ap;
|
|
721
|
+
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
722
|
+
ca_size_t pdims[CA_RANK_MAX];
|
|
723
|
+
|
|
724
|
+
ca_grid_describe_axes(ca, desc, pdims);
|
|
725
|
+
|
|
726
|
+
/* Writing the selected cells used to go through a whole-parent attach and
|
|
727
|
+
sync. Where that attach is a gather rather than an alias, the cells this
|
|
728
|
+
view did not select make the round trip for nothing -- and through a
|
|
729
|
+
lossy layer they do not come back the same. Hand each slab to the parent
|
|
730
|
+
as a region instead. (PROPOSAL_PARTIAL_FILL_WHOLE_ROOT_WRITEBACK.md) */
|
|
731
|
+
if ( !ca_is_attached(ca->parent) && !ca_attach_is_alias(ca->parent) ) {
|
|
732
|
+
ca_axis_dispatch_fill_value_via_parent(ca->parent, pdims, desc, ca->ndim,
|
|
733
|
+
ca->bytes, ca->elements, ptr);
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
|
|
353
737
|
ca_attach(ca->parent);
|
|
354
|
-
|
|
738
|
+
ca_axis_dispatch_fill_value(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
739
|
+
ca->elements, ptr);
|
|
355
740
|
ca_sync(ca->parent);
|
|
356
741
|
ca_detach(ca->parent);
|
|
357
742
|
}
|
|
@@ -367,271 +752,77 @@ ca_grid_func_create_mask (void *ap)
|
|
|
367
752
|
}
|
|
368
753
|
|
|
369
754
|
ca->mask = (CArray *) ca_grid_new_share(ca->parent->mask,
|
|
370
|
-
ca->
|
|
755
|
+
ca->ndim, ca->axes);
|
|
371
756
|
}
|
|
372
757
|
|
|
373
758
|
ca_operation_function_t ca_grid_func = {
|
|
374
759
|
-1, /* CA_OBJ_GRID */
|
|
375
|
-
|
|
760
|
+
CA_VIEW_ARRAY,
|
|
376
761
|
free_ca_grid,
|
|
377
762
|
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
763
|
ca_grid_func_allocate,
|
|
385
764
|
ca_grid_func_attach,
|
|
386
765
|
ca_grid_func_sync,
|
|
387
766
|
ca_grid_func_detach,
|
|
388
|
-
ca_grid_func_copy_data,
|
|
389
|
-
ca_grid_func_sync_data,
|
|
390
767
|
ca_grid_func_fill_data,
|
|
391
768
|
ca_grid_func_create_mask,
|
|
769
|
+
ca_grid_func_xfer_index,
|
|
770
|
+
ca_grid_func_xfer_addrs,
|
|
771
|
+
ca_grid_func_fold_stride,
|
|
772
|
+
ca_grid_func_xfer_stride,
|
|
773
|
+
ca_grid_func_xfer_all,
|
|
392
774
|
};
|
|
393
775
|
|
|
394
776
|
/* ------------------------------------------------------------------- */
|
|
395
777
|
|
|
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
778
|
VALUE
|
|
615
|
-
rb_ca_grid_new (VALUE cary,
|
|
779
|
+
rb_ca_grid_new (VALUE cary, int8_t ndim, cag_axis_t *protos)
|
|
616
780
|
{
|
|
617
781
|
volatile VALUE obj;
|
|
618
782
|
CArray *parent;
|
|
619
783
|
CAGrid *ca;
|
|
620
784
|
rb_check_carray_object(cary);
|
|
621
785
|
TypedData_Get_Struct(cary, CArray, &carray_data_type, parent);
|
|
622
|
-
ca = ca_grid_new(parent,
|
|
786
|
+
ca = ca_grid_new(parent, ndim, protos);
|
|
623
787
|
obj = ca_wrap_struct(ca);
|
|
624
788
|
rb_ca_set_parent(obj, cary);
|
|
625
|
-
rb_ca_data_type_inherit(obj, cary);
|
|
626
789
|
return obj;
|
|
627
790
|
}
|
|
628
791
|
|
|
629
|
-
/*
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
792
|
+
/* Detect a plain Ruby Range (Integer first/last, exclude_end?, step=1
|
|
793
|
+
implicit) and convert it to STRIDE (start, count, step=1).
|
|
794
|
+
Returns 1 on success (fills *out_start, *out_count), 0 on fallback
|
|
795
|
+
(caller should materialise to INDEX). Negative endpoints are
|
|
796
|
+
normalised against dim_size like everywhere else in CArray. */
|
|
797
|
+
static int
|
|
798
|
+
cag_range_to_stride (VALUE range, ca_size_t dim_size,
|
|
799
|
+
ca_size_t *out_start, ca_size_t *out_count)
|
|
800
|
+
{
|
|
801
|
+
VALUE rb_first, rb_last;
|
|
802
|
+
ca_size_t first, last, count;
|
|
803
|
+
int exclude_end;
|
|
804
|
+
|
|
805
|
+
if ( ! rb_obj_is_kind_of(range, rb_cRange) ) return 0;
|
|
806
|
+
rb_first = rb_funcall(range, rb_intern("first"), 0);
|
|
807
|
+
rb_last = rb_funcall(range, rb_intern("last"), 0);
|
|
808
|
+
if ( ! FIXNUM_P(rb_first) || ! FIXNUM_P(rb_last) ) return 0;
|
|
809
|
+
exclude_end = RTEST(rb_funcall(range, rb_intern("exclude_end?"), 0));
|
|
810
|
+
|
|
811
|
+
first = NUM2SIZE(rb_first);
|
|
812
|
+
last = NUM2SIZE(rb_last);
|
|
813
|
+
if (first < 0) first += dim_size;
|
|
814
|
+
if (last < 0) last += dim_size;
|
|
815
|
+
if (exclude_end) last -= 1;
|
|
816
|
+
|
|
817
|
+
if (first < 0 || first >= dim_size) return 0;
|
|
818
|
+
if (last < first - 1) return 0; /* empty range */
|
|
819
|
+
if (last >= dim_size) return 0;
|
|
820
|
+
count = last - first + 1;
|
|
821
|
+
|
|
822
|
+
*out_start = first;
|
|
823
|
+
*out_count = count;
|
|
824
|
+
return 1;
|
|
825
|
+
}
|
|
635
826
|
|
|
636
827
|
VALUE
|
|
637
828
|
rb_ca_grid (int argc, VALUE *argv, VALUE self)
|
|
@@ -639,12 +830,23 @@ rb_ca_grid (int argc, VALUE *argv, VALUE self)
|
|
|
639
830
|
volatile VALUE obj, ridx, rval;
|
|
640
831
|
volatile VALUE list = rb_ary_new();
|
|
641
832
|
CArray *ca;
|
|
642
|
-
CArray *ci[CA_RANK_MAX];
|
|
643
|
-
|
|
644
|
-
CArray *grid[CA_RANK_MAX];
|
|
833
|
+
CArray *ci[CA_RANK_MAX]; /* CAWrap holders for INDEX axes; NULL for STRIDE */
|
|
834
|
+
cag_axis_t protos[CA_RANK_MAX];
|
|
645
835
|
ca_size_t i;
|
|
646
836
|
|
|
647
|
-
|
|
837
|
+
/* Dispatch hook: route mixed AP + single boolean to CASelectAxis
|
|
838
|
+
(slab-copy optimised path). Falls through to per-cell CAGrid gather
|
|
839
|
+
when not eligible (integer index, multiple INDIRECT axes, indirect
|
|
840
|
+
not on axis 0). Inline argv[0] type check avoids the function call
|
|
841
|
+
when axis 0 is nil/Integer (most patterns with INDIRECT on inner axes). */
|
|
842
|
+
extern int ca_csa_dispatch_bypass;
|
|
843
|
+
if ( ! ca_csa_dispatch_bypass && argc > 0 && TYPE(argv[0]) == T_DATA ) {
|
|
844
|
+
if ( rb_ca_select_axis_eligible_p(argc, argv, self) ) {
|
|
845
|
+
return rb_ca_select_axis(argc, argv, self);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
648
850
|
|
|
649
851
|
ridx = rb_ary_new4(argc, argv);
|
|
650
852
|
|
|
@@ -679,43 +881,82 @@ rb_ca_grid (int argc, VALUE *argv, VALUE self)
|
|
|
679
881
|
return rb_ca_grid(argc, argv, ref);
|
|
680
882
|
}
|
|
681
883
|
|
|
682
|
-
|
|
884
|
+
/* Build per-axis protos:
|
|
885
|
+
nil -> STRIDE(0, parent.dim, 1), no CArray
|
|
886
|
+
Range -> STRIDE if plain integer Range, else fall through to INDEX
|
|
887
|
+
CArray -> INDEX with indices = (ca_size_t*)ca_wrap_readonly(...)->ptr */
|
|
888
|
+
for (i = 0; i < ca->ndim; i++) {
|
|
889
|
+
ca_size_t dim_size = ca->dim[i];
|
|
683
890
|
rval = rb_ary_entry(ridx, i);
|
|
891
|
+
ci[i] = NULL;
|
|
684
892
|
if ( NIL_P(rval) ) {
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
893
|
+
protos[i].kind = CAG_AXIS_STRIDE;
|
|
894
|
+
protos[i].count = dim_size;
|
|
895
|
+
protos[i].start = 0;
|
|
896
|
+
protos[i].step = 1;
|
|
897
|
+
protos[i].indices = NULL;
|
|
898
|
+
continue;
|
|
688
899
|
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
900
|
+
if ( rb_obj_is_kind_of(rval, rb_cRange) ) {
|
|
901
|
+
ca_size_t start, count;
|
|
902
|
+
if ( cag_range_to_stride(rval, dim_size, &start, &count) ) {
|
|
903
|
+
protos[i].kind = CAG_AXIS_STRIDE;
|
|
904
|
+
protos[i].count = count;
|
|
905
|
+
protos[i].start = start;
|
|
906
|
+
protos[i].step = 1;
|
|
907
|
+
protos[i].indices = NULL;
|
|
908
|
+
continue;
|
|
694
909
|
}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
910
|
+
/* fallback: materialise to integer array */
|
|
911
|
+
rval = rb_funcall(rb_mKernel, rb_intern("CA_SIZE"), 1, rval);
|
|
912
|
+
}
|
|
913
|
+
else if ( rb_obj_is_carray(rval) ) {
|
|
914
|
+
if ( rb_ca_is_boolean_type(rval) ) {
|
|
915
|
+
rval = rb_ca_where(rval);
|
|
700
916
|
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
917
|
+
}
|
|
918
|
+
else if ( TYPE(rval) == T_ARRAY ) {
|
|
919
|
+
rb_raise(rb_eRuntimeError, "not implemented for this index");
|
|
920
|
+
}
|
|
704
921
|
|
|
705
|
-
|
|
706
|
-
|
|
922
|
+
/* INDEX axis */
|
|
923
|
+
ci[i] = ca_wrap_readonly(rval, CA_SIZE);
|
|
924
|
+
rb_ary_push(list, rval);
|
|
925
|
+
ca_attach(ci[i]);
|
|
926
|
+
|
|
927
|
+
protos[i].kind = CAG_AXIS_INDEX;
|
|
928
|
+
if ( ca_is_any_masked(ci[i]) ) {
|
|
929
|
+
/* mask-filtered snapshot: skip masked cells. We point protos[i]
|
|
930
|
+
.indices at a temp buffer alloc'd here and freed after setup
|
|
931
|
+
copies it (setup snapshots into its own ALLOC). Caller-side
|
|
932
|
+
lifetime: the temp lives until ca_grid_new returns. */
|
|
933
|
+
ca_size_t gsize = ci[i]->elements - ca_count_masked(ci[i]);
|
|
934
|
+
ca_size_t *src = (ca_size_t *) ci[i]->ptr;
|
|
935
|
+
boolean8_t *m = (boolean8_t *) ci[i]->mask->ptr;
|
|
936
|
+
ca_size_t *tmp = ALLOC_N(ca_size_t, gsize > 0 ? gsize : 1);
|
|
937
|
+
ca_size_t j, n = 0;
|
|
938
|
+
for (j = 0; j < ci[i]->elements; j++) {
|
|
939
|
+
if ( ! m[j] ) tmp[n++] = src[j];
|
|
707
940
|
}
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
941
|
+
protos[i].count = gsize;
|
|
942
|
+
protos[i].indices = tmp;
|
|
943
|
+
} else {
|
|
944
|
+
protos[i].count = ci[i]->elements;
|
|
945
|
+
protos[i].indices = (ca_size_t *) ci[i]->ptr;
|
|
712
946
|
}
|
|
947
|
+
protos[i].start = 0;
|
|
948
|
+
protos[i].step = 0;
|
|
713
949
|
}
|
|
714
950
|
|
|
715
|
-
obj = rb_ca_grid_new(self,
|
|
951
|
+
obj = rb_ca_grid_new(self, ca->ndim, protos);
|
|
716
952
|
|
|
717
|
-
|
|
953
|
+
/* Cleanup: detach CAWraps + free temp masked-snapshot buffers (setup
|
|
954
|
+
has already copied indices into its own ALLOC). */
|
|
955
|
+
for (i = 0; i < ca->ndim; i++) {
|
|
718
956
|
if ( ci[i] ) {
|
|
957
|
+
if ( ca_is_any_masked(ci[i]) ) {
|
|
958
|
+
xfree(protos[i].indices);
|
|
959
|
+
}
|
|
719
960
|
ca_detach(ci[i]);
|
|
720
961
|
}
|
|
721
962
|
}
|
|
@@ -738,24 +979,197 @@ rb_ca_grid_initialize_copy (VALUE self, VALUE other)
|
|
|
738
979
|
TypedData_Get_Struct(self, CAGrid, &cagrid_data_type, ca);
|
|
739
980
|
TypedData_Get_Struct(other, CAGrid, &cagrid_data_type, cs);
|
|
740
981
|
|
|
741
|
-
|
|
742
|
-
|
|
982
|
+
if ( ca_func[CA_OBJ_GRID].pool_init ) {
|
|
983
|
+
ca_array_pool_alloc(ca, CA_OBJ_GRID, cs->ndim);
|
|
984
|
+
}
|
|
985
|
+
/* Share the source's axes buffer (CA_FLAG_SHARE_INDEX semantics:
|
|
986
|
+
source CAGrid owns the lifetime; clone aliases it). */
|
|
987
|
+
ca_grid_setup(ca, cs->parent, cs->ndim, cs->axes, 1);
|
|
743
988
|
|
|
744
989
|
return self;
|
|
745
990
|
}
|
|
746
991
|
|
|
747
992
|
|
|
748
993
|
|
|
994
|
+
/* ------------------------------------------------------------------- */
|
|
995
|
+
/* Producer interface: emit the per-axis descriptor array -- a 1:1
|
|
996
|
+
mechanical mapping from CAGrid's internal tagged storage to the
|
|
997
|
+
framework descriptor.
|
|
998
|
+
|
|
999
|
+
STRIDE axes (= nil-arg or arithmetic-progression Range) carry their
|
|
1000
|
+
actual start/step, so axis-merge can fire on these axes when they
|
|
1001
|
+
neighbour other STRIDE axes. INDEX axes borrow the owned
|
|
1002
|
+
ca->axes[k].indices snapshot. */
|
|
1003
|
+
|
|
1004
|
+
void
|
|
1005
|
+
ca_grid_describe_axes (void *ap, ca_axis_desc_t *out,
|
|
1006
|
+
ca_size_t *out_parent_dims)
|
|
1007
|
+
{
|
|
1008
|
+
CAGrid *ca = (CAGrid *) ap;
|
|
1009
|
+
int8_t k;
|
|
1010
|
+
for ( k = 0; k < ca->ndim; k++ ) {
|
|
1011
|
+
out_parent_dims[k] = ca->parent->dim[k];
|
|
1012
|
+
if ( ca->axes[k].kind == CAG_AXIS_STRIDE ) {
|
|
1013
|
+
out[k].kind = CA_AXIS_KIND_STRIDE;
|
|
1014
|
+
out[k].count = ca->axes[k].count;
|
|
1015
|
+
out[k].start = ca->axes[k].start;
|
|
1016
|
+
out[k].step = ca->axes[k].step;
|
|
1017
|
+
out[k].indices = NULL;
|
|
1018
|
+
} else {
|
|
1019
|
+
out[k].kind = CA_AXIS_KIND_INDEX;
|
|
1020
|
+
out[k].count = ca->axes[k].count;
|
|
1021
|
+
out[k].start = 0;
|
|
1022
|
+
out[k].step = 0;
|
|
1023
|
+
out[k].indices = ca->axes[k].indices;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
#ifdef CARRAY_DEV_BUILD
|
|
1029
|
+
/* ============================================================
|
|
1030
|
+
* Debug accessors (dev-only, stripped in release)
|
|
1031
|
+
*
|
|
1032
|
+
* Gated by CARRAY_DEV_BUILD (enabled via `extconf.rb --enable-dev-build`
|
|
1033
|
+
* or `CARRAY_DEV=1 rake build_ext`). They expose the per-axis descriptor
|
|
1034
|
+
* and the engine's raw output to Ruby so spec_ai can pin them; nothing in
|
|
1035
|
+
* lib/ or the rest of ext/ consumes them. CASelectAxis carries the same
|
|
1036
|
+
* four under the same fence.
|
|
1037
|
+
* ============================================================ */
|
|
1038
|
+
|
|
1039
|
+
/* Returns the per-axis descriptor as an Array, one entry per axis:
|
|
1040
|
+
[:stride, count, start, step] or [:index, count, indices]. */
|
|
1041
|
+
static VALUE
|
|
1042
|
+
rb_ca_grid_describe_axes (VALUE self)
|
|
1043
|
+
{
|
|
1044
|
+
CAGrid *ca;
|
|
1045
|
+
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
1046
|
+
VALUE arr, entry, idx_ary;
|
|
1047
|
+
int8_t k;
|
|
1048
|
+
ca_size_t i;
|
|
1049
|
+
|
|
1050
|
+
ca_size_t pdims[CA_RANK_MAX];
|
|
1051
|
+
TypedData_Get_Struct(self, CAGrid, &cagrid_data_type, ca);
|
|
1052
|
+
ca_grid_describe_axes(ca, desc, pdims);
|
|
1053
|
+
|
|
1054
|
+
arr = rb_ary_new_capa(ca->ndim);
|
|
1055
|
+
for ( k = 0; k < ca->ndim; k++ ) {
|
|
1056
|
+
if ( desc[k].kind == CA_AXIS_KIND_STRIDE ) {
|
|
1057
|
+
entry = rb_ary_new_capa(4);
|
|
1058
|
+
rb_ary_push(entry, ID2SYM(rb_intern("stride")));
|
|
1059
|
+
rb_ary_push(entry, SIZE2NUM(desc[k].count));
|
|
1060
|
+
rb_ary_push(entry, SIZE2NUM(desc[k].start));
|
|
1061
|
+
rb_ary_push(entry, SIZE2NUM(desc[k].step));
|
|
1062
|
+
} else {
|
|
1063
|
+
entry = rb_ary_new_capa(3);
|
|
1064
|
+
rb_ary_push(entry, ID2SYM(rb_intern("index")));
|
|
1065
|
+
rb_ary_push(entry, SIZE2NUM(desc[k].count));
|
|
1066
|
+
idx_ary = rb_ary_new_capa(desc[k].count);
|
|
1067
|
+
for ( i = 0; i < desc[k].count; i++ ) {
|
|
1068
|
+
rb_ary_push(idx_ary, SIZE2NUM(desc[k].indices[i]));
|
|
1069
|
+
}
|
|
1070
|
+
rb_ary_push(entry, idx_ary);
|
|
1071
|
+
}
|
|
1072
|
+
rb_ary_push(arr, entry);
|
|
1073
|
+
}
|
|
1074
|
+
return arr;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
/* Returns the attach engine's gathered buffer as a String. */
|
|
1078
|
+
static VALUE
|
|
1079
|
+
rb_ca_grid_dispatch_attach_debug (VALUE self)
|
|
1080
|
+
{
|
|
1081
|
+
CAGrid *ca;
|
|
1082
|
+
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
1083
|
+
char *buf;
|
|
1084
|
+
VALUE str;
|
|
1085
|
+
|
|
1086
|
+
ca_size_t pdims[CA_RANK_MAX];
|
|
1087
|
+
TypedData_Get_Struct(self, CAGrid, &cagrid_data_type, ca);
|
|
1088
|
+
ca_grid_describe_axes(ca, desc, pdims);
|
|
1089
|
+
|
|
1090
|
+
ca_attach(ca->parent);
|
|
1091
|
+
buf = ca_axis_dispatch_attach(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
1092
|
+
ca->elements, NULL);
|
|
1093
|
+
ca_detach(ca->parent);
|
|
1094
|
+
|
|
1095
|
+
str = rb_str_new(buf, ca->elements * ca->bytes);
|
|
1096
|
+
xfree(buf);
|
|
1097
|
+
return str;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
/* Drives the scatter engine with a view-shaped input String. */
|
|
1101
|
+
static VALUE
|
|
1102
|
+
rb_ca_grid_dispatch_scatter_debug (VALUE self, VALUE in_str)
|
|
1103
|
+
{
|
|
1104
|
+
CAGrid *ca;
|
|
1105
|
+
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
1106
|
+
ca_size_t expected;
|
|
1107
|
+
|
|
1108
|
+
Check_Type(in_str, T_STRING);
|
|
1109
|
+
TypedData_Get_Struct(self, CAGrid, &cagrid_data_type, ca);
|
|
1110
|
+
|
|
1111
|
+
expected = ca->elements * ca->bytes;
|
|
1112
|
+
if ( (ca_size_t) RSTRING_LEN(in_str) != expected ) {
|
|
1113
|
+
rb_raise(rb_eArgError,
|
|
1114
|
+
"CAGrid#_dispatch_scatter_debug: input string length %lld "
|
|
1115
|
+
"!= expected %lld",
|
|
1116
|
+
(long long) RSTRING_LEN(in_str), (long long) expected);
|
|
1117
|
+
}
|
|
1118
|
+
ca_size_t pdims[CA_RANK_MAX];
|
|
1119
|
+
ca_grid_describe_axes(ca, desc, pdims);
|
|
1120
|
+
|
|
1121
|
+
ca_attach(ca->parent);
|
|
1122
|
+
ca_axis_dispatch_scatter(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
1123
|
+
ca->elements, RSTRING_PTR(in_str));
|
|
1124
|
+
ca_sync(ca->parent);
|
|
1125
|
+
ca_detach(ca->parent);
|
|
1126
|
+
return Qnil;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
/* Drives the fill_value engine with a one-element String. */
|
|
1130
|
+
static VALUE
|
|
1131
|
+
rb_ca_grid_dispatch_fill_value_debug (VALUE self, VALUE val_str)
|
|
1132
|
+
{
|
|
1133
|
+
CAGrid *ca;
|
|
1134
|
+
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
1135
|
+
|
|
1136
|
+
Check_Type(val_str, T_STRING);
|
|
1137
|
+
TypedData_Get_Struct(self, CAGrid, &cagrid_data_type, ca);
|
|
1138
|
+
|
|
1139
|
+
if ( (ca_size_t) RSTRING_LEN(val_str) != ca->bytes ) {
|
|
1140
|
+
rb_raise(rb_eArgError,
|
|
1141
|
+
"CAGrid#_dispatch_fill_value_debug: value string length %lld "
|
|
1142
|
+
"!= bytes %lld",
|
|
1143
|
+
(long long) RSTRING_LEN(val_str), (long long) ca->bytes);
|
|
1144
|
+
}
|
|
1145
|
+
ca_size_t pdims[CA_RANK_MAX];
|
|
1146
|
+
ca_grid_describe_axes(ca, desc, pdims);
|
|
1147
|
+
|
|
1148
|
+
ca_attach(ca->parent);
|
|
1149
|
+
ca_axis_dispatch_fill_value(ca->parent, pdims, desc, ca->ndim, ca->bytes,
|
|
1150
|
+
ca->elements, RSTRING_PTR(val_str));
|
|
1151
|
+
ca_sync(ca->parent);
|
|
1152
|
+
ca_detach(ca->parent);
|
|
1153
|
+
return Qnil;
|
|
1154
|
+
}
|
|
1155
|
+
#endif /* CARRAY_DEV_BUILD */
|
|
1156
|
+
|
|
1157
|
+
/* ------------------------------------------------------------------- */
|
|
1158
|
+
|
|
749
1159
|
void
|
|
750
|
-
Init_ca_obj_grid ()
|
|
1160
|
+
Init_ca_obj_grid (void)
|
|
751
1161
|
{
|
|
752
|
-
rb_cCAGrid = rb_define_class("CAGrid",
|
|
1162
|
+
rb_cCAGrid = rb_define_class("CAGrid", rb_cCAView);
|
|
753
1163
|
rb_cCAGridMask = rb_define_class("CAGridMask", rb_cCAGrid);
|
|
754
1164
|
|
|
755
|
-
|
|
1165
|
+
ca_grid_func.struct_size = sizeof(CAGrid);
|
|
1166
|
+
ca_grid_func.pool_bytes = ca_grid_pool_bytes;
|
|
1167
|
+
ca_grid_func.pool_init = ca_grid_pool_init;
|
|
1168
|
+
|
|
1169
|
+
CA_OBJ_GRID = ca_install_obj_type(rb_cCAGrid,
|
|
756
1170
|
&cagrid_data_type,
|
|
757
1171
|
rb_cCAGridMask,
|
|
758
|
-
&cagrid_mask_data_type, ca_grid_func);
|
|
1172
|
+
&cagrid_mask_data_type, &ca_grid_func, sizeof(ca_grid_func));
|
|
759
1173
|
rb_define_const(rb_cObject, "CA_OBJ_GRID", INT2NUM(CA_OBJ_GRID));
|
|
760
1174
|
|
|
761
1175
|
rb_define_method(rb_cCArray, "grid", rb_ca_grid, -1);
|
|
@@ -763,5 +1177,17 @@ Init_ca_obj_grid ()
|
|
|
763
1177
|
rb_define_alloc_func(rb_cCAGrid, rb_ca_grid_s_allocate);
|
|
764
1178
|
rb_define_method(rb_cCAGrid, "initialize_copy",
|
|
765
1179
|
rb_ca_grid_initialize_copy, 1);
|
|
1180
|
+
|
|
1181
|
+
#ifdef CARRAY_DEV_BUILD
|
|
1182
|
+
/* debug accessors (dev-only, stripped in release) */
|
|
1183
|
+
rb_define_method(rb_cCAGrid, "_describe_axes",
|
|
1184
|
+
rb_ca_grid_describe_axes, 0);
|
|
1185
|
+
rb_define_method(rb_cCAGrid, "_dispatch_attach_debug",
|
|
1186
|
+
rb_ca_grid_dispatch_attach_debug, 0);
|
|
1187
|
+
rb_define_method(rb_cCAGrid, "_dispatch_scatter_debug",
|
|
1188
|
+
rb_ca_grid_dispatch_scatter_debug, 1);
|
|
1189
|
+
rb_define_method(rb_cCAGrid, "_dispatch_fill_value_debug",
|
|
1190
|
+
rb_ca_grid_dispatch_fill_value_debug, 1);
|
|
1191
|
+
#endif
|
|
766
1192
|
}
|
|
767
1193
|
|