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_roll.c
ADDED
|
@@ -0,0 +1,616 @@
|
|
|
1
|
+
/* ---------------------------------------------------------------------------
|
|
2
|
+
|
|
3
|
+
CARoll view: same-shape cyclic shift of the parent. Per-axis shift
|
|
4
|
+
is passed as multi-arg to `CArray#roll`.
|
|
5
|
+
|
|
6
|
+
Sibling of ca_obj_tile.c (CARoll is a `typedef CATile CARoll`; the
|
|
7
|
+
operation table is built by copying ca_tile_func and overriding the
|
|
8
|
+
slots that need shift-specific behavior).
|
|
9
|
+
|
|
10
|
+
Storage reuse: CATile's `reps[]` field is reinterpreted in CARoll as
|
|
11
|
+
`shift[]` (= normalised to `[0, parent.dim[k])`).
|
|
12
|
+
|
|
13
|
+
Region enumeration: each shifted axis contributes 2 stripes, so the
|
|
14
|
+
cartesian product yields 2^K regions where K counts non-zero shift
|
|
15
|
+
axes. Non-shifted axes give a single full-parent stripe.
|
|
16
|
+
|
|
17
|
+
---------------------------------------------------------------------------- */
|
|
18
|
+
|
|
19
|
+
#include "carray.h"
|
|
20
|
+
#include "ca_composite_dispatch.h"
|
|
21
|
+
#include "ca_obj_face.h"
|
|
22
|
+
|
|
23
|
+
/* ------------------------------------------------------------------- */
|
|
24
|
+
/* External: CATile's data type + base operation table (typedef shared). */
|
|
25
|
+
/* ------------------------------------------------------------------- */
|
|
26
|
+
|
|
27
|
+
extern const rb_data_type_t catile_data_type;
|
|
28
|
+
extern ca_operation_function_t ca_tile_func;
|
|
29
|
+
extern VALUE rb_cCATile;
|
|
30
|
+
|
|
31
|
+
/* ------------------------------------------------------------------- */
|
|
32
|
+
/* TypedData */
|
|
33
|
+
/* ------------------------------------------------------------------- */
|
|
34
|
+
|
|
35
|
+
static size_t
|
|
36
|
+
ca_roll_dsize (const void *ap)
|
|
37
|
+
{
|
|
38
|
+
const CARoll *ca = (const CARoll *) ap;
|
|
39
|
+
/* Layout inherited from CATile: dim + reps, each ALLOC_N(ndim). */
|
|
40
|
+
return sizeof(CARoll) + 2 * ca->ndim * sizeof(ca_size_t);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const rb_data_type_t caroll_data_type = {
|
|
44
|
+
.parent = &catile_data_type,
|
|
45
|
+
.wrap_struct_name = "CARoll",
|
|
46
|
+
.function = {
|
|
47
|
+
.dmark = ca_mark,
|
|
48
|
+
.dfree = ca_free,
|
|
49
|
+
.dsize = ca_roll_dsize,
|
|
50
|
+
.dcompact = NULL
|
|
51
|
+
},
|
|
52
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const rb_data_type_t caroll_mask_data_type = {
|
|
56
|
+
.parent = &caroll_data_type,
|
|
57
|
+
.wrap_struct_name = "CARollMask",
|
|
58
|
+
.function = {
|
|
59
|
+
.dmark = ca_mark,
|
|
60
|
+
.dfree = ca_free_nop,
|
|
61
|
+
.dsize = ca_roll_dsize,
|
|
62
|
+
.dcompact = NULL
|
|
63
|
+
},
|
|
64
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
int8_t CA_OBJ_ROLL;
|
|
68
|
+
|
|
69
|
+
VALUE rb_cCARoll;
|
|
70
|
+
VALUE rb_cCARollMask;
|
|
71
|
+
|
|
72
|
+
ca_operation_function_t ca_roll_func;
|
|
73
|
+
|
|
74
|
+
/* ------------------------------------------------------------------- */
|
|
75
|
+
/* setup / new / free / clone */
|
|
76
|
+
/* ------------------------------------------------------------------- */
|
|
77
|
+
|
|
78
|
+
/* shift[] semantics:
|
|
79
|
+
shift[k] > 0 : shift right (last shift[k] elements wrap to front)
|
|
80
|
+
shift[k] < 0 : shift left
|
|
81
|
+
shift[k] is normalised into [0, parent.dim[k]) modulo dim[k].
|
|
82
|
+
Missing axes (argc < ndim from Ruby): treated as shift = 0. */
|
|
83
|
+
int
|
|
84
|
+
ca_roll_setup (CARoll *ca, CArray *parent, ca_size_t *shift)
|
|
85
|
+
{
|
|
86
|
+
int8_t ndim = parent->ndim;
|
|
87
|
+
ca_size_t bytes = parent->bytes;
|
|
88
|
+
ca_size_t elements;
|
|
89
|
+
int8_t i;
|
|
90
|
+
|
|
91
|
+
elements = 1;
|
|
92
|
+
for (i = 0; i < ndim; i++) {
|
|
93
|
+
if ( parent->dim[i] <= 0 ) {
|
|
94
|
+
rb_raise(rb_eIndexError, "invalid parent dim for %d-th dimension", i);
|
|
95
|
+
}
|
|
96
|
+
elements *= parent->dim[i];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
ca->obj_type = CA_OBJ_ROLL;
|
|
100
|
+
ca->data_type = parent->data_type;
|
|
101
|
+
ca->flags = 0;
|
|
102
|
+
ca->ndim = ndim;
|
|
103
|
+
ca->bytes = bytes;
|
|
104
|
+
ca->elements = elements;
|
|
105
|
+
ca->ptr = NULL;
|
|
106
|
+
ca->mask = NULL;
|
|
107
|
+
|
|
108
|
+
ca->parent = parent;
|
|
109
|
+
ca->attach = 0;
|
|
110
|
+
ca->nosync = 0;
|
|
111
|
+
ca->reps = ALLOC_N(ca_size_t, ndim); /* repurposed as shift[] */
|
|
112
|
+
ca->dim = ALLOC_N(ca_size_t, ndim);
|
|
113
|
+
|
|
114
|
+
for (i = 0; i < ndim; i++) {
|
|
115
|
+
ca->dim[i] = parent->dim[i];
|
|
116
|
+
/* Normalise: ((shift[i] % dim[i]) + dim[i]) % dim[i] ∈ [0, dim[i]). */
|
|
117
|
+
ca_size_t s = shift[i] % parent->dim[i];
|
|
118
|
+
if ( s < 0 ) s += parent->dim[i];
|
|
119
|
+
ca->reps[i] = s;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if ( ca_has_mask(parent) ) {
|
|
123
|
+
ca_create_mask(ca);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
CARoll *
|
|
130
|
+
ca_roll_new (CArray *parent, ca_size_t *shift)
|
|
131
|
+
{
|
|
132
|
+
CARoll *ca = ALLOC(CARoll);
|
|
133
|
+
ca_roll_setup(ca, parent, shift);
|
|
134
|
+
return ca;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
static void
|
|
138
|
+
free_ca_roll (void *ap)
|
|
139
|
+
{
|
|
140
|
+
CARoll *ca = (CARoll *) ap;
|
|
141
|
+
if ( ca != NULL ) {
|
|
142
|
+
ca_free(ca->mask);
|
|
143
|
+
xfree(ca->reps);
|
|
144
|
+
xfree(ca->dim);
|
|
145
|
+
xfree(ca);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
static void *
|
|
150
|
+
ca_roll_func_clone (void *ap)
|
|
151
|
+
{
|
|
152
|
+
CARoll *ca = (CARoll *) ap;
|
|
153
|
+
return ca_roll_new(ca->parent, ca->reps); /* reps[] is already normalised shift[] */
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* ------------------------------------------------------------------- */
|
|
157
|
+
/* xfer_index / xfer_addrs / xfer_stride — periodic index map */
|
|
158
|
+
/* */
|
|
159
|
+
/* view[i_0, i_1, ...] = parent[(i_0 - shift_0 + dim_0) % dim_0, ...] */
|
|
160
|
+
/* */
|
|
161
|
+
/* CARoll inherits ca_tile_func by copy, so every xfer slot below must */
|
|
162
|
+
/* be re-registered in Init_ca_obj_roll to override the CATile version. */
|
|
163
|
+
/* ------------------------------------------------------------------- */
|
|
164
|
+
|
|
165
|
+
static void
|
|
166
|
+
ca_roll_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
167
|
+
{
|
|
168
|
+
CARoll *ca = (CARoll *) ap;
|
|
169
|
+
ca_size_t pidx[CA_RANK_MAX];
|
|
170
|
+
int8_t i;
|
|
171
|
+
for (i = 0; i < ca->ndim; i++) {
|
|
172
|
+
/* output[idx] = parent[(idx - shift + dim) % dim]. */
|
|
173
|
+
ca_size_t k = idx[i] - ca->reps[i];
|
|
174
|
+
if ( k < 0 ) k += ca->parent->dim[i];
|
|
175
|
+
pidx[i] = k;
|
|
176
|
+
}
|
|
177
|
+
ca_xfer_index(ca->parent, pidx, data, dir);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* Batched address gather/scatter. The periodic shift is 1:1 and
|
|
181
|
+
always in-bounds, so all addrs collapse to a single parent
|
|
182
|
+
ca_xfer_addrs call. */
|
|
183
|
+
static void
|
|
184
|
+
ca_roll_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
185
|
+
void *data, int dir)
|
|
186
|
+
{
|
|
187
|
+
CARoll *ca = (CARoll *) ap;
|
|
188
|
+
ca_size_t *paddrs;
|
|
189
|
+
ca_size_t i;
|
|
190
|
+
int8_t k;
|
|
191
|
+
volatile VALUE holder;
|
|
192
|
+
paddrs = ALLOCV_N(ca_size_t, holder, n);
|
|
193
|
+
for (i = 0; i < n; i++) {
|
|
194
|
+
ca_size_t vidx[CA_RANK_MAX], pidx[CA_RANK_MAX];
|
|
195
|
+
ca_addr2index((CArray *) ca, addrs[i], vidx);
|
|
196
|
+
for (k = 0; k < ca->ndim; k++) {
|
|
197
|
+
ca_size_t j = vidx[k] - ca->reps[k];
|
|
198
|
+
if ( j < 0 ) j += ca->parent->dim[k];
|
|
199
|
+
pidx[k] = j;
|
|
200
|
+
}
|
|
201
|
+
paddrs[i] = ca_index2addr(ca->parent, pidx);
|
|
202
|
+
}
|
|
203
|
+
ca_xfer_addrs(ca->parent, n, paddrs, data, dir);
|
|
204
|
+
ALLOCV_END(holder);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/* Structural region delivery for CARoll. The parent position along
|
|
208
|
+
each axis is `(view_pos - shift) mod parent.dim[k]`. view.dim ==
|
|
209
|
+
parent.dim, so a contiguous inner run wraps at most once and the
|
|
210
|
+
per-segment loop handles the wrap. Structural path requires
|
|
211
|
+
axis-aligned unit src step along the inner axis; otherwise falls
|
|
212
|
+
back to per-cell xfer_index. */
|
|
213
|
+
static void
|
|
214
|
+
ca_roll_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
215
|
+
ca_size_t *strides, void *data, int dir)
|
|
216
|
+
{
|
|
217
|
+
CARoll *ca = (CARoll *) ap;
|
|
218
|
+
CArray *parent = ca->parent;
|
|
219
|
+
int8_t ndim = ca->ndim;
|
|
220
|
+
int8_t inner = ndim - 1;
|
|
221
|
+
ca_size_t pnative[CA_RANK_MAX], rnative[CA_RANK_MAX], dstride[CA_RANK_MAX];
|
|
222
|
+
ca_size_t o[CA_RANK_MAX];
|
|
223
|
+
ca_size_t s;
|
|
224
|
+
int8_t k;
|
|
225
|
+
int structural = 1;
|
|
226
|
+
char *d = (char *) data;
|
|
227
|
+
|
|
228
|
+
s = parent->bytes;
|
|
229
|
+
for (k = ndim - 1; k >= 0; k--) { pnative[k] = s; s *= parent->dim[k]; }
|
|
230
|
+
s = ca->bytes;
|
|
231
|
+
for (k = ndim - 1; k >= 0; k--) { rnative[k] = s; s *= ca->dim[k]; }
|
|
232
|
+
s = ca->bytes;
|
|
233
|
+
for (k = ndim - 1; k >= 0; k--) { dstride[k] = s; s *= counts[k]; }
|
|
234
|
+
|
|
235
|
+
for (k = 0; k < ndim; k++) {
|
|
236
|
+
if (strides[k] % rnative[k] != 0 || strides[k] / rnative[k] != 1) {
|
|
237
|
+
structural = 0;
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (!structural) {
|
|
243
|
+
ca_size_t idx[CA_RANK_MAX], doff = 0, base = 0;
|
|
244
|
+
for (k = 0; k < ndim; k++) base += starts[k] * rnative[k];
|
|
245
|
+
for (k = 0; k < ndim; k++) idx[k] = 0;
|
|
246
|
+
while (1) {
|
|
247
|
+
ca_size_t roff = base, ridx[CA_RANK_MAX];
|
|
248
|
+
for (k = 0; k < ndim; k++) roff += idx[k] * strides[k];
|
|
249
|
+
ca_addr2index((CArray *) ca, roff / ca->bytes, ridx);
|
|
250
|
+
ca_roll_func_xfer_index(ca, ridx, d + doff, dir);
|
|
251
|
+
doff += ca->bytes;
|
|
252
|
+
k = ndim - 1;
|
|
253
|
+
while (k >= 0) { if (++idx[k] < counts[k]) break; idx[k] = 0; k--; }
|
|
254
|
+
if (k < 0) break;
|
|
255
|
+
}
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
for (k = 0; k < ndim; k++) o[k] = 0;
|
|
260
|
+
while (1) {
|
|
261
|
+
ca_size_t pbase = 0, doff = 0, i;
|
|
262
|
+
for (k = 0; k < inner; k++) {
|
|
263
|
+
ca_size_t j = (starts[k] + o[k]) - ca->reps[k];
|
|
264
|
+
if (j < 0) j += parent->dim[k];
|
|
265
|
+
pbase += j * pnative[k];
|
|
266
|
+
doff += o[k] * dstride[k];
|
|
267
|
+
}
|
|
268
|
+
i = 0;
|
|
269
|
+
while (i < counts[inner]) {
|
|
270
|
+
ca_size_t ppos = (starts[inner] + i) - ca->reps[inner];
|
|
271
|
+
if (ppos < 0) ppos += parent->dim[inner];
|
|
272
|
+
ca_size_t seg = parent->dim[inner] - ppos;
|
|
273
|
+
ca_size_t pstarts[CA_RANK_MAX], pcounts[CA_RANK_MAX], pstrides[CA_RANK_MAX];
|
|
274
|
+
if (seg > counts[inner] - i) seg = counts[inner] - i;
|
|
275
|
+
ca_addr2index((CArray *) parent, (pbase + ppos * pnative[inner]) / parent->bytes, pstarts);
|
|
276
|
+
for (k = 0; k < ndim; k++) { pcounts[k] = 1; pstrides[k] = 0; }
|
|
277
|
+
pcounts[inner] = seg;
|
|
278
|
+
pstrides[inner] = pnative[inner];
|
|
279
|
+
ca_xfer_stride(parent, pstarts, pcounts, pstrides, d + doff + i * dstride[inner], dir);
|
|
280
|
+
i += seg;
|
|
281
|
+
}
|
|
282
|
+
k = inner - 1;
|
|
283
|
+
while (k >= 0) { if (++o[k] < counts[k]) break; o[k] = 0; k--; }
|
|
284
|
+
if (k < 0) break;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/* ------------------------------------------------------------------- */
|
|
289
|
+
/* attach / sync — enumerate 2^K stripe regions */
|
|
290
|
+
/* */
|
|
291
|
+
/* Per axis k: */
|
|
292
|
+
/* shift[k] == 0 : */
|
|
293
|
+
/* one full-axis stripe (parent_start=0, count=dim, off=0) */
|
|
294
|
+
/* shift[k] > 0 : */
|
|
295
|
+
/* stripe A (last shift[k] parent cells wrap to output front): */
|
|
296
|
+
/* parent_start[k] = dim[k] - shift[k] */
|
|
297
|
+
/* count[k] = shift[k] */
|
|
298
|
+
/* output_offset[k]= 0 */
|
|
299
|
+
/* stripe B (remaining cells): */
|
|
300
|
+
/* parent_start[k] = 0 */
|
|
301
|
+
/* count[k] = dim[k] - shift[k] */
|
|
302
|
+
/* output_offset[k]= shift[k] */
|
|
303
|
+
/* */
|
|
304
|
+
/* Total regions = 2^K where K = number of axes with shift != 0. */
|
|
305
|
+
/* ------------------------------------------------------------------- */
|
|
306
|
+
|
|
307
|
+
static void
|
|
308
|
+
ca_roll_compute_strides (CARoll *ca,
|
|
309
|
+
ca_size_t *parent_strides,
|
|
310
|
+
ca_size_t *output_strides)
|
|
311
|
+
{
|
|
312
|
+
ca_size_t s;
|
|
313
|
+
int8_t k;
|
|
314
|
+
s = ca->bytes;
|
|
315
|
+
for ( k = ca->ndim - 1; k >= 0; k-- ) {
|
|
316
|
+
parent_strides[k] = s;
|
|
317
|
+
s *= ca->parent->dim[k];
|
|
318
|
+
}
|
|
319
|
+
s = ca->bytes;
|
|
320
|
+
for ( k = ca->ndim - 1; k >= 0; k-- ) {
|
|
321
|
+
output_strides[k] = s;
|
|
322
|
+
s *= ca->dim[k];
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/* Walk regions via a bitmap over the K shifted axes. For each region
|
|
327
|
+
(bitmap value 0..2^K-1), build parent_start[] / count[] /
|
|
328
|
+
output_offset[] and call ca_composite_region_gather (attach) or
|
|
329
|
+
ca_composite_region_scatter (sync). */
|
|
330
|
+
static void
|
|
331
|
+
ca_roll_iterate_regions (CARoll *ca, char *out_ptr, int direction)
|
|
332
|
+
{
|
|
333
|
+
ca_size_t parent_strides[CA_RANK_MAX];
|
|
334
|
+
ca_size_t output_strides[CA_RANK_MAX];
|
|
335
|
+
ca_size_t parent_start[CA_RANK_MAX];
|
|
336
|
+
ca_size_t output_offset[CA_RANK_MAX];
|
|
337
|
+
ca_size_t count[CA_RANK_MAX];
|
|
338
|
+
int8_t shifted_axes[CA_RANK_MAX];
|
|
339
|
+
int8_t n_shifted = 0;
|
|
340
|
+
int8_t k;
|
|
341
|
+
ca_size_t bytes = ca->bytes;
|
|
342
|
+
int8_t ndim = ca->ndim;
|
|
343
|
+
int region, total_regions;
|
|
344
|
+
|
|
345
|
+
ca_roll_compute_strides(ca, parent_strides, output_strides);
|
|
346
|
+
|
|
347
|
+
/* Identify shifted axes; set baseline (= stripe B for shifted, full for non-shifted). */
|
|
348
|
+
for ( k = 0; k < ndim; k++ ) {
|
|
349
|
+
if ( ca->reps[k] != 0 ) {
|
|
350
|
+
shifted_axes[n_shifted++] = k;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
total_regions = 1 << n_shifted;
|
|
355
|
+
|
|
356
|
+
for ( region = 0; region < total_regions; region++ ) {
|
|
357
|
+
/* Initialise: non-shifted axes = full. */
|
|
358
|
+
for ( k = 0; k < ndim; k++ ) {
|
|
359
|
+
if ( ca->reps[k] == 0 ) {
|
|
360
|
+
parent_start[k] = 0;
|
|
361
|
+
count[k] = ca->parent->dim[k];
|
|
362
|
+
output_offset[k] = 0;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
/* For each shifted axis, pick stripe based on region bit. */
|
|
366
|
+
for ( int b = 0; b < n_shifted; b++ ) {
|
|
367
|
+
int8_t ax = shifted_axes[b];
|
|
368
|
+
ca_size_t shift = ca->reps[ax];
|
|
369
|
+
ca_size_t pdim = ca->parent->dim[ax];
|
|
370
|
+
if ( (region >> b) & 1 ) {
|
|
371
|
+
/* Stripe B: remaining elements after the wrapped tail. */
|
|
372
|
+
parent_start[ax] = 0;
|
|
373
|
+
count[ax] = pdim - shift;
|
|
374
|
+
output_offset[ax] = shift;
|
|
375
|
+
} else {
|
|
376
|
+
/* Stripe A: last `shift` elements wrap to front. */
|
|
377
|
+
parent_start[ax] = pdim - shift;
|
|
378
|
+
count[ax] = shift;
|
|
379
|
+
output_offset[ax] = 0;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if ( direction == 0 ) {
|
|
384
|
+
ca_composite_region_gather(ca->parent->ptr, parent_strides,
|
|
385
|
+
parent_start,
|
|
386
|
+
out_ptr, output_strides, output_offset,
|
|
387
|
+
count, ndim, bytes);
|
|
388
|
+
} else {
|
|
389
|
+
ca_composite_region_scatter(ca->parent->ptr, parent_strides,
|
|
390
|
+
parent_start,
|
|
391
|
+
out_ptr, output_strides, output_offset,
|
|
392
|
+
count, ndim, bytes);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
static void
|
|
398
|
+
ca_roll_func_allocate (void *ap)
|
|
399
|
+
{
|
|
400
|
+
CARoll *ca = (CARoll *) ap;
|
|
401
|
+
ca_attach(ca->parent);
|
|
402
|
+
ca->ptr = xmalloc(ca_length(ca));
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
static void
|
|
406
|
+
ca_roll_func_attach (void *ap)
|
|
407
|
+
{
|
|
408
|
+
CARoll *ca = (CARoll *) ap;
|
|
409
|
+
ca_attach(ca->parent);
|
|
410
|
+
ca->ptr = xmalloc(ca_length(ca));
|
|
411
|
+
ca_roll_iterate_regions(ca, ca->ptr, 0);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
static void
|
|
415
|
+
ca_roll_func_sync (void *ap)
|
|
416
|
+
{
|
|
417
|
+
CARoll *ca = (CARoll *) ap;
|
|
418
|
+
ca_roll_iterate_regions(ca, ca->ptr, 1);
|
|
419
|
+
ca_sync(ca->parent);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
static void
|
|
423
|
+
ca_roll_func_detach (void *ap)
|
|
424
|
+
{
|
|
425
|
+
CARoll *ca = (CARoll *) ap;
|
|
426
|
+
xfree(ca->ptr);
|
|
427
|
+
ca->ptr = NULL;
|
|
428
|
+
ca_detach(ca->parent);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/* Fast path (hot parent): drive the region walk directly against
|
|
432
|
+
parent->ptr. Cold parent: fall back to a scratch 2-pass (gather
|
|
433
|
+
parent into scratch, walk regions against the scratch, scatter
|
|
434
|
+
back on PUT). Deliberately does not call ca_attach(parent) — that
|
|
435
|
+
would re-introduce the silent transitive attach the fast path was
|
|
436
|
+
built to avoid. */
|
|
437
|
+
static void
|
|
438
|
+
ca_roll_func_xfer_all (void *ap, void *data, int dir)
|
|
439
|
+
{
|
|
440
|
+
CARoll *ca = (CARoll *) ap;
|
|
441
|
+
if ( ca->parent->ptr ) {
|
|
442
|
+
ca_roll_iterate_regions(ca, (char *) data, dir == CA_XFER_PUT);
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
{
|
|
446
|
+
volatile VALUE holder;
|
|
447
|
+
CArray *parent = ca->parent;
|
|
448
|
+
ca_size_t plen = parent->elements * parent->bytes;
|
|
449
|
+
char *parent_scratch = ALLOCV_N(char, holder, plen);
|
|
450
|
+
char *parent_ptr_saved = parent->ptr;
|
|
451
|
+
ca_xfer_all(parent, parent_scratch, CA_XFER_GET);
|
|
452
|
+
parent->ptr = parent_scratch;
|
|
453
|
+
ca_roll_iterate_regions(ca, (char *) data, dir == CA_XFER_PUT);
|
|
454
|
+
if ( dir == CA_XFER_PUT ) {
|
|
455
|
+
ca_xfer_all(parent, parent_scratch, CA_XFER_PUT);
|
|
456
|
+
}
|
|
457
|
+
parent->ptr = parent_ptr_saved;
|
|
458
|
+
ALLOCV_END(holder);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
static void
|
|
463
|
+
ca_roll_func_fill_data (void *ap, void *ptr)
|
|
464
|
+
{
|
|
465
|
+
CARoll *ca = (CARoll *) ap;
|
|
466
|
+
/* Each parent cell appears exactly once in the view, so a broadcast
|
|
467
|
+
fill is equivalent to filling the parent once. */
|
|
468
|
+
ca_fill(ca->parent, ptr);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
static void
|
|
472
|
+
ca_roll_func_create_mask (void *ap)
|
|
473
|
+
{
|
|
474
|
+
CARoll *ca = (CARoll *) ap;
|
|
475
|
+
ca_update_mask(ca->parent);
|
|
476
|
+
if ( ! ca->parent->mask ) {
|
|
477
|
+
ca_create_mask(ca->parent);
|
|
478
|
+
}
|
|
479
|
+
ca->mask = (CArray *) ca_roll_new(ca->parent->mask, ca->reps);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/* ------------------------------------------------------------------- */
|
|
483
|
+
/* Ruby surface */
|
|
484
|
+
/* ------------------------------------------------------------------- */
|
|
485
|
+
|
|
486
|
+
VALUE
|
|
487
|
+
rb_ca_roll_new (VALUE cary, ca_size_t *shift)
|
|
488
|
+
{
|
|
489
|
+
volatile VALUE obj;
|
|
490
|
+
CArray *parent;
|
|
491
|
+
CARoll *ca;
|
|
492
|
+
rb_check_carray_object(cary);
|
|
493
|
+
TypedData_Get_Struct(cary, CArray, &carray_data_type, parent);
|
|
494
|
+
ca = ca_roll_new(parent, shift);
|
|
495
|
+
obj = ca_wrap_struct(ca);
|
|
496
|
+
rb_ca_set_parent(obj, cary);
|
|
497
|
+
return obj;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/* CArray#roll(*shifts) — cyclic shift along each axis.
|
|
501
|
+
argc < ndim : missing axes take shift = 0.
|
|
502
|
+
argc > ndim : ArgumentError. */
|
|
503
|
+
static VALUE
|
|
504
|
+
rb_ca_roll (int argc, VALUE *argv, VALUE self)
|
|
505
|
+
{
|
|
506
|
+
CArray *ca;
|
|
507
|
+
volatile VALUE ropt;
|
|
508
|
+
ca_size_t shift[CA_RANK_MAX];
|
|
509
|
+
int8_t i;
|
|
510
|
+
|
|
511
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
512
|
+
|
|
513
|
+
/* Shifts are positional only. A trailing Hash is a keyword argument
|
|
514
|
+
that would otherwise reach NUM2SIZE and surface as a TypeError. */
|
|
515
|
+
ropt = rb_pop_options(&argc, &argv);
|
|
516
|
+
rb_reject_options(ropt);
|
|
517
|
+
|
|
518
|
+
if ( argc > ca->ndim ) {
|
|
519
|
+
rb_raise(rb_eArgError,
|
|
520
|
+
"roll: too many args (%d), expected at most %d (= ndim)",
|
|
521
|
+
argc, ca->ndim);
|
|
522
|
+
}
|
|
523
|
+
for ( i = 0; i < ca->ndim; i++ ) {
|
|
524
|
+
if ( i < argc ) {
|
|
525
|
+
shift[i] = NUM2SIZE(argv[i]);
|
|
526
|
+
} else {
|
|
527
|
+
shift[i] = 0;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
{
|
|
531
|
+
VALUE obj = rb_ca_roll_new(self, shift);
|
|
532
|
+
CA_FACE_LIFT_IF_FACE(obj, self, ca);
|
|
533
|
+
return obj;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/* `roll!` intentionally absent. Canonical in-place idiom is
|
|
538
|
+
`ca[] = ca.roll(...)`. */
|
|
539
|
+
|
|
540
|
+
static VALUE
|
|
541
|
+
rb_ca_roll_s_allocate (VALUE klass)
|
|
542
|
+
{
|
|
543
|
+
CARoll *ca;
|
|
544
|
+
return TypedData_Make_Struct(klass, CARoll, &caroll_data_type, ca);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
static VALUE
|
|
548
|
+
rb_ca_roll_initialize_copy (VALUE self, VALUE other)
|
|
549
|
+
{
|
|
550
|
+
CARoll *ca, *cs;
|
|
551
|
+
TypedData_Get_Struct(self, CARoll, &caroll_data_type, ca);
|
|
552
|
+
TypedData_Get_Struct(other, CARoll, &caroll_data_type, cs);
|
|
553
|
+
ca_roll_setup(ca, cs->parent, cs->reps);
|
|
554
|
+
return self;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/* Debug-only accessor returning the roll descriptor as a Hash
|
|
558
|
+
(`shifts`, `n_regions`, `ndim`). Not part of the public surface. */
|
|
559
|
+
static VALUE
|
|
560
|
+
rb_ca_roll_descriptor (VALUE self)
|
|
561
|
+
{
|
|
562
|
+
CARoll *ca = (CARoll *) DATA_PTR(self);
|
|
563
|
+
VALUE hash, shifts_ary;
|
|
564
|
+
int8_t k;
|
|
565
|
+
int n_shifted = 0;
|
|
566
|
+
|
|
567
|
+
shifts_ary = rb_ary_new_capa(ca->ndim);
|
|
568
|
+
for ( k = 0; k < ca->ndim; k++ ) {
|
|
569
|
+
rb_ary_push(shifts_ary, SIZE2NUM(ca->reps[k]));
|
|
570
|
+
if ( ca->reps[k] != 0 ) n_shifted++;
|
|
571
|
+
}
|
|
572
|
+
hash = rb_hash_new();
|
|
573
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("shifts")), shifts_ary);
|
|
574
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("n_regions")), INT2NUM(1 << n_shifted));
|
|
575
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("ndim")), INT2NUM(ca->ndim));
|
|
576
|
+
return hash;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
void
|
|
580
|
+
Init_ca_obj_roll (void)
|
|
581
|
+
{
|
|
582
|
+
/* Build ca_roll_func by copying ca_tile_func and overriding the
|
|
583
|
+
slots that need CARoll-specific behavior. */
|
|
584
|
+
ca_roll_func = ca_tile_func;
|
|
585
|
+
ca_roll_func.free_object = free_ca_roll;
|
|
586
|
+
ca_roll_func.clone = ca_roll_func_clone;
|
|
587
|
+
ca_roll_func.allocate = ca_roll_func_allocate;
|
|
588
|
+
ca_roll_func.attach = ca_roll_func_attach;
|
|
589
|
+
ca_roll_func.sync = ca_roll_func_sync;
|
|
590
|
+
ca_roll_func.detach = ca_roll_func_detach;
|
|
591
|
+
ca_roll_func.fill_data = ca_roll_func_fill_data;
|
|
592
|
+
ca_roll_func.create_mask = ca_roll_func_create_mask;
|
|
593
|
+
ca_roll_func.xfer_index = ca_roll_func_xfer_index;
|
|
594
|
+
ca_roll_func.xfer_addrs = ca_roll_func_xfer_addrs;
|
|
595
|
+
ca_roll_func.xfer_stride = ca_roll_func_xfer_stride;
|
|
596
|
+
ca_roll_func.xfer_all = ca_roll_func_xfer_all;
|
|
597
|
+
|
|
598
|
+
rb_cCARoll = rb_define_class("CARoll", rb_cCATile);
|
|
599
|
+
rb_cCARollMask = rb_define_class("CARollMask", rb_cCARoll);
|
|
600
|
+
|
|
601
|
+
CA_OBJ_ROLL = ca_install_obj_type(rb_cCARoll,
|
|
602
|
+
&caroll_data_type,
|
|
603
|
+
rb_cCARollMask,
|
|
604
|
+
&caroll_mask_data_type, &ca_roll_func, sizeof(ca_roll_func));
|
|
605
|
+
rb_define_const(rb_cObject, "CA_OBJ_ROLL", INT2NUM(CA_OBJ_ROLL));
|
|
606
|
+
|
|
607
|
+
rb_define_method(rb_cCArray, "roll", rb_ca_roll, -1);
|
|
608
|
+
|
|
609
|
+
rb_define_alloc_func(rb_cCARoll, rb_ca_roll_s_allocate);
|
|
610
|
+
rb_define_method(rb_cCARoll, "initialize_copy",
|
|
611
|
+
rb_ca_roll_initialize_copy, 1);
|
|
612
|
+
|
|
613
|
+
/* Debug accessor, not part of the public surface. */
|
|
614
|
+
rb_define_method(rb_cCARoll, "_roll_descriptor",
|
|
615
|
+
rb_ca_roll_descriptor, 0);
|
|
616
|
+
}
|