carray 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +5 -25
- data/CHANGELOG.md +16 -0
- data/LICENSE +1 -1
- data/NEWS.md +3 -0
- data/README.md +128 -44
- data/carray.gemspec +22 -24
- data/ext/ca_array_pool.c +91 -0
- data/ext/ca_axis_descriptor.h +186 -0
- data/ext/ca_axis_dispatch.c +924 -0
- data/ext/ca_axis_group.c +1208 -0
- data/ext/ca_bincmp_dispatch.c +76 -0
- data/ext/ca_bincmp_dispatch.h +85 -0
- data/ext/ca_binop_dispatch.c +125 -0
- data/ext/ca_binop_dispatch.h +159 -0
- data/ext/ca_categorical_iterator.c +1375 -0
- data/ext/ca_compare.c +94 -0
- data/ext/ca_compare.h +26 -0
- data/ext/ca_composite_dispatch.c +414 -0
- data/ext/ca_composite_dispatch.h +116 -0
- data/ext/ca_for_buffer.h +96 -0
- data/ext/ca_for_each_element.h +241 -0
- data/ext/ca_group_iter.c +304 -0
- data/ext/ca_iter_substrate.h +325 -0
- data/ext/ca_kernel_iterator.c +4321 -0
- data/ext/ca_kernel_iterator.h +2603 -0
- data/ext/ca_moncmp_dispatch.c +37 -0
- data/ext/ca_moncmp_dispatch.h +62 -0
- data/ext/ca_monop_dispatch.c +200 -0
- data/ext/ca_monop_dispatch.h +235 -0
- data/ext/ca_obj_array.c +355 -359
- data/ext/ca_obj_bincmp.c +809 -0
- data/ext/ca_obj_binop.c +892 -0
- data/ext/ca_obj_bitarray.c +369 -164
- data/ext/ca_obj_bitfield.c +294 -234
- data/ext/ca_obj_block.c +189 -711
- data/ext/ca_obj_byte_swap.c +766 -0
- data/ext/ca_obj_const_string.c +965 -0
- data/ext/ca_obj_face.c +670 -0
- data/ext/ca_obj_face.h +247 -0
- data/ext/ca_obj_fake.c +228 -100
- data/ext/ca_obj_farray.c +54 -441
- data/ext/ca_obj_field.c +82 -529
- data/ext/ca_obj_fixlen_string.c +306 -0
- data/ext/ca_obj_grid.c +858 -440
- data/ext/ca_obj_meld.c +1034 -0
- data/ext/ca_obj_moncmp.c +569 -0
- data/ext/ca_obj_monop.c +1111 -0
- data/ext/ca_obj_object.c +774 -298
- data/ext/ca_obj_record.c +468 -0
- data/ext/ca_obj_reduce.c +97 -82
- data/ext/ca_obj_refer.c +569 -459
- data/ext/ca_obj_remap.c +475 -0
- data/ext/ca_obj_repeat.c +92 -477
- data/ext/ca_obj_roll.c +616 -0
- data/ext/ca_obj_select.c +344 -296
- data/ext/ca_obj_select_axis.c +1296 -0
- data/ext/ca_obj_shift.c +230 -792
- data/ext/ca_obj_source.c +78 -0
- data/ext/ca_obj_stack.c +1173 -0
- data/ext/ca_obj_stride.c +2501 -0
- data/ext/ca_obj_string.c +268 -0
- data/ext/ca_obj_tile.c +614 -0
- data/ext/ca_obj_time.c +546 -0
- data/ext/ca_obj_timedelta.c +435 -0
- data/ext/ca_obj_transpose.c +62 -516
- data/ext/ca_obj_triop.c +746 -0
- data/ext/ca_obj_unbound_repeat.c +208 -241
- data/ext/ca_obj_window.c +1131 -563
- data/ext/ca_op_byte_swap.c +175 -0
- data/ext/ca_op_ipower.c +319 -0
- data/ext/ca_op_powi.h +88 -0
- data/ext/ca_sort_kernels.h +132 -0
- data/ext/ca_sweep_engine.c +430 -0
- data/ext/ca_sweep_engine.h +157 -0
- data/ext/ca_transform_common.c +228 -0
- data/ext/ca_triop_dispatch.c +55 -0
- data/ext/ca_triop_dispatch.h +62 -0
- data/ext/carray.h +795 -402
- data/ext/carray_access.c +831 -711
- data/ext/carray_attribute.c +98 -330
- data/ext/carray_bincount.c +255 -0
- data/ext/carray_broadcast.c +283 -0
- data/ext/carray_call_cfunc.c +1360 -828
- data/ext/carray_call_cfunc.h +160 -0
- data/ext/carray_cast.c +1212 -301
- data/ext/carray_cast_func.rb +81 -40
- data/ext/carray_class.c +53 -63
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +350 -346
- data/ext/carray_copy.c +156 -268
- data/ext/carray_core.c +1342 -199
- data/ext/carray_count.c +312 -0
- data/ext/carray_data_type.c +43 -19
- data/ext/carray_element.c +585 -213
- data/ext/carray_factorize.c +2542 -0
- data/ext/carray_generate.c +230 -559
- data/ext/carray_histogram.c +490 -0
- data/ext/carray_hold.c +228 -0
- data/ext/carray_index_classifier.c +1035 -0
- data/ext/carray_index_classifier.h +27 -0
- data/ext/carray_internal.h +120 -0
- data/ext/carray_kernels_bincmp.c +4445 -0
- data/ext/carray_kernels_binop.c +10979 -0
- data/ext/carray_kernels_init.c +36 -0
- data/ext/carray_kernels_map.c +3466 -0
- data/ext/carray_kernels_moncmp.c +2096 -0
- data/ext/carray_kernels_monop.c +18312 -0
- data/ext/carray_kernels_reduce_aggregate.c +25836 -0
- data/ext/carray_kernels_reduce_boolean.c +329 -0
- data/ext/carray_kernels_reduce_cumulative.c +14592 -0
- data/ext/carray_kernels_reduce_extreme.c +16947 -0
- data/ext/carray_kernels_reduce_variance.c +3909 -0
- data/ext/carray_kernels_scan.c +3692 -0
- data/ext/carray_kernels_search.c +32137 -0
- data/ext/carray_kernels_sort.c +10625 -0
- data/ext/carray_kernels_triop.c +1391 -0
- data/ext/carray_lazy.c +567 -0
- data/ext/carray_loop.c +88 -200
- data/ext/carray_mask.c +848 -154
- data/ext/carray_math_kernel.h +120 -0
- data/ext/carray_mathfunc.c +10 -241
- data/ext/carray_median_percentile.c +1257 -0
- data/ext/carray_memory_view.c +1625 -0
- data/ext/carray_operator.c +1526 -318
- data/ext/carray_order.c +664 -1394
- data/ext/carray_partition.c +416 -0
- data/ext/carray_random.c +518 -0
- data/ext/carray_scatter.c +357 -0
- data/ext/carray_slab.c +1219 -0
- data/ext/carray_slab.h +84 -0
- data/ext/carray_sort.c +829 -0
- data/ext/carray_sort_kernel.c +620 -0
- data/ext/carray_struct.c +695 -0
- data/ext/carray_test.c +343 -229
- data/ext/carray_undef.c +34 -17
- data/ext/carray_utils.c +175 -74
- data/ext/extconf.rb +216 -55
- data/ext/mk_call_cfunc.rb +480 -0
- data/ext/mkkernel.rb +8842 -0
- data/ext/ruby_carray.c +202 -101
- data/ext/version.h +4 -14
- data/ext/version.rb +5 -13
- data/lib/carray/arrow_tensor.rb +401 -0
- data/lib/carray/attribute.rb +166 -0
- data/lib/carray/autoload_carray.rb +220 -0
- data/lib/carray/autoload_method_extension.rb +44 -0
- data/lib/carray/axis_group.rb +711 -0
- data/lib/carray/basics.rb +481 -0
- data/lib/carray/bincount_nd.rb +358 -0
- data/lib/carray/block_iterator.rb +604 -0
- data/lib/carray/boolean_reduce.rb +109 -0
- data/lib/carray/categorical.rb +561 -0
- data/lib/carray/categorical_iterator.rb +1062 -0
- data/lib/carray/complex.rb +150 -0
- data/lib/carray/conditional.rb +216 -0
- data/lib/carray/const_string.rb +228 -0
- data/lib/carray/construct.rb +139 -328
- data/lib/carray/core_extensions.rb +240 -0
- data/lib/carray/data_type_extension.rb +233 -0
- data/lib/carray/fixlen_string.rb +95 -0
- data/lib/carray/frame/concat.rb +132 -0
- data/lib/carray/frame/convert.rb +95 -0
- data/lib/carray/frame/csv_parser.rb +211 -0
- data/lib/carray/frame/frame.rb +649 -0
- data/lib/carray/frame/group.rb +186 -0
- data/lib/carray/frame/io.rb +164 -0
- data/lib/carray/frame/join.rb +248 -0
- data/lib/carray/frame/records.rb +99 -0
- data/lib/carray/frame/sort.rb +113 -0
- data/lib/carray/frame/verbs.rb +299 -0
- data/lib/carray/frame.rb +16 -0
- data/lib/carray/histogram.rb +512 -0
- data/lib/carray/inspect.rb +37 -20
- data/lib/carray/iterator.rb +57 -349
- data/lib/carray/lazy.rb +889 -0
- data/lib/carray/mask_gap_fill.rb +200 -0
- data/lib/carray/math.rb +78 -342
- data/lib/carray/meld_reduce.rb +289 -0
- data/lib/carray/methods/align_addr.rb +116 -0
- data/lib/carray/methods/bin.rb +128 -0
- data/lib/carray/methods/bincount.rb +87 -0
- data/lib/carray/methods/bit_string.rb +92 -0
- data/lib/carray/methods/broadcast.rb +63 -0
- data/lib/carray/methods/choose.rb +39 -0
- data/lib/carray/methods/composition.rb +280 -0
- data/lib/carray/methods/gather_nd.rb +206 -0
- data/lib/carray/methods/index.rb +39 -0
- data/lib/carray/methods/insert_block.rb +99 -0
- data/lib/carray/methods/is_in.rb +141 -0
- data/lib/carray/methods/join.rb +90 -0
- data/lib/carray/methods/locate_addr.rb +47 -0
- data/lib/carray/methods/mask_duplicates.rb +41 -0
- data/lib/carray/methods/meshgrid.rb +91 -0
- data/lib/carray/methods/mode.rb +126 -0
- data/lib/carray/methods/nunique.rb +46 -0
- data/lib/carray/methods/resize.rb +56 -0
- data/lib/carray/methods/snap.rb +156 -0
- data/lib/carray/methods/string_format.rb +57 -0
- data/lib/carray/methods/unique.rb +47 -0
- data/lib/carray/methods/value_counts.rb +71 -0
- data/lib/carray/mkmf.rb +124 -101
- data/lib/carray/runtime.rb +108 -0
- data/lib/carray/serialize.rb +478 -167
- data/lib/carray/slab_iterator.rb +292 -0
- data/lib/carray/stack.rb +291 -0
- data/lib/carray/string.rb +56 -180
- data/lib/carray/string_operation_extension.rb +289 -0
- data/lib/carray/struct.rb +335 -323
- data/lib/carray/struct_builder.rb +697 -0
- data/lib/carray/table.rb +41 -2
- data/lib/carray/time.rb +2255 -38
- data/lib/carray/window_iterator.rb +655 -0
- data/lib/carray.rb +55 -57
- metadata +163 -130
- data/Rakefile +0 -51
- data/TODO.md +0 -18
- data/ext/ca_iter_block.c +0 -257
- data/ext/ca_iter_dimension.c +0 -299
- data/ext/ca_iter_window.c +0 -214
- data/ext/ca_obj_mapping.c +0 -644
- data/ext/carray_iterator.c +0 -641
- data/ext/carray_math.rb +0 -850
- data/ext/carray_numeric.c +0 -259
- data/ext/carray_sort_addr.c +0 -254
- data/ext/carray_stat.c +0 -2100
- data/ext/carray_stat_proc.rb +0 -1999
- data/ext/mkmath.rb +0 -741
- data/ext/ruby_ccomplex.c +0 -509
- data/ext/ruby_float_func.c +0 -86
- data/lib/carray/array.rb +0 -8
- data/lib/carray/autoload/autoload_base.rb +0 -19
- data/lib/carray/autoload/autoload_gem_cairo.rb +0 -9
- data/lib/carray/autoload/autoload_gem_ffi.rb +0 -9
- data/lib/carray/autoload/autoload_gem_gnuplot.rb +0 -2
- data/lib/carray/autoload/autoload_gem_io_csv.rb +0 -14
- data/lib/carray/autoload/autoload_gem_io_pg.rb +0 -6
- data/lib/carray/autoload/autoload_gem_io_sqlite3.rb +0 -12
- data/lib/carray/autoload/autoload_gem_narray.rb +0 -10
- data/lib/carray/autoload/autoload_gem_numo_narray.rb +0 -15
- data/lib/carray/autoload/autoload_gem_opencv.rb +0 -16
- data/lib/carray/autoload/autoload_gem_random.rb +0 -8
- data/lib/carray/autoload/autoload_gem_rmagick.rb +0 -23
- data/lib/carray/autoload/autoload_gem_zimg.rb +0 -3
- data/lib/carray/autoload/autoload_io_imagemagick.rb +0 -6
- data/lib/carray/autoload/autoload_math_histogram.rb +0 -5
- data/lib/carray/autoload/autoload_math_recurrence.rb +0 -6
- data/lib/carray/autoload/autoload_object_iterator.rb +0 -1
- data/lib/carray/autoload/autoload_object_link.rb +0 -1
- data/lib/carray/autoload/autoload_object_pack.rb +0 -2
- data/lib/carray/autoload.rb +0 -141
- data/lib/carray/basic.rb +0 -191
- data/lib/carray/broadcast.rb +0 -101
- data/lib/carray/compose.rb +0 -315
- data/lib/carray/convert.rb +0 -115
- data/lib/carray/info.rb +0 -110
- data/lib/carray/io/imagemagick.rb +0 -235
- data/lib/carray/mask.rb +0 -102
- data/lib/carray/math/histogram.rb +0 -177
- data/lib/carray/math/recurrence.rb +0 -93
- data/lib/carray/object/ca_obj_iterator.rb +0 -50
- data/lib/carray/object/ca_obj_link.rb +0 -50
- data/lib/carray/object/ca_obj_pack.rb +0 -99
- data/lib/carray/obsolete.rb +0 -256
- data/lib/carray/ordering.rb +0 -181
- data/lib/carray/testing.rb +0 -51
- data/lib/carray/transform.rb +0 -109
- data/misc/Methods.ja.md +0 -182
- data/misc/NOTE +0 -51
- data/spec/Classes/CABitfield_spec.rb +0 -58
- data/spec/Classes/CABlockIterator_spec.rb +0 -114
- data/spec/Classes/CABlock_spec.rb +0 -205
- data/spec/Classes/CAField_spec.rb +0 -39
- data/spec/Classes/CAGrid_spec.rb +0 -75
- data/spec/Classes/CAMap_spec.rb +0 -0
- data/spec/Classes/CAMapping_spec.rb +0 -105
- data/spec/Classes/CAObject_attribute_spec.rb +0 -33
- data/spec/Classes/CAObject_spec.rb +0 -33
- data/spec/Classes/CARefer_spec.rb +0 -93
- data/spec/Classes/CARepeat_spec.rb +0 -65
- data/spec/Classes/CASelect_spec.rb +0 -22
- data/spec/Classes/CAShift_spec.rb +0 -16
- data/spec/Classes/CAStruct_spec.rb +0 -71
- data/spec/Classes/CATranspose_spec.rb +0 -60
- data/spec/Classes/CAUnboudRepeat_spec.rb +0 -102
- data/spec/Classes/CAWindow_spec.rb +0 -54
- data/spec/Classes/CAWrap_spec.rb +0 -8
- data/spec/Classes/CArray_spec.rb +0 -184
- data/spec/Classes/CScalar_spec.rb +0 -55
- data/spec/Classes/ex1.rb +0 -46
- data/spec/Features/feature_130_spec.rb +0 -19
- data/spec/Features/feature_attributes_spec.rb +0 -280
- data/spec/Features/feature_boolean_spec.rb +0 -98
- data/spec/Features/feature_broadcast.rb +0 -116
- data/spec/Features/feature_cast_function.rb +0 -19
- data/spec/Features/feature_cast_spec.rb +0 -33
- data/spec/Features/feature_class_spec.rb +0 -84
- data/spec/Features/feature_complex_spec.rb +0 -42
- data/spec/Features/feature_composite_spec.rb +0 -124
- data/spec/Features/feature_convert_spec.rb +0 -46
- data/spec/Features/feature_copy_spec.rb +0 -123
- data/spec/Features/feature_creation_spec.rb +0 -84
- data/spec/Features/feature_element_spec.rb +0 -144
- data/spec/Features/feature_extream_spec.rb +0 -54
- data/spec/Features/feature_generate_spec.rb +0 -74
- data/spec/Features/feature_index_spec.rb +0 -69
- data/spec/Features/feature_mask_spec.rb +0 -580
- data/spec/Features/feature_math_spec.rb +0 -97
- data/spec/Features/feature_order_spec.rb +0 -146
- data/spec/Features/feature_ref_store_spec.rb +0 -209
- data/spec/Features/feature_serialization_spec.rb +0 -125
- data/spec/Features/feature_stat_spec.rb +0 -397
- data/spec/Features/feature_virtual_spec.rb +0 -48
- data/spec/Features/method_eq_spec.rb +0 -81
- data/spec/Features/method_is_nan_spec.rb +0 -12
- data/spec/Features/method_map_spec.rb +0 -54
- data/spec/Features/method_max_with.rb +0 -20
- data/spec/Features/method_min_with.rb +0 -19
- data/spec/Features/method_ne_spec.rb +0 -18
- data/spec/Features/method_project_spec.rb +0 -188
- data/spec/Features/method_ref_spec.rb +0 -27
- data/spec/Features/method_round_spec.rb +0 -11
- data/spec/Features/method_s_linspace_spec.rb +0 -48
- data/spec/Features/method_s_span_spec.rb +0 -14
- data/spec/Features/method_seq_spec.rb +0 -47
- data/spec/Features/method_sort_with.rb +0 -43
- data/spec/Features/method_sorted_with.rb +0 -29
- data/spec/Features/method_span_spec.rb +0 -42
- data/spec/Features/method_wrap_readonly_spec.rb +0 -43
- data/spec/UnitTest/test_CAVirtual.rb +0 -214
- data/spec/spec_all.rb +0 -10
- data/utils/ca_ase.rb +0 -21
- data/utils/ca_methods.rb +0 -15
- data/utils/cast_checker.rb +0 -30
- data/utils/convert_test.rb +0 -73
- data/utils/extract_yard.rb +0 -22
- data/utils/guess_shape.rb +0 -76
- data/utils/monkey_patch_methods.rb +0 -62
- data/utils/remove_resource_fork.sh +0 -5
data/ext/ca_obj_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,21 +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 = {
|
|
86
|
+
.parent = &carray_data_type,
|
|
63
87
|
.wrap_struct_name = "CAObjectMask",
|
|
64
88
|
.function = {
|
|
65
89
|
.dmark = ca_mark,
|
|
66
90
|
.dfree = ca_free,
|
|
67
|
-
.dsize =
|
|
91
|
+
.dsize = ca_objectmask_dsize,
|
|
68
92
|
.dcompact = NULL
|
|
69
93
|
},
|
|
70
94
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
@@ -73,16 +97,16 @@ const rb_data_type_t caobjectmask_data_type = {
|
|
|
73
97
|
static int8_t CA_OBJ_OBJECT_MASK;
|
|
74
98
|
VALUE rb_cCAObjectMask;
|
|
75
99
|
|
|
76
|
-
/* yard:
|
|
77
|
-
class CAObjectMask < CAVirtual # :nodoc:
|
|
78
|
-
end
|
|
79
|
-
*/
|
|
80
|
-
|
|
81
|
-
|
|
82
100
|
static CAObjectMask *
|
|
83
101
|
ca_objmask_new (VALUE array, int8_t ndim, ca_size_t *dim)
|
|
84
102
|
{
|
|
85
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;
|
|
86
110
|
ca_wrap_setup_null((CArray *)ca, CA_BOOLEAN, ndim, dim, 0, NULL);
|
|
87
111
|
ca->obj_type = CA_OBJ_OBJECT_MASK;
|
|
88
112
|
ca->array = array;
|
|
@@ -105,111 +129,99 @@ ca_objmask_func_clone (void *ap)
|
|
|
105
129
|
return ca_objmask_new(ca->array, ca->ndim, ca->dim);
|
|
106
130
|
}
|
|
107
131
|
|
|
108
|
-
|
|
109
|
-
|
|
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)
|
|
110
139
|
{
|
|
111
|
-
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
112
140
|
volatile VALUE ridx, raddr, rval;
|
|
113
141
|
int i;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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);
|
|
127
162
|
}
|
|
128
|
-
rval = rb_funcall(ca->array, rb_intern("mask_fetch_index"), 1, ridx);
|
|
129
|
-
*(uint8_t*) ptr = NUM2INT(rval) == 0 ? 0 : 1;
|
|
130
|
-
ca_array_func_store_index(ca, idx, ptr);
|
|
131
163
|
}
|
|
132
164
|
else {
|
|
133
|
-
|
|
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
|
+
}
|
|
134
180
|
}
|
|
135
181
|
}
|
|
136
182
|
|
|
137
|
-
void
|
|
138
|
-
|
|
183
|
+
static void
|
|
184
|
+
ca_objmask_xfer_index_one (CAObjectMask *ca, ca_size_t *idx, void *ptr, int dir)
|
|
139
185
|
{
|
|
140
|
-
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
141
186
|
volatile VALUE ridx, raddr, rval;
|
|
142
187
|
int i;
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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);
|
|
148
207
|
}
|
|
149
|
-
rval = rb_funcall(ca->array, rb_intern("mask_fetch_index"), 1, ridx);
|
|
150
|
-
*(uint8_t*) ptr = NUM2INT(rval) == 0 ? 0 : 1;
|
|
151
|
-
ca_array_func_store_index(ca, idx, ptr);
|
|
152
|
-
}
|
|
153
|
-
else if ( rb_obj_respond_to(ca->array, rb_intern("mask_fetch_addr"), Qtrue) ) {
|
|
154
|
-
ca_size_t addr = ca_index2addr(ca, idx);
|
|
155
|
-
raddr = SIZE2NUM(addr);
|
|
156
|
-
rval = rb_funcall(ca->array, rb_intern("mask_fetch_addr"), 1, raddr);
|
|
157
|
-
*(uint8_t*) ptr = NUM2INT(rval) == 0 ? 0 : 1;
|
|
158
|
-
ca_array_func_store_addr(ca, addr, ptr);
|
|
159
208
|
}
|
|
160
209
|
else {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
170
|
-
volatile VALUE ridx, raddr, rval;
|
|
171
|
-
int i;
|
|
172
|
-
|
|
173
|
-
ca_array_func_store_addr(ca, addr, ptr);
|
|
174
|
-
rval = INT2NUM( *(uint8_t*)ptr );
|
|
175
|
-
if ( rb_obj_respond_to(ca->array, rb_intern("mask_store_addr"), Qtrue) ) {
|
|
176
|
-
raddr = SIZE2NUM(addr);
|
|
177
|
-
rb_funcall(ca->array, rb_intern("mask_store_addr"), 2, raddr, rval);
|
|
178
|
-
}
|
|
179
|
-
else if ( rb_obj_respond_to(ca->array, rb_intern("mask_store_index"), Qtrue) ) {
|
|
180
|
-
ca_size_t idx[CA_RANK_MAX];
|
|
181
|
-
ca_addr2index(ca, addr, idx);
|
|
182
|
-
ridx = rb_ary_new2(ca->ndim);
|
|
183
|
-
for (i=0; i<ca->ndim; i++) {
|
|
184
|
-
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);
|
|
185
218
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
void
|
|
191
|
-
ca_objmask_func_store_index (void *ap, ca_size_t *idx, void *ptr)
|
|
192
|
-
{
|
|
193
|
-
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
194
|
-
volatile VALUE ridx, raddr, rval;
|
|
195
|
-
int i;
|
|
196
|
-
|
|
197
|
-
ca_array_func_store_index(ca, idx, ptr);
|
|
198
|
-
rval = INT2NUM( *(uint8_t*)ptr );
|
|
199
|
-
|
|
200
|
-
if ( rb_obj_respond_to(ca->array, rb_intern("mask_store_index"), Qtrue) ) {
|
|
201
|
-
ridx = rb_ary_new2(ca->ndim);
|
|
202
|
-
for (i=0; i<ca->ndim; i++) {
|
|
203
|
-
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);
|
|
204
223
|
}
|
|
205
|
-
rb_funcall(ca->array, rb_intern("mask_store_index"), 2, ridx, rval);
|
|
206
|
-
}
|
|
207
|
-
else if ( rb_obj_respond_to(ca->array, rb_intern("mask_store_addr"), Qtrue) ) {
|
|
208
|
-
ca_size_t addr = ca_index2addr(ca, idx);
|
|
209
|
-
raddr = SIZE2NUM(addr);
|
|
210
|
-
rb_funcall(ca->array, rb_intern("mask_store_addr"), 2, raddr, rval);
|
|
211
224
|
}
|
|
212
|
-
|
|
213
225
|
}
|
|
214
226
|
|
|
215
227
|
static void
|
|
@@ -233,46 +245,146 @@ ca_objmask_func_sync (void *ap)
|
|
|
233
245
|
}
|
|
234
246
|
|
|
235
247
|
static void
|
|
236
|
-
|
|
248
|
+
ca_objmask_func_xfer_all (void *ap, void *data, int dir)
|
|
237
249
|
{
|
|
238
250
|
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
239
|
-
if (
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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
|
+
}
|
|
245
262
|
}
|
|
246
263
|
else {
|
|
247
|
-
|
|
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));
|
|
248
285
|
}
|
|
249
286
|
}
|
|
250
287
|
|
|
251
288
|
static void
|
|
252
|
-
|
|
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)
|
|
253
305
|
{
|
|
254
306
|
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
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;
|
|
261
319
|
}
|
|
262
|
-
|
|
263
|
-
|
|
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
|
+
}
|
|
264
327
|
}
|
|
265
328
|
}
|
|
266
329
|
|
|
267
|
-
|
|
268
|
-
|
|
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)
|
|
269
337
|
{
|
|
270
338
|
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
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
|
+
int aligned = 1;
|
|
356
|
+
for ( k = 0; k < ndim; k++ ) {
|
|
357
|
+
if ( strides[k] <= 0 || strides[k] % native[k] != 0 ) { aligned = 0; break; }
|
|
358
|
+
steps[k] = strides[k] / native[k];
|
|
359
|
+
}
|
|
360
|
+
if ( aligned ) {
|
|
361
|
+
volatile VALUE rstarts, rcounts, rsteps, rdata;
|
|
362
|
+
rstarts = rb_ary_new_capa(ndim);
|
|
363
|
+
rcounts = rb_ary_new_capa(ndim);
|
|
364
|
+
rsteps = rb_ary_new_capa(ndim);
|
|
365
|
+
for ( k = 0; k < ndim; k++ ) {
|
|
366
|
+
rb_ary_push(rstarts, SIZE2NUM(starts[k]));
|
|
367
|
+
rb_ary_push(rcounts, SIZE2NUM(counts[k]));
|
|
368
|
+
rb_ary_push(rsteps, SIZE2NUM(steps[k]));
|
|
369
|
+
}
|
|
370
|
+
rdata = ca_object_wrap_transient(ca->data_type, ca->bytes,
|
|
371
|
+
ndim, counts, data, dir);
|
|
372
|
+
rb_funcall(ca->array, mid_block, 4, rstarts, rcounts, rsteps, rdata);
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
275
375
|
}
|
|
376
|
+
|
|
377
|
+
vaddrs = ALLOCV_N(ca_size_t, holder, n);
|
|
378
|
+
for (k = 0; k < ndim; k++) idx[k] = 0;
|
|
379
|
+
for (i = 0; i < n; i++) {
|
|
380
|
+
ca_size_t off = base;
|
|
381
|
+
for (k = 0; k < ndim; k++) off += idx[k] * strides[k];
|
|
382
|
+
vaddrs[i] = off / ca->bytes;
|
|
383
|
+
k = ndim - 1;
|
|
384
|
+
while (k >= 0) { if (++idx[k] < counts[k]) break; idx[k] = 0; k--; }
|
|
385
|
+
}
|
|
386
|
+
ca_objmask_func_xfer_addrs(ca, n, vaddrs, data, dir);
|
|
387
|
+
ALLOCV_END(holder);
|
|
276
388
|
}
|
|
277
389
|
|
|
278
390
|
static ca_operation_function_t ca_objmask_func = {
|
|
@@ -280,27 +392,24 @@ static ca_operation_function_t ca_objmask_func = {
|
|
|
280
392
|
CA_REAL_ARRAY,
|
|
281
393
|
free_ca_wrap,
|
|
282
394
|
ca_objmask_func_clone,
|
|
283
|
-
ca_array_func_ptr_at_addr,
|
|
284
|
-
ca_array_func_ptr_at_index,
|
|
285
|
-
ca_objmask_func_fetch_addr,
|
|
286
|
-
ca_objmask_func_fetch_index,
|
|
287
|
-
ca_objmask_func_store_addr,
|
|
288
|
-
ca_objmask_func_store_index,
|
|
289
395
|
ca_array_func_allocate,
|
|
290
396
|
ca_objmask_func_attach,
|
|
291
397
|
ca_objmask_func_sync,
|
|
292
398
|
ca_array_func_detach,
|
|
293
|
-
ca_objmask_func_copy_data,
|
|
294
|
-
ca_objmask_func_sync_data,
|
|
295
399
|
ca_objmask_func_fill_data,
|
|
296
400
|
ca_array_func_create_mask,
|
|
401
|
+
ca_objmask_func_xfer_index,
|
|
402
|
+
ca_objmask_func_xfer_addrs,
|
|
403
|
+
NULL, /* fold_stride: never-fold (callback boundary) */
|
|
404
|
+
ca_objmask_func_xfer_stride,
|
|
405
|
+
ca_objmask_func_xfer_all,
|
|
297
406
|
};
|
|
298
407
|
|
|
299
408
|
static VALUE
|
|
300
409
|
rb_ca_objmask_s_allocate (VALUE klass)
|
|
301
410
|
{
|
|
302
411
|
CAObjectMask *ca;
|
|
303
|
-
return TypedData_Make_Struct(klass, CAObjectMask, &
|
|
412
|
+
return TypedData_Make_Struct(klass, CAObjectMask, &caobjectmask_data_type, ca);
|
|
304
413
|
}
|
|
305
414
|
|
|
306
415
|
static VALUE
|
|
@@ -360,7 +469,9 @@ ca_object_setup (CAObject *ca,
|
|
|
360
469
|
ca->attach = 0;
|
|
361
470
|
ca->nosync = 0;
|
|
362
471
|
|
|
363
|
-
ca->
|
|
472
|
+
if ( ! ca->_pool ) {
|
|
473
|
+
ca->dim = ALLOC_N(ca_size_t, ndim);
|
|
474
|
+
}
|
|
364
475
|
|
|
365
476
|
ca->data = ca_wrap_new_null(data_type, ndim, dim, bytes, NULL);
|
|
366
477
|
|
|
@@ -372,7 +483,7 @@ ca_object_setup (CAObject *ca,
|
|
|
372
483
|
static CAObject *
|
|
373
484
|
ca_object_new (int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes)
|
|
374
485
|
{
|
|
375
|
-
CAObject *ca =
|
|
486
|
+
CAObject *ca = (CAObject *) ca_array_alloc(CA_OBJ_OBJECT, ndim);
|
|
376
487
|
ca_object_setup(ca, data_type, ndim, dim, bytes);
|
|
377
488
|
return ca;
|
|
378
489
|
}
|
|
@@ -383,8 +494,13 @@ free_ca_object (void *ap)
|
|
|
383
494
|
CAObject *ca = (CAObject *) ap;
|
|
384
495
|
if ( ca != NULL ) {
|
|
385
496
|
/* ca->mask will be GC-ed by Ruby interpreter */
|
|
386
|
-
|
|
387
|
-
|
|
497
|
+
if ( ca->_pool ) {
|
|
498
|
+
ca_array_free(ca); /* dim lives in _pool */
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
xfree(ca->dim);
|
|
502
|
+
xfree(ca);
|
|
503
|
+
}
|
|
388
504
|
}
|
|
389
505
|
}
|
|
390
506
|
|
|
@@ -394,186 +510,252 @@ static void *
|
|
|
394
510
|
ca_object_func_clone (void *ap)
|
|
395
511
|
{
|
|
396
512
|
CAObject *ca = (CAObject *) ap;
|
|
397
|
-
return ca_object_new(ca->
|
|
513
|
+
return ca_object_new(ca->data_type, ca->ndim, ca->dim, ca->bytes);
|
|
398
514
|
}
|
|
399
515
|
|
|
400
516
|
#define ca_object_func_ptr_at_addr ca_array_func_ptr_at_addr
|
|
401
517
|
#define ca_object_func_ptr_at_index ca_array_func_ptr_at_index
|
|
402
518
|
|
|
519
|
+
/* per-cell cores: the addr- and index-primary Ruby-callback bridge logic,
|
|
520
|
+
direction-unified. The fetch_* / store_* slots below are thin
|
|
521
|
+
forwarders onto these. */
|
|
403
522
|
static void
|
|
404
|
-
|
|
523
|
+
ca_object_xfer_addr_one (CAObject *ca, ca_size_t addr, void *ptr, int dir)
|
|
405
524
|
{
|
|
406
|
-
CAObject *ca = (CAObject *) ap;
|
|
407
525
|
volatile VALUE ridx, raddr, rval;
|
|
408
526
|
int i;
|
|
409
|
-
if (
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
527
|
+
if ( dir == CA_XFER_GET ) {
|
|
528
|
+
if ( rb_obj_respond_to(ca->self, rb_intern("fetch_addr"), Qtrue) ) {
|
|
529
|
+
raddr = SIZE2NUM(addr);
|
|
530
|
+
rval = rb_funcall(ca->self, rb_intern("fetch_addr"), 1, raddr);
|
|
531
|
+
if ( rval == CA_UNDEF ) {
|
|
532
|
+
ca_update_mask(ca);
|
|
533
|
+
if ( ! ca->mask ) {
|
|
534
|
+
ca_create_mask(ca);
|
|
535
|
+
}
|
|
536
|
+
*((boolean8_t*)ca->mask->ptr + addr) = 1;
|
|
537
|
+
if ( ca->data_type == CA_OBJECT ) {
|
|
538
|
+
rb_ca_obj2ptr(ca->self, INT2NUM(0), ptr);
|
|
539
|
+
}
|
|
416
540
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
541
|
+
else {
|
|
542
|
+
if ( ca_has_mask(ca) ) {
|
|
543
|
+
*((boolean8_t*)ca->mask->ptr + addr) = 0;
|
|
544
|
+
}
|
|
545
|
+
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
420
546
|
}
|
|
421
547
|
}
|
|
422
548
|
else {
|
|
423
|
-
|
|
424
|
-
|
|
549
|
+
ca_size_t idx[CA_RANK_MAX];
|
|
550
|
+
ca_addr2index(ca, addr, idx);
|
|
551
|
+
ridx = rb_ary_new2(ca->ndim);
|
|
552
|
+
for (i=0; i<ca->ndim; i++) {
|
|
553
|
+
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
554
|
+
}
|
|
555
|
+
rval = rb_funcall(ca->self, rb_intern("fetch_index"), 1, ridx);
|
|
556
|
+
if ( rval == CA_UNDEF ) {
|
|
557
|
+
ca_update_mask(ca);
|
|
558
|
+
if ( ! ca->mask ) {
|
|
559
|
+
ca_create_mask(ca);
|
|
560
|
+
}
|
|
561
|
+
*((boolean8_t*)ca->mask->ptr + ca_index2addr(ca->mask, idx)) = 1;
|
|
562
|
+
if ( ca->data_type == CA_OBJECT ) {
|
|
563
|
+
rb_ca_obj2ptr(ca->self, INT2NUM(0), ptr);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
else {
|
|
567
|
+
if ( ca_has_mask(ca) ) {
|
|
568
|
+
*((boolean8_t*)ca->mask->ptr + ca_index2addr(ca->mask, idx)) = 0;
|
|
569
|
+
}
|
|
570
|
+
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
425
571
|
}
|
|
426
|
-
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
427
572
|
}
|
|
428
573
|
}
|
|
429
574
|
else {
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
435
|
-
}
|
|
436
|
-
rval = rb_funcall(ca->self, rb_intern("fetch_index"), 1, ridx);
|
|
437
|
-
if ( rval == CA_UNDEF ) {
|
|
438
|
-
ca_update_mask(ca);
|
|
439
|
-
if ( ! ca->mask ) {
|
|
440
|
-
ca_create_mask(ca);
|
|
441
|
-
}
|
|
442
|
-
*(boolean8_t*)ca_ptr_at_index(ca->mask, idx) = 1;
|
|
443
|
-
if ( ca->data_type == CA_OBJECT ) {
|
|
444
|
-
rb_ca_obj2ptr(ca->self, INT2NUM(0), ptr);
|
|
445
|
-
}
|
|
575
|
+
if ( rb_obj_respond_to(ca->self, rb_intern("store_addr"), Qtrue) ) {
|
|
576
|
+
raddr = SIZE2NUM(addr);
|
|
577
|
+
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
578
|
+
rb_funcall(ca->self, rb_intern("store_addr"), 2, raddr, rval);
|
|
446
579
|
}
|
|
447
580
|
else {
|
|
448
|
-
|
|
449
|
-
|
|
581
|
+
ca_size_t idx[CA_RANK_MAX];
|
|
582
|
+
ca_addr2index(ca, addr, idx);
|
|
583
|
+
ridx = rb_ary_new2(ca->ndim);
|
|
584
|
+
for (i=0; i<ca->ndim; i++) {
|
|
585
|
+
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
450
586
|
}
|
|
451
|
-
|
|
587
|
+
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
588
|
+
rb_funcall(ca->self, rb_intern("store_index"), 2, ridx, rval);
|
|
452
589
|
}
|
|
453
590
|
}
|
|
454
591
|
}
|
|
455
592
|
|
|
456
593
|
static void
|
|
457
|
-
|
|
594
|
+
ca_object_xfer_index_one (CAObject *ca, ca_size_t *idx, void *ptr, int dir)
|
|
458
595
|
{
|
|
459
|
-
CAObject *ca = (CAObject *) ap;
|
|
460
596
|
volatile VALUE ridx, raddr, rval;
|
|
461
597
|
int i;
|
|
462
|
-
if (
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
598
|
+
if ( dir == CA_XFER_GET ) {
|
|
599
|
+
if ( rb_obj_respond_to(ca->self, rb_intern("fetch_index"), Qtrue) ) {
|
|
600
|
+
ridx = rb_ary_new2(ca->ndim);
|
|
601
|
+
for (i=0; i<ca->ndim; i++) {
|
|
602
|
+
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
603
|
+
}
|
|
604
|
+
rval = rb_funcall(ca->self, rb_intern("fetch_index"), 1, ridx);
|
|
605
|
+
if ( rval == CA_UNDEF ) {
|
|
606
|
+
ca_update_mask(ca);
|
|
607
|
+
if ( ! ca->mask ) {
|
|
608
|
+
ca_create_mask(ca);
|
|
609
|
+
}
|
|
610
|
+
*((boolean8_t*)ca->mask->ptr + ca_index2addr(ca->mask, idx)) = 1;
|
|
611
|
+
if ( ca->data_type == CA_OBJECT ) {
|
|
612
|
+
rb_ca_obj2ptr(ca->self, INT2NUM(0), ptr);
|
|
613
|
+
}
|
|
472
614
|
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
615
|
+
else {
|
|
616
|
+
if ( ca_has_mask(ca) ) {
|
|
617
|
+
*((boolean8_t*)ca->mask->ptr + ca_index2addr(ca->mask, idx)) = 0;
|
|
618
|
+
}
|
|
619
|
+
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
476
620
|
}
|
|
477
621
|
}
|
|
478
622
|
else {
|
|
479
|
-
|
|
480
|
-
|
|
623
|
+
ca_size_t addr = ca_index2addr(ca, idx);
|
|
624
|
+
raddr = SIZE2NUM(addr);
|
|
625
|
+
rval = rb_funcall(ca->self, rb_intern("fetch_addr"), 1, raddr);
|
|
626
|
+
if ( rval == CA_UNDEF ) {
|
|
627
|
+
ca_update_mask(ca);
|
|
628
|
+
if ( ! ca->mask ) {
|
|
629
|
+
ca_create_mask(ca);
|
|
630
|
+
}
|
|
631
|
+
*((boolean8_t*)ca->mask->ptr + addr) = 1;
|
|
632
|
+
if ( ca->data_type == CA_OBJECT ) {
|
|
633
|
+
rb_ca_obj2ptr(ca->self, INT2NUM(0), ptr);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
if ( ca_has_mask(ca) ) {
|
|
638
|
+
*((boolean8_t*)ca->mask->ptr + addr) = 0;
|
|
639
|
+
}
|
|
640
|
+
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
481
641
|
}
|
|
482
|
-
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
483
642
|
}
|
|
484
643
|
}
|
|
485
644
|
else {
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
ca_update_mask(ca);
|
|
491
|
-
if ( ! ca->mask ) {
|
|
492
|
-
ca_create_mask(ca);
|
|
493
|
-
}
|
|
494
|
-
*(boolean8_t*)ca_ptr_at_addr(ca->mask, addr) = 1;
|
|
495
|
-
if ( ca->data_type == CA_OBJECT ) {
|
|
496
|
-
rb_ca_obj2ptr(ca->self, INT2NUM(0), ptr);
|
|
645
|
+
if ( rb_obj_respond_to(ca->self, rb_intern("store_index"), Qtrue) ) {
|
|
646
|
+
ridx = rb_ary_new2(ca->ndim);
|
|
647
|
+
for (i=0; i<ca->ndim; i++) {
|
|
648
|
+
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
497
649
|
}
|
|
650
|
+
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
651
|
+
rb_funcall(ca->self, rb_intern("store_index"), 2, ridx, rval);
|
|
498
652
|
}
|
|
499
653
|
else {
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
654
|
+
ca_size_t addr = ca_index2addr(ca, idx);
|
|
655
|
+
raddr = SIZE2NUM(addr);
|
|
656
|
+
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
657
|
+
rb_funcall(ca->self, rb_intern("store_addr"), 2, raddr, rval);
|
|
504
658
|
}
|
|
505
659
|
}
|
|
506
660
|
}
|
|
507
661
|
|
|
508
662
|
static void
|
|
509
|
-
|
|
663
|
+
ca_object_func_allocate (void *ap)
|
|
510
664
|
{
|
|
511
665
|
CAObject *ca = (CAObject *) ap;
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
if (
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
666
|
+
/* ca->data->ptr = ALLOC_N(char, ca_length(ca)); */
|
|
667
|
+
ca->data->ptr = xmalloc(ca_length(ca));
|
|
668
|
+
if ( ca_is_object_type(ca->data) ) { /* GC safe */
|
|
669
|
+
VALUE *p = (VALUE *) ca->data->ptr;
|
|
670
|
+
VALUE zero = INT2NUM(0);
|
|
671
|
+
ca_size_t i;
|
|
672
|
+
for (i=0; i<ca->elements; i++) {
|
|
673
|
+
*p++ = zero;
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
ca->ptr = ca->data->ptr;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
/* ca_object_dispatch_{copy,sync,fill}: bulk-path entry points used by
|
|
680
|
+
func_attach / func_sync / func_{copy,sync,fill}_data.
|
|
681
|
+
|
|
682
|
+
Contract: prefer user-supplied bulk methods (copy_data / sync_data /
|
|
683
|
+
fill_data) when defined; otherwise fall back to per-element
|
|
684
|
+
fetch_addr / store_addr loops, which themselves dispatch through the
|
|
685
|
+
existing fetch_addr<->fetch_index and store_addr<->store_index mutual
|
|
686
|
+
fallback at line 418/471/523/546.
|
|
687
|
+
|
|
688
|
+
Net effect: a CAObject subclass that only defines fetch_addr (or
|
|
689
|
+
only fetch_index) becomes fully usable -- to_ca, attach, sync,
|
|
690
|
+
arithmetic all work via the slow per-element fallback. The fast bulk
|
|
691
|
+
path is opt-in by defining copy_data / sync_data / fill_data. */
|
|
692
|
+
|
|
693
|
+
static void
|
|
694
|
+
ca_object_dispatch_copy (CAObject *ca, void *ptr)
|
|
695
|
+
{
|
|
696
|
+
if ( rb_obj_respond_to(ca->self, rb_intern("copy_data"), Qtrue) ) {
|
|
697
|
+
char *ptr0 = ca->data->ptr;
|
|
698
|
+
ca->data->ptr = ptr;
|
|
699
|
+
rb_funcall(ca->self, rb_intern("copy_data"),
|
|
700
|
+
1, rb_ivar_get(ca->self, rb_intern("__data__")));
|
|
701
|
+
ca->data->ptr = ptr0;
|
|
518
702
|
}
|
|
519
703
|
else {
|
|
520
|
-
ca_size_t
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
704
|
+
ca_size_t addr;
|
|
705
|
+
char *base = (char *) ptr;
|
|
706
|
+
for ( addr = 0; addr < ca->elements; addr++ ) {
|
|
707
|
+
ca_object_xfer_addr_one(ca, addr, base + addr * ca->bytes, CA_XFER_GET);
|
|
525
708
|
}
|
|
526
|
-
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
527
|
-
rb_funcall(ca->self, rb_intern("store_index"), 2, ridx, rval);
|
|
528
709
|
}
|
|
529
710
|
}
|
|
530
711
|
|
|
531
712
|
static void
|
|
532
|
-
|
|
713
|
+
ca_object_dispatch_sync (CAObject *ca, void *ptr)
|
|
533
714
|
{
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
541
|
-
}
|
|
542
|
-
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
543
|
-
rb_funcall(ca->self, rb_intern("store_index"), 2, ridx, rval);
|
|
715
|
+
if ( rb_obj_respond_to(ca->self, rb_intern("sync_data"), Qtrue) ) {
|
|
716
|
+
char *ptr0 = ca->data->ptr;
|
|
717
|
+
ca->data->ptr = ptr;
|
|
718
|
+
rb_funcall(ca->self, rb_intern("sync_data"),
|
|
719
|
+
1, rb_ivar_get(ca->self, rb_intern("__data__")));
|
|
720
|
+
ca->data->ptr = ptr0;
|
|
544
721
|
}
|
|
545
722
|
else {
|
|
546
|
-
ca_size_t addr
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
723
|
+
ca_size_t addr;
|
|
724
|
+
char *base = (char *) ptr;
|
|
725
|
+
for ( addr = 0; addr < ca->elements; addr++ ) {
|
|
726
|
+
ca_object_xfer_addr_one(ca, addr, base + addr * ca->bytes, CA_XFER_PUT);
|
|
727
|
+
}
|
|
550
728
|
}
|
|
551
729
|
}
|
|
552
730
|
|
|
553
731
|
static void
|
|
554
|
-
|
|
732
|
+
ca_object_dispatch_fill (CAObject *ca, void *ptr)
|
|
555
733
|
{
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
*p++ = zero;
|
|
734
|
+
if ( rb_obj_respond_to(ca->self, rb_intern("fill_data"), Qtrue) ) {
|
|
735
|
+
volatile VALUE rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
736
|
+
rb_funcall(ca->self, rb_intern("fill_data"), 1, rval);
|
|
737
|
+
}
|
|
738
|
+
else {
|
|
739
|
+
ca_size_t addr;
|
|
740
|
+
for ( addr = 0; addr < ca->elements; addr++ ) {
|
|
741
|
+
ca_object_xfer_addr_one(ca, addr, ptr, CA_XFER_PUT);
|
|
565
742
|
}
|
|
566
743
|
}
|
|
567
|
-
ca->ptr = ca->data->ptr;
|
|
568
744
|
}
|
|
569
745
|
|
|
570
746
|
static void
|
|
571
747
|
ca_object_func_attach (void *ap)
|
|
572
748
|
{
|
|
573
749
|
CAObject *ca = (CAObject *) ap;
|
|
574
|
-
|
|
750
|
+
/* Face mode → thin-forward to parent (= bypass the Ruby callback; same
|
|
751
|
+
semantic as ca_face_* helpers; CAObject prefix == CAView prefix so
|
|
752
|
+
layout is compatible). */
|
|
753
|
+
if ( ca_is_face(ca) ) {
|
|
754
|
+
ca_face_attach(ap);
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
575
757
|
/* ca->data->ptr = ALLOC_N(char, ca_length(ca)); */
|
|
576
|
-
ca->data->ptr =
|
|
758
|
+
ca->data->ptr = xmalloc(ca_length(ca));
|
|
577
759
|
if ( ca_is_object_type(ca->data) ) { /* GC safe */
|
|
578
760
|
VALUE *p = (VALUE *) ca->data->ptr;
|
|
579
761
|
VALUE zero = INT2NUM(0);
|
|
@@ -582,8 +764,8 @@ ca_object_func_attach (void *ap)
|
|
|
582
764
|
*p++ = zero;
|
|
583
765
|
}
|
|
584
766
|
}
|
|
585
|
-
ca->ptr = ca->data->ptr;
|
|
586
|
-
|
|
767
|
+
ca->ptr = ca->data->ptr;
|
|
768
|
+
ca_object_dispatch_copy(ca, ca->ptr);
|
|
587
769
|
if ( ca_has_mask(ca->data) ) {
|
|
588
770
|
ca_update_mask(ca);
|
|
589
771
|
if ( ! ca->mask ) {
|
|
@@ -596,48 +778,227 @@ static void
|
|
|
596
778
|
ca_object_func_sync (void *ap)
|
|
597
779
|
{
|
|
598
780
|
CAObject *ca = (CAObject *) ap;
|
|
599
|
-
|
|
600
|
-
|
|
781
|
+
if ( ca_is_face(ca) ) {
|
|
782
|
+
ca_face_sync(ap);
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
ca_object_dispatch_sync(ca, ca->data->ptr);
|
|
601
786
|
}
|
|
602
787
|
|
|
603
788
|
static void
|
|
604
789
|
ca_object_func_detach (void *ap)
|
|
605
790
|
{
|
|
606
791
|
CAObject *ca = (CAObject *) ap;
|
|
607
|
-
|
|
792
|
+
if ( ca_is_face(ca) ) {
|
|
793
|
+
ca_face_detach(ap);
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
xfree(ca->data->ptr);
|
|
608
797
|
ca->data->ptr = NULL;
|
|
609
798
|
ca->ptr = NULL;
|
|
610
799
|
}
|
|
611
800
|
|
|
801
|
+
/* xfer_*: CAObject is a per-element Ruby callback bridge -- a never-fold
|
|
802
|
+
boundary with no axis structure. GC
|
|
803
|
+
protection (cyclic + rb_protect on GET) for CA_OBJECT element type is
|
|
804
|
+
supplied by the central ca_xfer_* dispatchers, so these per-cell loops run
|
|
805
|
+
raw. */
|
|
806
|
+
|
|
807
|
+
/* Build a transient borrowed-buffer CArray for partial-region callbacks.
|
|
808
|
+
|
|
809
|
+
Used by ca_object_func_xfer_{stride,addrs} (and mask variants) to wrap the
|
|
810
|
+
slot's `data` buffer in a Ruby-visible CArray (counts-shape for block,
|
|
811
|
+
[n] for addrs) before invoking copy_block / sync_block / copy_addrs /
|
|
812
|
+
sync_addrs. Lifecycle: buffer is owned by the slot caller; the wrapper
|
|
813
|
+
installs free_ca_wrap as dfree, so the underlying ptr is NOT freed when
|
|
814
|
+
the wrapper is GC'd.
|
|
815
|
+
|
|
816
|
+
Object data_type GC safety: for GET (dir == CA_XFER_GET) the buffer may be
|
|
817
|
+
uninitialized garbage on entry, so we INT2NUM(0) zero-fill before
|
|
818
|
+
wrapping (same idiom as ca_object_func_allocate). PUT entries are
|
|
819
|
+
already valid VALUEs and need no init. */
|
|
820
|
+
static VALUE
|
|
821
|
+
ca_object_wrap_transient (int8_t data_type, ca_size_t bytes,
|
|
822
|
+
int8_t ndim, ca_size_t *dim, void *data, int dir)
|
|
823
|
+
{
|
|
824
|
+
CAWrap *wrap;
|
|
825
|
+
ca_size_t n = 1, i;
|
|
826
|
+
|
|
827
|
+
for ( i = 0; i < ndim; i++ ) n *= dim[i];
|
|
828
|
+
|
|
829
|
+
if ( dir == CA_XFER_GET && data_type == CA_OBJECT ) {
|
|
830
|
+
VALUE *p = (VALUE *) data;
|
|
831
|
+
VALUE zero = INT2NUM(0);
|
|
832
|
+
for ( i = 0; i < n; i++ ) p[i] = zero;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
wrap = ca_wrap_new(data_type, ndim, dim, bytes, NULL, (char *) data);
|
|
836
|
+
return ca_wrap_struct(wrap);
|
|
837
|
+
}
|
|
838
|
+
|
|
612
839
|
static void
|
|
613
|
-
|
|
840
|
+
ca_object_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
614
841
|
{
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
ca->data->ptr = ptr0;
|
|
842
|
+
if ( ca_is_face((CAObject *) ap) ) {
|
|
843
|
+
ca_face_xfer_index(ap, idx, data, dir);
|
|
844
|
+
return;
|
|
845
|
+
}
|
|
846
|
+
ca_object_xfer_index_one((CAObject *) ap, idx, data, dir);
|
|
621
847
|
}
|
|
622
848
|
|
|
849
|
+
/* Bulk-addrs path. When `copy_addrs` / `sync_addrs` is defined, dispatch
|
|
850
|
+
the entire address list in one Ruby call (1-D transient wrappers for
|
|
851
|
+
addrs and data). Otherwise fall back to a per-cell loop. */
|
|
623
852
|
static void
|
|
624
|
-
|
|
853
|
+
ca_object_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
854
|
+
void *data, int dir)
|
|
625
855
|
{
|
|
626
|
-
CAObject
|
|
627
|
-
|
|
628
|
-
ca
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
856
|
+
CAObject *ca = (CAObject *) ap;
|
|
857
|
+
ID mid;
|
|
858
|
+
if ( ca_is_face(ca) ) {
|
|
859
|
+
ca_face_xfer_addrs(ap, n, addrs, data, dir);
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
862
|
+
mid = (dir == CA_XFER_GET) ? rb_intern("copy_addrs")
|
|
863
|
+
: rb_intern("sync_addrs");
|
|
864
|
+
|
|
865
|
+
if ( n > 0 && rb_obj_respond_to(ca->self, mid, Qtrue) ) {
|
|
866
|
+
volatile VALUE raddrs, rdata;
|
|
867
|
+
ca_size_t dim1[1] = { n };
|
|
868
|
+
raddrs = ca_object_wrap_transient(CA_SIZE, sizeof(ca_size_t),
|
|
869
|
+
1, dim1, addrs, CA_XFER_PUT);
|
|
870
|
+
rdata = ca_object_wrap_transient(ca->data_type, ca->bytes,
|
|
871
|
+
1, dim1, data, dir);
|
|
872
|
+
rb_funcall(ca->self, mid, 2, raddrs, rdata);
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
{
|
|
877
|
+
char *d = (char *) data;
|
|
878
|
+
ca_size_t i;
|
|
879
|
+
for ( i = 0; i < n; i++ ) {
|
|
880
|
+
ca_object_xfer_addr_one(ca, addrs[i], d + i * ca->bytes, dir);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
/* Partial-region dispatch.
|
|
886
|
+
|
|
887
|
+
Gate: if `copy_block` / `sync_block` is defined AND all per-axis byte
|
|
888
|
+
strides represent an order-preserving, step >= 1 sub-region of self
|
|
889
|
+
(i.e. strides[k] > 0 && strides[k] % native[k] == 0), invoke the
|
|
890
|
+
high-level callback with index-space (starts, counts, steps) and a
|
|
891
|
+
counts-shaped transient. Empty region (any counts[k] == 0) returns
|
|
892
|
+
early without invoking the callback. Otherwise (negative/zero/non-
|
|
893
|
+
aligned strides, or callback undefined) fall back to flat-addr
|
|
894
|
+
expansion -> xfer_addrs (which itself may dispatch to copy_addrs /
|
|
895
|
+
sync_addrs if defined, else per-cell).
|
|
896
|
+
|
|
897
|
+
Gate proof: gate passes => for all k, strides[k] = m_k *
|
|
898
|
+
native[k] with m_k >= 1. If block axis k mapped to self axis pi(k),
|
|
899
|
+
strides[k] = native[pi(k)] would force native[pi(k)] >= native[k] hence
|
|
900
|
+
pi(k) <= k for all k. native is strictly decreasing in k, so the only
|
|
901
|
+
permutation satisfying pi(k) <= k for all k is identity. Therefore gate
|
|
902
|
+
passage <=> each block axis k traverses self axis k with step m_k.
|
|
903
|
+
Transpose / fancy / sub-element / negative / zero stride all fail the
|
|
904
|
+
gate and route to addrs path. */
|
|
905
|
+
static void
|
|
906
|
+
ca_object_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
907
|
+
ca_size_t *strides, void *data, int dir)
|
|
908
|
+
{
|
|
909
|
+
CAObject *ca = (CAObject *) ap;
|
|
910
|
+
int8_t ndim;
|
|
911
|
+
ca_size_t native[CA_RANK_MAX], steps[CA_RANK_MAX], idx[CA_RANK_MAX];
|
|
912
|
+
ca_size_t *vaddrs;
|
|
913
|
+
ca_size_t base = 0, n = 1, i, s;
|
|
914
|
+
int8_t k;
|
|
915
|
+
volatile VALUE holder;
|
|
916
|
+
ID mid_block;
|
|
917
|
+
|
|
918
|
+
if ( ca_is_face(ca) ) {
|
|
919
|
+
ca_face_xfer_stride(ap, starts, counts, strides, data, dir);
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
ndim = ca->ndim;
|
|
924
|
+
mid_block = (dir == CA_XFER_GET) ? rb_intern("copy_block")
|
|
925
|
+
: rb_intern("sync_block");
|
|
926
|
+
|
|
927
|
+
s = ca->bytes;
|
|
928
|
+
for (k = ndim - 1; k >= 0; k--) { native[k] = s; s *= ca->dim[k]; }
|
|
929
|
+
for (k = 0; k < ndim; k++) { base += starts[k] * native[k]; n *= counts[k]; }
|
|
930
|
+
|
|
931
|
+
/* empty region: nothing to transfer */
|
|
932
|
+
if ( n == 0 ) return;
|
|
933
|
+
|
|
934
|
+
/* gate:
|
|
935
|
+
- reject strides[k] <= 0 (negative / zero broadcast)
|
|
936
|
+
- C99 makes (-native) % native == 0 true, so we must reject <= 0
|
|
937
|
+
before the % check
|
|
938
|
+
- given %==0 + >0, strides/native >= 1 holds automatically */
|
|
939
|
+
if ( rb_obj_respond_to(ca->self, mid_block, Qtrue) ) {
|
|
940
|
+
int aligned = 1;
|
|
941
|
+
for ( k = 0; k < ndim; k++ ) {
|
|
942
|
+
if ( strides[k] <= 0 || strides[k] % native[k] != 0 ) { aligned = 0; break; }
|
|
943
|
+
steps[k] = strides[k] / native[k]; /* >= 1 by construction */
|
|
944
|
+
}
|
|
945
|
+
if ( aligned ) {
|
|
946
|
+
/* high-level per-axis sub-region: dispatch copy_block / sync_block */
|
|
947
|
+
volatile VALUE rstarts, rcounts, rsteps, rdata;
|
|
948
|
+
rstarts = rb_ary_new_capa(ndim);
|
|
949
|
+
rcounts = rb_ary_new_capa(ndim);
|
|
950
|
+
rsteps = rb_ary_new_capa(ndim);
|
|
951
|
+
for ( k = 0; k < ndim; k++ ) {
|
|
952
|
+
rb_ary_push(rstarts, SIZE2NUM(starts[k]));
|
|
953
|
+
rb_ary_push(rcounts, SIZE2NUM(counts[k]));
|
|
954
|
+
rb_ary_push(rsteps, SIZE2NUM(steps[k]));
|
|
955
|
+
}
|
|
956
|
+
rdata = ca_object_wrap_transient(ca->data_type, ca->bytes,
|
|
957
|
+
ndim, counts, data, dir);
|
|
958
|
+
rb_funcall(ca->self, mid_block, 4, rstarts, rcounts, rsteps, rdata);
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
/* fallback: flat-addr expansion -> xfer_addrs (per-cell or copy_addrs).
|
|
964
|
+
Handles negative strides, zero stride (broadcast), sub-element, and
|
|
965
|
+
fancy permutations. Same body as the non-block path. */
|
|
966
|
+
vaddrs = ALLOCV_N(ca_size_t, holder, n);
|
|
967
|
+
for (k = 0; k < ndim; k++) idx[k] = 0;
|
|
968
|
+
for (i = 0; i < n; i++) {
|
|
969
|
+
ca_size_t off = base;
|
|
970
|
+
for (k = 0; k < ndim; k++) off += idx[k] * strides[k];
|
|
971
|
+
vaddrs[i] = off / ca->bytes;
|
|
972
|
+
k = ndim - 1;
|
|
973
|
+
while (k >= 0) { if (++idx[k] < counts[k]) break; idx[k] = 0; k--; }
|
|
974
|
+
}
|
|
975
|
+
ca_object_func_xfer_addrs(ca, n, vaddrs, data, dir);
|
|
976
|
+
ALLOCV_END(holder);
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
static void
|
|
980
|
+
ca_object_func_xfer_all (void *ap, void *data, int dir)
|
|
981
|
+
{
|
|
982
|
+
if ( ca_is_face((CAObject *) ap) ) {
|
|
983
|
+
ca_face_xfer_all(ap, data, dir);
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
if ( dir == CA_XFER_GET ) {
|
|
987
|
+
ca_object_dispatch_copy((CAObject *) ap, data);
|
|
988
|
+
}
|
|
989
|
+
else {
|
|
990
|
+
ca_object_dispatch_sync((CAObject *) ap, data);
|
|
991
|
+
}
|
|
632
992
|
}
|
|
633
993
|
|
|
634
994
|
static void
|
|
635
995
|
ca_object_func_fill_data (void *ap, void *ptr)
|
|
636
996
|
{
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
997
|
+
if ( ca_is_face((CAObject *) ap) ) {
|
|
998
|
+
ca_face_fill_data(ap, ptr);
|
|
999
|
+
return;
|
|
1000
|
+
}
|
|
1001
|
+
ca_object_dispatch_fill((CAObject *) ap, ptr);
|
|
641
1002
|
}
|
|
642
1003
|
|
|
643
1004
|
static void
|
|
@@ -645,6 +1006,18 @@ ca_object_func_create_mask (void *ap)
|
|
|
645
1006
|
{
|
|
646
1007
|
CAObject *ca = (CAObject *) ap;
|
|
647
1008
|
volatile VALUE rmask;
|
|
1009
|
+
if ( ca_is_face(ca) ) {
|
|
1010
|
+
/* Face: the mask refers to the parent's mask (same as the C-level Face
|
|
1011
|
+
create_mask, e.g. ca_time_func_create_mask). Storage is the
|
|
1012
|
+
parent, so the mask must be the parent's, not the internal __data__. */
|
|
1013
|
+
ca_update_mask(ca->parent);
|
|
1014
|
+
if ( ! ca->parent->mask ) {
|
|
1015
|
+
ca_create_mask(ca->parent);
|
|
1016
|
+
}
|
|
1017
|
+
ca->mask = (CArray *) ca_refer_new(ca->parent->mask,
|
|
1018
|
+
CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
648
1021
|
if ( rb_obj_respond_to(ca->self, rb_intern("create_mask"), Qtrue) ) {
|
|
649
1022
|
rb_funcall(ca->self, rb_intern("create_mask"), 0);
|
|
650
1023
|
}
|
|
@@ -663,23 +1036,20 @@ ca_object_func_create_mask (void *ap)
|
|
|
663
1036
|
|
|
664
1037
|
ca_operation_function_t ca_object_func = {
|
|
665
1038
|
-1, /* CA_OBJ_OBJECT */
|
|
666
|
-
|
|
1039
|
+
CA_VIEW_ARRAY,
|
|
667
1040
|
free_ca_object,
|
|
668
1041
|
ca_object_func_clone,
|
|
669
|
-
ca_object_func_ptr_at_addr,
|
|
670
|
-
ca_object_func_ptr_at_index,
|
|
671
|
-
ca_object_func_fetch_addr,
|
|
672
|
-
ca_object_func_fetch_index,
|
|
673
|
-
ca_object_func_store_addr,
|
|
674
|
-
ca_object_func_store_index,
|
|
675
1042
|
ca_object_func_allocate,
|
|
676
1043
|
ca_object_func_attach,
|
|
677
1044
|
ca_object_func_sync,
|
|
678
1045
|
ca_object_func_detach,
|
|
679
|
-
ca_object_func_copy_data,
|
|
680
|
-
ca_object_func_sync_data,
|
|
681
1046
|
ca_object_func_fill_data,
|
|
682
1047
|
ca_object_func_create_mask,
|
|
1048
|
+
ca_object_func_xfer_index,
|
|
1049
|
+
ca_object_func_xfer_addrs,
|
|
1050
|
+
NULL, /* fold_stride: never-fold (callback boundary) */
|
|
1051
|
+
ca_object_func_xfer_stride,
|
|
1052
|
+
ca_object_func_xfer_all,
|
|
683
1053
|
};
|
|
684
1054
|
|
|
685
1055
|
/* ------------------------------------------------------------------- */
|
|
@@ -688,7 +1058,7 @@ static VALUE
|
|
|
688
1058
|
rb_ca_object_s_allocate (VALUE klass)
|
|
689
1059
|
{
|
|
690
1060
|
CAObject *ca;
|
|
691
|
-
return
|
|
1061
|
+
return TypedData_Make_Struct(klass, CAObject, &caobject_data_type, ca);
|
|
692
1062
|
}
|
|
693
1063
|
|
|
694
1064
|
static VALUE
|
|
@@ -700,13 +1070,28 @@ rb_ca_object_initialize_copy (VALUE self, VALUE other)
|
|
|
700
1070
|
TypedData_Get_Struct(self, CAObject, &caobject_data_type, ca);
|
|
701
1071
|
TypedData_Get_Struct(other, CAObject, &caobject_data_type, cs);
|
|
702
1072
|
|
|
1073
|
+
if ( ca_func[CA_OBJ_OBJECT].pool_init ) {
|
|
1074
|
+
ca_array_pool_alloc(ca, CA_OBJ_OBJECT, cs->ndim);
|
|
1075
|
+
}
|
|
703
1076
|
ca_object_setup(ca, cs->data_type, cs->ndim, cs->dim, cs->bytes);
|
|
704
1077
|
ca->self = self;
|
|
705
1078
|
|
|
706
|
-
|
|
1079
|
+
/* preserve flags (e.g. CA_FLAG_READ_ONLY) and structural parent;
|
|
1080
|
+
ca_object_setup zeroed both, so restore from the source.
|
|
1081
|
+
Copy the @parent ivar directly rather than via rb_ca_set_parent --
|
|
1082
|
+
the latter would re-freeze self when parent is frozen, but
|
|
1083
|
+
dup/clone semantics for freezing are handled separately by Ruby. */
|
|
1084
|
+
ca->flags = cs->flags;
|
|
1085
|
+
ca->parent = cs->parent;
|
|
1086
|
+
if ( cs->parent ) {
|
|
1087
|
+
volatile VALUE rparent = rb_ivar_get(other, rb_intern("parent"));
|
|
1088
|
+
if ( ! NIL_P(rparent) ) {
|
|
1089
|
+
rb_ivar_set(self, rb_intern("parent"), rparent);
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
|
|
707
1093
|
|
|
708
1094
|
data = ca_wrap_struct(ca->data);
|
|
709
|
-
rb_ca_data_type_inherit(data, self);
|
|
710
1095
|
rb_ivar_set(self, rb_intern("__data__"), data);
|
|
711
1096
|
|
|
712
1097
|
ca_update_mask(cs);
|
|
@@ -722,7 +1107,9 @@ rb_ca_object_initialize_copy (VALUE self, VALUE other)
|
|
|
722
1107
|
static VALUE
|
|
723
1108
|
rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
724
1109
|
{
|
|
725
|
-
volatile VALUE rtype, rdim, ropt, rbytes = Qnil, rrdonly = Qnil,
|
|
1110
|
+
volatile VALUE rtype, rdim, ropt, rbytes = Qnil, rrdonly = Qnil,
|
|
1111
|
+
rparent = Qnil, rface = Qnil, rstorage = Qnil, rdata,
|
|
1112
|
+
rorderable = Qnil, rcomparable = Qnil;
|
|
726
1113
|
CAObject *ca;
|
|
727
1114
|
int8_t data_type, ndim;
|
|
728
1115
|
ca_size_t dim[CA_RANK_MAX];
|
|
@@ -730,15 +1117,47 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
730
1117
|
int i;
|
|
731
1118
|
|
|
732
1119
|
rb_scan_args(argc, argv, "21", (VALUE *) &rtype, (VALUE *) &rdim, (VALUE *) &ropt);
|
|
733
|
-
rb_scan_options(ropt, "bytes,read_only,parent",
|
|
734
|
-
&rbytes, &rrdonly, &rparent
|
|
1120
|
+
rb_scan_options(ropt, "bytes,read_only,parent,face,storage,orderable_storage,comparable_storage",
|
|
1121
|
+
&rbytes, &rrdonly, &rparent, &rface, &rstorage,
|
|
1122
|
+
&rorderable, &rcomparable);
|
|
735
1123
|
|
|
736
|
-
if ( ( ! NIL_P(rparent) ) && rb_obj_is_carray(rparent) ) {
|
|
1124
|
+
if ( ( ! NIL_P(rparent) ) && ( ! rb_obj_is_carray(rparent) ) ) {
|
|
737
1125
|
rb_raise(rb_eRuntimeError, "option :parent should be a carray");
|
|
738
1126
|
}
|
|
739
1127
|
|
|
1128
|
+
/* :storage is meaningful only under face: true (= it documents the
|
|
1129
|
+
parent's storage data_type, which is otherwise inferred from
|
|
1130
|
+
parent.data_type). Reject misuse loudly so the contract is explicit. */
|
|
1131
|
+
if ( ! NIL_P(rstorage) && ! RTEST(rface) ) {
|
|
1132
|
+
rb_raise(rb_eArgError,
|
|
1133
|
+
"CAObject: :storage is only meaningful with face: true "
|
|
1134
|
+
"(use the data_type argument for non-Face CAObject)");
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
/* Face ordering/search opt-in: a Ruby-defined Face wires the C flags via
|
|
1138
|
+
these kwargs instead of a Ruby callback, so a Face can still be
|
|
1139
|
+
authored C-only. Both are meaningful only under face: true. */
|
|
1140
|
+
if ( ( RTEST(rorderable) || RTEST(rcomparable) ) && ! RTEST(rface) ) {
|
|
1141
|
+
rb_raise(rb_eArgError,
|
|
1142
|
+
"CAObject: :orderable_storage / :comparable_storage are only "
|
|
1143
|
+
"meaningful with face: true");
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
/* face: true requires :parent. Under Face semantics the parent is the
|
|
1147
|
+
true storage owner and CAObject itself carries the semantic identity.
|
|
1148
|
+
The declared data_type is the SURFACE (= what dispatch sees);
|
|
1149
|
+
parent.data_type is the STORAGE. They may differ (= NonNumeric Face
|
|
1150
|
+
declares surface = CA_FIXLEN to gate mkkernel numeric ops while
|
|
1151
|
+
storage stays e.g. int64). */
|
|
1152
|
+
if ( RTEST(rface) ) {
|
|
1153
|
+
if ( NIL_P(rparent) ) {
|
|
1154
|
+
rb_raise(rb_eArgError,
|
|
1155
|
+
"CAObject Face mode (= face: true) requires :parent option "
|
|
1156
|
+
"(= storage CArray)");
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
|
|
740
1160
|
rb_ca_guess_type_and_bytes(rtype, rbytes, &data_type, &bytes);
|
|
741
|
-
rb_ca_data_type_import(self, rtype);
|
|
742
1161
|
|
|
743
1162
|
Check_Type(rdim, T_ARRAY);
|
|
744
1163
|
|
|
@@ -752,7 +1171,6 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
752
1171
|
ca->self = self;
|
|
753
1172
|
|
|
754
1173
|
rdata = ca_wrap_struct(ca->data);
|
|
755
|
-
rb_ca_data_type_inherit(rdata, self);
|
|
756
1174
|
|
|
757
1175
|
rb_ivar_set(self, rb_intern("__data__"), rdata);
|
|
758
1176
|
|
|
@@ -765,22 +1183,72 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
765
1183
|
TypedData_Get_Struct(rparent, CArray, &carray_data_type, cp);
|
|
766
1184
|
ca->parent = cp;
|
|
767
1185
|
rb_ca_set_parent(self, rparent);
|
|
1186
|
+
|
|
1187
|
+
/* Face mode invariants. The check the author opts into depends on
|
|
1188
|
+
whether :storage is explicit:
|
|
1189
|
+
- :storage omitted → "surface == storage" contract:
|
|
1190
|
+
surface (= declared data_type) must equal
|
|
1191
|
+
parent.data_type. This catches typos for
|
|
1192
|
+
Numeric Face authors who didn't intend
|
|
1193
|
+
surface/storage to differ.
|
|
1194
|
+
- :storage given → "surface != storage" opted-in:
|
|
1195
|
+
surface is free (= e.g. CA_FIXLEN for
|
|
1196
|
+
NonNumeric Face), :storage must agree with
|
|
1197
|
+
parent.data_type, and bytes must match. */
|
|
1198
|
+
if ( RTEST(rface) ) {
|
|
1199
|
+
if ( bytes != cp->bytes ) {
|
|
1200
|
+
rb_raise(rb_eTypeError,
|
|
1201
|
+
"CAObject Face: bytes mismatch "
|
|
1202
|
+
"(declared=%lld, parent=%lld)",
|
|
1203
|
+
(long long) bytes, (long long) cp->bytes);
|
|
1204
|
+
}
|
|
1205
|
+
if ( NIL_P(rstorage) ) {
|
|
1206
|
+
/* surface == storage contract */
|
|
1207
|
+
if ( cp->data_type != data_type ) {
|
|
1208
|
+
rb_raise(rb_eTypeError,
|
|
1209
|
+
"CAObject Face: parent data_type mismatch "
|
|
1210
|
+
"(declared=%d, parent=%d). Use :storage option to "
|
|
1211
|
+
"opt into surface != storage (NonNumeric Face).",
|
|
1212
|
+
(int) data_type, (int) cp->data_type);
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
else {
|
|
1216
|
+
/* opted-in surface != storage: validate :storage against parent */
|
|
1217
|
+
int8_t declared_storage;
|
|
1218
|
+
ca_size_t declared_storage_bytes;
|
|
1219
|
+
rb_ca_guess_type_and_bytes(rstorage, Qnil,
|
|
1220
|
+
&declared_storage, &declared_storage_bytes);
|
|
1221
|
+
if ( cp->data_type != declared_storage ) {
|
|
1222
|
+
rb_raise(rb_eTypeError,
|
|
1223
|
+
"CAObject Face: :storage mismatch "
|
|
1224
|
+
"(declared=%d, parent.data_type=%d)",
|
|
1225
|
+
(int) declared_storage, (int) cp->data_type);
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
ca_set_flag(ca, CA_FLAG_IS_FACE);
|
|
1229
|
+
if ( RTEST(rorderable) ) {
|
|
1230
|
+
ca_set_flag(ca, CA_FLAG_FACE_ORDERABLE_STORAGE);
|
|
1231
|
+
}
|
|
1232
|
+
if ( RTEST(rcomparable) ) {
|
|
1233
|
+
ca_set_flag(ca, CA_FLAG_FACE_COMPARABLE_STORAGE);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
768
1236
|
}
|
|
769
|
-
|
|
1237
|
+
|
|
770
1238
|
ca_update_mask(ca);
|
|
771
1239
|
|
|
772
1240
|
return Qnil;
|
|
773
1241
|
}
|
|
774
1242
|
|
|
775
1243
|
void
|
|
776
|
-
Init_ca_obj_object ()
|
|
1244
|
+
Init_ca_obj_object (void)
|
|
777
1245
|
{
|
|
778
1246
|
rb_cCAObjectMask = rb_define_class("CAObjectMask", rb_cCArray);
|
|
779
1247
|
|
|
780
1248
|
CA_OBJ_OBJECT_MASK = ca_install_obj_type(rb_cCAObjectMask,
|
|
781
1249
|
&caobjectmask_data_type,
|
|
782
1250
|
rb_cCArrayMask,
|
|
783
|
-
&carray_data_type, ca_objmask_func);
|
|
1251
|
+
&carray_data_type, &ca_objmask_func, sizeof(ca_objmask_func));
|
|
784
1252
|
rb_define_const(rb_cObject, "CA_OBJ_OBJECT_MASK", INT2NUM(CA_OBJ_OBJECT_MASK));
|
|
785
1253
|
|
|
786
1254
|
rb_define_alloc_func(rb_cCAObjectMask, rb_ca_objmask_s_allocate);
|
|
@@ -790,6 +1258,14 @@ Init_ca_obj_object ()
|
|
|
790
1258
|
|
|
791
1259
|
rb_define_const(rb_cObject, "CA_OBJ_OBJECT", INT2NUM(CA_OBJ_OBJECT));
|
|
792
1260
|
|
|
1261
|
+
/* CA_OBJ_OBJECT is a builtin obj_type: carray_core.c assigned
|
|
1262
|
+
ca_func[CA_OBJ_OBJECT] = ca_object_func (without pool hooks) before
|
|
1263
|
+
this runs. Override the three pool slots in place (same pattern as
|
|
1264
|
+
CABlock overriding the CAStride baseline). */
|
|
1265
|
+
ca_func[CA_OBJ_OBJECT].struct_size = sizeof(CAObject);
|
|
1266
|
+
ca_func[CA_OBJ_OBJECT].pool_bytes = ca_object_pool_bytes;
|
|
1267
|
+
ca_func[CA_OBJ_OBJECT].pool_init = ca_object_pool_init;
|
|
1268
|
+
|
|
793
1269
|
rb_define_alloc_func(rb_cCAObject, rb_ca_object_s_allocate);
|
|
794
1270
|
rb_define_method(rb_cCAObject, "initialize_copy",
|
|
795
1271
|
rb_ca_object_initialize_copy, 1);
|