carray 2.0.1 → 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 +772 -297
- 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 +229 -791
- 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 +207 -240
- 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 -329
- 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 +1341 -198
- 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 +5 -15
- 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/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,146 @@ 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
|
+
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
|
+
}
|
|
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--; }
|
|
276
385
|
}
|
|
386
|
+
ca_objmask_func_xfer_addrs(ca, n, vaddrs, data, dir);
|
|
387
|
+
ALLOCV_END(holder);
|
|
277
388
|
}
|
|
278
389
|
|
|
279
390
|
static ca_operation_function_t ca_objmask_func = {
|
|
@@ -281,27 +392,24 @@ static ca_operation_function_t ca_objmask_func = {
|
|
|
281
392
|
CA_REAL_ARRAY,
|
|
282
393
|
free_ca_wrap,
|
|
283
394
|
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
395
|
ca_array_func_allocate,
|
|
291
396
|
ca_objmask_func_attach,
|
|
292
397
|
ca_objmask_func_sync,
|
|
293
398
|
ca_array_func_detach,
|
|
294
|
-
ca_objmask_func_copy_data,
|
|
295
|
-
ca_objmask_func_sync_data,
|
|
296
399
|
ca_objmask_func_fill_data,
|
|
297
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,
|
|
298
406
|
};
|
|
299
407
|
|
|
300
408
|
static VALUE
|
|
301
409
|
rb_ca_objmask_s_allocate (VALUE klass)
|
|
302
410
|
{
|
|
303
411
|
CAObjectMask *ca;
|
|
304
|
-
return TypedData_Make_Struct(klass, CAObjectMask, &
|
|
412
|
+
return TypedData_Make_Struct(klass, CAObjectMask, &caobjectmask_data_type, ca);
|
|
305
413
|
}
|
|
306
414
|
|
|
307
415
|
static VALUE
|
|
@@ -361,7 +469,9 @@ ca_object_setup (CAObject *ca,
|
|
|
361
469
|
ca->attach = 0;
|
|
362
470
|
ca->nosync = 0;
|
|
363
471
|
|
|
364
|
-
ca->
|
|
472
|
+
if ( ! ca->_pool ) {
|
|
473
|
+
ca->dim = ALLOC_N(ca_size_t, ndim);
|
|
474
|
+
}
|
|
365
475
|
|
|
366
476
|
ca->data = ca_wrap_new_null(data_type, ndim, dim, bytes, NULL);
|
|
367
477
|
|
|
@@ -373,7 +483,7 @@ ca_object_setup (CAObject *ca,
|
|
|
373
483
|
static CAObject *
|
|
374
484
|
ca_object_new (int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes)
|
|
375
485
|
{
|
|
376
|
-
CAObject *ca =
|
|
486
|
+
CAObject *ca = (CAObject *) ca_array_alloc(CA_OBJ_OBJECT, ndim);
|
|
377
487
|
ca_object_setup(ca, data_type, ndim, dim, bytes);
|
|
378
488
|
return ca;
|
|
379
489
|
}
|
|
@@ -384,8 +494,13 @@ free_ca_object (void *ap)
|
|
|
384
494
|
CAObject *ca = (CAObject *) ap;
|
|
385
495
|
if ( ca != NULL ) {
|
|
386
496
|
/* ca->mask will be GC-ed by Ruby interpreter */
|
|
387
|
-
|
|
388
|
-
|
|
497
|
+
if ( ca->_pool ) {
|
|
498
|
+
ca_array_free(ca); /* dim lives in _pool */
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
xfree(ca->dim);
|
|
502
|
+
xfree(ca);
|
|
503
|
+
}
|
|
389
504
|
}
|
|
390
505
|
}
|
|
391
506
|
|
|
@@ -395,186 +510,252 @@ static void *
|
|
|
395
510
|
ca_object_func_clone (void *ap)
|
|
396
511
|
{
|
|
397
512
|
CAObject *ca = (CAObject *) ap;
|
|
398
|
-
return ca_object_new(ca->
|
|
513
|
+
return ca_object_new(ca->data_type, ca->ndim, ca->dim, ca->bytes);
|
|
399
514
|
}
|
|
400
515
|
|
|
401
516
|
#define ca_object_func_ptr_at_addr ca_array_func_ptr_at_addr
|
|
402
517
|
#define ca_object_func_ptr_at_index ca_array_func_ptr_at_index
|
|
403
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. */
|
|
404
522
|
static void
|
|
405
|
-
|
|
523
|
+
ca_object_xfer_addr_one (CAObject *ca, ca_size_t addr, void *ptr, int dir)
|
|
406
524
|
{
|
|
407
|
-
CAObject *ca = (CAObject *) ap;
|
|
408
525
|
volatile VALUE ridx, raddr, rval;
|
|
409
526
|
int i;
|
|
410
|
-
if (
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
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
|
+
}
|
|
417
540
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
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);
|
|
421
546
|
}
|
|
422
547
|
}
|
|
423
548
|
else {
|
|
424
|
-
|
|
425
|
-
|
|
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);
|
|
426
571
|
}
|
|
427
|
-
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
428
572
|
}
|
|
429
573
|
}
|
|
430
574
|
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
|
-
}
|
|
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);
|
|
447
579
|
}
|
|
448
580
|
else {
|
|
449
|
-
|
|
450
|
-
|
|
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]));
|
|
451
586
|
}
|
|
452
|
-
|
|
587
|
+
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
588
|
+
rb_funcall(ca->self, rb_intern("store_index"), 2, ridx, rval);
|
|
453
589
|
}
|
|
454
590
|
}
|
|
455
591
|
}
|
|
456
592
|
|
|
457
593
|
static void
|
|
458
|
-
|
|
594
|
+
ca_object_xfer_index_one (CAObject *ca, ca_size_t *idx, void *ptr, int dir)
|
|
459
595
|
{
|
|
460
|
-
CAObject *ca = (CAObject *) ap;
|
|
461
596
|
volatile VALUE ridx, raddr, rval;
|
|
462
597
|
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);
|
|
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]));
|
|
473
603
|
}
|
|
474
|
-
|
|
475
|
-
if (
|
|
476
|
-
|
|
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
|
+
}
|
|
614
|
+
}
|
|
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);
|
|
477
620
|
}
|
|
478
621
|
}
|
|
479
622
|
else {
|
|
480
|
-
|
|
481
|
-
|
|
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);
|
|
482
641
|
}
|
|
483
|
-
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
484
642
|
}
|
|
485
643
|
}
|
|
486
644
|
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);
|
|
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]));
|
|
498
649
|
}
|
|
650
|
+
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
651
|
+
rb_funcall(ca->self, rb_intern("store_index"), 2, ridx, rval);
|
|
499
652
|
}
|
|
500
653
|
else {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
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);
|
|
505
658
|
}
|
|
506
659
|
}
|
|
507
660
|
}
|
|
508
661
|
|
|
509
662
|
static void
|
|
510
|
-
|
|
663
|
+
ca_object_func_allocate (void *ap)
|
|
511
664
|
{
|
|
512
665
|
CAObject *ca = (CAObject *) ap;
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
if (
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
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;
|
|
519
702
|
}
|
|
520
703
|
else {
|
|
521
|
-
ca_size_t
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
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);
|
|
526
708
|
}
|
|
527
|
-
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
528
|
-
rb_funcall(ca->self, rb_intern("store_index"), 2, ridx, rval);
|
|
529
709
|
}
|
|
530
710
|
}
|
|
531
711
|
|
|
532
712
|
static void
|
|
533
|
-
|
|
713
|
+
ca_object_dispatch_sync (CAObject *ca, void *ptr)
|
|
534
714
|
{
|
|
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);
|
|
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;
|
|
545
721
|
}
|
|
546
722
|
else {
|
|
547
|
-
ca_size_t addr
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
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
|
+
}
|
|
551
728
|
}
|
|
552
729
|
}
|
|
553
730
|
|
|
554
731
|
static void
|
|
555
|
-
|
|
732
|
+
ca_object_dispatch_fill (CAObject *ca, void *ptr)
|
|
556
733
|
{
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
*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);
|
|
566
742
|
}
|
|
567
743
|
}
|
|
568
|
-
ca->ptr = ca->data->ptr;
|
|
569
744
|
}
|
|
570
745
|
|
|
571
746
|
static void
|
|
572
747
|
ca_object_func_attach (void *ap)
|
|
573
748
|
{
|
|
574
749
|
CAObject *ca = (CAObject *) ap;
|
|
575
|
-
|
|
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
|
+
}
|
|
576
757
|
/* ca->data->ptr = ALLOC_N(char, ca_length(ca)); */
|
|
577
|
-
ca->data->ptr =
|
|
758
|
+
ca->data->ptr = xmalloc(ca_length(ca));
|
|
578
759
|
if ( ca_is_object_type(ca->data) ) { /* GC safe */
|
|
579
760
|
VALUE *p = (VALUE *) ca->data->ptr;
|
|
580
761
|
VALUE zero = INT2NUM(0);
|
|
@@ -583,8 +764,8 @@ ca_object_func_attach (void *ap)
|
|
|
583
764
|
*p++ = zero;
|
|
584
765
|
}
|
|
585
766
|
}
|
|
586
|
-
ca->ptr = ca->data->ptr;
|
|
587
|
-
|
|
767
|
+
ca->ptr = ca->data->ptr;
|
|
768
|
+
ca_object_dispatch_copy(ca, ca->ptr);
|
|
588
769
|
if ( ca_has_mask(ca->data) ) {
|
|
589
770
|
ca_update_mask(ca);
|
|
590
771
|
if ( ! ca->mask ) {
|
|
@@ -597,48 +778,227 @@ static void
|
|
|
597
778
|
ca_object_func_sync (void *ap)
|
|
598
779
|
{
|
|
599
780
|
CAObject *ca = (CAObject *) ap;
|
|
600
|
-
|
|
601
|
-
|
|
781
|
+
if ( ca_is_face(ca) ) {
|
|
782
|
+
ca_face_sync(ap);
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
ca_object_dispatch_sync(ca, ca->data->ptr);
|
|
602
786
|
}
|
|
603
787
|
|
|
604
788
|
static void
|
|
605
789
|
ca_object_func_detach (void *ap)
|
|
606
790
|
{
|
|
607
791
|
CAObject *ca = (CAObject *) ap;
|
|
608
|
-
|
|
792
|
+
if ( ca_is_face(ca) ) {
|
|
793
|
+
ca_face_detach(ap);
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
xfree(ca->data->ptr);
|
|
609
797
|
ca->data->ptr = NULL;
|
|
610
798
|
ca->ptr = NULL;
|
|
611
799
|
}
|
|
612
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
|
+
|
|
613
839
|
static void
|
|
614
|
-
|
|
840
|
+
ca_object_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
615
841
|
{
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
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);
|
|
622
847
|
}
|
|
623
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. */
|
|
624
852
|
static void
|
|
625
|
-
|
|
853
|
+
ca_object_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
854
|
+
void *data, int dir)
|
|
626
855
|
{
|
|
627
|
-
CAObject
|
|
628
|
-
|
|
629
|
-
ca
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
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
|
+
}
|
|
633
992
|
}
|
|
634
993
|
|
|
635
994
|
static void
|
|
636
995
|
ca_object_func_fill_data (void *ap, void *ptr)
|
|
637
996
|
{
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
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);
|
|
642
1002
|
}
|
|
643
1003
|
|
|
644
1004
|
static void
|
|
@@ -646,6 +1006,18 @@ ca_object_func_create_mask (void *ap)
|
|
|
646
1006
|
{
|
|
647
1007
|
CAObject *ca = (CAObject *) ap;
|
|
648
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
|
+
}
|
|
649
1021
|
if ( rb_obj_respond_to(ca->self, rb_intern("create_mask"), Qtrue) ) {
|
|
650
1022
|
rb_funcall(ca->self, rb_intern("create_mask"), 0);
|
|
651
1023
|
}
|
|
@@ -664,23 +1036,20 @@ ca_object_func_create_mask (void *ap)
|
|
|
664
1036
|
|
|
665
1037
|
ca_operation_function_t ca_object_func = {
|
|
666
1038
|
-1, /* CA_OBJ_OBJECT */
|
|
667
|
-
|
|
1039
|
+
CA_VIEW_ARRAY,
|
|
668
1040
|
free_ca_object,
|
|
669
1041
|
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
1042
|
ca_object_func_allocate,
|
|
677
1043
|
ca_object_func_attach,
|
|
678
1044
|
ca_object_func_sync,
|
|
679
1045
|
ca_object_func_detach,
|
|
680
|
-
ca_object_func_copy_data,
|
|
681
|
-
ca_object_func_sync_data,
|
|
682
1046
|
ca_object_func_fill_data,
|
|
683
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,
|
|
684
1053
|
};
|
|
685
1054
|
|
|
686
1055
|
/* ------------------------------------------------------------------- */
|
|
@@ -701,13 +1070,28 @@ rb_ca_object_initialize_copy (VALUE self, VALUE other)
|
|
|
701
1070
|
TypedData_Get_Struct(self, CAObject, &caobject_data_type, ca);
|
|
702
1071
|
TypedData_Get_Struct(other, CAObject, &caobject_data_type, cs);
|
|
703
1072
|
|
|
1073
|
+
if ( ca_func[CA_OBJ_OBJECT].pool_init ) {
|
|
1074
|
+
ca_array_pool_alloc(ca, CA_OBJ_OBJECT, cs->ndim);
|
|
1075
|
+
}
|
|
704
1076
|
ca_object_setup(ca, cs->data_type, cs->ndim, cs->dim, cs->bytes);
|
|
705
1077
|
ca->self = self;
|
|
706
1078
|
|
|
707
|
-
|
|
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
|
+
|
|
708
1093
|
|
|
709
1094
|
data = ca_wrap_struct(ca->data);
|
|
710
|
-
rb_ca_data_type_inherit(data, self);
|
|
711
1095
|
rb_ivar_set(self, rb_intern("__data__"), data);
|
|
712
1096
|
|
|
713
1097
|
ca_update_mask(cs);
|
|
@@ -723,7 +1107,9 @@ rb_ca_object_initialize_copy (VALUE self, VALUE other)
|
|
|
723
1107
|
static VALUE
|
|
724
1108
|
rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
725
1109
|
{
|
|
726
|
-
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;
|
|
727
1113
|
CAObject *ca;
|
|
728
1114
|
int8_t data_type, ndim;
|
|
729
1115
|
ca_size_t dim[CA_RANK_MAX];
|
|
@@ -731,15 +1117,47 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
731
1117
|
int i;
|
|
732
1118
|
|
|
733
1119
|
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
|
|
1120
|
+
rb_scan_options(ropt, "bytes,read_only,parent,face,storage,orderable_storage,comparable_storage",
|
|
1121
|
+
&rbytes, &rrdonly, &rparent, &rface, &rstorage,
|
|
1122
|
+
&rorderable, &rcomparable);
|
|
736
1123
|
|
|
737
|
-
if ( ( ! NIL_P(rparent) ) && rb_obj_is_carray(rparent) ) {
|
|
1124
|
+
if ( ( ! NIL_P(rparent) ) && ( ! rb_obj_is_carray(rparent) ) ) {
|
|
738
1125
|
rb_raise(rb_eRuntimeError, "option :parent should be a carray");
|
|
739
1126
|
}
|
|
740
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
|
+
|
|
741
1160
|
rb_ca_guess_type_and_bytes(rtype, rbytes, &data_type, &bytes);
|
|
742
|
-
rb_ca_data_type_import(self, rtype);
|
|
743
1161
|
|
|
744
1162
|
Check_Type(rdim, T_ARRAY);
|
|
745
1163
|
|
|
@@ -753,7 +1171,6 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
753
1171
|
ca->self = self;
|
|
754
1172
|
|
|
755
1173
|
rdata = ca_wrap_struct(ca->data);
|
|
756
|
-
rb_ca_data_type_inherit(rdata, self);
|
|
757
1174
|
|
|
758
1175
|
rb_ivar_set(self, rb_intern("__data__"), rdata);
|
|
759
1176
|
|
|
@@ -766,6 +1183,56 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
766
1183
|
TypedData_Get_Struct(rparent, CArray, &carray_data_type, cp);
|
|
767
1184
|
ca->parent = cp;
|
|
768
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
|
+
}
|
|
769
1236
|
}
|
|
770
1237
|
|
|
771
1238
|
ca_update_mask(ca);
|
|
@@ -774,14 +1241,14 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
774
1241
|
}
|
|
775
1242
|
|
|
776
1243
|
void
|
|
777
|
-
Init_ca_obj_object ()
|
|
1244
|
+
Init_ca_obj_object (void)
|
|
778
1245
|
{
|
|
779
1246
|
rb_cCAObjectMask = rb_define_class("CAObjectMask", rb_cCArray);
|
|
780
1247
|
|
|
781
1248
|
CA_OBJ_OBJECT_MASK = ca_install_obj_type(rb_cCAObjectMask,
|
|
782
1249
|
&caobjectmask_data_type,
|
|
783
1250
|
rb_cCArrayMask,
|
|
784
|
-
&carray_data_type, ca_objmask_func);
|
|
1251
|
+
&carray_data_type, &ca_objmask_func, sizeof(ca_objmask_func));
|
|
785
1252
|
rb_define_const(rb_cObject, "CA_OBJ_OBJECT_MASK", INT2NUM(CA_OBJ_OBJECT_MASK));
|
|
786
1253
|
|
|
787
1254
|
rb_define_alloc_func(rb_cCAObjectMask, rb_ca_objmask_s_allocate);
|
|
@@ -791,6 +1258,14 @@ Init_ca_obj_object ()
|
|
|
791
1258
|
|
|
792
1259
|
rb_define_const(rb_cObject, "CA_OBJ_OBJECT", INT2NUM(CA_OBJ_OBJECT));
|
|
793
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
|
+
|
|
794
1269
|
rb_define_alloc_func(rb_cCAObject, rb_ca_object_s_allocate);
|
|
795
1270
|
rb_define_method(rb_cCAObject, "initialize_copy",
|
|
796
1271
|
rb_ca_object_initialize_copy, 1);
|