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_refer.c
CHANGED
|
@@ -1,22 +1,49 @@
|
|
|
1
1
|
/* ---------------------------------------------------------------------------
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
CARefer view: strided reinterpretation of the parent (`#refer`)
|
|
4
|
+
plus the two shape-only rewrites `#reshape` and `#flatten`.
|
|
5
|
+
Byte-level reinterpret (a different `data_type` / `bytes`) that
|
|
6
|
+
CAStride cannot express is what makes CARefer distinct — plain
|
|
7
|
+
same-shape reshape usually rewrites to CAStride directly through
|
|
8
|
+
ca_reshape_try_strides.
|
|
4
9
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
Sibling of ca_obj_stride.c (CARefer's operation table is
|
|
11
|
+
ca_stride_func with `free_object` / `clone` / `create_mask`
|
|
12
|
+
overridden for the byte-reinterpret mask paths).
|
|
8
13
|
|
|
9
14
|
---------------------------------------------------------------------------- */
|
|
10
15
|
|
|
11
16
|
#include "carray.h"
|
|
17
|
+
#include "carray_internal.h" /* per-obj_type view constructors */
|
|
18
|
+
#include "ca_obj_face.h" /* CA_FACE_LIFT_IF_FACE for CARecord parent */
|
|
19
|
+
|
|
20
|
+
extern ca_operation_function_t ca_stride_func;
|
|
21
|
+
|
|
22
|
+
VALUE rb_cCARefer;
|
|
23
|
+
VALUE rb_cCAReferMask;
|
|
24
|
+
|
|
25
|
+
/* CARefer ops: ca_stride_func + custom free + custom create_mask.
|
|
26
|
+
Filled in at Init time so the function pointers are valid before
|
|
27
|
+
carray_core's baseline registration is overridden. */
|
|
28
|
+
static ca_operation_function_t ca_refer_func;
|
|
12
29
|
|
|
30
|
+
static size_t
|
|
31
|
+
ca_refer_dsize (const void *ap)
|
|
32
|
+
{
|
|
33
|
+
const CARefer *ca = (const CARefer *) ap;
|
|
34
|
+
return sizeof(CARefer) + 2 * ca->ndim * sizeof(ca_size_t);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* TypedData parent chain: carefer -> castride -> caview -> carray.
|
|
38
|
+
Inheriting from castride_data_type lets CAStride accessor methods
|
|
39
|
+
(#strides, #byte_offset) accept CARefer instances. */
|
|
13
40
|
const rb_data_type_t carefer_data_type = {
|
|
14
|
-
.parent = &
|
|
41
|
+
.parent = &castride_data_type,
|
|
15
42
|
.wrap_struct_name = "CARefer",
|
|
16
43
|
.function = {
|
|
17
44
|
.dmark = ca_mark,
|
|
18
45
|
.dfree = ca_free,
|
|
19
|
-
.dsize =
|
|
46
|
+
.dsize = ca_refer_dsize,
|
|
20
47
|
.dcompact = NULL
|
|
21
48
|
},
|
|
22
49
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
@@ -28,104 +55,77 @@ const rb_data_type_t carefer_mask_data_type = {
|
|
|
28
55
|
.function = {
|
|
29
56
|
.dmark = NULL,
|
|
30
57
|
.dfree = ca_free_nop,
|
|
31
|
-
.dsize =
|
|
58
|
+
.dsize = ca_refer_dsize,
|
|
32
59
|
.dcompact = NULL
|
|
33
60
|
},
|
|
34
61
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
35
62
|
};
|
|
36
63
|
|
|
37
|
-
|
|
38
|
-
VALUE rb_cCAReferMask;
|
|
39
|
-
|
|
40
|
-
/* yard:
|
|
41
|
-
class CARefer < CAVirtual # :nodoc:
|
|
42
|
-
end
|
|
43
|
-
*/
|
|
64
|
+
/* ------------------------------------------------------------------- */
|
|
44
65
|
|
|
45
|
-
|
|
66
|
+
int
|
|
46
67
|
ca_refer_setup (CARefer *ca, CArray *parent,
|
|
47
68
|
int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes,
|
|
48
69
|
ca_size_t offset)
|
|
49
70
|
{
|
|
50
|
-
ca_size_t elements,
|
|
71
|
+
ca_size_t elements, strides[CA_RANK_MAX];
|
|
72
|
+
ca_size_t parent_bytes = parent->bytes;
|
|
73
|
+
ca_size_t base_offset;
|
|
74
|
+
ca_size_t s;
|
|
51
75
|
int8_t i;
|
|
52
|
-
int is_deformed;
|
|
53
76
|
|
|
54
77
|
CA_CHECK_DATA_TYPE(data_type);
|
|
55
78
|
CA_CHECK_RANK(ndim);
|
|
56
79
|
CA_CHECK_DIM(ndim, dim);
|
|
57
80
|
CA_CHECK_BYTES(data_type, bytes);
|
|
58
81
|
|
|
59
|
-
if (
|
|
60
|
-
rb_raise(rb_eRuntimeError,
|
|
82
|
+
if (ca_is_object_type(parent) && data_type != CA_OBJECT) {
|
|
83
|
+
rb_raise(rb_eRuntimeError,
|
|
84
|
+
"object array can't be referred by other data type");
|
|
61
85
|
}
|
|
62
|
-
|
|
63
|
-
if ( parent->elements && bytes > parent->bytes * parent->elements ) {
|
|
86
|
+
if (parent->elements && bytes > parent_bytes * parent->elements) {
|
|
64
87
|
rb_raise(rb_eRuntimeError, "bytes exceeds the data size of referent");
|
|
65
88
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
ratio = 1;
|
|
70
|
-
elements = 1;
|
|
71
|
-
for (i=0; i<ndim; i++) {
|
|
72
|
-
elements *= dim[i];
|
|
73
|
-
if ( dim[i] != parent->dim[i] ) {
|
|
74
|
-
is_deformed |= 1;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
if ( bytes < parent->bytes ) {
|
|
78
|
-
if ( parent->bytes % bytes != 0 ) {
|
|
79
|
-
rb_raise(rb_eRuntimeError, "bytes of reference array must be a multiple of that of referent");
|
|
80
|
-
}
|
|
81
|
-
is_deformed = -2;
|
|
82
|
-
ratio = parent->bytes / bytes;
|
|
89
|
+
if (bytes < parent_bytes && parent_bytes % bytes != 0) {
|
|
90
|
+
rb_raise(rb_eRuntimeError,
|
|
91
|
+
"bytes of reference array must be a multiple of that of referent");
|
|
83
92
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
is_deformed = 2;
|
|
89
|
-
ratio = bytes / parent->bytes;
|
|
93
|
+
if (bytes > parent_bytes && bytes % parent_bytes != 0) {
|
|
94
|
+
rb_raise(rb_eRuntimeError,
|
|
95
|
+
"bytes of reference array must be a multiple of that of referent");
|
|
90
96
|
}
|
|
91
|
-
if (
|
|
97
|
+
if (offset < 0) {
|
|
92
98
|
rb_raise(rb_eRuntimeError, "negative offset is not permitted for CARefer");
|
|
93
99
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
100
|
+
elements = 1;
|
|
101
|
+
for (i = 0; i < ndim; i++) elements *= dim[i];
|
|
102
|
+
if ((bytes * elements + parent_bytes * offset) >
|
|
103
|
+
(parent_bytes * parent->elements)) {
|
|
104
|
+
rb_raise(rb_eRuntimeError,
|
|
105
|
+
"data size of reference array must not exceed that of referent");
|
|
98
106
|
}
|
|
99
107
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
ca->elements = elements;
|
|
106
|
-
ca->dim = ALLOC_N(ca_size_t, ndim);
|
|
107
|
-
ca->ptr = NULL;
|
|
108
|
-
ca->mask = NULL;
|
|
109
|
-
ca->mask0 = NULL;
|
|
110
|
-
|
|
111
|
-
ca->parent = parent;
|
|
112
|
-
ca->attach = 0;
|
|
113
|
-
ca->nosync = 0;
|
|
114
|
-
|
|
115
|
-
ca->is_deformed = (int8_t) is_deformed;
|
|
116
|
-
ca->ratio = ratio;
|
|
117
|
-
ca->offset = offset;
|
|
118
|
-
|
|
119
|
-
if ( ca->offset > 0 && ca->is_deformed == 0 ) {
|
|
120
|
-
ca->is_deformed = 1;
|
|
108
|
+
/* strides: row-major contiguous over the view's own dim, in view bytes */
|
|
109
|
+
s = bytes;
|
|
110
|
+
for (i = ndim - 1; i >= 0; i--) {
|
|
111
|
+
strides[i] = s;
|
|
112
|
+
s *= dim[i];
|
|
121
113
|
}
|
|
114
|
+
/* base_offset is in bytes: `offset` is in parent-element units. */
|
|
115
|
+
base_offset = offset * parent_bytes;
|
|
116
|
+
|
|
117
|
+
/* CAREFUL: initialise mask0 before ca_stride_setup — the setup
|
|
118
|
+
may dispatch to ca_refer_func_create_mask, which writes to
|
|
119
|
+
mask0. Leaving it uninitialised risks freeing a garbage
|
|
120
|
+
pointer during error unwind. */
|
|
121
|
+
ca->mask0 = NULL;
|
|
122
122
|
|
|
123
|
-
|
|
123
|
+
ca_stride_setup((CAStride *) ca, CA_OBJ_REFER, parent,
|
|
124
|
+
data_type, bytes, ndim, dim, strides, base_offset);
|
|
124
125
|
|
|
125
|
-
if (
|
|
126
|
+
if (ca_is_scalar(parent)) {
|
|
126
127
|
ca_set_flag(ca, CA_FLAG_SCALAR);
|
|
127
128
|
}
|
|
128
|
-
|
|
129
129
|
return 0;
|
|
130
130
|
}
|
|
131
131
|
|
|
@@ -134,7 +134,7 @@ ca_refer_new (CArray *parent,
|
|
|
134
134
|
int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes,
|
|
135
135
|
ca_size_t offset)
|
|
136
136
|
{
|
|
137
|
-
CARefer *ca =
|
|
137
|
+
CARefer *ca = (CARefer *) ca_array_alloc(CA_OBJ_REFER, ndim);
|
|
138
138
|
ca_refer_setup(ca, parent, data_type, ndim, dim, bytes, offset);
|
|
139
139
|
return ca;
|
|
140
140
|
}
|
|
@@ -143,351 +143,81 @@ static void
|
|
|
143
143
|
free_ca_refer (void *ap)
|
|
144
144
|
{
|
|
145
145
|
CARefer *ca = (CARefer *) ap;
|
|
146
|
-
if (
|
|
146
|
+
if (ca == NULL) return;
|
|
147
|
+
/* Free the byte-reinterpret intermediate mask, if any. */
|
|
148
|
+
ca_free(ca->mask0);
|
|
149
|
+
/* The rest mirrors free_ca_stride. */
|
|
150
|
+
ca_free(ca->mask);
|
|
151
|
+
if (ca->_pool) {
|
|
152
|
+
ca_array_free(ca);
|
|
153
|
+
} else {
|
|
154
|
+
xfree(ca->strides);
|
|
147
155
|
xfree(ca->dim);
|
|
148
|
-
ca_free(ca->mask);
|
|
149
|
-
ca_free(ca->mask0);
|
|
150
156
|
xfree(ca);
|
|
151
157
|
}
|
|
152
158
|
}
|
|
153
159
|
|
|
154
|
-
/* ------------------------------------------------------------------- */
|
|
155
|
-
|
|
156
160
|
static void *
|
|
157
161
|
ca_refer_func_clone (void *ap)
|
|
158
162
|
{
|
|
159
163
|
CARefer *ca = (CARefer *) ap;
|
|
160
|
-
return ca_refer_new(ca->parent,
|
|
161
|
-
ca->
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
static char *
|
|
165
|
-
ca_refer_func_ptr_at_addr (void *ap, ca_size_t addr)
|
|
166
|
-
{
|
|
167
|
-
CARefer *ca = (CARefer *) ap;
|
|
168
|
-
ca_size_t minor;
|
|
169
|
-
switch ( ca->is_deformed ) {
|
|
170
|
-
case 0:
|
|
171
|
-
case 1:
|
|
172
|
-
return ca->ptr + ca->bytes * addr;
|
|
173
|
-
case -2:
|
|
174
|
-
minor = (addr * ca->bytes) % ca->parent->bytes;
|
|
175
|
-
return ca->ptr + ca->bytes * addr + minor;
|
|
176
|
-
case 2:
|
|
177
|
-
return ca->ptr + ca->bytes * (addr * ca->ratio);
|
|
178
|
-
default:
|
|
179
|
-
rb_raise(rb_eRuntimeError, "[BUG]");
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
static char *
|
|
184
|
-
ca_refer_func_ptr_at_index (void *ap, ca_size_t *idx)
|
|
185
|
-
{
|
|
186
|
-
CARefer *ca = (CARefer*) ap;
|
|
187
|
-
ca_size_t *dim = ca->dim;
|
|
188
|
-
int8_t i;
|
|
189
|
-
ca_size_t n;
|
|
190
|
-
n = idx[0]; /* n = idx[0]*dim[1]*dim[2]*...*dim[ndim-1] */
|
|
191
|
-
for (i=1; i<ca->ndim; i++) { /* + idx[1]*dim[1]*dim[2]*...*dim[ndim-1] */
|
|
192
|
-
n = dim[i]*n+idx[i]; /* ... + idx[ndim-2]*dim[1] + idx[ndim-1] */
|
|
193
|
-
}
|
|
194
|
-
return ca->ptr + ca->bytes * n;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
static void
|
|
198
|
-
ca_refer_func_fetch_addr (void *ap, ca_size_t addr, void *ptr)
|
|
199
|
-
{
|
|
200
|
-
CARefer *ca = (CARefer *) ap;
|
|
201
|
-
ca_size_t major, minor;
|
|
202
|
-
switch ( ca->is_deformed ) {
|
|
203
|
-
case 0:
|
|
204
|
-
ca_fetch_addr(ca->parent, addr, ptr);
|
|
205
|
-
case 1:
|
|
206
|
-
ca_fetch_addr(ca->parent, addr + ca->offset, ptr);
|
|
207
|
-
break;
|
|
208
|
-
case -2: {
|
|
209
|
-
major = (addr * ca->bytes) / ca->parent->bytes;
|
|
210
|
-
minor = (addr * ca->bytes) % ca->parent->bytes;
|
|
211
|
-
if ( ca->parent->bytes <= 256 ) {
|
|
212
|
-
char val[256];
|
|
213
|
-
ca_fetch_addr(ca->parent, major + ca->offset, val);
|
|
214
|
-
memcpy(ptr, val+minor, ca->bytes);
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
char *val = malloc_with_check(ca->parent->bytes);
|
|
218
|
-
ca_fetch_addr(ca->parent, major + ca->offset, val);
|
|
219
|
-
memcpy(ptr, val+minor, ca->bytes);
|
|
220
|
-
free(val);
|
|
221
|
-
}
|
|
222
|
-
break;
|
|
223
|
-
}
|
|
224
|
-
case 2: {
|
|
225
|
-
int i;
|
|
226
|
-
for (i=0; i<ca->ratio; i++) {
|
|
227
|
-
ca_fetch_addr(ca->parent,
|
|
228
|
-
addr * ca->ratio + i + ca->offset,
|
|
229
|
-
(char *) ptr + i * ca->parent->bytes);
|
|
230
|
-
}
|
|
231
|
-
break;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
static void
|
|
237
|
-
ca_refer_func_fetch_index (void *ap, ca_size_t *idx, void *ptr)
|
|
238
|
-
{
|
|
239
|
-
CARefer *ca = (CARefer *) ap;
|
|
240
|
-
if ( ca->is_deformed ) {
|
|
241
|
-
ca_size_t *dim = ca->dim;
|
|
242
|
-
int8_t i;
|
|
243
|
-
ca_size_t n;
|
|
244
|
-
n = idx[0];
|
|
245
|
-
for (i=1; i<ca->ndim; i++) {
|
|
246
|
-
n = dim[i]*n+idx[i];
|
|
247
|
-
}
|
|
248
|
-
ca_refer_func_fetch_addr(ca, n, ptr);
|
|
249
|
-
}
|
|
250
|
-
else {
|
|
251
|
-
ca_fetch_index(ca->parent, idx, ptr);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
static void
|
|
256
|
-
ca_refer_func_store_addr (void *ap, ca_size_t addr, void *ptr)
|
|
257
|
-
{
|
|
258
|
-
CARefer *ca = (CARefer *) ap;
|
|
259
|
-
ca_size_t major, minor;
|
|
260
|
-
switch ( ca->is_deformed ) {
|
|
261
|
-
case 0:
|
|
262
|
-
ca_store_addr(ca->parent, addr, ptr);
|
|
263
|
-
break;
|
|
264
|
-
case 1:
|
|
265
|
-
ca_store_addr(ca->parent, addr + ca->offset, ptr);
|
|
266
|
-
break;
|
|
267
|
-
case -2: {
|
|
268
|
-
major = (addr * ca->bytes) / ca->parent->bytes;
|
|
269
|
-
minor = (addr * ca->bytes) % ca->parent->bytes;
|
|
270
|
-
if ( ca->parent->bytes <= 256 ) {
|
|
271
|
-
char val[256];
|
|
272
|
-
ca_fetch_addr(ca->parent, major + ca->offset, val);
|
|
273
|
-
memcpy(val+minor, ptr, ca->bytes);
|
|
274
|
-
ca_store_addr(ca->parent, major + ca->offset, val);
|
|
275
|
-
}
|
|
276
|
-
else {
|
|
277
|
-
char *val = malloc_with_check(ca->parent->bytes);
|
|
278
|
-
ca_fetch_addr(ca->parent, major + ca->offset, val);
|
|
279
|
-
memcpy(val+minor, ptr, ca->bytes);
|
|
280
|
-
ca_store_addr(ca->parent, major + ca->offset, val);
|
|
281
|
-
free(val);
|
|
282
|
-
}
|
|
283
|
-
break;
|
|
284
|
-
}
|
|
285
|
-
case 2: {
|
|
286
|
-
int i;
|
|
287
|
-
for (i=0; i<ca->ratio; i++) {
|
|
288
|
-
ca_store_addr(ca->parent,
|
|
289
|
-
addr * ca->ratio + i + ca->offset,
|
|
290
|
-
(char *) ptr + i * ca->parent->bytes);
|
|
291
|
-
}
|
|
292
|
-
break;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
static void
|
|
298
|
-
ca_refer_func_store_index (void *ap, ca_size_t *idx, void *ptr)
|
|
299
|
-
{
|
|
300
|
-
CARefer *ca = (CARefer *) ap;
|
|
301
|
-
if ( ca->is_deformed ) {
|
|
302
|
-
ca_size_t *dim = ca->dim;
|
|
303
|
-
int8_t i;
|
|
304
|
-
ca_size_t n;
|
|
305
|
-
n = idx[0];
|
|
306
|
-
for (i=1; i<ca->ndim; i++) {
|
|
307
|
-
n = dim[i]*n+idx[i];
|
|
308
|
-
}
|
|
309
|
-
ca_refer_func_store_addr(ca, n, ptr);
|
|
310
|
-
}
|
|
311
|
-
else {
|
|
312
|
-
ca_store_index(ca->parent, idx, ptr);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
static void
|
|
317
|
-
ca_refer_func_allocate (void *ap)
|
|
318
|
-
{
|
|
319
|
-
CARefer *ca = (CARefer *) ap;
|
|
320
|
-
ca_allocate(ca->parent);
|
|
321
|
-
ca->ptr = ca->parent->ptr + ca->parent->bytes * ca->offset;
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
static void
|
|
326
|
-
ca_refer_func_attach (void *ap)
|
|
327
|
-
{
|
|
328
|
-
CARefer *ca = (CARefer *) ap;
|
|
329
|
-
ca_attach(ca->parent);
|
|
330
|
-
ca->ptr = ca->parent->ptr + ca->parent->bytes * ca->offset;
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
static void
|
|
335
|
-
ca_refer_func_sync (void *ap)
|
|
336
|
-
{
|
|
337
|
-
CARefer *ca = (CARefer *) ap;
|
|
338
|
-
ca_sync(ca->parent);
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
static void
|
|
343
|
-
ca_refer_func_detach (void *ap)
|
|
344
|
-
{
|
|
345
|
-
CARefer *ca = (CARefer *) ap;
|
|
346
|
-
ca->ptr = NULL;
|
|
347
|
-
ca_detach(ca->parent);
|
|
348
|
-
return;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
static void
|
|
352
|
-
ca_refer_func_copy_data (void *ap, void *ptr)
|
|
353
|
-
{
|
|
354
|
-
CARefer *ca = (CARefer *) ap;
|
|
355
|
-
if ( ptr != ca->ptr ) {
|
|
356
|
-
ca_attach(ca->parent);
|
|
357
|
-
memmove(ptr,
|
|
358
|
-
ca->parent->ptr + ca->parent->bytes * ca->offset,
|
|
359
|
-
ca_length(ca));
|
|
360
|
-
ca_detach(ca->parent);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
static void
|
|
365
|
-
ca_refer_func_sync_data (void *ap, void *ptr)
|
|
366
|
-
{
|
|
367
|
-
CARefer *ca = (CARefer *) ap;
|
|
368
|
-
if ( ptr != ca->ptr ) {
|
|
369
|
-
ca_allocate(ca->parent);
|
|
370
|
-
memmove(ca->parent->ptr + ca->parent->bytes * ca->offset,
|
|
371
|
-
ptr,
|
|
372
|
-
ca_length(ca));
|
|
373
|
-
ca_sync(ca->parent);
|
|
374
|
-
ca_detach(ca->parent);
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
#define proc_fill_bang_fixlen() \
|
|
379
|
-
{ \
|
|
380
|
-
ca_size_t i; \
|
|
381
|
-
ca_size_t bytes = ca->bytes; \
|
|
382
|
-
char *p = ca->parent->ptr + ca->parent->bytes * ca->offset; \
|
|
383
|
-
for (i=ca->elements; i; i--, p+=bytes) { \
|
|
384
|
-
memcpy(p, val, bytes); \
|
|
385
|
-
} \
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
#define proc_fill_bang(type) \
|
|
389
|
-
{ \
|
|
390
|
-
ca_size_t i; \
|
|
391
|
-
type *p = (type *)(ca->parent->ptr + ca->parent->bytes * ca->offset); \
|
|
392
|
-
type v = *(type *)val; \
|
|
393
|
-
for (i=ca->elements; i; i--, p++) { \
|
|
394
|
-
*p = v; \
|
|
395
|
-
} \
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
static void
|
|
399
|
-
ca_refer_func_fill_data (void *ap, void *val)
|
|
400
|
-
{
|
|
401
|
-
CARefer *ca = (CARefer *) ap;
|
|
402
|
-
|
|
403
|
-
ca_allocate(ca->parent);
|
|
404
|
-
|
|
405
|
-
switch ( ca->data_type ) {
|
|
406
|
-
case CA_FIXLEN: proc_fill_bang_fixlen(); break;
|
|
407
|
-
case CA_BOOLEAN:
|
|
408
|
-
case CA_INT8:
|
|
409
|
-
case CA_UINT8: proc_fill_bang(int8_t); break;
|
|
410
|
-
case CA_INT16:
|
|
411
|
-
case CA_UINT16: proc_fill_bang(int16_t); break;
|
|
412
|
-
case CA_INT32:
|
|
413
|
-
case CA_UINT32:
|
|
414
|
-
case CA_FLOAT32: proc_fill_bang(int32_t); break;
|
|
415
|
-
case CA_INT64:
|
|
416
|
-
case CA_UINT64:
|
|
417
|
-
case CA_FLOAT64: proc_fill_bang(float64_t); break;
|
|
418
|
-
case CA_FLOAT128: proc_fill_bang(float128_t); break;
|
|
419
|
-
#ifdef HAVE_COMPLEX_H
|
|
420
|
-
case CA_CMPLX64: proc_fill_bang(cmplx64_t); break;
|
|
421
|
-
case CA_CMPLX128: proc_fill_bang(cmplx128_t); break;
|
|
422
|
-
case CA_CMPLX256: proc_fill_bang(cmplx256_t); break;
|
|
423
|
-
#endif
|
|
424
|
-
case CA_OBJECT: proc_fill_bang(VALUE); break;
|
|
425
|
-
default: rb_bug("array has an unknown data type");
|
|
426
|
-
}
|
|
427
|
-
ca_sync(ca->parent);
|
|
428
|
-
ca_detach(ca->parent);
|
|
164
|
+
return ca_refer_new(ca->parent, ca->data_type, ca->ndim, ca->dim,
|
|
165
|
+
ca->bytes, ca->base_offset / ca->parent->bytes);
|
|
429
166
|
}
|
|
430
167
|
|
|
431
168
|
static void
|
|
432
169
|
ca_refer_func_create_mask (void *ap)
|
|
433
170
|
{
|
|
434
171
|
CARefer *ca = (CARefer *) ap;
|
|
172
|
+
ca_size_t parent_bytes = ca->parent->bytes;
|
|
173
|
+
ca_size_t parent_offset;
|
|
435
174
|
|
|
436
175
|
ca_update_mask(ca->parent);
|
|
437
|
-
if (
|
|
176
|
+
if (! ca->parent->mask) {
|
|
438
177
|
ca_create_mask(ca->parent);
|
|
439
178
|
}
|
|
440
179
|
|
|
441
|
-
|
|
180
|
+
parent_offset = ca->base_offset / parent_bytes;
|
|
181
|
+
|
|
182
|
+
if (ca->bytes == parent_bytes) {
|
|
183
|
+
/* Same-width reinterpret / reshape. Mask is a CARefer over
|
|
184
|
+
the parent's mask with the same logical shape and offset. */
|
|
442
185
|
ca->mask =
|
|
443
186
|
(CArray *) ca_refer_new(ca->parent->mask,
|
|
444
|
-
CA_BOOLEAN, ca->ndim, ca->dim, 0,
|
|
445
|
-
}
|
|
446
|
-
else if (
|
|
187
|
+
CA_BOOLEAN, ca->ndim, ca->dim, 0, parent_offset);
|
|
188
|
+
}
|
|
189
|
+
else if (ca->bytes < parent_bytes) {
|
|
190
|
+
/* Divided reinterpret: one parent element splits into
|
|
191
|
+
ratio = parent_bytes / bytes view elements. Build a
|
|
192
|
+
CARepeat that broadcasts each parent mask bit across the
|
|
193
|
+
ratio sub-positions, then refer-reshape it to the view's
|
|
194
|
+
actual shape. */
|
|
195
|
+
ca_size_t ratio = parent_bytes / ca->bytes;
|
|
447
196
|
ca_size_t count[CA_RANK_MAX];
|
|
448
|
-
|
|
449
|
-
for (i=0; i<ca->parent->ndim; i++)
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
ca->mask0 =
|
|
454
|
-
(CArray *) ca_repeat_new(ca->parent->mask, ca->parent->ndim+1, count);
|
|
197
|
+
int8_t i;
|
|
198
|
+
for (i = 0; i < ca->parent->ndim; i++) count[i] = 0;
|
|
199
|
+
count[ca->parent->ndim] = ratio;
|
|
200
|
+
ca->mask0 =
|
|
201
|
+
(CArray *) ca_repeat_new(ca->parent->mask, ca->parent->ndim + 1, count);
|
|
455
202
|
ca_unset_flag(ca->mask0, CA_FLAG_READ_ONLY);
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
CA_BOOLEAN, ca->ndim, ca->dim, 0, ca->offset);
|
|
203
|
+
ca->mask =
|
|
204
|
+
(CArray *) ca_refer_new(ca->mask0,
|
|
205
|
+
CA_BOOLEAN, ca->ndim, ca->dim, 0, parent_offset);
|
|
460
206
|
}
|
|
461
|
-
else
|
|
462
|
-
/*
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
207
|
+
else {
|
|
208
|
+
/* Spanned reinterpret: ratio = bytes / parent_bytes parent
|
|
209
|
+
elements fold into one view element. Build a CAReduce that
|
|
210
|
+
OR-reduces the ratio adjacent parent mask bits into one
|
|
211
|
+
mask bit, then refer-reshape to the view's shape. */
|
|
212
|
+
ca_size_t ratio = ca->bytes / parent_bytes;
|
|
213
|
+
ca->mask0 =
|
|
214
|
+
(CArray *) ca_reduce_new(ca->parent->mask, ratio, parent_offset);
|
|
215
|
+
ca->mask =
|
|
216
|
+
(CArray *) ca_refer_new(ca->mask0,
|
|
217
|
+
CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
|
|
467
218
|
}
|
|
468
219
|
}
|
|
469
220
|
|
|
470
|
-
ca_operation_function_t ca_refer_func = {
|
|
471
|
-
CA_OBJ_REFER,
|
|
472
|
-
CA_VIRTUAL_ARRAY,
|
|
473
|
-
free_ca_refer,
|
|
474
|
-
ca_refer_func_clone,
|
|
475
|
-
ca_refer_func_ptr_at_addr,
|
|
476
|
-
ca_refer_func_ptr_at_index,
|
|
477
|
-
ca_refer_func_fetch_addr,
|
|
478
|
-
ca_refer_func_fetch_index,
|
|
479
|
-
ca_refer_func_store_addr,
|
|
480
|
-
ca_refer_func_store_index,
|
|
481
|
-
ca_refer_func_allocate,
|
|
482
|
-
ca_refer_func_attach,
|
|
483
|
-
ca_refer_func_sync,
|
|
484
|
-
ca_refer_func_detach,
|
|
485
|
-
ca_refer_func_copy_data,
|
|
486
|
-
ca_refer_func_sync_data,
|
|
487
|
-
ca_refer_func_fill_data,
|
|
488
|
-
ca_refer_func_create_mask,
|
|
489
|
-
};
|
|
490
|
-
|
|
491
221
|
/* ------------------------------------------------------------------- */
|
|
492
222
|
|
|
493
223
|
static VALUE
|
|
@@ -501,31 +231,175 @@ static VALUE
|
|
|
501
231
|
rb_ca_refer_initialize_copy (VALUE self, VALUE other)
|
|
502
232
|
{
|
|
503
233
|
CARefer *ca, *cs;
|
|
504
|
-
|
|
505
234
|
TypedData_Get_Struct(self, CARefer, &carefer_data_type, ca);
|
|
506
235
|
TypedData_Get_Struct(other, CARefer, &carefer_data_type, cs);
|
|
507
|
-
|
|
236
|
+
if ( ca_func[CA_OBJ_REFER].pool_init ) {
|
|
237
|
+
ca_array_pool_alloc(ca, CA_OBJ_REFER, cs->ndim);
|
|
238
|
+
}
|
|
239
|
+
/* CAREFUL: rebuild through ca_refer_setup's (data_type, ndim,
|
|
240
|
+
dim, bytes, offset) form. The CAStride (strides, base_offset)
|
|
241
|
+
form would lose the parent-element offset semantics on
|
|
242
|
+
unusual mod-bytes alignments. */
|
|
508
243
|
ca_refer_setup(ca, cs->parent, cs->data_type, cs->ndim, cs->dim,
|
|
509
|
-
|
|
510
|
-
|
|
244
|
+
cs->bytes, cs->base_offset / cs->parent->bytes);
|
|
511
245
|
return self;
|
|
512
246
|
}
|
|
513
247
|
|
|
514
|
-
/*
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
248
|
+
/* Reshape-stride rewrite.
|
|
249
|
+
*
|
|
250
|
+
* Try to express `parent` reshaped to `new_dim` as a CAStride over
|
|
251
|
+
* the deepest non-CAStride ancestor (returned in *out_root) with
|
|
252
|
+
* explicit strides + base_offset in that root's byte coord. Used
|
|
253
|
+
* by rb_ca_reshape and rb_ca_flatten before falling back to
|
|
254
|
+
* ca_refer_new.
|
|
255
|
+
*
|
|
256
|
+
* Pre-conditions (contract from the callers):
|
|
257
|
+
* - product of new_dim == parent->elements
|
|
258
|
+
* - bytes (== parent->bytes) and data_type (== parent->data_type)
|
|
259
|
+
* unchanged, offset == 0 implicit
|
|
260
|
+
*
|
|
261
|
+
* Returns 1 on success with *out_root, out_strides[0..new_ndim-1]
|
|
262
|
+
* and *out_base filled. The caller then constructs
|
|
263
|
+
* ca_stride_new(CA_OBJ_STRIDE, *out_root, ..., out_strides, *out_base);
|
|
264
|
+
* the CAStride's parent is *out_root (not the immediate caller
|
|
265
|
+
* parent), which lets compose-fold treat the whole reshape as a
|
|
266
|
+
* single-step gather from the entity.
|
|
267
|
+
*
|
|
268
|
+
* Returns 0 on failure: the caller must fall back to ca_refer_new.
|
|
269
|
+
*
|
|
270
|
+
* Algorithm:
|
|
271
|
+
* 1. Resolve parent into (root, root_strides, root_base) via
|
|
272
|
+
* ca_stride_compose_to_root for the CAStride family, or
|
|
273
|
+
* row-major derivation for a plain CArray entity. Other
|
|
274
|
+
* obj_types fail immediately.
|
|
275
|
+
* 2. Match ranges of parent axes to new axes so element products
|
|
276
|
+
* agree. Inside each matched range, root_strides must be
|
|
277
|
+
* inter-axis contiguous. */
|
|
278
|
+
static int
|
|
279
|
+
ca_reshape_try_strides (CArray *parent,
|
|
280
|
+
const ca_size_t *new_dim,
|
|
281
|
+
int8_t new_ndim,
|
|
282
|
+
CArray **out_root,
|
|
283
|
+
ca_size_t *out_strides,
|
|
284
|
+
ca_size_t *out_base)
|
|
285
|
+
{
|
|
286
|
+
ca_size_t pstrides_buf[CA_RANK_MAX];
|
|
287
|
+
ca_size_t pstrides_composed[CA_RANK_MAX];
|
|
288
|
+
const ca_size_t *pstrides;
|
|
289
|
+
ca_size_t pbase;
|
|
290
|
+
ca_size_t bytes = parent->bytes;
|
|
291
|
+
int8_t pndim = parent->ndim;
|
|
292
|
+
int8_t k;
|
|
293
|
+
CArray *root;
|
|
294
|
+
|
|
295
|
+
/* Resolve parent into (root, pstrides, pbase) in root's byte coord. */
|
|
296
|
+
if (ca_func[parent->obj_type].attach == ca_stride_func.attach) {
|
|
297
|
+
/* CAStride family: fold the parent's own view through its
|
|
298
|
+
ancestor chain, producing strides + base in the deepest
|
|
299
|
+
non-CAStride ancestor's coord. */
|
|
300
|
+
ca_stride_compose_to_root((CAStride *) parent,
|
|
301
|
+
&root, pstrides_composed, &pbase);
|
|
302
|
+
pstrides = pstrides_composed;
|
|
303
|
+
} else if (parent->obj_type == CA_OBJ_ARRAY
|
|
304
|
+
|| parent->obj_type == CA_OBJ_ARRAY_WRAP
|
|
305
|
+
|| parent->obj_type == CA_OBJ_SCALAR) {
|
|
306
|
+
/* Plain CArray entity: row-major contig, base 0. */
|
|
307
|
+
ca_size_t s = bytes;
|
|
308
|
+
for (k = pndim - 1; k >= 0; k--) {
|
|
309
|
+
pstrides_buf[k] = s;
|
|
310
|
+
s *= parent->dim[k];
|
|
311
|
+
}
|
|
312
|
+
pstrides = pstrides_buf;
|
|
313
|
+
pbase = 0;
|
|
314
|
+
root = parent;
|
|
315
|
+
(void) pstrides_composed;
|
|
316
|
+
} else {
|
|
317
|
+
/* CASelect / CAReduce / CAGrid / CAObject / CAField etc. — no usable
|
|
318
|
+
strides representation for reshape rewrite. */
|
|
319
|
+
return 0;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
*out_root = root;
|
|
323
|
+
|
|
324
|
+
/* Zero-element corner case: nothing to gather; trivial reshape. */
|
|
325
|
+
if (parent->elements == 0) {
|
|
326
|
+
for (k = 0; k < new_ndim; k++) out_strides[k] = 0;
|
|
327
|
+
*out_base = pbase;
|
|
328
|
+
return 1;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/* Scalar reshape (new_ndim == 0) only valid if elements == 1 — but
|
|
332
|
+
CArray's reshape rejects argc==0 earlier; defensive return for safety. */
|
|
333
|
+
if (new_ndim == 0) {
|
|
334
|
+
*out_base = pbase;
|
|
335
|
+
return parent->elements == 1 ? 1 : 0;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/* Match ranges outer-to-inner. Skip dim==1 axes on either side
|
|
339
|
+
(they contribute no displacement; we'll assign stride 0 to dim==1
|
|
340
|
+
new axes after matching). */
|
|
341
|
+
int8_t oi = 0, ni = 0;
|
|
342
|
+
|
|
343
|
+
while (oi < pndim && ni < new_ndim) {
|
|
344
|
+
/* Skip leading dim==1 new axes (no parent axis consumed) */
|
|
345
|
+
if (new_dim[ni] == 1) {
|
|
346
|
+
out_strides[ni] = 0;
|
|
347
|
+
ni++;
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
/* Skip leading dim==1 parent axes (no contribution) */
|
|
351
|
+
if (parent->dim[oi] == 1) {
|
|
352
|
+
oi++;
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
int8_t oj = oi + 1;
|
|
357
|
+
int8_t nj = ni + 1;
|
|
358
|
+
ca_size_t old_prod = parent->dim[oi];
|
|
359
|
+
ca_size_t new_prod = new_dim[ni];
|
|
360
|
+
|
|
361
|
+
while (old_prod != new_prod) {
|
|
362
|
+
if (old_prod < new_prod) {
|
|
363
|
+
/* Need to extend old range; require inter-axis contig */
|
|
364
|
+
if (oj >= pndim) return 0;
|
|
365
|
+
if (parent->dim[oj] == 0) return 0; /* shouldn't happen */
|
|
366
|
+
if (pstrides[oj - 1] != pstrides[oj] * parent->dim[oj]) return 0;
|
|
367
|
+
old_prod *= parent->dim[oj];
|
|
368
|
+
oj++;
|
|
369
|
+
} else {
|
|
370
|
+
if (nj >= new_ndim) return 0;
|
|
371
|
+
if (new_dim[nj] == 0) return 0;
|
|
372
|
+
new_prod *= new_dim[nj];
|
|
373
|
+
nj++;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/* Range matched: assign strides to new axes [ni..nj).
|
|
378
|
+
Innermost gets parent's innermost stride in the matched old range.
|
|
379
|
+
Outer new axes scale by following new_dim. */
|
|
380
|
+
out_strides[nj - 1] = pstrides[oj - 1];
|
|
381
|
+
for (k = nj - 2; k >= ni; k--) {
|
|
382
|
+
out_strides[k] = out_strides[k + 1] * new_dim[k + 1];
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
oi = oj;
|
|
386
|
+
ni = nj;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/* Trailing dim==1 axes in either side */
|
|
390
|
+
while (ni < new_ndim) {
|
|
391
|
+
if (new_dim[ni] != 1) return 0;
|
|
392
|
+
out_strides[ni] = 0;
|
|
393
|
+
ni++;
|
|
394
|
+
}
|
|
395
|
+
while (oi < pndim) {
|
|
396
|
+
if (parent->dim[oi] != 1) return 0;
|
|
397
|
+
oi++;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
*out_base = pbase;
|
|
401
|
+
return 1;
|
|
402
|
+
}
|
|
529
403
|
|
|
530
404
|
static VALUE
|
|
531
405
|
rb_ca_refer (int argc, VALUE *argv, VALUE self)
|
|
@@ -541,85 +415,66 @@ rb_ca_refer (int argc, VALUE *argv, VALUE self)
|
|
|
541
415
|
|
|
542
416
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
543
417
|
|
|
544
|
-
if (
|
|
418
|
+
if (argc == 0) {
|
|
545
419
|
data_type = ca->data_type;
|
|
546
420
|
bytes = ca->bytes;
|
|
547
421
|
ndim = ca->ndim;
|
|
548
|
-
for (i=0; i<ndim; i++)
|
|
549
|
-
|
|
550
|
-
}
|
|
551
|
-
cr = ca_refer_new((CArray*)ca, data_type, ndim, dim, bytes, offset);
|
|
422
|
+
for (i = 0; i < ndim; i++) dim[i] = ca->dim[i];
|
|
423
|
+
cr = ca_refer_new((CArray *) ca, data_type, ndim, dim, bytes, offset);
|
|
552
424
|
obj = ca_wrap_struct(cr);
|
|
553
425
|
rb_ca_set_parent(obj, self);
|
|
554
|
-
rb_ca_data_type_inherit(obj, self);
|
|
555
426
|
}
|
|
556
427
|
else {
|
|
557
428
|
volatile VALUE rtype, rdim, ropt, rbytes = Qnil, roffset = Qnil;
|
|
558
|
-
|
|
559
429
|
ropt = rb_pop_options(&argc, &argv);
|
|
560
430
|
rb_scan_args(argc, argv, "11", (VALUE *) &rtype, (VALUE *) &rdim);
|
|
561
431
|
rb_scan_options(ropt, "bytes,offset", &rbytes, &roffset);
|
|
562
|
-
|
|
563
|
-
if ( NIL_P(rbytes) ) {
|
|
564
|
-
rbytes = rb_ca_bytes(self);
|
|
565
|
-
}
|
|
566
|
-
|
|
432
|
+
if (NIL_P(rbytes)) rbytes = rb_ca_bytes(self);
|
|
567
433
|
rb_ca_guess_type_and_bytes(rtype, rbytes, &data_type, &bytes);
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
rb_raise(rb_eRuntimeError,
|
|
434
|
+
if (NIL_P(rdim)) {
|
|
435
|
+
if (ca->bytes != bytes) {
|
|
436
|
+
rb_raise(rb_eRuntimeError,
|
|
572
437
|
"specify dimension shape for different byte size");
|
|
573
|
-
}
|
|
574
|
-
else {
|
|
438
|
+
} else {
|
|
575
439
|
rdim = rb_ca_dim(self);
|
|
576
440
|
}
|
|
577
441
|
}
|
|
578
|
-
|
|
579
442
|
Check_Type(rdim, T_ARRAY);
|
|
580
443
|
ndim = RARRAY_LEN(rdim);
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
if ( ! NIL_P(roffset) ) {
|
|
587
|
-
offset = NUM2SIZE(roffset);
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
cr = ca_refer_new((CArray*)ca, data_type, ndim, dim, bytes, offset);
|
|
444
|
+
for (i = 0; i < ndim; i++) dim[i] = NUM2SIZE(rb_ary_entry(rdim, i));
|
|
445
|
+
if (! NIL_P(roffset)) offset = NUM2SIZE(roffset);
|
|
446
|
+
cr = ca_refer_new((CArray *) ca, data_type, ndim, dim, bytes, offset);
|
|
591
447
|
obj = ca_wrap_struct(cr);
|
|
592
448
|
rb_ca_set_parent(obj, self);
|
|
593
|
-
|
|
449
|
+
/* When rtype is a data_class, wrap the result in CARecord so
|
|
450
|
+
the data_class is carried even if self is not itself a Face. */
|
|
451
|
+
if ( rb_obj_is_data_class(rtype) ) {
|
|
452
|
+
obj = rb_funcall(rb_const_get(rb_cObject, rb_intern("CARecord")),
|
|
453
|
+
rb_intern("wrap"), 2, obj, rtype);
|
|
454
|
+
return obj;
|
|
455
|
+
}
|
|
594
456
|
}
|
|
595
|
-
|
|
457
|
+
CA_FACE_LIFT_IF_FACE(obj, self, ca);
|
|
596
458
|
return obj;
|
|
597
459
|
}
|
|
598
460
|
|
|
599
|
-
/* api: rb_ca_refer_new
|
|
600
|
-
*/
|
|
601
|
-
|
|
602
461
|
VALUE
|
|
603
462
|
rb_ca_refer_new (VALUE self,
|
|
604
463
|
int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes,
|
|
605
464
|
ca_size_t offset)
|
|
606
465
|
{
|
|
607
466
|
volatile VALUE list, rdim, ropt;
|
|
608
|
-
CArray *ca;
|
|
609
467
|
int8_t i;
|
|
610
468
|
|
|
611
|
-
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
612
|
-
|
|
613
469
|
rdim = rb_ary_new2(ndim);
|
|
614
|
-
for (i=0; i<ndim; i++) {
|
|
470
|
+
for (i = 0; i < ndim; i++) {
|
|
615
471
|
rb_ary_store(rdim, i, SIZE2NUM(dim[i]));
|
|
616
472
|
}
|
|
617
473
|
|
|
618
474
|
list = rb_ary_new2(3);
|
|
619
|
-
if (
|
|
475
|
+
if (data_type == CA_FIXLEN && rb_ca_has_data_class(self)) {
|
|
620
476
|
rb_ary_store(list, 0, rb_ca_data_class(self));
|
|
621
|
-
}
|
|
622
|
-
else {
|
|
477
|
+
} else {
|
|
623
478
|
rb_ary_store(list, 0, INT2NUM(data_type));
|
|
624
479
|
}
|
|
625
480
|
rb_ary_store(list, 1, rdim);
|
|
@@ -627,21 +482,276 @@ rb_ca_refer_new (VALUE self,
|
|
|
627
482
|
rb_set_options(ropt, "bytes,offset", SIZE2NUM(bytes), SIZE2NUM(offset));
|
|
628
483
|
rb_ary_store(list, 2, ropt);
|
|
629
484
|
|
|
630
|
-
return rb_ca_refer(3,
|
|
485
|
+
return rb_ca_refer(3, (VALUE *) RARRAY_CONST_PTR(list), self);
|
|
631
486
|
}
|
|
632
487
|
|
|
488
|
+
/* CArray#reshape(*newdim) — returns a view of self with the new
|
|
489
|
+
shape (a CAStride when ca_reshape_try_strides succeeds, otherwise
|
|
490
|
+
a CARefer). Each element of `newdim` is either:
|
|
491
|
+
- Integer : the new size for that axis
|
|
492
|
+
- nil : copy from the source. Axes left of the auto-infer
|
|
493
|
+
placeholder use ca->dim[i] in position order; axes
|
|
494
|
+
to its right use ca->dim[ca->ndim - (argc - i)] so
|
|
495
|
+
trailing nils mirror trailing source axes.
|
|
496
|
+
- -1 / `:~` : one axis inferred from elements / (product of the
|
|
497
|
+
others). At most one placeholder is allowed.
|
|
498
|
+
|
|
499
|
+
Also exported (declared in carray.h) so downstream C extensions
|
|
500
|
+
can build a reshape view directly:
|
|
501
|
+
|
|
502
|
+
VALUE args[] = {INT2NUM(3), INT2NUM(2)};
|
|
503
|
+
VALUE view = rb_ca_reshape(2, args, ca);
|
|
504
|
+
|
|
505
|
+
For typed-dim usage (bypassing the placeholder vocabulary) call
|
|
506
|
+
rb_ca_refer_new(self, ca->data_type, ndim, dim, ca->bytes, 0). */
|
|
507
|
+
VALUE
|
|
508
|
+
rb_ca_reshape (int argc, VALUE *argv, VALUE self)
|
|
509
|
+
{
|
|
510
|
+
CArray *ca;
|
|
511
|
+
CARefer *cr;
|
|
512
|
+
ca_size_t new_dim[CA_RANK_MAX];
|
|
513
|
+
ca_size_t prod = 1;
|
|
514
|
+
int placeholder_idx = -1; /* axis with `-1` or `:~` infer placeholder */
|
|
515
|
+
int i;
|
|
516
|
+
volatile VALUE obj;
|
|
517
|
+
VALUE sym_tilde = ID2SYM(rb_intern("~")); /* :~ = infer-placeholder alias for -1 */
|
|
633
518
|
|
|
634
|
-
|
|
635
|
-
|
|
519
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
520
|
+
|
|
521
|
+
if (argc < 0 || argc > CA_RANK_MAX) {
|
|
522
|
+
rb_raise(rb_eArgError, "reshape: invalid number of dims (%d)", argc);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/* Locate the (at most one) auto-infer placeholder. `-1` is the
|
|
526
|
+
conventional spelling; `:~` is the unified auto-fill sigil
|
|
527
|
+
(same meaning). */
|
|
528
|
+
for (i = 0; i < argc; i++) {
|
|
529
|
+
if ( (FIXNUM_P(argv[i]) && FIX2LONG(argv[i]) == -1)
|
|
530
|
+
|| argv[i] == sym_tilde ) {
|
|
531
|
+
if (placeholder_idx >= 0) {
|
|
532
|
+
rb_raise(rb_eRuntimeError,
|
|
533
|
+
"reshape: only one auto-infer placeholder (-1 / :~) allowed");
|
|
534
|
+
}
|
|
535
|
+
placeholder_idx = i;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/* Resolve every non-placeholder axis. */
|
|
540
|
+
for (i = 0; i < argc; i++) {
|
|
541
|
+
if (i == placeholder_idx) continue;
|
|
542
|
+
if (NIL_P(argv[i])) {
|
|
543
|
+
/* Two-sweep nil resolution:
|
|
544
|
+
- With a placeholder: forward-map before it, mirror from
|
|
545
|
+
the end after.
|
|
546
|
+
- Without a placeholder: forward-map while in range,
|
|
547
|
+
otherwise mirror from the end so trailing nils pick up
|
|
548
|
+
the tail source axes (e.g. b.ndim=1, b.reshape(1, nil)
|
|
549
|
+
-> (1, 3)). */
|
|
550
|
+
int src;
|
|
551
|
+
if (placeholder_idx >= 0) {
|
|
552
|
+
src = (i < placeholder_idx) ? i : ca->ndim - (argc - i);
|
|
553
|
+
} else {
|
|
554
|
+
src = (i < ca->ndim) ? i : ca->ndim - (argc - i);
|
|
555
|
+
}
|
|
556
|
+
if (src < 0 || src >= ca->ndim) {
|
|
557
|
+
rb_raise(rb_eRuntimeError,
|
|
558
|
+
"reshape: nil at axis %d has no source dim", i);
|
|
559
|
+
}
|
|
560
|
+
new_dim[i] = ca->dim[src];
|
|
561
|
+
}
|
|
562
|
+
else {
|
|
563
|
+
new_dim[i] = NUM2SIZE(argv[i]);
|
|
564
|
+
}
|
|
565
|
+
prod *= new_dim[i];
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/* Resolve placeholder dim from the leftover total. */
|
|
569
|
+
if (placeholder_idx >= 0) {
|
|
570
|
+
if (prod == 0 || ca->elements % prod != 0) {
|
|
571
|
+
rb_raise(rb_eRuntimeError,
|
|
572
|
+
"reshape: cannot infer dim for `-1` placeholder");
|
|
573
|
+
}
|
|
574
|
+
new_dim[placeholder_idx] = ca->elements / prod;
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
/* CAREFUL: strict element conservation. Without a placeholder
|
|
578
|
+
the resolved product must equal the source element count.
|
|
579
|
+
A smaller shape would silently truncate data (a CARefer over
|
|
580
|
+
a subset), and on non-contiguous parents the compose-fold
|
|
581
|
+
path corrupts data outright — hence the raise. */
|
|
582
|
+
if (prod != ca->elements) {
|
|
583
|
+
rb_raise(rb_eRuntimeError,
|
|
584
|
+
"reshape: cannot reshape array of %lld elements into a shape "
|
|
585
|
+
"of %lld elements (use -1 / :~ to infer a dim)",
|
|
586
|
+
(long long) ca->elements, (long long) prod);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/* Try the stride rewrite first. On success, construct a
|
|
591
|
+
CAStride directly over the deepest non-CAStride ancestor
|
|
592
|
+
(out_root) with composed strides + base in that root's byte
|
|
593
|
+
coord. The Ruby-level parent ref is still `self`, so the
|
|
594
|
+
immediate parent stays alive through GC. On failure, fall
|
|
595
|
+
through to the CARefer path. */
|
|
596
|
+
{
|
|
597
|
+
CArray *out_root;
|
|
598
|
+
ca_size_t out_strides[CA_RANK_MAX];
|
|
599
|
+
ca_size_t out_base;
|
|
600
|
+
if (ca_reshape_try_strides(ca, new_dim, (int8_t) argc,
|
|
601
|
+
&out_root, out_strides, &out_base)) {
|
|
602
|
+
CAStride *cs = ca_stride_new(CA_OBJ_STRIDE, out_root,
|
|
603
|
+
ca->data_type, ca->bytes,
|
|
604
|
+
(int8_t) argc, new_dim,
|
|
605
|
+
out_strides, out_base);
|
|
606
|
+
obj = ca_wrap_struct(cs);
|
|
607
|
+
rb_ca_set_parent(obj, self);
|
|
608
|
+
CA_FACE_LIFT_IF_FACE(obj, self, ca);
|
|
609
|
+
return obj;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
cr = ca_refer_new(ca, ca->data_type, (int8_t) argc,
|
|
614
|
+
new_dim, ca->bytes, 0);
|
|
615
|
+
obj = ca_wrap_struct(cr);
|
|
616
|
+
rb_ca_set_parent(obj, self);
|
|
617
|
+
CA_FACE_LIFT_IF_FACE(obj, self, ca);
|
|
618
|
+
return obj;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/* CArray#flatten — a 1-D view of all elements in row-major order
|
|
622
|
+
(a CAStride when ca_reshape_try_strides succeeds, otherwise a
|
|
623
|
+
CARefer). Also exported (declared in carray.h). */
|
|
624
|
+
VALUE
|
|
625
|
+
rb_ca_flatten (VALUE self)
|
|
636
626
|
{
|
|
637
|
-
|
|
627
|
+
CArray *ca;
|
|
628
|
+
CARefer *cr;
|
|
629
|
+
ca_size_t dim[1];
|
|
630
|
+
volatile VALUE obj;
|
|
638
631
|
|
|
639
|
-
|
|
632
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
633
|
+
dim[0] = ca->elements;
|
|
634
|
+
|
|
635
|
+
{
|
|
636
|
+
CArray *out_root;
|
|
637
|
+
ca_size_t out_strides[1];
|
|
638
|
+
ca_size_t out_base;
|
|
639
|
+
if (ca_reshape_try_strides(ca, dim, 1, &out_root, out_strides, &out_base)) {
|
|
640
|
+
CAStride *cs = ca_stride_new(CA_OBJ_STRIDE, out_root,
|
|
641
|
+
ca->data_type, ca->bytes,
|
|
642
|
+
1, dim, out_strides, out_base);
|
|
643
|
+
obj = ca_wrap_struct(cs);
|
|
644
|
+
rb_ca_set_parent(obj, self);
|
|
645
|
+
CA_FACE_LIFT_IF_FACE(obj, self, ca);
|
|
646
|
+
return obj;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
640
649
|
|
|
641
|
-
|
|
650
|
+
cr = ca_refer_new(ca, ca->data_type, 1, dim, ca->bytes, 0);
|
|
651
|
+
obj = ca_wrap_struct(cr);
|
|
652
|
+
rb_ca_set_parent(obj, self);
|
|
653
|
+
CA_FACE_LIFT_IF_FACE(obj, self, ca);
|
|
654
|
+
return obj;
|
|
655
|
+
}
|
|
642
656
|
|
|
657
|
+
/* The bare size-1 insertion primitive, in the SOURCE frame: each position
|
|
658
|
+
names the existing axis the new axis goes *before* (ndim = append at the
|
|
659
|
+
end; negatives count from the end gap). A position given more than once
|
|
660
|
+
stacks several length-1 axes before that source axis. Positions do not
|
|
661
|
+
shift as other axes are inserted.
|
|
662
|
+
|
|
663
|
+
a = CArray.int32(2, 3) # shape [2, 3]
|
|
664
|
+
insert before axis 0 -> [1, 2, 3]
|
|
665
|
+
insert before axis 2 (= -1, end) -> [2, 3, 1]
|
|
666
|
+
before axis 0 and the end -> [1, 2, 3, 1]
|
|
667
|
+
before axis 0 twice -> [1, 1, 2, 3]
|
|
668
|
+
|
|
669
|
+
Returns a CARefer view (zero-copy alias to +self+'s data, via reshape).
|
|
670
|
+
Bound to the internal name __insert_axis_size1__; the user-facing
|
|
671
|
+
insert_axis (with the repeat: keyword) is the Ruby method in
|
|
672
|
+
lib/carray/basics.rb, which builds on this primitive.
|
|
673
|
+
|
|
674
|
+
Non-static so external CIFY consumers (= carray_order.c,
|
|
675
|
+
carray_median_percentile.c) can call directly; they pass a single axis,
|
|
676
|
+
for which the source and output frames coincide. */
|
|
677
|
+
VALUE
|
|
678
|
+
rb_ca_insert_axis (int argc, VALUE *argv, VALUE self)
|
|
679
|
+
{
|
|
680
|
+
CArray *ca;
|
|
681
|
+
VALUE new_argv[CA_RANK_MAX];
|
|
682
|
+
int gap_count[CA_RANK_MAX + 1];
|
|
683
|
+
int ndim, new_ndim, ngap;
|
|
684
|
+
int i, c, k;
|
|
685
|
+
|
|
686
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
687
|
+
|
|
688
|
+
ndim = (int) ca->ndim;
|
|
689
|
+
new_ndim = ndim + argc;
|
|
690
|
+
if (new_ndim > CA_RANK_MAX) {
|
|
691
|
+
rb_raise(rb_eArgError,
|
|
692
|
+
"insert_axis: resulting ndim %d exceeds CA_RANK_MAX %d",
|
|
693
|
+
new_ndim, CA_RANK_MAX);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
ngap = ndim + 1; /* gaps live in [0, ndim] (ndim = the end gap) */
|
|
697
|
+
|
|
698
|
+
/* Tally how many new axes go before each source axis (gap). Negative
|
|
699
|
+
positions count from the end gap; duplicates are allowed (stacking). */
|
|
700
|
+
for (i = 0; i <= ndim; i++) {
|
|
701
|
+
gap_count[i] = 0;
|
|
702
|
+
}
|
|
703
|
+
for (i = 0; i < argc; i++) {
|
|
704
|
+
int raw = NUM2INT(argv[i]);
|
|
705
|
+
int g = (raw < 0) ? raw + ngap : raw;
|
|
706
|
+
if (g < 0 || g >= ngap) {
|
|
707
|
+
rb_raise(rb_eArgError,
|
|
708
|
+
"insert_axis: axis %d out of range for ndim %d", raw, ndim);
|
|
709
|
+
}
|
|
710
|
+
gap_count[g]++;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/* Build the output dim list: before each source axis emit its tally of
|
|
714
|
+
length-1 axes, then the source dim; finally the end-gap tally. */
|
|
715
|
+
k = 0;
|
|
716
|
+
for (i = 0; i < ndim; i++) {
|
|
717
|
+
for (c = 0; c < gap_count[i]; c++) {
|
|
718
|
+
new_argv[k++] = INT2NUM(1);
|
|
719
|
+
}
|
|
720
|
+
new_argv[k++] = SIZE2NUM(ca->dim[i]);
|
|
721
|
+
}
|
|
722
|
+
for (c = 0; c < gap_count[ndim]; c++) {
|
|
723
|
+
new_argv[k++] = INT2NUM(1);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
return rb_ca_reshape(new_ndim, new_argv, self);
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
void
|
|
730
|
+
Init_ca_obj_refer (void)
|
|
731
|
+
{
|
|
732
|
+
/* rb_cCARefer, CA_OBJ_REFER are defined in ruby_carray.c /
|
|
733
|
+
carray_core.c. Build the custom op table and override the
|
|
734
|
+
baseline registration installed by Init_carray_core. */
|
|
735
|
+
ca_refer_func = ca_stride_func;
|
|
736
|
+
ca_refer_func.free_object = free_ca_refer;
|
|
737
|
+
ca_refer_func.clone = ca_refer_func_clone;
|
|
738
|
+
ca_refer_func.create_mask = ca_refer_func_create_mask;
|
|
739
|
+
/* CARefer's struct is larger than CAStride (adds mask0); inherit
|
|
740
|
+
CAStride's pool_bytes / pool_init (dim + strides) but override
|
|
741
|
+
struct_size so ca_array_alloc reserves the right amount. */
|
|
742
|
+
ca_refer_func.struct_size = sizeof(CARefer);
|
|
743
|
+
ca_func[CA_OBJ_REFER] = ca_refer_func;
|
|
744
|
+
|
|
745
|
+
rb_define_const(rb_cObject, "CA_OBJ_REFER", INT2NUM(CA_OBJ_REFER));
|
|
746
|
+
|
|
747
|
+
rb_define_method(rb_cCArray, "refer", rb_ca_refer, -1);
|
|
748
|
+
rb_define_method(rb_cCArray, "reshape", rb_ca_reshape, -1);
|
|
749
|
+
rb_define_method(rb_cCArray, "flatten", rb_ca_flatten, 0);
|
|
750
|
+
/* The bare size-1 primitive. The user-facing `insert_axis` (with its
|
|
751
|
+
`repeat:` keyword) is the Ruby method in lib/carray/basics.rb, which
|
|
752
|
+
owns the name and calls this primitive. */
|
|
753
|
+
rb_define_method(rb_cCArray, "__insert_axis_size1__", rb_ca_insert_axis, -1);
|
|
643
754
|
rb_define_alloc_func(rb_cCARefer, rb_ca_refer_s_allocate);
|
|
644
755
|
rb_define_method(rb_cCARefer, "initialize_copy",
|
|
645
|
-
|
|
756
|
+
rb_ca_refer_initialize_copy, 1);
|
|
646
757
|
}
|
|
647
|
-
|