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_object.c
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/* ---------------------------------------------------------------------------
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Copyright (C) 2005-2020 Hiroki Motoyoshi
|
|
3
|
+
CAObject: the per-element Ruby-callback bridge view. Each cell read /
|
|
4
|
+
write forwards to the user object's fetch_* / store_* (and optional
|
|
5
|
+
bulk copy_* / sync_* / *_block) callbacks. Also the base for Faces
|
|
6
|
+
authored in Ruby (face: true wraps a storage parent).
|
|
8
7
|
|
|
9
8
|
---------------------------------------------------------------------------- */
|
|
10
9
|
|
|
@@ -35,14 +34,38 @@
|
|
|
35
34
|
*/
|
|
36
35
|
|
|
37
36
|
#include "carray.h"
|
|
37
|
+
#include "ca_obj_face.h" /* ca_face_* helpers for Face mode shortcuts */
|
|
38
|
+
|
|
39
|
+
static size_t
|
|
40
|
+
ca_object_dsize (const void *ap)
|
|
41
|
+
{
|
|
42
|
+
const CAObject *ca = (const CAObject *) ap;
|
|
43
|
+
return sizeof(CAObject) + ca->ndim * sizeof(ca_size_t);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Pool framework hooks: single ndim-sized tail (dim) in the _pool buffer
|
|
47
|
+
(uniform alloc/free discipline). */
|
|
48
|
+
static size_t
|
|
49
|
+
ca_object_pool_bytes (int8_t ndim)
|
|
50
|
+
{
|
|
51
|
+
ca_size_t n = (ndim > 0) ? ndim : 1;
|
|
52
|
+
return (size_t) n * sizeof(ca_size_t);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static void
|
|
56
|
+
ca_object_pool_init (void *ap, int8_t ndim)
|
|
57
|
+
{
|
|
58
|
+
CAObject *ca = (CAObject *) ap;
|
|
59
|
+
ca->dim = (ca_size_t *) ca->_pool;
|
|
60
|
+
}
|
|
38
61
|
|
|
39
62
|
const rb_data_type_t caobject_data_type = {
|
|
40
|
-
.parent = &
|
|
63
|
+
.parent = &caview_data_type,
|
|
41
64
|
.wrap_struct_name = "CAObject",
|
|
42
65
|
.function = {
|
|
43
66
|
.dmark = ca_mark,
|
|
44
67
|
.dfree = ca_free,
|
|
45
|
-
.dsize =
|
|
68
|
+
.dsize = ca_object_dsize,
|
|
46
69
|
.dcompact = NULL
|
|
47
70
|
},
|
|
48
71
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
@@ -50,22 +73,22 @@ const rb_data_type_t caobject_data_type = {
|
|
|
50
73
|
|
|
51
74
|
VALUE rb_cCAObject;
|
|
52
75
|
|
|
53
|
-
|
|
54
|
-
/* yard:
|
|
55
|
-
class CAObject < CAVirtual # :nodoc:
|
|
56
|
-
end
|
|
57
|
-
*/
|
|
58
|
-
|
|
59
|
-
|
|
60
76
|
/* ---------------------------------------------------------------------- */
|
|
61
77
|
|
|
78
|
+
static size_t
|
|
79
|
+
ca_objectmask_dsize (const void *ap)
|
|
80
|
+
{
|
|
81
|
+
const CAObjectMask *ca = (const CAObjectMask *) ap;
|
|
82
|
+
return sizeof(CAObjectMask) + ca->ndim * sizeof(ca_size_t);
|
|
83
|
+
}
|
|
84
|
+
|
|
62
85
|
const rb_data_type_t caobjectmask_data_type = {
|
|
63
|
-
.parent = &carray_data_type,
|
|
86
|
+
.parent = &carray_data_type,
|
|
64
87
|
.wrap_struct_name = "CAObjectMask",
|
|
65
88
|
.function = {
|
|
66
89
|
.dmark = ca_mark,
|
|
67
90
|
.dfree = ca_free,
|
|
68
|
-
.dsize =
|
|
91
|
+
.dsize = ca_objectmask_dsize,
|
|
69
92
|
.dcompact = NULL
|
|
70
93
|
},
|
|
71
94
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
@@ -74,16 +97,16 @@ const rb_data_type_t caobjectmask_data_type = {
|
|
|
74
97
|
static int8_t CA_OBJ_OBJECT_MASK;
|
|
75
98
|
VALUE rb_cCAObjectMask;
|
|
76
99
|
|
|
77
|
-
/* yard:
|
|
78
|
-
class CAObjectMask < CAVirtual # :nodoc:
|
|
79
|
-
end
|
|
80
|
-
*/
|
|
81
|
-
|
|
82
|
-
|
|
83
100
|
static CAObjectMask *
|
|
84
101
|
ca_objmask_new (VALUE array, int8_t ndim, ca_size_t *dim)
|
|
85
102
|
{
|
|
86
103
|
CAObjectMask *ca = ALLOC(CAObjectMask);
|
|
104
|
+
/* CA_OBJ_OBJECT_MASK registers no pool_init, so it lives on the legacy
|
|
105
|
+
ALLOC_N path (dim allocated separately, freed via free_ca_wrap's else
|
|
106
|
+
branch). ALLOC leaves _pool uninitialized; carray_setup_i keys the
|
|
107
|
+
dim allocation on _pool == NULL, so leaving it as garbage skips the
|
|
108
|
+
allocation and crashes the memcpy. Force the legacy path. */
|
|
109
|
+
ca->_pool = NULL;
|
|
87
110
|
ca_wrap_setup_null((CArray *)ca, CA_BOOLEAN, ndim, dim, 0, NULL);
|
|
88
111
|
ca->obj_type = CA_OBJ_OBJECT_MASK;
|
|
89
112
|
ca->array = array;
|
|
@@ -106,111 +129,99 @@ ca_objmask_func_clone (void *ap)
|
|
|
106
129
|
return ca_objmask_new(ca->array, ca->ndim, ca->dim);
|
|
107
130
|
}
|
|
108
131
|
|
|
109
|
-
|
|
110
|
-
|
|
132
|
+
/* per-cell cores: objmask reads/writes its own CA_BOOLEAN bit storage
|
|
133
|
+
(a contiguous wrap over the shared mask bytes) AND mirrors through the
|
|
134
|
+
user's Ruby mask_fetch_* / mask_store_* callbacks. Entity bit access
|
|
135
|
+
goes through ca_array_func_xfer_index / xfer_addrs. GET/PUT
|
|
136
|
+
direction-unified; the slots below forward. */
|
|
137
|
+
static void
|
|
138
|
+
ca_objmask_xfer_addr_one (CAObjectMask *ca, ca_size_t addr, void *ptr, int dir)
|
|
111
139
|
{
|
|
112
|
-
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
113
140
|
volatile VALUE ridx, raddr, rval;
|
|
114
141
|
int i;
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
142
|
+
if ( dir == CA_XFER_GET ) {
|
|
143
|
+
if ( rb_obj_respond_to(ca->array, rb_intern("mask_fetch_addr"), Qtrue) ) {
|
|
144
|
+
raddr = SIZE2NUM(addr);
|
|
145
|
+
rval = rb_funcall(ca->array, rb_intern("mask_fetch_addr"), 1, raddr);
|
|
146
|
+
*(uint8_t*) ptr = NUM2INT(rval) == 0 ? 0 : 1;
|
|
147
|
+
ca_array_func_xfer_addrs(ca, 1, &addr, ptr, CA_XFER_PUT);
|
|
148
|
+
}
|
|
149
|
+
else if ( rb_obj_respond_to(ca->array, rb_intern("mask_fetch_index"), Qtrue) ) {
|
|
150
|
+
ca_size_t idx[CA_RANK_MAX];
|
|
151
|
+
ca_addr2index((CArray *)ca, addr, idx);
|
|
152
|
+
ridx = rb_ary_new2(ca->ndim);
|
|
153
|
+
for (i=0; i<ca->ndim; i++) {
|
|
154
|
+
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
155
|
+
}
|
|
156
|
+
rval = rb_funcall(ca->array, rb_intern("mask_fetch_index"), 1, ridx);
|
|
157
|
+
*(uint8_t*) ptr = NUM2INT(rval) == 0 ? 0 : 1;
|
|
158
|
+
ca_array_func_xfer_index(ca, idx, ptr, CA_XFER_PUT);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
ca_array_func_xfer_addrs(ca, 1, &addr, ptr, CA_XFER_GET);
|
|
128
162
|
}
|
|
129
|
-
rval = rb_funcall(ca->array, rb_intern("mask_fetch_index"), 1, ridx);
|
|
130
|
-
*(uint8_t*) ptr = NUM2INT(rval) == 0 ? 0 : 1;
|
|
131
|
-
ca_array_func_store_index(ca, idx, ptr);
|
|
132
163
|
}
|
|
133
164
|
else {
|
|
134
|
-
|
|
165
|
+
ca_array_func_xfer_addrs(ca, 1, &addr, ptr, CA_XFER_PUT);
|
|
166
|
+
rval = INT2NUM( *(uint8_t*)ptr );
|
|
167
|
+
if ( rb_obj_respond_to(ca->array, rb_intern("mask_store_addr"), Qtrue) ) {
|
|
168
|
+
raddr = SIZE2NUM(addr);
|
|
169
|
+
rb_funcall(ca->array, rb_intern("mask_store_addr"), 2, raddr, rval);
|
|
170
|
+
}
|
|
171
|
+
else if ( rb_obj_respond_to(ca->array, rb_intern("mask_store_index"), Qtrue) ) {
|
|
172
|
+
ca_size_t idx[CA_RANK_MAX];
|
|
173
|
+
ca_addr2index((CArray *)ca, addr, idx);
|
|
174
|
+
ridx = rb_ary_new2(ca->ndim);
|
|
175
|
+
for (i=0; i<ca->ndim; i++) {
|
|
176
|
+
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
177
|
+
}
|
|
178
|
+
rb_funcall(ca->array, rb_intern("mask_store_index"), 2, ridx, rval);
|
|
179
|
+
}
|
|
135
180
|
}
|
|
136
181
|
}
|
|
137
182
|
|
|
138
|
-
void
|
|
139
|
-
|
|
183
|
+
static void
|
|
184
|
+
ca_objmask_xfer_index_one (CAObjectMask *ca, ca_size_t *idx, void *ptr, int dir)
|
|
140
185
|
{
|
|
141
|
-
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
142
186
|
volatile VALUE ridx, raddr, rval;
|
|
143
187
|
int i;
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
188
|
+
if ( dir == CA_XFER_GET ) {
|
|
189
|
+
if ( rb_obj_respond_to(ca->array, rb_intern("mask_fetch_index"), Qtrue) ) {
|
|
190
|
+
ridx = rb_ary_new2(ca->ndim);
|
|
191
|
+
for (i=0; i<ca->ndim; i++) {
|
|
192
|
+
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
193
|
+
}
|
|
194
|
+
rval = rb_funcall(ca->array, rb_intern("mask_fetch_index"), 1, ridx);
|
|
195
|
+
*(uint8_t*) ptr = NUM2INT(rval) == 0 ? 0 : 1;
|
|
196
|
+
ca_array_func_xfer_index(ca, idx, ptr, CA_XFER_PUT);
|
|
197
|
+
}
|
|
198
|
+
else if ( rb_obj_respond_to(ca->array, rb_intern("mask_fetch_addr"), Qtrue) ) {
|
|
199
|
+
ca_size_t addr = ca_index2addr((CArray *)ca, idx);
|
|
200
|
+
raddr = SIZE2NUM(addr);
|
|
201
|
+
rval = rb_funcall(ca->array, rb_intern("mask_fetch_addr"), 1, raddr);
|
|
202
|
+
*(uint8_t*) ptr = NUM2INT(rval) == 0 ? 0 : 1;
|
|
203
|
+
ca_array_func_xfer_addrs(ca, 1, &addr, ptr, CA_XFER_PUT);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
ca_array_func_xfer_index(ca, idx, ptr, CA_XFER_GET);
|
|
149
207
|
}
|
|
150
|
-
rval = rb_funcall(ca->array, rb_intern("mask_fetch_index"), 1, ridx);
|
|
151
|
-
*(uint8_t*) ptr = NUM2INT(rval) == 0 ? 0 : 1;
|
|
152
|
-
ca_array_func_store_index(ca, idx, ptr);
|
|
153
|
-
}
|
|
154
|
-
else if ( rb_obj_respond_to(ca->array, rb_intern("mask_fetch_addr"), Qtrue) ) {
|
|
155
|
-
ca_size_t addr = ca_index2addr(ca, idx);
|
|
156
|
-
raddr = SIZE2NUM(addr);
|
|
157
|
-
rval = rb_funcall(ca->array, rb_intern("mask_fetch_addr"), 1, raddr);
|
|
158
|
-
*(uint8_t*) ptr = NUM2INT(rval) == 0 ? 0 : 1;
|
|
159
|
-
ca_array_func_store_addr(ca, addr, ptr);
|
|
160
208
|
}
|
|
161
209
|
else {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
171
|
-
volatile VALUE ridx, raddr, rval;
|
|
172
|
-
int i;
|
|
173
|
-
|
|
174
|
-
ca_array_func_store_addr(ca, addr, ptr);
|
|
175
|
-
rval = INT2NUM( *(uint8_t*)ptr );
|
|
176
|
-
if ( rb_obj_respond_to(ca->array, rb_intern("mask_store_addr"), Qtrue) ) {
|
|
177
|
-
raddr = SIZE2NUM(addr);
|
|
178
|
-
rb_funcall(ca->array, rb_intern("mask_store_addr"), 2, raddr, rval);
|
|
179
|
-
}
|
|
180
|
-
else if ( rb_obj_respond_to(ca->array, rb_intern("mask_store_index"), Qtrue) ) {
|
|
181
|
-
ca_size_t idx[CA_RANK_MAX];
|
|
182
|
-
ca_addr2index(ca, addr, idx);
|
|
183
|
-
ridx = rb_ary_new2(ca->ndim);
|
|
184
|
-
for (i=0; i<ca->ndim; i++) {
|
|
185
|
-
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
210
|
+
ca_array_func_xfer_index(ca, idx, ptr, CA_XFER_PUT);
|
|
211
|
+
rval = INT2NUM( *(uint8_t*)ptr );
|
|
212
|
+
if ( rb_obj_respond_to(ca->array, rb_intern("mask_store_index"), Qtrue) ) {
|
|
213
|
+
ridx = rb_ary_new2(ca->ndim);
|
|
214
|
+
for (i=0; i<ca->ndim; i++) {
|
|
215
|
+
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
216
|
+
}
|
|
217
|
+
rb_funcall(ca->array, rb_intern("mask_store_index"), 2, ridx, rval);
|
|
186
218
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
void
|
|
192
|
-
ca_objmask_func_store_index (void *ap, ca_size_t *idx, void *ptr)
|
|
193
|
-
{
|
|
194
|
-
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
195
|
-
volatile VALUE ridx, raddr, rval;
|
|
196
|
-
int i;
|
|
197
|
-
|
|
198
|
-
ca_array_func_store_index(ca, idx, ptr);
|
|
199
|
-
rval = INT2NUM( *(uint8_t*)ptr );
|
|
200
|
-
|
|
201
|
-
if ( rb_obj_respond_to(ca->array, rb_intern("mask_store_index"), Qtrue) ) {
|
|
202
|
-
ridx = rb_ary_new2(ca->ndim);
|
|
203
|
-
for (i=0; i<ca->ndim; i++) {
|
|
204
|
-
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
219
|
+
else if ( rb_obj_respond_to(ca->array, rb_intern("mask_store_addr"), Qtrue) ) {
|
|
220
|
+
ca_size_t addr = ca_index2addr((CArray *)ca, idx);
|
|
221
|
+
raddr = SIZE2NUM(addr);
|
|
222
|
+
rb_funcall(ca->array, rb_intern("mask_store_addr"), 2, raddr, rval);
|
|
205
223
|
}
|
|
206
|
-
rb_funcall(ca->array, rb_intern("mask_store_index"), 2, ridx, rval);
|
|
207
224
|
}
|
|
208
|
-
else if ( rb_obj_respond_to(ca->array, rb_intern("mask_store_addr"), Qtrue) ) {
|
|
209
|
-
ca_size_t addr = ca_index2addr(ca, idx);
|
|
210
|
-
raddr = SIZE2NUM(addr);
|
|
211
|
-
rb_funcall(ca->array, rb_intern("mask_store_addr"), 2, raddr, rval);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
225
|
}
|
|
215
226
|
|
|
216
227
|
static void
|
|
@@ -234,46 +245,149 @@ ca_objmask_func_sync (void *ap)
|
|
|
234
245
|
}
|
|
235
246
|
|
|
236
247
|
static void
|
|
237
|
-
|
|
248
|
+
ca_objmask_func_xfer_all (void *ap, void *data, int dir)
|
|
238
249
|
{
|
|
239
250
|
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
240
|
-
if (
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
251
|
+
if ( dir == CA_XFER_GET ) {
|
|
252
|
+
if ( rb_obj_respond_to(ca->array, rb_intern("mask_copy_data"), Qtrue) ) {
|
|
253
|
+
char *ptr0 = ca->ptr;
|
|
254
|
+
ca->ptr = (char *) data;
|
|
255
|
+
rb_funcall(ca->array, rb_intern("mask_copy_data"),
|
|
256
|
+
1, ca_objmask_mask_data(ca));
|
|
257
|
+
ca->ptr = ptr0;
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
ca_array_func_xfer_all(ca, data, CA_XFER_GET);
|
|
261
|
+
}
|
|
246
262
|
}
|
|
247
263
|
else {
|
|
248
|
-
|
|
264
|
+
if ( rb_obj_respond_to(ca->array, rb_intern("mask_copy_data"), Qtrue) ) {
|
|
265
|
+
char *ptr0 = ca->ptr;
|
|
266
|
+
ca->ptr = (char *) data;
|
|
267
|
+
rb_funcall(ca->array, rb_intern("mask_sync_data"),
|
|
268
|
+
1, ca_objmask_mask_data(ca));
|
|
269
|
+
ca->ptr = ptr0;
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
ca_array_func_xfer_all(ca, data, CA_XFER_PUT);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
void
|
|
278
|
+
ca_objmask_func_fill_data (void *ap, void *val)
|
|
279
|
+
{
|
|
280
|
+
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
281
|
+
ca_array_func_fill_data(ca, val);
|
|
282
|
+
if ( rb_obj_respond_to(ca->array, rb_intern("mask_fill_data"), Qtrue) ) {
|
|
283
|
+
rb_funcall(ca->array, rb_intern("mask_fill_data"),
|
|
284
|
+
1, INT2NUM(*(uint8_t*)val));
|
|
249
285
|
}
|
|
250
286
|
}
|
|
251
287
|
|
|
252
288
|
static void
|
|
253
|
-
|
|
289
|
+
ca_objmask_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
290
|
+
{
|
|
291
|
+
ca_objmask_xfer_index_one((CAObjectMask *) ap, idx, data, dir);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/* Forward declaration: ca_object_wrap_transient (defined further down,
|
|
295
|
+
near the data-side xfer functions). */
|
|
296
|
+
static VALUE
|
|
297
|
+
ca_object_wrap_transient (int8_t data_type, ca_size_t bytes,
|
|
298
|
+
int8_t ndim, ca_size_t *dim, void *data, int dir);
|
|
299
|
+
|
|
300
|
+
/* Mask parallel of the bulk-addrs path. When `mask_copy_addrs` /
|
|
301
|
+
`mask_sync_addrs` is defined, 1-call bulk dispatch; else per-cell loop. */
|
|
302
|
+
static void
|
|
303
|
+
ca_objmask_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
304
|
+
void *data, int dir)
|
|
254
305
|
{
|
|
255
306
|
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
307
|
+
ID mid = (dir == CA_XFER_GET) ? rb_intern("mask_copy_addrs")
|
|
308
|
+
: rb_intern("mask_sync_addrs");
|
|
309
|
+
|
|
310
|
+
if ( n > 0 && rb_obj_respond_to(ca->array, mid, Qtrue) ) {
|
|
311
|
+
volatile VALUE raddrs, rdata;
|
|
312
|
+
ca_size_t dim1[1] = { n };
|
|
313
|
+
raddrs = ca_object_wrap_transient(CA_SIZE, sizeof(ca_size_t),
|
|
314
|
+
1, dim1, addrs, CA_XFER_PUT);
|
|
315
|
+
rdata = ca_object_wrap_transient(ca->data_type, ca->bytes,
|
|
316
|
+
1, dim1, data, dir);
|
|
317
|
+
rb_funcall(ca->array, mid, 2, raddrs, rdata);
|
|
318
|
+
return;
|
|
262
319
|
}
|
|
263
|
-
|
|
264
|
-
|
|
320
|
+
|
|
321
|
+
{
|
|
322
|
+
char *d = (char *) data;
|
|
323
|
+
ca_size_t i;
|
|
324
|
+
for ( i = 0; i < n; i++ ) {
|
|
325
|
+
ca_objmask_xfer_addr_one(ca, addrs[i], d + i * ca->bytes, dir);
|
|
326
|
+
}
|
|
265
327
|
}
|
|
266
328
|
}
|
|
267
329
|
|
|
268
|
-
|
|
269
|
-
|
|
330
|
+
/* Mask parallel of the partial-region path. Same per-axis index-step
|
|
331
|
+
gate; dispatches mask_copy_block / mask_sync_block when the gate passes
|
|
332
|
+
and the callback is defined. Otherwise falls back to flat-addr
|
|
333
|
+
expansion -> mask xfer_addrs. */
|
|
334
|
+
static void
|
|
335
|
+
ca_objmask_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
336
|
+
ca_size_t *strides, void *data, int dir)
|
|
270
337
|
{
|
|
271
338
|
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
339
|
+
int8_t ndim = ca->ndim;
|
|
340
|
+
ca_size_t native[CA_RANK_MAX], steps[CA_RANK_MAX], idx[CA_RANK_MAX];
|
|
341
|
+
ca_size_t *vaddrs;
|
|
342
|
+
ca_size_t base = 0, n = 1, i, s;
|
|
343
|
+
int8_t k;
|
|
344
|
+
volatile VALUE holder;
|
|
345
|
+
ID mid_block = (dir == CA_XFER_GET) ? rb_intern("mask_copy_block")
|
|
346
|
+
: rb_intern("mask_sync_block");
|
|
347
|
+
|
|
348
|
+
s = ca->bytes;
|
|
349
|
+
for (k = ndim - 1; k >= 0; k--) { native[k] = s; s *= ca->dim[k]; }
|
|
350
|
+
for (k = 0; k < ndim; k++) { base += starts[k] * native[k]; n *= counts[k]; }
|
|
351
|
+
|
|
352
|
+
if ( n == 0 ) return;
|
|
353
|
+
|
|
354
|
+
if ( rb_obj_respond_to(ca->array, mid_block, Qtrue) ) {
|
|
355
|
+
/* The request is over the view's addresses, so a transposed / flat
|
|
356
|
+
request is legal; the per-axis copy_block dispatch below would
|
|
357
|
+
misread it. See ca_xfer_stride_request_is_axis_box (carray.h). */
|
|
358
|
+
int aligned = ca_xfer_stride_request_is_axis_box(ca, starts, counts, strides);
|
|
359
|
+
for ( k = 0; aligned && k < ndim; k++ ) {
|
|
360
|
+
if ( strides[k] <= 0 || strides[k] % native[k] != 0 ) { aligned = 0; break; }
|
|
361
|
+
steps[k] = strides[k] / native[k];
|
|
362
|
+
}
|
|
363
|
+
if ( aligned ) {
|
|
364
|
+
volatile VALUE rstarts, rcounts, rsteps, rdata;
|
|
365
|
+
rstarts = rb_ary_new_capa(ndim);
|
|
366
|
+
rcounts = rb_ary_new_capa(ndim);
|
|
367
|
+
rsteps = rb_ary_new_capa(ndim);
|
|
368
|
+
for ( k = 0; k < ndim; k++ ) {
|
|
369
|
+
rb_ary_push(rstarts, SIZE2NUM(starts[k]));
|
|
370
|
+
rb_ary_push(rcounts, SIZE2NUM(counts[k]));
|
|
371
|
+
rb_ary_push(rsteps, SIZE2NUM(steps[k]));
|
|
372
|
+
}
|
|
373
|
+
rdata = ca_object_wrap_transient(ca->data_type, ca->bytes,
|
|
374
|
+
ndim, counts, data, dir);
|
|
375
|
+
rb_funcall(ca->array, mid_block, 4, rstarts, rcounts, rsteps, rdata);
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
vaddrs = ALLOCV_N(ca_size_t, holder, n);
|
|
381
|
+
for (k = 0; k < ndim; k++) idx[k] = 0;
|
|
382
|
+
for (i = 0; i < n; i++) {
|
|
383
|
+
ca_size_t off = base;
|
|
384
|
+
for (k = 0; k < ndim; k++) off += idx[k] * strides[k];
|
|
385
|
+
vaddrs[i] = off / ca->bytes;
|
|
386
|
+
k = ndim - 1;
|
|
387
|
+
while (k >= 0) { if (++idx[k] < counts[k]) break; idx[k] = 0; k--; }
|
|
276
388
|
}
|
|
389
|
+
ca_objmask_func_xfer_addrs(ca, n, vaddrs, data, dir);
|
|
390
|
+
ALLOCV_END(holder);
|
|
277
391
|
}
|
|
278
392
|
|
|
279
393
|
static ca_operation_function_t ca_objmask_func = {
|
|
@@ -281,27 +395,24 @@ static ca_operation_function_t ca_objmask_func = {
|
|
|
281
395
|
CA_REAL_ARRAY,
|
|
282
396
|
free_ca_wrap,
|
|
283
397
|
ca_objmask_func_clone,
|
|
284
|
-
ca_array_func_ptr_at_addr,
|
|
285
|
-
ca_array_func_ptr_at_index,
|
|
286
|
-
ca_objmask_func_fetch_addr,
|
|
287
|
-
ca_objmask_func_fetch_index,
|
|
288
|
-
ca_objmask_func_store_addr,
|
|
289
|
-
ca_objmask_func_store_index,
|
|
290
398
|
ca_array_func_allocate,
|
|
291
399
|
ca_objmask_func_attach,
|
|
292
400
|
ca_objmask_func_sync,
|
|
293
401
|
ca_array_func_detach,
|
|
294
|
-
ca_objmask_func_copy_data,
|
|
295
|
-
ca_objmask_func_sync_data,
|
|
296
402
|
ca_objmask_func_fill_data,
|
|
297
403
|
ca_array_func_create_mask,
|
|
404
|
+
ca_objmask_func_xfer_index,
|
|
405
|
+
ca_objmask_func_xfer_addrs,
|
|
406
|
+
NULL, /* fold_stride: never-fold (callback boundary) */
|
|
407
|
+
ca_objmask_func_xfer_stride,
|
|
408
|
+
ca_objmask_func_xfer_all,
|
|
298
409
|
};
|
|
299
410
|
|
|
300
411
|
static VALUE
|
|
301
412
|
rb_ca_objmask_s_allocate (VALUE klass)
|
|
302
413
|
{
|
|
303
414
|
CAObjectMask *ca;
|
|
304
|
-
return TypedData_Make_Struct(klass, CAObjectMask, &
|
|
415
|
+
return TypedData_Make_Struct(klass, CAObjectMask, &caobjectmask_data_type, ca);
|
|
305
416
|
}
|
|
306
417
|
|
|
307
418
|
static VALUE
|
|
@@ -361,7 +472,9 @@ ca_object_setup (CAObject *ca,
|
|
|
361
472
|
ca->attach = 0;
|
|
362
473
|
ca->nosync = 0;
|
|
363
474
|
|
|
364
|
-
ca->
|
|
475
|
+
if ( ! ca->_pool ) {
|
|
476
|
+
ca->dim = ALLOC_N(ca_size_t, ndim);
|
|
477
|
+
}
|
|
365
478
|
|
|
366
479
|
ca->data = ca_wrap_new_null(data_type, ndim, dim, bytes, NULL);
|
|
367
480
|
|
|
@@ -373,7 +486,7 @@ ca_object_setup (CAObject *ca,
|
|
|
373
486
|
static CAObject *
|
|
374
487
|
ca_object_new (int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes)
|
|
375
488
|
{
|
|
376
|
-
CAObject *ca =
|
|
489
|
+
CAObject *ca = (CAObject *) ca_array_alloc(CA_OBJ_OBJECT, ndim);
|
|
377
490
|
ca_object_setup(ca, data_type, ndim, dim, bytes);
|
|
378
491
|
return ca;
|
|
379
492
|
}
|
|
@@ -384,8 +497,13 @@ free_ca_object (void *ap)
|
|
|
384
497
|
CAObject *ca = (CAObject *) ap;
|
|
385
498
|
if ( ca != NULL ) {
|
|
386
499
|
/* ca->mask will be GC-ed by Ruby interpreter */
|
|
387
|
-
|
|
388
|
-
|
|
500
|
+
if ( ca->_pool ) {
|
|
501
|
+
ca_array_free(ca); /* dim lives in _pool */
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
xfree(ca->dim);
|
|
505
|
+
xfree(ca);
|
|
506
|
+
}
|
|
389
507
|
}
|
|
390
508
|
}
|
|
391
509
|
|
|
@@ -395,186 +513,252 @@ static void *
|
|
|
395
513
|
ca_object_func_clone (void *ap)
|
|
396
514
|
{
|
|
397
515
|
CAObject *ca = (CAObject *) ap;
|
|
398
|
-
return ca_object_new(ca->
|
|
516
|
+
return ca_object_new(ca->data_type, ca->ndim, ca->dim, ca->bytes);
|
|
399
517
|
}
|
|
400
518
|
|
|
401
519
|
#define ca_object_func_ptr_at_addr ca_array_func_ptr_at_addr
|
|
402
520
|
#define ca_object_func_ptr_at_index ca_array_func_ptr_at_index
|
|
403
521
|
|
|
522
|
+
/* per-cell cores: the addr- and index-primary Ruby-callback bridge logic,
|
|
523
|
+
direction-unified. The fetch_* / store_* slots below are thin
|
|
524
|
+
forwarders onto these. */
|
|
404
525
|
static void
|
|
405
|
-
|
|
526
|
+
ca_object_xfer_addr_one (CAObject *ca, ca_size_t addr, void *ptr, int dir)
|
|
406
527
|
{
|
|
407
|
-
CAObject *ca = (CAObject *) ap;
|
|
408
528
|
volatile VALUE ridx, raddr, rval;
|
|
409
529
|
int i;
|
|
410
|
-
if (
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
530
|
+
if ( dir == CA_XFER_GET ) {
|
|
531
|
+
if ( rb_obj_respond_to(ca->self, rb_intern("fetch_addr"), Qtrue) ) {
|
|
532
|
+
raddr = SIZE2NUM(addr);
|
|
533
|
+
rval = rb_funcall(ca->self, rb_intern("fetch_addr"), 1, raddr);
|
|
534
|
+
if ( rval == CA_UNDEF ) {
|
|
535
|
+
ca_update_mask(ca);
|
|
536
|
+
if ( ! ca->mask ) {
|
|
537
|
+
ca_create_mask(ca);
|
|
538
|
+
}
|
|
539
|
+
*((boolean8_t*)ca->mask->ptr + addr) = 1;
|
|
540
|
+
if ( ca->data_type == CA_OBJECT ) {
|
|
541
|
+
rb_ca_obj2ptr(ca->self, INT2NUM(0), ptr);
|
|
542
|
+
}
|
|
417
543
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
544
|
+
else {
|
|
545
|
+
if ( ca_has_mask(ca) ) {
|
|
546
|
+
*((boolean8_t*)ca->mask->ptr + addr) = 0;
|
|
547
|
+
}
|
|
548
|
+
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
421
549
|
}
|
|
422
550
|
}
|
|
423
551
|
else {
|
|
424
|
-
|
|
425
|
-
|
|
552
|
+
ca_size_t idx[CA_RANK_MAX];
|
|
553
|
+
ca_addr2index(ca, addr, idx);
|
|
554
|
+
ridx = rb_ary_new2(ca->ndim);
|
|
555
|
+
for (i=0; i<ca->ndim; i++) {
|
|
556
|
+
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
557
|
+
}
|
|
558
|
+
rval = rb_funcall(ca->self, rb_intern("fetch_index"), 1, ridx);
|
|
559
|
+
if ( rval == CA_UNDEF ) {
|
|
560
|
+
ca_update_mask(ca);
|
|
561
|
+
if ( ! ca->mask ) {
|
|
562
|
+
ca_create_mask(ca);
|
|
563
|
+
}
|
|
564
|
+
*((boolean8_t*)ca->mask->ptr + ca_index2addr(ca->mask, idx)) = 1;
|
|
565
|
+
if ( ca->data_type == CA_OBJECT ) {
|
|
566
|
+
rb_ca_obj2ptr(ca->self, INT2NUM(0), ptr);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
else {
|
|
570
|
+
if ( ca_has_mask(ca) ) {
|
|
571
|
+
*((boolean8_t*)ca->mask->ptr + ca_index2addr(ca->mask, idx)) = 0;
|
|
572
|
+
}
|
|
573
|
+
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
426
574
|
}
|
|
427
|
-
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
428
575
|
}
|
|
429
576
|
}
|
|
430
577
|
else {
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
436
|
-
}
|
|
437
|
-
rval = rb_funcall(ca->self, rb_intern("fetch_index"), 1, ridx);
|
|
438
|
-
if ( rval == CA_UNDEF ) {
|
|
439
|
-
ca_update_mask(ca);
|
|
440
|
-
if ( ! ca->mask ) {
|
|
441
|
-
ca_create_mask(ca);
|
|
442
|
-
}
|
|
443
|
-
*(boolean8_t*)ca_ptr_at_index(ca->mask, idx) = 1;
|
|
444
|
-
if ( ca->data_type == CA_OBJECT ) {
|
|
445
|
-
rb_ca_obj2ptr(ca->self, INT2NUM(0), ptr);
|
|
446
|
-
}
|
|
578
|
+
if ( rb_obj_respond_to(ca->self, rb_intern("store_addr"), Qtrue) ) {
|
|
579
|
+
raddr = SIZE2NUM(addr);
|
|
580
|
+
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
581
|
+
rb_funcall(ca->self, rb_intern("store_addr"), 2, raddr, rval);
|
|
447
582
|
}
|
|
448
583
|
else {
|
|
449
|
-
|
|
450
|
-
|
|
584
|
+
ca_size_t idx[CA_RANK_MAX];
|
|
585
|
+
ca_addr2index(ca, addr, idx);
|
|
586
|
+
ridx = rb_ary_new2(ca->ndim);
|
|
587
|
+
for (i=0; i<ca->ndim; i++) {
|
|
588
|
+
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
451
589
|
}
|
|
452
|
-
|
|
590
|
+
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
591
|
+
rb_funcall(ca->self, rb_intern("store_index"), 2, ridx, rval);
|
|
453
592
|
}
|
|
454
593
|
}
|
|
455
594
|
}
|
|
456
595
|
|
|
457
596
|
static void
|
|
458
|
-
|
|
597
|
+
ca_object_xfer_index_one (CAObject *ca, ca_size_t *idx, void *ptr, int dir)
|
|
459
598
|
{
|
|
460
|
-
CAObject *ca = (CAObject *) ap;
|
|
461
599
|
volatile VALUE ridx, raddr, rval;
|
|
462
600
|
int i;
|
|
463
|
-
if (
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
rval = rb_funcall(ca->self, rb_intern("fetch_index"), 1, ridx);
|
|
469
|
-
if ( rval == CA_UNDEF ) {
|
|
470
|
-
ca_update_mask(ca);
|
|
471
|
-
if ( ! ca->mask ) {
|
|
472
|
-
ca_create_mask(ca);
|
|
601
|
+
if ( dir == CA_XFER_GET ) {
|
|
602
|
+
if ( rb_obj_respond_to(ca->self, rb_intern("fetch_index"), Qtrue) ) {
|
|
603
|
+
ridx = rb_ary_new2(ca->ndim);
|
|
604
|
+
for (i=0; i<ca->ndim; i++) {
|
|
605
|
+
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
473
606
|
}
|
|
474
|
-
|
|
475
|
-
if (
|
|
476
|
-
|
|
607
|
+
rval = rb_funcall(ca->self, rb_intern("fetch_index"), 1, ridx);
|
|
608
|
+
if ( rval == CA_UNDEF ) {
|
|
609
|
+
ca_update_mask(ca);
|
|
610
|
+
if ( ! ca->mask ) {
|
|
611
|
+
ca_create_mask(ca);
|
|
612
|
+
}
|
|
613
|
+
*((boolean8_t*)ca->mask->ptr + ca_index2addr(ca->mask, idx)) = 1;
|
|
614
|
+
if ( ca->data_type == CA_OBJECT ) {
|
|
615
|
+
rb_ca_obj2ptr(ca->self, INT2NUM(0), ptr);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
else {
|
|
619
|
+
if ( ca_has_mask(ca) ) {
|
|
620
|
+
*((boolean8_t*)ca->mask->ptr + ca_index2addr(ca->mask, idx)) = 0;
|
|
621
|
+
}
|
|
622
|
+
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
477
623
|
}
|
|
478
624
|
}
|
|
479
625
|
else {
|
|
480
|
-
|
|
481
|
-
|
|
626
|
+
ca_size_t addr = ca_index2addr(ca, idx);
|
|
627
|
+
raddr = SIZE2NUM(addr);
|
|
628
|
+
rval = rb_funcall(ca->self, rb_intern("fetch_addr"), 1, raddr);
|
|
629
|
+
if ( rval == CA_UNDEF ) {
|
|
630
|
+
ca_update_mask(ca);
|
|
631
|
+
if ( ! ca->mask ) {
|
|
632
|
+
ca_create_mask(ca);
|
|
633
|
+
}
|
|
634
|
+
*((boolean8_t*)ca->mask->ptr + addr) = 1;
|
|
635
|
+
if ( ca->data_type == CA_OBJECT ) {
|
|
636
|
+
rb_ca_obj2ptr(ca->self, INT2NUM(0), ptr);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
else {
|
|
640
|
+
if ( ca_has_mask(ca) ) {
|
|
641
|
+
*((boolean8_t*)ca->mask->ptr + addr) = 0;
|
|
642
|
+
}
|
|
643
|
+
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
482
644
|
}
|
|
483
|
-
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
484
645
|
}
|
|
485
646
|
}
|
|
486
647
|
else {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
ca_update_mask(ca);
|
|
492
|
-
if ( ! ca->mask ) {
|
|
493
|
-
ca_create_mask(ca);
|
|
494
|
-
}
|
|
495
|
-
*(boolean8_t*)ca_ptr_at_addr(ca->mask, addr) = 1;
|
|
496
|
-
if ( ca->data_type == CA_OBJECT ) {
|
|
497
|
-
rb_ca_obj2ptr(ca->self, INT2NUM(0), ptr);
|
|
648
|
+
if ( rb_obj_respond_to(ca->self, rb_intern("store_index"), Qtrue) ) {
|
|
649
|
+
ridx = rb_ary_new2(ca->ndim);
|
|
650
|
+
for (i=0; i<ca->ndim; i++) {
|
|
651
|
+
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
498
652
|
}
|
|
653
|
+
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
654
|
+
rb_funcall(ca->self, rb_intern("store_index"), 2, ridx, rval);
|
|
499
655
|
}
|
|
500
656
|
else {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
657
|
+
ca_size_t addr = ca_index2addr(ca, idx);
|
|
658
|
+
raddr = SIZE2NUM(addr);
|
|
659
|
+
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
660
|
+
rb_funcall(ca->self, rb_intern("store_addr"), 2, raddr, rval);
|
|
505
661
|
}
|
|
506
662
|
}
|
|
507
663
|
}
|
|
508
664
|
|
|
509
665
|
static void
|
|
510
|
-
|
|
666
|
+
ca_object_func_allocate (void *ap)
|
|
511
667
|
{
|
|
512
668
|
CAObject *ca = (CAObject *) ap;
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
if (
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
669
|
+
/* ca->data->ptr = ALLOC_N(char, ca_length(ca)); */
|
|
670
|
+
ca->data->ptr = xmalloc(ca_length(ca));
|
|
671
|
+
if ( ca_is_object_type(ca->data) ) { /* GC safe */
|
|
672
|
+
VALUE *p = (VALUE *) ca->data->ptr;
|
|
673
|
+
VALUE zero = INT2NUM(0);
|
|
674
|
+
ca_size_t i;
|
|
675
|
+
for (i=0; i<ca->elements; i++) {
|
|
676
|
+
*p++ = zero;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
ca->ptr = ca->data->ptr;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/* ca_object_dispatch_{copy,sync,fill}: bulk-path entry points used by
|
|
683
|
+
func_attach / func_sync / func_{copy,sync,fill}_data.
|
|
684
|
+
|
|
685
|
+
Contract: prefer user-supplied bulk methods (copy_data / sync_data /
|
|
686
|
+
fill_data) when defined; otherwise fall back to per-element
|
|
687
|
+
fetch_addr / store_addr loops, which themselves dispatch through the
|
|
688
|
+
existing fetch_addr<->fetch_index and store_addr<->store_index mutual
|
|
689
|
+
fallback at line 418/471/523/546.
|
|
690
|
+
|
|
691
|
+
Net effect: a CAObject subclass that only defines fetch_addr (or
|
|
692
|
+
only fetch_index) becomes fully usable -- to_ca, attach, sync,
|
|
693
|
+
arithmetic all work via the slow per-element fallback. The fast bulk
|
|
694
|
+
path is opt-in by defining copy_data / sync_data / fill_data. */
|
|
695
|
+
|
|
696
|
+
static void
|
|
697
|
+
ca_object_dispatch_copy (CAObject *ca, void *ptr)
|
|
698
|
+
{
|
|
699
|
+
if ( rb_obj_respond_to(ca->self, rb_intern("copy_data"), Qtrue) ) {
|
|
700
|
+
char *ptr0 = ca->data->ptr;
|
|
701
|
+
ca->data->ptr = ptr;
|
|
702
|
+
rb_funcall(ca->self, rb_intern("copy_data"),
|
|
703
|
+
1, rb_ivar_get(ca->self, rb_intern("__data__")));
|
|
704
|
+
ca->data->ptr = ptr0;
|
|
519
705
|
}
|
|
520
706
|
else {
|
|
521
|
-
ca_size_t
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
707
|
+
ca_size_t addr;
|
|
708
|
+
char *base = (char *) ptr;
|
|
709
|
+
for ( addr = 0; addr < ca->elements; addr++ ) {
|
|
710
|
+
ca_object_xfer_addr_one(ca, addr, base + addr * ca->bytes, CA_XFER_GET);
|
|
526
711
|
}
|
|
527
|
-
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
528
|
-
rb_funcall(ca->self, rb_intern("store_index"), 2, ridx, rval);
|
|
529
712
|
}
|
|
530
713
|
}
|
|
531
714
|
|
|
532
715
|
static void
|
|
533
|
-
|
|
716
|
+
ca_object_dispatch_sync (CAObject *ca, void *ptr)
|
|
534
717
|
{
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
542
|
-
}
|
|
543
|
-
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
544
|
-
rb_funcall(ca->self, rb_intern("store_index"), 2, ridx, rval);
|
|
718
|
+
if ( rb_obj_respond_to(ca->self, rb_intern("sync_data"), Qtrue) ) {
|
|
719
|
+
char *ptr0 = ca->data->ptr;
|
|
720
|
+
ca->data->ptr = ptr;
|
|
721
|
+
rb_funcall(ca->self, rb_intern("sync_data"),
|
|
722
|
+
1, rb_ivar_get(ca->self, rb_intern("__data__")));
|
|
723
|
+
ca->data->ptr = ptr0;
|
|
545
724
|
}
|
|
546
725
|
else {
|
|
547
|
-
ca_size_t addr
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
726
|
+
ca_size_t addr;
|
|
727
|
+
char *base = (char *) ptr;
|
|
728
|
+
for ( addr = 0; addr < ca->elements; addr++ ) {
|
|
729
|
+
ca_object_xfer_addr_one(ca, addr, base + addr * ca->bytes, CA_XFER_PUT);
|
|
730
|
+
}
|
|
551
731
|
}
|
|
552
732
|
}
|
|
553
733
|
|
|
554
734
|
static void
|
|
555
|
-
|
|
735
|
+
ca_object_dispatch_fill (CAObject *ca, void *ptr)
|
|
556
736
|
{
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
*p++ = zero;
|
|
737
|
+
if ( rb_obj_respond_to(ca->self, rb_intern("fill_data"), Qtrue) ) {
|
|
738
|
+
volatile VALUE rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
739
|
+
rb_funcall(ca->self, rb_intern("fill_data"), 1, rval);
|
|
740
|
+
}
|
|
741
|
+
else {
|
|
742
|
+
ca_size_t addr;
|
|
743
|
+
for ( addr = 0; addr < ca->elements; addr++ ) {
|
|
744
|
+
ca_object_xfer_addr_one(ca, addr, ptr, CA_XFER_PUT);
|
|
566
745
|
}
|
|
567
746
|
}
|
|
568
|
-
ca->ptr = ca->data->ptr;
|
|
569
747
|
}
|
|
570
748
|
|
|
571
749
|
static void
|
|
572
750
|
ca_object_func_attach (void *ap)
|
|
573
751
|
{
|
|
574
752
|
CAObject *ca = (CAObject *) ap;
|
|
575
|
-
|
|
753
|
+
/* Face mode → thin-forward to parent (= bypass the Ruby callback; same
|
|
754
|
+
semantic as ca_face_* helpers; CAObject prefix == CAView prefix so
|
|
755
|
+
layout is compatible). */
|
|
756
|
+
if ( ca_is_face(ca) ) {
|
|
757
|
+
ca_face_attach(ap);
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
576
760
|
/* ca->data->ptr = ALLOC_N(char, ca_length(ca)); */
|
|
577
|
-
ca->data->ptr =
|
|
761
|
+
ca->data->ptr = xmalloc(ca_length(ca));
|
|
578
762
|
if ( ca_is_object_type(ca->data) ) { /* GC safe */
|
|
579
763
|
VALUE *p = (VALUE *) ca->data->ptr;
|
|
580
764
|
VALUE zero = INT2NUM(0);
|
|
@@ -583,8 +767,8 @@ ca_object_func_attach (void *ap)
|
|
|
583
767
|
*p++ = zero;
|
|
584
768
|
}
|
|
585
769
|
}
|
|
586
|
-
ca->ptr = ca->data->ptr;
|
|
587
|
-
|
|
770
|
+
ca->ptr = ca->data->ptr;
|
|
771
|
+
ca_object_dispatch_copy(ca, ca->ptr);
|
|
588
772
|
if ( ca_has_mask(ca->data) ) {
|
|
589
773
|
ca_update_mask(ca);
|
|
590
774
|
if ( ! ca->mask ) {
|
|
@@ -597,48 +781,317 @@ static void
|
|
|
597
781
|
ca_object_func_sync (void *ap)
|
|
598
782
|
{
|
|
599
783
|
CAObject *ca = (CAObject *) ap;
|
|
600
|
-
|
|
601
|
-
|
|
784
|
+
if ( ca_is_face(ca) ) {
|
|
785
|
+
ca_face_sync(ap);
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
788
|
+
ca_object_dispatch_sync(ca, ca->data->ptr);
|
|
602
789
|
}
|
|
603
790
|
|
|
604
791
|
static void
|
|
605
792
|
ca_object_func_detach (void *ap)
|
|
606
793
|
{
|
|
607
794
|
CAObject *ca = (CAObject *) ap;
|
|
608
|
-
|
|
795
|
+
if ( ca_is_face(ca) ) {
|
|
796
|
+
ca_face_detach(ap);
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
xfree(ca->data->ptr);
|
|
609
800
|
ca->data->ptr = NULL;
|
|
610
801
|
ca->ptr = NULL;
|
|
611
802
|
}
|
|
612
803
|
|
|
804
|
+
/* xfer_*: CAObject is a per-element Ruby callback bridge -- a never-fold
|
|
805
|
+
boundary with no axis structure. GC
|
|
806
|
+
protection (cyclic + rb_protect on GET) for CA_OBJECT element type is
|
|
807
|
+
supplied by the central ca_xfer_* dispatchers, so these per-cell loops run
|
|
808
|
+
raw. */
|
|
809
|
+
|
|
810
|
+
/* Build a transient borrowed-buffer CArray for partial-region callbacks.
|
|
811
|
+
|
|
812
|
+
Used by ca_object_func_xfer_{stride,addrs} (and mask variants) to wrap the
|
|
813
|
+
slot's `data` buffer in a Ruby-visible CArray (counts-shape for block,
|
|
814
|
+
[n] for addrs) before invoking copy_block / sync_block / copy_addrs /
|
|
815
|
+
sync_addrs. Lifecycle: buffer is owned by the slot caller; the wrapper
|
|
816
|
+
installs free_ca_wrap as dfree, so the underlying ptr is NOT freed when
|
|
817
|
+
the wrapper is GC'd.
|
|
818
|
+
|
|
819
|
+
Object data_type GC safety: for GET (dir == CA_XFER_GET) the buffer may be
|
|
820
|
+
uninitialized garbage on entry, so we INT2NUM(0) zero-fill before
|
|
821
|
+
wrapping (same idiom as ca_object_func_allocate). PUT entries are
|
|
822
|
+
already valid VALUEs and need no init. */
|
|
823
|
+
static VALUE
|
|
824
|
+
ca_object_wrap_transient (int8_t data_type, ca_size_t bytes,
|
|
825
|
+
int8_t ndim, ca_size_t *dim, void *data, int dir)
|
|
826
|
+
{
|
|
827
|
+
CAWrap *wrap;
|
|
828
|
+
ca_size_t n = 1, i;
|
|
829
|
+
|
|
830
|
+
for ( i = 0; i < ndim; i++ ) n *= dim[i];
|
|
831
|
+
|
|
832
|
+
if ( dir == CA_XFER_GET && data_type == CA_OBJECT ) {
|
|
833
|
+
VALUE *p = (VALUE *) data;
|
|
834
|
+
VALUE zero = INT2NUM(0);
|
|
835
|
+
for ( i = 0; i < n; i++ ) p[i] = zero;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
wrap = ca_wrap_new(data_type, ndim, dim, bytes, NULL, (char *) data);
|
|
839
|
+
return ca_wrap_struct(wrap);
|
|
840
|
+
}
|
|
841
|
+
|
|
613
842
|
static void
|
|
614
|
-
|
|
843
|
+
ca_object_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
615
844
|
{
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
ca->data->ptr = ptr0;
|
|
845
|
+
if ( ca_is_face((CAObject *) ap) ) {
|
|
846
|
+
ca_face_xfer_index(ap, idx, data, dir);
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
ca_object_xfer_index_one((CAObject *) ap, idx, data, dir);
|
|
622
850
|
}
|
|
623
851
|
|
|
852
|
+
/* Bulk-addrs path. When `copy_addrs` / `sync_addrs` is defined, dispatch
|
|
853
|
+
the entire address list in one Ruby call (1-D transient wrappers for
|
|
854
|
+
addrs and data). Otherwise fall back to a per-cell loop. */
|
|
624
855
|
static void
|
|
625
|
-
|
|
856
|
+
ca_object_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
857
|
+
void *data, int dir)
|
|
626
858
|
{
|
|
627
|
-
CAObject
|
|
628
|
-
|
|
629
|
-
ca
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
859
|
+
CAObject *ca = (CAObject *) ap;
|
|
860
|
+
ID mid;
|
|
861
|
+
if ( ca_is_face(ca) ) {
|
|
862
|
+
ca_face_xfer_addrs(ap, n, addrs, data, dir);
|
|
863
|
+
return;
|
|
864
|
+
}
|
|
865
|
+
mid = (dir == CA_XFER_GET) ? rb_intern("copy_addrs")
|
|
866
|
+
: rb_intern("sync_addrs");
|
|
867
|
+
|
|
868
|
+
if ( n > 0 && rb_obj_respond_to(ca->self, mid, Qtrue) ) {
|
|
869
|
+
volatile VALUE raddrs, rdata;
|
|
870
|
+
ca_size_t dim1[1] = { n };
|
|
871
|
+
raddrs = ca_object_wrap_transient(CA_SIZE, sizeof(ca_size_t),
|
|
872
|
+
1, dim1, addrs, CA_XFER_PUT);
|
|
873
|
+
rdata = ca_object_wrap_transient(ca->data_type, ca->bytes,
|
|
874
|
+
1, dim1, data, dir);
|
|
875
|
+
rb_funcall(ca->self, mid, 2, raddrs, rdata);
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
{
|
|
880
|
+
char *d = (char *) data;
|
|
881
|
+
ca_size_t i;
|
|
882
|
+
for ( i = 0; i < n; i++ ) {
|
|
883
|
+
ca_object_xfer_addr_one(ca, addrs[i], d + i * ca->bytes, dir);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
/* Partial-region dispatch.
|
|
889
|
+
|
|
890
|
+
Gate: if `copy_block` / `sync_block` is defined AND all per-axis byte
|
|
891
|
+
strides represent an order-preserving, step >= 1 sub-region of self
|
|
892
|
+
(i.e. strides[k] > 0 && strides[k] % native[k] == 0), invoke the
|
|
893
|
+
high-level callback with index-space (starts, counts, steps) and a
|
|
894
|
+
counts-shaped transient. Empty region (any counts[k] == 0) returns
|
|
895
|
+
early without invoking the callback. Otherwise (negative/zero/non-
|
|
896
|
+
aligned strides, or callback undefined) fall back to flat-addr
|
|
897
|
+
expansion -> xfer_addrs (which itself may dispatch to copy_addrs /
|
|
898
|
+
sync_addrs if defined, else per-cell).
|
|
899
|
+
|
|
900
|
+
Gate proof: gate passes => for all k, strides[k] = m_k *
|
|
901
|
+
native[k] with m_k >= 1. If block axis k mapped to self axis pi(k),
|
|
902
|
+
strides[k] = native[pi(k)] would force native[pi(k)] >= native[k] hence
|
|
903
|
+
pi(k) <= k for all k. native is strictly decreasing in k, so the only
|
|
904
|
+
permutation satisfying pi(k) <= k for all k is identity. Therefore gate
|
|
905
|
+
passage <=> each block axis k traverses self axis k with step m_k.
|
|
906
|
+
Transpose / fancy / sub-element / negative / zero stride all fail the
|
|
907
|
+
gate and route to addrs path. */
|
|
908
|
+
static void
|
|
909
|
+
ca_object_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
910
|
+
ca_size_t *strides, void *data, int dir)
|
|
911
|
+
{
|
|
912
|
+
CAObject *ca = (CAObject *) ap;
|
|
913
|
+
int8_t ndim;
|
|
914
|
+
ca_size_t native[CA_RANK_MAX], steps[CA_RANK_MAX], idx[CA_RANK_MAX];
|
|
915
|
+
ca_size_t *vaddrs;
|
|
916
|
+
ca_size_t base = 0, n = 1, i, s;
|
|
917
|
+
int8_t k;
|
|
918
|
+
volatile VALUE holder;
|
|
919
|
+
ID mid_block;
|
|
920
|
+
|
|
921
|
+
if ( ca_is_face(ca) ) {
|
|
922
|
+
ca_face_xfer_stride(ap, starts, counts, strides, data, dir);
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
ndim = ca->ndim;
|
|
927
|
+
mid_block = (dir == CA_XFER_GET) ? rb_intern("copy_block")
|
|
928
|
+
: rb_intern("sync_block");
|
|
929
|
+
|
|
930
|
+
s = ca->bytes;
|
|
931
|
+
for (k = ndim - 1; k >= 0; k--) { native[k] = s; s *= ca->dim[k]; }
|
|
932
|
+
for (k = 0; k < ndim; k++) { base += starts[k] * native[k]; n *= counts[k]; }
|
|
933
|
+
|
|
934
|
+
/* empty region: nothing to transfer */
|
|
935
|
+
if ( n == 0 ) return;
|
|
936
|
+
|
|
937
|
+
/* gate:
|
|
938
|
+
- reject strides[k] <= 0 (negative / zero broadcast)
|
|
939
|
+
- C99 makes (-native) % native == 0 true, so we must reject <= 0
|
|
940
|
+
before the % check
|
|
941
|
+
- given %==0 + >0, strides/native >= 1 holds automatically */
|
|
942
|
+
if ( rb_obj_respond_to(ca->self, mid_block, Qtrue) ) {
|
|
943
|
+
/* The request is over the view's addresses, so a transposed / flat
|
|
944
|
+
request is legal; the per-axis copy_block dispatch below would
|
|
945
|
+
misread it. See ca_xfer_stride_request_is_axis_box (carray.h). */
|
|
946
|
+
int aligned = ca_xfer_stride_request_is_axis_box(ca, starts, counts, strides);
|
|
947
|
+
for ( k = 0; aligned && k < ndim; k++ ) {
|
|
948
|
+
if ( strides[k] <= 0 || strides[k] % native[k] != 0 ) { aligned = 0; break; }
|
|
949
|
+
steps[k] = strides[k] / native[k]; /* >= 1 by construction */
|
|
950
|
+
}
|
|
951
|
+
if ( aligned ) {
|
|
952
|
+
/* high-level per-axis sub-region: dispatch copy_block / sync_block */
|
|
953
|
+
volatile VALUE rstarts, rcounts, rsteps, rdata;
|
|
954
|
+
rstarts = rb_ary_new_capa(ndim);
|
|
955
|
+
rcounts = rb_ary_new_capa(ndim);
|
|
956
|
+
rsteps = rb_ary_new_capa(ndim);
|
|
957
|
+
for ( k = 0; k < ndim; k++ ) {
|
|
958
|
+
rb_ary_push(rstarts, SIZE2NUM(starts[k]));
|
|
959
|
+
rb_ary_push(rcounts, SIZE2NUM(counts[k]));
|
|
960
|
+
rb_ary_push(rsteps, SIZE2NUM(steps[k]));
|
|
961
|
+
}
|
|
962
|
+
rdata = ca_object_wrap_transient(ca->data_type, ca->bytes,
|
|
963
|
+
ndim, counts, data, dir);
|
|
964
|
+
rb_funcall(ca->self, mid_block, 4, rstarts, rcounts, rsteps, rdata);
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
/* fallback: flat-addr expansion -> xfer_addrs (per-cell or copy_addrs).
|
|
970
|
+
Handles negative strides, zero stride (broadcast), sub-element, and
|
|
971
|
+
fancy permutations. Same body as the non-block path. */
|
|
972
|
+
vaddrs = ALLOCV_N(ca_size_t, holder, n);
|
|
973
|
+
for (k = 0; k < ndim; k++) idx[k] = 0;
|
|
974
|
+
for (i = 0; i < n; i++) {
|
|
975
|
+
ca_size_t off = base;
|
|
976
|
+
for (k = 0; k < ndim; k++) off += idx[k] * strides[k];
|
|
977
|
+
vaddrs[i] = off / ca->bytes;
|
|
978
|
+
k = ndim - 1;
|
|
979
|
+
while (k >= 0) { if (++idx[k] < counts[k]) break; idx[k] = 0; k--; }
|
|
980
|
+
}
|
|
981
|
+
ca_object_func_xfer_addrs(ca, n, vaddrs, data, dir);
|
|
982
|
+
ALLOCV_END(holder);
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
static void
|
|
986
|
+
ca_object_func_xfer_all (void *ap, void *data, int dir)
|
|
987
|
+
{
|
|
988
|
+
if ( ca_is_face((CAObject *) ap) ) {
|
|
989
|
+
ca_face_xfer_all(ap, data, dir);
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
if ( dir == CA_XFER_GET ) {
|
|
993
|
+
ca_object_dispatch_copy((CAObject *) ap, data);
|
|
994
|
+
}
|
|
995
|
+
else {
|
|
996
|
+
ca_object_dispatch_sync((CAObject *) ap, data);
|
|
997
|
+
}
|
|
633
998
|
}
|
|
634
999
|
|
|
635
1000
|
static void
|
|
636
1001
|
ca_object_func_fill_data (void *ap, void *ptr)
|
|
1002
|
+
{
|
|
1003
|
+
if ( ca_is_face((CAObject *) ap) ) {
|
|
1004
|
+
ca_face_fill_data(ap, ptr);
|
|
1005
|
+
return;
|
|
1006
|
+
}
|
|
1007
|
+
ca_object_dispatch_fill((CAObject *) ap, ptr);
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
/* Partial fill. fill_data carries no region and can only say "fill
|
|
1011
|
+
everything I cover", so before these two slots existed the only way to
|
|
1012
|
+
fill part of a CAObject was the per-cell default -- one store_addr per
|
|
1013
|
+
cell. The region arrives in the view's own address space. With
|
|
1014
|
+
`fill_block` defined (and the region an axis-aligned forward sub-box of
|
|
1015
|
+
self) it becomes one call; with `fill_addrs` defined it becomes one call
|
|
1016
|
+
per address window. With neither defined the behaviour is exactly the
|
|
1017
|
+
old default, so an existing subclass sees no change. */
|
|
1018
|
+
static void
|
|
1019
|
+
ca_object_func_fill_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *ptr)
|
|
637
1020
|
{
|
|
638
1021
|
CAObject *ca = (CAObject *) ap;
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
1022
|
+
ID mid = rb_intern("fill_addrs");
|
|
1023
|
+
|
|
1024
|
+
if ( ca_is_face(ca) ) {
|
|
1025
|
+
ca_face_fill_addrs(ap, n, addrs, ptr);
|
|
1026
|
+
return;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
if ( n > 0 && rb_obj_respond_to(ca->self, mid, Qtrue) ) {
|
|
1030
|
+
volatile VALUE raddrs, rval;
|
|
1031
|
+
ca_size_t dim1[1] = { n };
|
|
1032
|
+
raddrs = ca_object_wrap_transient(CA_SIZE, sizeof(ca_size_t),
|
|
1033
|
+
1, dim1, addrs, CA_XFER_PUT);
|
|
1034
|
+
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
1035
|
+
rb_funcall(ca->self, mid, 2, raddrs, rval);
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
ca_fill_addrs_default(ap, n, addrs, ptr);
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
/* Gate: one region axis per view axis, forward, and a whole number of
|
|
1043
|
+
elements per step. native is strictly decreasing, so steps[k] =
|
|
1044
|
+
m_k * native[k] with m_k >= 1 admits only the identity permutation --
|
|
1045
|
+
transpose, negative and zero (broadcast) steps, sub-element steps and
|
|
1046
|
+
dimension-dropping regions all fail it and take the addrs route. The
|
|
1047
|
+
bound check then confirms the decomposed box lies inside self. */
|
|
1048
|
+
static void
|
|
1049
|
+
ca_object_func_fill_stride (void *ap, ca_size_t base, int8_t ndim,
|
|
1050
|
+
ca_size_t *counts, ca_size_t *steps, void *ptr)
|
|
1051
|
+
{
|
|
1052
|
+
CAObject *ca = (CAObject *) ap;
|
|
1053
|
+
ca_size_t native[CA_RANK_MAX], istep[CA_RANK_MAX], start[CA_RANK_MAX];
|
|
1054
|
+
ca_size_t s;
|
|
1055
|
+
int8_t k;
|
|
1056
|
+
ID mid = rb_intern("fill_block");
|
|
1057
|
+
|
|
1058
|
+
if ( ca_is_face(ca) ) {
|
|
1059
|
+
ca_face_fill_stride(ap, base, ndim, counts, steps, ptr);
|
|
1060
|
+
return;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
if ( ndim == ca->ndim && rb_obj_respond_to(ca->self, mid, Qtrue) ) {
|
|
1064
|
+
int aligned = 1;
|
|
1065
|
+
s = 1;
|
|
1066
|
+
for ( k = ca->ndim - 1; k >= 0; k-- ) { native[k] = s; s *= ca->dim[k]; }
|
|
1067
|
+
for ( k = 0; k < ndim; k++ ) {
|
|
1068
|
+
if ( steps[k] <= 0 || steps[k] % native[k] != 0 ) { aligned = 0; break; }
|
|
1069
|
+
istep[k] = steps[k] / native[k];
|
|
1070
|
+
start[k] = ( base / native[k] ) % ca->dim[k];
|
|
1071
|
+
if ( start[k] + ( counts[k] - 1 ) * istep[k] >= ca->dim[k] ) {
|
|
1072
|
+
aligned = 0;
|
|
1073
|
+
break;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
if ( aligned ) {
|
|
1077
|
+
volatile VALUE rstarts, rcounts, rsteps, rval;
|
|
1078
|
+
rstarts = rb_ary_new_capa(ndim);
|
|
1079
|
+
rcounts = rb_ary_new_capa(ndim);
|
|
1080
|
+
rsteps = rb_ary_new_capa(ndim);
|
|
1081
|
+
for ( k = 0; k < ndim; k++ ) {
|
|
1082
|
+
rb_ary_push(rstarts, SIZE2NUM(start[k]));
|
|
1083
|
+
rb_ary_push(rcounts, SIZE2NUM(counts[k]));
|
|
1084
|
+
rb_ary_push(rsteps, SIZE2NUM(istep[k]));
|
|
1085
|
+
}
|
|
1086
|
+
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
1087
|
+
rb_funcall(ca->self, mid, 4, rstarts, rcounts, rsteps, rval);
|
|
1088
|
+
return;
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
/* addrs route: address windows -> ca_fill_addrs -> `fill_addrs` when the
|
|
1093
|
+
author defined it, else the per-cell default. */
|
|
1094
|
+
ca_fill_stride_via_addrs(ap, base, ndim, counts, steps, ptr);
|
|
642
1095
|
}
|
|
643
1096
|
|
|
644
1097
|
static void
|
|
@@ -646,6 +1099,18 @@ ca_object_func_create_mask (void *ap)
|
|
|
646
1099
|
{
|
|
647
1100
|
CAObject *ca = (CAObject *) ap;
|
|
648
1101
|
volatile VALUE rmask;
|
|
1102
|
+
if ( ca_is_face(ca) ) {
|
|
1103
|
+
/* Face: the mask refers to the parent's mask (same as the C-level Face
|
|
1104
|
+
create_mask, e.g. ca_time_func_create_mask). Storage is the
|
|
1105
|
+
parent, so the mask must be the parent's, not the internal __data__. */
|
|
1106
|
+
ca_update_mask(ca->parent);
|
|
1107
|
+
if ( ! ca->parent->mask ) {
|
|
1108
|
+
ca_create_mask(ca->parent);
|
|
1109
|
+
}
|
|
1110
|
+
ca->mask = (CArray *) ca_refer_new(ca->parent->mask,
|
|
1111
|
+
CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
|
|
1112
|
+
return;
|
|
1113
|
+
}
|
|
649
1114
|
if ( rb_obj_respond_to(ca->self, rb_intern("create_mask"), Qtrue) ) {
|
|
650
1115
|
rb_funcall(ca->self, rb_intern("create_mask"), 0);
|
|
651
1116
|
}
|
|
@@ -664,23 +1129,22 @@ ca_object_func_create_mask (void *ap)
|
|
|
664
1129
|
|
|
665
1130
|
ca_operation_function_t ca_object_func = {
|
|
666
1131
|
-1, /* CA_OBJ_OBJECT */
|
|
667
|
-
|
|
1132
|
+
CA_VIEW_ARRAY,
|
|
668
1133
|
free_ca_object,
|
|
669
1134
|
ca_object_func_clone,
|
|
670
|
-
ca_object_func_ptr_at_addr,
|
|
671
|
-
ca_object_func_ptr_at_index,
|
|
672
|
-
ca_object_func_fetch_addr,
|
|
673
|
-
ca_object_func_fetch_index,
|
|
674
|
-
ca_object_func_store_addr,
|
|
675
|
-
ca_object_func_store_index,
|
|
676
1135
|
ca_object_func_allocate,
|
|
677
1136
|
ca_object_func_attach,
|
|
678
1137
|
ca_object_func_sync,
|
|
679
1138
|
ca_object_func_detach,
|
|
680
|
-
ca_object_func_copy_data,
|
|
681
|
-
ca_object_func_sync_data,
|
|
682
1139
|
ca_object_func_fill_data,
|
|
683
1140
|
ca_object_func_create_mask,
|
|
1141
|
+
ca_object_func_xfer_index,
|
|
1142
|
+
ca_object_func_xfer_addrs,
|
|
1143
|
+
NULL, /* fold_stride: never-fold (callback boundary) */
|
|
1144
|
+
ca_object_func_xfer_stride,
|
|
1145
|
+
ca_object_func_xfer_all,
|
|
1146
|
+
.fill_addrs = ca_object_func_fill_addrs,
|
|
1147
|
+
.fill_stride = ca_object_func_fill_stride,
|
|
684
1148
|
};
|
|
685
1149
|
|
|
686
1150
|
/* ------------------------------------------------------------------- */
|
|
@@ -701,13 +1165,28 @@ rb_ca_object_initialize_copy (VALUE self, VALUE other)
|
|
|
701
1165
|
TypedData_Get_Struct(self, CAObject, &caobject_data_type, ca);
|
|
702
1166
|
TypedData_Get_Struct(other, CAObject, &caobject_data_type, cs);
|
|
703
1167
|
|
|
1168
|
+
if ( ca_func[CA_OBJ_OBJECT].pool_init ) {
|
|
1169
|
+
ca_array_pool_alloc(ca, CA_OBJ_OBJECT, cs->ndim);
|
|
1170
|
+
}
|
|
704
1171
|
ca_object_setup(ca, cs->data_type, cs->ndim, cs->dim, cs->bytes);
|
|
705
1172
|
ca->self = self;
|
|
706
1173
|
|
|
707
|
-
|
|
1174
|
+
/* preserve flags (e.g. CA_FLAG_READ_ONLY) and structural parent;
|
|
1175
|
+
ca_object_setup zeroed both, so restore from the source.
|
|
1176
|
+
Copy the @parent ivar directly rather than via rb_ca_set_parent --
|
|
1177
|
+
the latter would re-freeze self when parent is frozen, but
|
|
1178
|
+
dup/clone semantics for freezing are handled separately by Ruby. */
|
|
1179
|
+
ca->flags = cs->flags;
|
|
1180
|
+
ca->parent = cs->parent;
|
|
1181
|
+
if ( cs->parent ) {
|
|
1182
|
+
volatile VALUE rparent = rb_ivar_get(other, rb_intern("parent"));
|
|
1183
|
+
if ( ! NIL_P(rparent) ) {
|
|
1184
|
+
rb_ivar_set(self, rb_intern("parent"), rparent);
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
|
|
708
1188
|
|
|
709
1189
|
data = ca_wrap_struct(ca->data);
|
|
710
|
-
rb_ca_data_type_inherit(data, self);
|
|
711
1190
|
rb_ivar_set(self, rb_intern("__data__"), data);
|
|
712
1191
|
|
|
713
1192
|
ca_update_mask(cs);
|
|
@@ -723,7 +1202,9 @@ rb_ca_object_initialize_copy (VALUE self, VALUE other)
|
|
|
723
1202
|
static VALUE
|
|
724
1203
|
rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
725
1204
|
{
|
|
726
|
-
volatile VALUE rtype, rdim, ropt, rbytes = Qnil, rrdonly = Qnil,
|
|
1205
|
+
volatile VALUE rtype, rdim, ropt, rbytes = Qnil, rrdonly = Qnil,
|
|
1206
|
+
rparent = Qnil, rface = Qnil, rstorage = Qnil, rdata,
|
|
1207
|
+
rorderable = Qnil, rcomparable = Qnil;
|
|
727
1208
|
CAObject *ca;
|
|
728
1209
|
int8_t data_type, ndim;
|
|
729
1210
|
ca_size_t dim[CA_RANK_MAX];
|
|
@@ -731,15 +1212,47 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
731
1212
|
int i;
|
|
732
1213
|
|
|
733
1214
|
rb_scan_args(argc, argv, "21", (VALUE *) &rtype, (VALUE *) &rdim, (VALUE *) &ropt);
|
|
734
|
-
rb_scan_options(ropt, "bytes,read_only,parent",
|
|
735
|
-
&rbytes, &rrdonly, &rparent
|
|
1215
|
+
rb_scan_options(ropt, "bytes,read_only,parent,face,storage,orderable_storage,comparable_storage",
|
|
1216
|
+
&rbytes, &rrdonly, &rparent, &rface, &rstorage,
|
|
1217
|
+
&rorderable, &rcomparable);
|
|
736
1218
|
|
|
737
|
-
if ( ( ! NIL_P(rparent) ) && rb_obj_is_carray(rparent) ) {
|
|
1219
|
+
if ( ( ! NIL_P(rparent) ) && ( ! rb_obj_is_carray(rparent) ) ) {
|
|
738
1220
|
rb_raise(rb_eRuntimeError, "option :parent should be a carray");
|
|
739
1221
|
}
|
|
740
1222
|
|
|
1223
|
+
/* :storage is meaningful only under face: true (= it documents the
|
|
1224
|
+
parent's storage data_type, which is otherwise inferred from
|
|
1225
|
+
parent.data_type). Reject misuse loudly so the contract is explicit. */
|
|
1226
|
+
if ( ! NIL_P(rstorage) && ! RTEST(rface) ) {
|
|
1227
|
+
rb_raise(rb_eArgError,
|
|
1228
|
+
"CAObject: :storage is only meaningful with face: true "
|
|
1229
|
+
"(use the data_type argument for non-Face CAObject)");
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
/* Face ordering/search opt-in: a Ruby-defined Face wires the C flags via
|
|
1233
|
+
these kwargs instead of a Ruby callback, so a Face can still be
|
|
1234
|
+
authored C-only. Both are meaningful only under face: true. */
|
|
1235
|
+
if ( ( RTEST(rorderable) || RTEST(rcomparable) ) && ! RTEST(rface) ) {
|
|
1236
|
+
rb_raise(rb_eArgError,
|
|
1237
|
+
"CAObject: :orderable_storage / :comparable_storage are only "
|
|
1238
|
+
"meaningful with face: true");
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
/* face: true requires :parent. Under Face semantics the parent is the
|
|
1242
|
+
true storage owner and CAObject itself carries the semantic identity.
|
|
1243
|
+
The declared data_type is the SURFACE (= what dispatch sees);
|
|
1244
|
+
parent.data_type is the STORAGE. They may differ (= NonNumeric Face
|
|
1245
|
+
declares surface = CA_FIXLEN to gate mkkernel numeric ops while
|
|
1246
|
+
storage stays e.g. int64). */
|
|
1247
|
+
if ( RTEST(rface) ) {
|
|
1248
|
+
if ( NIL_P(rparent) ) {
|
|
1249
|
+
rb_raise(rb_eArgError,
|
|
1250
|
+
"CAObject Face mode (= face: true) requires :parent option "
|
|
1251
|
+
"(= storage CArray)");
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
|
|
741
1255
|
rb_ca_guess_type_and_bytes(rtype, rbytes, &data_type, &bytes);
|
|
742
|
-
rb_ca_data_type_import(self, rtype);
|
|
743
1256
|
|
|
744
1257
|
Check_Type(rdim, T_ARRAY);
|
|
745
1258
|
|
|
@@ -753,7 +1266,6 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
753
1266
|
ca->self = self;
|
|
754
1267
|
|
|
755
1268
|
rdata = ca_wrap_struct(ca->data);
|
|
756
|
-
rb_ca_data_type_inherit(rdata, self);
|
|
757
1269
|
|
|
758
1270
|
rb_ivar_set(self, rb_intern("__data__"), rdata);
|
|
759
1271
|
|
|
@@ -766,6 +1278,56 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
766
1278
|
TypedData_Get_Struct(rparent, CArray, &carray_data_type, cp);
|
|
767
1279
|
ca->parent = cp;
|
|
768
1280
|
rb_ca_set_parent(self, rparent);
|
|
1281
|
+
|
|
1282
|
+
/* Face mode invariants. The check the author opts into depends on
|
|
1283
|
+
whether :storage is explicit:
|
|
1284
|
+
- :storage omitted → "surface == storage" contract:
|
|
1285
|
+
surface (= declared data_type) must equal
|
|
1286
|
+
parent.data_type. This catches typos for
|
|
1287
|
+
Numeric Face authors who didn't intend
|
|
1288
|
+
surface/storage to differ.
|
|
1289
|
+
- :storage given → "surface != storage" opted-in:
|
|
1290
|
+
surface is free (= e.g. CA_FIXLEN for
|
|
1291
|
+
NonNumeric Face), :storage must agree with
|
|
1292
|
+
parent.data_type, and bytes must match. */
|
|
1293
|
+
if ( RTEST(rface) ) {
|
|
1294
|
+
if ( bytes != cp->bytes ) {
|
|
1295
|
+
rb_raise(rb_eTypeError,
|
|
1296
|
+
"CAObject Face: bytes mismatch "
|
|
1297
|
+
"(declared=%lld, parent=%lld)",
|
|
1298
|
+
(long long) bytes, (long long) cp->bytes);
|
|
1299
|
+
}
|
|
1300
|
+
if ( NIL_P(rstorage) ) {
|
|
1301
|
+
/* surface == storage contract */
|
|
1302
|
+
if ( cp->data_type != data_type ) {
|
|
1303
|
+
rb_raise(rb_eTypeError,
|
|
1304
|
+
"CAObject Face: parent data_type mismatch "
|
|
1305
|
+
"(declared=%d, parent=%d). Use :storage option to "
|
|
1306
|
+
"opt into surface != storage (NonNumeric Face).",
|
|
1307
|
+
(int) data_type, (int) cp->data_type);
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
else {
|
|
1311
|
+
/* opted-in surface != storage: validate :storage against parent */
|
|
1312
|
+
int8_t declared_storage;
|
|
1313
|
+
ca_size_t declared_storage_bytes;
|
|
1314
|
+
rb_ca_guess_type_and_bytes(rstorage, Qnil,
|
|
1315
|
+
&declared_storage, &declared_storage_bytes);
|
|
1316
|
+
if ( cp->data_type != declared_storage ) {
|
|
1317
|
+
rb_raise(rb_eTypeError,
|
|
1318
|
+
"CAObject Face: :storage mismatch "
|
|
1319
|
+
"(declared=%d, parent.data_type=%d)",
|
|
1320
|
+
(int) declared_storage, (int) cp->data_type);
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
ca_set_flag(ca, CA_FLAG_IS_FACE);
|
|
1324
|
+
if ( RTEST(rorderable) ) {
|
|
1325
|
+
ca_set_flag(ca, CA_FLAG_FACE_ORDERABLE_STORAGE);
|
|
1326
|
+
}
|
|
1327
|
+
if ( RTEST(rcomparable) ) {
|
|
1328
|
+
ca_set_flag(ca, CA_FLAG_FACE_COMPARABLE_STORAGE);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
769
1331
|
}
|
|
770
1332
|
|
|
771
1333
|
ca_update_mask(ca);
|
|
@@ -774,14 +1336,14 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
774
1336
|
}
|
|
775
1337
|
|
|
776
1338
|
void
|
|
777
|
-
Init_ca_obj_object ()
|
|
1339
|
+
Init_ca_obj_object (void)
|
|
778
1340
|
{
|
|
779
1341
|
rb_cCAObjectMask = rb_define_class("CAObjectMask", rb_cCArray);
|
|
780
1342
|
|
|
781
1343
|
CA_OBJ_OBJECT_MASK = ca_install_obj_type(rb_cCAObjectMask,
|
|
782
1344
|
&caobjectmask_data_type,
|
|
783
1345
|
rb_cCArrayMask,
|
|
784
|
-
&carray_data_type, ca_objmask_func);
|
|
1346
|
+
&carray_data_type, &ca_objmask_func, sizeof(ca_objmask_func));
|
|
785
1347
|
rb_define_const(rb_cObject, "CA_OBJ_OBJECT_MASK", INT2NUM(CA_OBJ_OBJECT_MASK));
|
|
786
1348
|
|
|
787
1349
|
rb_define_alloc_func(rb_cCAObjectMask, rb_ca_objmask_s_allocate);
|
|
@@ -791,6 +1353,14 @@ Init_ca_obj_object ()
|
|
|
791
1353
|
|
|
792
1354
|
rb_define_const(rb_cObject, "CA_OBJ_OBJECT", INT2NUM(CA_OBJ_OBJECT));
|
|
793
1355
|
|
|
1356
|
+
/* CA_OBJ_OBJECT is a builtin obj_type: carray_core.c assigned
|
|
1357
|
+
ca_func[CA_OBJ_OBJECT] = ca_object_func (without pool hooks) before
|
|
1358
|
+
this runs. Override the three pool slots in place (same pattern as
|
|
1359
|
+
CABlock overriding the CAStride baseline). */
|
|
1360
|
+
ca_func[CA_OBJ_OBJECT].struct_size = sizeof(CAObject);
|
|
1361
|
+
ca_func[CA_OBJ_OBJECT].pool_bytes = ca_object_pool_bytes;
|
|
1362
|
+
ca_func[CA_OBJ_OBJECT].pool_init = ca_object_pool_init;
|
|
1363
|
+
|
|
794
1364
|
rb_define_alloc_func(rb_cCAObject, rb_ca_object_s_allocate);
|
|
795
1365
|
rb_define_method(rb_cCAObject, "initialize_copy",
|
|
796
1366
|
rb_ca_object_initialize_copy, 1);
|