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
|
@@ -0,0 +1,766 @@
|
|
|
1
|
+
/* ---------------------------------------------------------------------------
|
|
2
|
+
|
|
3
|
+
CAByteSwap view: element-wise byte-order reversal of the parent.
|
|
4
|
+
Same shape and byte width as the parent; materialises on attach
|
|
5
|
+
with the byte swap applied. Sibling of CAFake (both are
|
|
6
|
+
value-conversion views under CAView).
|
|
7
|
+
|
|
8
|
+
Numeric primitive parents route through CAMonOp(byte_swap) by
|
|
9
|
+
`rb_ca_swap_bytes` — this file's CAByteSwap handles the residual
|
|
10
|
+
cases (CA_FIXLEN with data_class field-recursive swap, bare
|
|
11
|
+
fixlen buffers) that the monop kernel table does not cover.
|
|
12
|
+
|
|
13
|
+
---------------------------------------------------------------------------- */
|
|
14
|
+
|
|
15
|
+
#include "carray.h"
|
|
16
|
+
#include "ca_iter_substrate.h" /* ca_xfer_stride_transform_fused */
|
|
17
|
+
#include "ca_monop_dispatch.h" /* CA_MONOP_BYTE_SWAP dispatch id */
|
|
18
|
+
#include "ca_obj_face.h" /* CA_FACE_LIFT_IF_FACE for CARecord parent */
|
|
19
|
+
|
|
20
|
+
/* CAStride family identification (used for fast-path eligibility). */
|
|
21
|
+
extern ca_operation_function_t ca_stride_func;
|
|
22
|
+
|
|
23
|
+
/* Reverse the byte order of each `bytes`-wide element in place.
|
|
24
|
+
Element-local (no cross-element dependency), so the same routine
|
|
25
|
+
serves both the internal recursion helper rb_ca_swap_bytes_bang
|
|
26
|
+
and CAByteSwap's materialise — the caller just points it at the
|
|
27
|
+
target buffer (self->ptr or a scratch). */
|
|
28
|
+
void
|
|
29
|
+
ca_swap_bytes (char *ptr, ca_size_t bytes, ca_size_t elements)
|
|
30
|
+
{
|
|
31
|
+
char *p;
|
|
32
|
+
char val;
|
|
33
|
+
ca_size_t i;
|
|
34
|
+
|
|
35
|
+
#define SWAP_BYTE(a, b) (val = (a), (a) = (b), (b) = val)
|
|
36
|
+
|
|
37
|
+
switch ( bytes ) {
|
|
38
|
+
case 1:
|
|
39
|
+
break;
|
|
40
|
+
case 2:
|
|
41
|
+
for (i=0; i<elements; i++) {
|
|
42
|
+
p = ptr + 2*i;
|
|
43
|
+
SWAP_BYTE(p[0], p[1]);
|
|
44
|
+
}
|
|
45
|
+
break;
|
|
46
|
+
case 4:
|
|
47
|
+
for (i=0; i<elements; i++) {
|
|
48
|
+
p = ptr + 4*i;
|
|
49
|
+
SWAP_BYTE(p[0], p[3]);
|
|
50
|
+
SWAP_BYTE(p[1], p[2]);
|
|
51
|
+
}
|
|
52
|
+
break;
|
|
53
|
+
case 8:
|
|
54
|
+
for (i=0; i<elements; i++) {
|
|
55
|
+
p = ptr + 8*i;
|
|
56
|
+
SWAP_BYTE(p[0], p[7]);
|
|
57
|
+
SWAP_BYTE(p[1], p[6]);
|
|
58
|
+
SWAP_BYTE(p[2], p[5]);
|
|
59
|
+
SWAP_BYTE(p[3], p[4]);
|
|
60
|
+
}
|
|
61
|
+
break;
|
|
62
|
+
case 16:
|
|
63
|
+
for (i=0; i<elements; i++) {
|
|
64
|
+
p = ptr + 16*i;
|
|
65
|
+
SWAP_BYTE(p[0], p[15]);
|
|
66
|
+
SWAP_BYTE(p[1], p[14]);
|
|
67
|
+
SWAP_BYTE(p[2], p[13]);
|
|
68
|
+
SWAP_BYTE(p[3], p[12]);
|
|
69
|
+
SWAP_BYTE(p[4], p[11]);
|
|
70
|
+
SWAP_BYTE(p[5], p[10]);
|
|
71
|
+
SWAP_BYTE(p[6], p[9]);
|
|
72
|
+
SWAP_BYTE(p[7], p[8]);
|
|
73
|
+
}
|
|
74
|
+
break;
|
|
75
|
+
default: {
|
|
76
|
+
char *p1, *p2;
|
|
77
|
+
for (i=0; i<elements; i++) {
|
|
78
|
+
p = ptr + i*bytes;
|
|
79
|
+
p1 = p;
|
|
80
|
+
p2 = p+bytes-1;
|
|
81
|
+
while (p1<p2) {
|
|
82
|
+
SWAP_BYTE(*p1, *p2);
|
|
83
|
+
p1++; p2--;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
#undef SWAP_BYTE
|
|
91
|
+
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* Dispatch a byte-order swap of a buffer by data_type. Complex
|
|
95
|
+
types swap their two halves independently; everything else swaps
|
|
96
|
+
`bytes`-wide elements directly.
|
|
97
|
+
*
|
|
98
|
+
* CAREFUL: CA_FIXLEN structs with a data_class are NOT handled
|
|
99
|
+
* here — the caller must decompose them into their primitive
|
|
100
|
+
* fields (see ca_byte_swap_apply / _one).
|
|
101
|
+
*
|
|
102
|
+
* extern-visible so CAMonOp(byte_swap) in ca_obj_monop.c can share
|
|
103
|
+
* the same primitive for its writable lifecycle. */
|
|
104
|
+
void
|
|
105
|
+
ca_byte_swap_buffer (int8_t data_type, ca_size_t bytes, ca_size_t elements,
|
|
106
|
+
char *buf)
|
|
107
|
+
{
|
|
108
|
+
switch ( data_type ) {
|
|
109
|
+
case CA_CMPLX64:
|
|
110
|
+
ca_swap_bytes(buf, 4, 2 * elements);
|
|
111
|
+
break;
|
|
112
|
+
case CA_CMPLX128:
|
|
113
|
+
ca_swap_bytes(buf, 8, 2 * elements);
|
|
114
|
+
break;
|
|
115
|
+
default:
|
|
116
|
+
ca_swap_bytes(buf, bytes, elements);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
typedef struct {
|
|
121
|
+
int16_t obj_type;
|
|
122
|
+
int8_t data_type;
|
|
123
|
+
int8_t ndim;
|
|
124
|
+
int32_t flags;
|
|
125
|
+
ca_size_t bytes;
|
|
126
|
+
ca_size_t elements;
|
|
127
|
+
ca_size_t *dim;
|
|
128
|
+
char *ptr;
|
|
129
|
+
CArray *mask;
|
|
130
|
+
char *_pool; /* framework-managed pool buffer (NULL = legacy ALLOC_N path). */
|
|
131
|
+
CArray *parent;
|
|
132
|
+
uint32_t attach;
|
|
133
|
+
uint8_t nosync;
|
|
134
|
+
/* ----- tail (must be marked by dmark) ----- */
|
|
135
|
+
VALUE data_class; /* parent's data_class, or Qnil if none. Snapshot
|
|
136
|
+
at setup time so attach can do field-recursive
|
|
137
|
+
swap on CA_FIXLEN structs without access to a
|
|
138
|
+
Ruby self VALUE. */
|
|
139
|
+
} CAByteSwap;
|
|
140
|
+
|
|
141
|
+
static size_t
|
|
142
|
+
ca_byte_swap_dsize (const void *ap)
|
|
143
|
+
{
|
|
144
|
+
const CAByteSwap *ca = (const CAByteSwap *) ap;
|
|
145
|
+
return sizeof(CAByteSwap) + ca->ndim * sizeof(ca_size_t);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* Pool framework hooks: single ndim-sized tail (dim) in the _pool
|
|
149
|
+
buffer. See ca_array_pool.c for the shared alloc/free discipline. */
|
|
150
|
+
static size_t
|
|
151
|
+
ca_byte_swap_pool_bytes (int8_t ndim)
|
|
152
|
+
{
|
|
153
|
+
ca_size_t n = (ndim > 0) ? ndim : 1;
|
|
154
|
+
return (size_t) n * sizeof(ca_size_t);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
static void
|
|
158
|
+
ca_byte_swap_pool_init (void *ap, int8_t ndim)
|
|
159
|
+
{
|
|
160
|
+
CAByteSwap *ca = (CAByteSwap *) ap;
|
|
161
|
+
ca->dim = (ca_size_t *) ca->_pool;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/* Custom dmark: ca_mark walks the standard prefix; the data_class
|
|
165
|
+
tail is a VALUE snapshot that must also be marked so the Class
|
|
166
|
+
stays alive across GC while the view holds it. */
|
|
167
|
+
static void
|
|
168
|
+
ca_byte_swap_mark (void *ap)
|
|
169
|
+
{
|
|
170
|
+
CAByteSwap *ca = (CAByteSwap *) ap;
|
|
171
|
+
ca_mark(ca);
|
|
172
|
+
rb_gc_mark(ca->data_class);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const rb_data_type_t cabyteswap_data_type = {
|
|
176
|
+
.parent = &caview_data_type,
|
|
177
|
+
.wrap_struct_name = "CAByteSwap",
|
|
178
|
+
.function = {
|
|
179
|
+
.dmark = ca_byte_swap_mark,
|
|
180
|
+
.dfree = ca_free,
|
|
181
|
+
.dsize = ca_byte_swap_dsize,
|
|
182
|
+
.dcompact = NULL
|
|
183
|
+
},
|
|
184
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
static int8_t CA_OBJ_BYTE_SWAP;
|
|
188
|
+
VALUE rb_cCAByteSwap;
|
|
189
|
+
|
|
190
|
+
/* ------------------------------------------------------------------- */
|
|
191
|
+
|
|
192
|
+
int
|
|
193
|
+
ca_byte_swap_setup (CAByteSwap *ca, CArray *parent, VALUE data_class)
|
|
194
|
+
{
|
|
195
|
+
CA_CHECK_DATA_TYPE(parent->data_type);
|
|
196
|
+
|
|
197
|
+
if ( parent->data_type == CA_OBJECT ) {
|
|
198
|
+
rb_raise(rb_eCADataTypeError, "object array can't be byte-swapped");
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
ca->obj_type = CA_OBJ_BYTE_SWAP;
|
|
202
|
+
ca->data_type = parent->data_type;
|
|
203
|
+
ca->flags = 0;
|
|
204
|
+
ca->ndim = parent->ndim;
|
|
205
|
+
ca->bytes = parent->bytes;
|
|
206
|
+
ca->elements = parent->elements;
|
|
207
|
+
ca->ptr = NULL;
|
|
208
|
+
ca->mask = NULL;
|
|
209
|
+
if ( ! ca->_pool ) {
|
|
210
|
+
ca->dim = ALLOC_N(ca_size_t, ca->ndim);
|
|
211
|
+
}
|
|
212
|
+
memcpy(ca->dim, parent->dim, ca->ndim * sizeof(ca_size_t));
|
|
213
|
+
|
|
214
|
+
ca->parent = parent;
|
|
215
|
+
ca->attach = 0;
|
|
216
|
+
ca->nosync = 0;
|
|
217
|
+
ca->data_class = data_class; /* Qnil if parent has no data_class */
|
|
218
|
+
|
|
219
|
+
if ( ca_has_mask(parent) ) {
|
|
220
|
+
ca_create_mask(ca);
|
|
221
|
+
}
|
|
222
|
+
if ( ca_is_scalar(parent) ) {
|
|
223
|
+
ca_set_flag(ca, CA_FLAG_SCALAR);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return 0;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
CAByteSwap *
|
|
230
|
+
ca_byte_swap_new (CArray *parent, VALUE data_class)
|
|
231
|
+
{
|
|
232
|
+
CAByteSwap *ca = (CAByteSwap *) ca_array_alloc(CA_OBJ_BYTE_SWAP, parent->ndim);
|
|
233
|
+
ca_byte_swap_setup(ca, parent, data_class);
|
|
234
|
+
return ca;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
static void
|
|
238
|
+
free_ca_byte_swap (void *ap)
|
|
239
|
+
{
|
|
240
|
+
CAByteSwap *ca = (CAByteSwap *) ap;
|
|
241
|
+
if ( ca != NULL ) {
|
|
242
|
+
ca_free(ca->mask);
|
|
243
|
+
if ( ca->_pool ) {
|
|
244
|
+
ca_array_free(ca); /* dim lives in _pool */
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
xfree(ca->dim);
|
|
248
|
+
xfree(ca);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/* ------------------------------------------------------------------- */
|
|
254
|
+
|
|
255
|
+
/* Apply the byte-swap transformation to a buffer in place.
|
|
256
|
+
Three cases:
|
|
257
|
+
- CA_FIXLEN + data_class: walk each record's fields recursively
|
|
258
|
+
via a temporary CAWrap + rb_ca_swap_bytes_bang.
|
|
259
|
+
- CA_CMPLX64 / CA_CMPLX128: swap each 4 / 8-byte half independently
|
|
260
|
+
so the real / imaginary components are individually correct.
|
|
261
|
+
- other primitives / bare fixlen: ca_swap_bytes(buf, bytes, elements). */
|
|
262
|
+
static void
|
|
263
|
+
ca_byte_swap_apply (CAByteSwap *ca, char *buf)
|
|
264
|
+
{
|
|
265
|
+
if ( ca->data_type == CA_FIXLEN && RTEST(ca->data_class) ) {
|
|
266
|
+
volatile VALUE wrap = rb_ca_wrap_new(CA_FIXLEN, ca->ndim, ca->dim,
|
|
267
|
+
ca->bytes, NULL, buf);
|
|
268
|
+
/* data_class travels on CARecord (Face), so wrap the transient
|
|
269
|
+
into CARecord to let rb_ca_swap_bytes_bang see the fields. */
|
|
270
|
+
wrap = rb_funcall(rb_const_get(rb_cObject, rb_intern("CARecord")),
|
|
271
|
+
rb_intern("wrap"), 2, wrap, ca->data_class);
|
|
272
|
+
rb_ca_swap_bytes_bang(wrap);
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
ca_byte_swap_buffer(ca->data_type, ca->bytes, ca->elements, buf);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/* Swap a single element worth of bytes in place (for fetch / store /
|
|
279
|
+
fill paths). Always succeeds: CA_FIXLEN + data_class recurses via
|
|
280
|
+
a transient CAWrap of width 1 (per-field swap, mirrors bulk path);
|
|
281
|
+
bare FIXLEN does flat byte swap of one cell; primitives use their
|
|
282
|
+
widths. Per-cell paths never call ca_attach. */
|
|
283
|
+
static int
|
|
284
|
+
ca_byte_swap_apply_one (CAByteSwap *ca, char *buf)
|
|
285
|
+
{
|
|
286
|
+
if ( ca->data_type == CA_FIXLEN && RTEST(ca->data_class) ) {
|
|
287
|
+
ca_size_t one = 1;
|
|
288
|
+
volatile VALUE wrap = rb_ca_wrap_new(CA_FIXLEN, 1, &one,
|
|
289
|
+
ca->bytes, NULL, buf);
|
|
290
|
+
/* Same CARecord-wrap trick as ca_byte_swap_apply, but for a
|
|
291
|
+
single cell. */
|
|
292
|
+
wrap = rb_funcall(rb_const_get(rb_cObject, rb_intern("CARecord")),
|
|
293
|
+
rb_intern("wrap"), 2, wrap, ca->data_class);
|
|
294
|
+
rb_ca_swap_bytes_bang(wrap);
|
|
295
|
+
return 1;
|
|
296
|
+
}
|
|
297
|
+
ca_byte_swap_buffer(ca->data_type, ca->bytes, 1, buf);
|
|
298
|
+
return 1;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/* ------------------------------------------------------------------- */
|
|
302
|
+
|
|
303
|
+
static void *
|
|
304
|
+
ca_byte_swap_func_clone (void *ap)
|
|
305
|
+
{
|
|
306
|
+
CAByteSwap *ca = (CAByteSwap *) ap;
|
|
307
|
+
return ca_byte_swap_new(ca->parent, ca->data_class);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/* Per-cell get / put: fetch parent cell + swap into caller buffer
|
|
311
|
+
(GET), or swap a caller copy + store it back (PUT). Never calls
|
|
312
|
+
ca_attach — the swap primitive works on any stack scratch. */
|
|
313
|
+
static void
|
|
314
|
+
ca_byte_swap_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
315
|
+
{
|
|
316
|
+
CAByteSwap *ca = (CAByteSwap *) ap;
|
|
317
|
+
if ( dir == CA_XFER_GET ) {
|
|
318
|
+
ca_fetch_index(ca->parent, idx, data);
|
|
319
|
+
ca_byte_swap_apply_one(ca, (char *) data);
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
char v[32];
|
|
323
|
+
char *buf = (ca->bytes <= 32) ? v : xmalloc(ca->bytes);
|
|
324
|
+
memcpy(buf, data, ca->bytes);
|
|
325
|
+
ca_byte_swap_apply_one(ca, buf);
|
|
326
|
+
ca_store_index(ca->parent, idx, buf);
|
|
327
|
+
if ( buf != v ) xfree(buf);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/* Batched gather / scatter. CAByteSwap is 1:1 same-size with its
|
|
332
|
+
parent, so the incoming address list is delivered as-is to the
|
|
333
|
+
parent in one call; the byte swap is applied to the delivered
|
|
334
|
+
buffer in place. CA_FIXLEN + data_class cases swap field-
|
|
335
|
+
recursively per cell; everything else uses the bulk primitive. */
|
|
336
|
+
static void
|
|
337
|
+
ca_byte_swap_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
338
|
+
void *data, int dir)
|
|
339
|
+
{
|
|
340
|
+
CAByteSwap *ca = (CAByteSwap *) ap;
|
|
341
|
+
char *d = (char *) data;
|
|
342
|
+
int is_struct = ( ca->data_type == CA_FIXLEN && RTEST(ca->data_class) );
|
|
343
|
+
ca_size_t i;
|
|
344
|
+
|
|
345
|
+
if ( dir == CA_XFER_GET ) {
|
|
346
|
+
ca_xfer_addrs(ca->parent, n, addrs, data, CA_XFER_GET);
|
|
347
|
+
if ( is_struct ) {
|
|
348
|
+
for (i = 0; i < n; i++) ca_byte_swap_apply_one(ca, d + i * ca->bytes);
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
ca_byte_swap_buffer(ca->data_type, ca->bytes, n, d);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
char *v;
|
|
356
|
+
volatile VALUE holder;
|
|
357
|
+
v = ALLOCV_N(char, holder, n * ca->bytes);
|
|
358
|
+
memcpy(v, data, n * ca->bytes);
|
|
359
|
+
if ( is_struct ) {
|
|
360
|
+
for (i = 0; i < n; i++) ca_byte_swap_apply_one(ca, v + i * ca->bytes);
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
ca_byte_swap_buffer(ca->data_type, ca->bytes, n, v);
|
|
364
|
+
}
|
|
365
|
+
ca_xfer_addrs(ca->parent, n, addrs, v, CA_XFER_PUT);
|
|
366
|
+
ALLOCV_END(holder);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/* CAByteSwap is a never-fold transform boundary that is size-
|
|
371
|
+
preserving (parent.bytes == view.bytes), so the incoming region
|
|
372
|
+
recurses through parent.xfer_stride and the swap is applied to
|
|
373
|
+
the contiguous delivered buffer. Parent's own stride chain
|
|
374
|
+
folds to entity inside the recursive call, so this file does not
|
|
375
|
+
attach the parent directly. */
|
|
376
|
+
|
|
377
|
+
/* Per-row byte-swap transform callbacks for the shared fused
|
|
378
|
+
xfer_stride helper. src and dst share the same bytes (view is
|
|
379
|
+
size-preserving), so a plain memcpy + ca_byte_swap_buffer in
|
|
380
|
+
place is enough. */
|
|
381
|
+
static void
|
|
382
|
+
ca_byte_swap_xform_get (ca_size_t n, CArray *src_arr, char *src_row,
|
|
383
|
+
CArray *dst_arr, char *dst_row)
|
|
384
|
+
{
|
|
385
|
+
CAByteSwap *cb = (CAByteSwap *) dst_arr;
|
|
386
|
+
memcpy(dst_row, src_row, n * cb->bytes);
|
|
387
|
+
ca_byte_swap_buffer(cb->data_type, cb->bytes, n, dst_row);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
static void
|
|
391
|
+
ca_byte_swap_xform_put (ca_size_t n, CArray *src_arr, char *src_row,
|
|
392
|
+
CArray *dst_arr, char *dst_row)
|
|
393
|
+
{
|
|
394
|
+
CAByteSwap *cb = (CAByteSwap *) src_arr;
|
|
395
|
+
memcpy(dst_row, src_row, n * cb->bytes);
|
|
396
|
+
ca_byte_swap_buffer(cb->data_type, cb->bytes, n, dst_row);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/* Fast path (non-struct): compose-fold walk with per-row byte
|
|
400
|
+
swap, no scratch for the whole region. CA_FIXLEN + data_class
|
|
401
|
+
cases fall back to the scratch-and-swap 2-pass because they need
|
|
402
|
+
per-cell field-recursive swap that the fused helper cannot
|
|
403
|
+
express. */
|
|
404
|
+
static void
|
|
405
|
+
ca_byte_swap_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
406
|
+
ca_size_t *strides, void *data, int dir)
|
|
407
|
+
{
|
|
408
|
+
CAByteSwap *ca = (CAByteSwap *) ap;
|
|
409
|
+
char *d = (char *) data;
|
|
410
|
+
int is_struct = ( ca->data_type == CA_FIXLEN && RTEST(ca->data_class) );
|
|
411
|
+
ca_size_t n = 1, i;
|
|
412
|
+
int8_t k;
|
|
413
|
+
|
|
414
|
+
if ( !is_struct ) {
|
|
415
|
+
if ( ca_xfer_stride_transform_fused((CArray *)ca, ca->parent,
|
|
416
|
+
starts, counts, strides,
|
|
417
|
+
d, dir,
|
|
418
|
+
ca_byte_swap_xform_get,
|
|
419
|
+
ca_byte_swap_xform_put) ) {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/* Fallback scratch-and-swap 2-pass (handles struct case + cold
|
|
425
|
+
boundary parents). */
|
|
426
|
+
for ( k = 0; k < ca->ndim; k++ ) n *= counts[k];
|
|
427
|
+
if ( dir == CA_XFER_GET ) {
|
|
428
|
+
ca_xfer_stride(ca->parent, starts, counts, strides, data, CA_XFER_GET);
|
|
429
|
+
if ( is_struct ) {
|
|
430
|
+
for (i = 0; i < n; i++) ca_byte_swap_apply_one(ca, d + i * ca->bytes);
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
ca_byte_swap_buffer(ca->data_type, ca->bytes, n, d);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
char *v;
|
|
438
|
+
volatile VALUE holder;
|
|
439
|
+
v = ALLOCV_N(char, holder, n * ca->bytes);
|
|
440
|
+
memcpy(v, data, n * ca->bytes);
|
|
441
|
+
if ( is_struct ) {
|
|
442
|
+
for (i = 0; i < n; i++) ca_byte_swap_apply_one(ca, v + i * ca->bytes);
|
|
443
|
+
}
|
|
444
|
+
else {
|
|
445
|
+
ca_byte_swap_buffer(ca->data_type, ca->bytes, n, v);
|
|
446
|
+
}
|
|
447
|
+
ca_xfer_stride(ca->parent, starts, counts, strides, v, CA_XFER_PUT);
|
|
448
|
+
ALLOCV_END(holder);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
static void
|
|
453
|
+
ca_byte_swap_func_allocate (void *ap)
|
|
454
|
+
{
|
|
455
|
+
CAByteSwap *ca = (CAByteSwap *) ap;
|
|
456
|
+
ca_attach(ca->parent);
|
|
457
|
+
ca->ptr = xmalloc(ca_length(ca));
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
static void
|
|
461
|
+
ca_byte_swap_func_attach (void *ap)
|
|
462
|
+
{
|
|
463
|
+
CAByteSwap *ca = (CAByteSwap *) ap;
|
|
464
|
+
ca_attach(ca->parent);
|
|
465
|
+
ca->ptr = xmalloc(ca_length(ca));
|
|
466
|
+
memcpy(ca->ptr, ca->parent->ptr, ca_length(ca));
|
|
467
|
+
ca_byte_swap_apply(ca, ca->ptr);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
static void
|
|
471
|
+
ca_byte_swap_func_sync (void *ap)
|
|
472
|
+
{
|
|
473
|
+
CAByteSwap *ca = (CAByteSwap *) ap;
|
|
474
|
+
/* Swap is involutive, so applying it once to the view buffer
|
|
475
|
+
restores the parent byte order before the copy-back. */
|
|
476
|
+
ca_byte_swap_apply(ca, ca->ptr);
|
|
477
|
+
memcpy(ca->parent->ptr, ca->ptr, ca_length(ca));
|
|
478
|
+
ca_sync(ca->parent);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
static void
|
|
482
|
+
ca_byte_swap_func_detach (void *ap)
|
|
483
|
+
{
|
|
484
|
+
CAByteSwap *ca = (CAByteSwap *) ap;
|
|
485
|
+
xfree(ca->ptr);
|
|
486
|
+
ca->ptr = NULL;
|
|
487
|
+
ca_detach(ca->parent);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/* Whole-view transfer as a thin wrapper around xfer_stride.
|
|
491
|
+
Deliberately does not call ca_attach(parent) — the underlying
|
|
492
|
+
xfer_stride reaches the parent through the fused helper (or,
|
|
493
|
+
for cold non-CAStride parents, its own scratch-and-swap 2-pass)
|
|
494
|
+
without needing a whole-view attach here. */
|
|
495
|
+
static void
|
|
496
|
+
ca_byte_swap_func_xfer_all (void *ap, void *data, int dir)
|
|
497
|
+
{
|
|
498
|
+
CAByteSwap *ca = (CAByteSwap *) ap;
|
|
499
|
+
ca_size_t starts[CA_RANK_MAX];
|
|
500
|
+
ca_size_t native[CA_RANK_MAX];
|
|
501
|
+
int8_t k;
|
|
502
|
+
ca_size_t s = ca->bytes;
|
|
503
|
+
for ( k = ca->ndim - 1; k >= 0; k-- ) { native[k] = s; s *= ca->dim[k]; }
|
|
504
|
+
for ( k = 0; k < ca->ndim; k++ ) starts[k] = 0;
|
|
505
|
+
ca_xfer_stride(ca, starts, ca->dim, native, data, dir);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
static void
|
|
509
|
+
ca_byte_swap_func_fill_data (void *ap, void *ptr)
|
|
510
|
+
{
|
|
511
|
+
CAByteSwap *ca = (CAByteSwap *) ap;
|
|
512
|
+
char v[32];
|
|
513
|
+
char *buf = (ca->bytes <= 32) ? v : xmalloc(ca->bytes);
|
|
514
|
+
memcpy(buf, ptr, ca->bytes);
|
|
515
|
+
if ( !ca_byte_swap_apply_one(ca, buf) ) {
|
|
516
|
+
/* Bare CA_FIXLEN fill: broadcast the raw bytes into the view
|
|
517
|
+
buffer through attach/sync so the parent sees the correct
|
|
518
|
+
byte order after mapping back. */
|
|
519
|
+
ca_attach(ca);
|
|
520
|
+
{
|
|
521
|
+
ca_size_t i;
|
|
522
|
+
for (i = 0; i < ca->elements; i++) {
|
|
523
|
+
memcpy(ca->ptr + i * ca->bytes, ptr, ca->bytes);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
ca_sync(ca);
|
|
527
|
+
ca_detach(ca);
|
|
528
|
+
if ( buf != v ) xfree(buf);
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
ca_fill(ca->parent, buf);
|
|
532
|
+
if ( buf != v ) xfree(buf);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/* fill_data with a region. Swapping is per value, not per cell, so the one
|
|
536
|
+
value is swapped once and the region passes to the parent as it stands --
|
|
537
|
+
a swap view reorders bytes within a cell, never cells within the array, so
|
|
538
|
+
its addresses are the parent's. A bare CA_FIXLEN has no swap to apply and
|
|
539
|
+
falls to the per-cell walk, which at least stays inside the region. */
|
|
540
|
+
|
|
541
|
+
static void
|
|
542
|
+
ca_byte_swap_func_fill_stride (void *ap, ca_size_t base, int8_t ndim,
|
|
543
|
+
ca_size_t *counts, ca_size_t *steps, void *ptr)
|
|
544
|
+
{
|
|
545
|
+
CAByteSwap *ca = (CAByteSwap *) ap;
|
|
546
|
+
char v[32];
|
|
547
|
+
char *buf = (ca->bytes <= 32) ? v : xmalloc(ca->bytes);
|
|
548
|
+
memcpy(buf, ptr, ca->bytes);
|
|
549
|
+
if ( ca_byte_swap_apply_one(ca, buf) ) {
|
|
550
|
+
ca_fill_stride(ca->parent, base, ndim, counts, steps, buf);
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
ca_fill_stride_default(ca, base, ndim, counts, steps, ptr);
|
|
554
|
+
}
|
|
555
|
+
if ( buf != v ) xfree(buf);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
static void
|
|
559
|
+
ca_byte_swap_func_fill_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
560
|
+
void *ptr)
|
|
561
|
+
{
|
|
562
|
+
CAByteSwap *ca = (CAByteSwap *) ap;
|
|
563
|
+
char v[32];
|
|
564
|
+
char *buf = (ca->bytes <= 32) ? v : xmalloc(ca->bytes);
|
|
565
|
+
memcpy(buf, ptr, ca->bytes);
|
|
566
|
+
if ( ca_byte_swap_apply_one(ca, buf) ) {
|
|
567
|
+
ca_fill_addrs(ca->parent, n, addrs, buf);
|
|
568
|
+
}
|
|
569
|
+
else {
|
|
570
|
+
ca_fill_addrs_default(ca, n, addrs, ptr);
|
|
571
|
+
}
|
|
572
|
+
if ( buf != v ) xfree(buf);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
static void
|
|
576
|
+
ca_byte_swap_func_create_mask (void *ap)
|
|
577
|
+
{
|
|
578
|
+
CAByteSwap *ca = (CAByteSwap *) ap;
|
|
579
|
+
ca_update_mask(ca->parent);
|
|
580
|
+
if ( ! ca->parent->mask ) {
|
|
581
|
+
ca_create_mask(ca->parent);
|
|
582
|
+
}
|
|
583
|
+
/* Mask is byte-wide (boolean), so the swap is a no-op for the
|
|
584
|
+
mask itself. Share the parent's mask via a CARefer to keep the
|
|
585
|
+
two in lockstep. */
|
|
586
|
+
ca->mask =
|
|
587
|
+
(CArray *) ca_refer_new(ca->parent->mask,
|
|
588
|
+
CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
ca_operation_function_t ca_byte_swap_func = {
|
|
592
|
+
-1, /* CA_OBJ_BYTE_SWAP */
|
|
593
|
+
CA_VIEW_ARRAY,
|
|
594
|
+
free_ca_byte_swap,
|
|
595
|
+
ca_byte_swap_func_clone,
|
|
596
|
+
ca_byte_swap_func_allocate,
|
|
597
|
+
ca_byte_swap_func_attach,
|
|
598
|
+
ca_byte_swap_func_sync,
|
|
599
|
+
ca_byte_swap_func_detach,
|
|
600
|
+
ca_byte_swap_func_fill_data,
|
|
601
|
+
ca_byte_swap_func_create_mask,
|
|
602
|
+
ca_byte_swap_func_xfer_index,
|
|
603
|
+
ca_byte_swap_func_xfer_addrs,
|
|
604
|
+
NULL, /* fold_stride: never fold — value-conversion boundary */
|
|
605
|
+
ca_byte_swap_func_xfer_stride,
|
|
606
|
+
ca_byte_swap_func_xfer_all,
|
|
607
|
+
.fill_addrs = ca_byte_swap_func_fill_addrs,
|
|
608
|
+
.fill_stride = ca_byte_swap_func_fill_stride,
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
/* ------------------------------------------------------------------- */
|
|
612
|
+
|
|
613
|
+
/* Defined in ca_obj_monop.c (single-op CAMonOp builder).
|
|
614
|
+
Called below for primitive-numeric byte swap. */
|
|
615
|
+
extern VALUE rb_ca_monop_build (VALUE cary, uint16_t op_id);
|
|
616
|
+
|
|
617
|
+
VALUE
|
|
618
|
+
rb_ca_byte_swap_new (VALUE cary)
|
|
619
|
+
{
|
|
620
|
+
volatile VALUE obj, data_class;
|
|
621
|
+
CArray *parent;
|
|
622
|
+
CAByteSwap *ca;
|
|
623
|
+
rb_check_carray_object(cary);
|
|
624
|
+
TypedData_Get_Struct(cary, CArray, &carray_data_type, parent);
|
|
625
|
+
|
|
626
|
+
/* Primitive numeric routes to CAMonOp(byte_swap), which owns the
|
|
627
|
+
numeric byte_swap kernel and its writable lifecycle. CAByteSwap
|
|
628
|
+
handles the residual cases the monop kernel table does not
|
|
629
|
+
cover: CA_FIXLEN with data_class (field-recursive swap needs a
|
|
630
|
+
Ruby callback), bare CA_FIXLEN (variable bytes-per-cell), and
|
|
631
|
+
CA_OBJECT (rejected in setup). */
|
|
632
|
+
if ( parent->data_type != CA_FIXLEN && parent->data_type != CA_OBJECT ) {
|
|
633
|
+
return rb_ca_monop_build(cary, CA_MONOP_BYTE_SWAP);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/* Snapshot data_class (or Qnil) so attach can do the field-
|
|
637
|
+
recursive swap without needing to resolve `self` again. */
|
|
638
|
+
data_class = rb_ca_data_class(cary);
|
|
639
|
+
ca = ca_byte_swap_new(parent, data_class);
|
|
640
|
+
obj = ca_wrap_struct(ca);
|
|
641
|
+
rb_ca_set_parent(obj, cary);
|
|
642
|
+
/* Lift back into a Face when `self` is a CARecord so field
|
|
643
|
+
projection and data_class queries keep working through the
|
|
644
|
+
swap_bytes view. */
|
|
645
|
+
CA_FACE_LIFT_IF_FACE(obj, cary, parent);
|
|
646
|
+
return obj;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
static VALUE
|
|
650
|
+
rb_ca_byte_swap_s_allocate (VALUE klass)
|
|
651
|
+
{
|
|
652
|
+
CAByteSwap *ca;
|
|
653
|
+
return TypedData_Make_Struct(klass, CAByteSwap, &cabyteswap_data_type, ca);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
static VALUE
|
|
657
|
+
rb_ca_byte_swap_initialize_copy (VALUE self, VALUE other)
|
|
658
|
+
{
|
|
659
|
+
CAByteSwap *ca, *cs;
|
|
660
|
+
TypedData_Get_Struct(self, CAByteSwap, &cabyteswap_data_type, ca);
|
|
661
|
+
TypedData_Get_Struct(other, CAByteSwap, &cabyteswap_data_type, cs);
|
|
662
|
+
if ( ca_func[CA_OBJ_BYTE_SWAP].pool_init ) {
|
|
663
|
+
ca_array_pool_alloc(ca, CA_OBJ_BYTE_SWAP, cs->parent->ndim);
|
|
664
|
+
}
|
|
665
|
+
ca_byte_swap_setup(ca, cs->parent, cs->data_class);
|
|
666
|
+
return self;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/* CArray#swap_bytes — lazy CAByteSwap (or CAMonOp for primitive
|
|
670
|
+
numeric) view whose cells are byte-swapped versions of self's
|
|
671
|
+
cells; materialises on attach. */
|
|
672
|
+
VALUE
|
|
673
|
+
rb_ca_swap_bytes (VALUE self)
|
|
674
|
+
{
|
|
675
|
+
return rb_ca_byte_swap_new(self);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
/* CArray#endian(byte_order) — returns a view of self in the
|
|
679
|
+
requested byte order. Accepts :preserve / :native (both
|
|
680
|
+
identity, since CArrays are stored host-endian), :big (identity
|
|
681
|
+
on big-endian hosts, otherwise a byte-swap view), or :little
|
|
682
|
+
(identity on little-endian hosts, otherwise a byte-swap view).
|
|
683
|
+
The keyword set matches bulk-memory-view's
|
|
684
|
+
`BulkMemoryView.from(producer, endian:)`. */
|
|
685
|
+
VALUE
|
|
686
|
+
rb_ca_endian (VALUE self, VALUE byte_order)
|
|
687
|
+
{
|
|
688
|
+
ID sym;
|
|
689
|
+
if ( !SYMBOL_P(byte_order) ) {
|
|
690
|
+
rb_raise(rb_eArgError,
|
|
691
|
+
"endian: must be :preserve, :native, :big, or :little");
|
|
692
|
+
}
|
|
693
|
+
sym = SYM2ID(byte_order);
|
|
694
|
+
if ( sym == rb_intern("preserve") || sym == rb_intern("native") ) {
|
|
695
|
+
return self;
|
|
696
|
+
}
|
|
697
|
+
if ( sym == rb_intern("big") ) {
|
|
698
|
+
return (ca_endian == CA_BIG_ENDIAN) ? self : rb_ca_byte_swap_new(self);
|
|
699
|
+
}
|
|
700
|
+
if ( sym == rb_intern("little") ) {
|
|
701
|
+
return (ca_endian == CA_LITTLE_ENDIAN) ? self : rb_ca_byte_swap_new(self);
|
|
702
|
+
}
|
|
703
|
+
rb_raise(rb_eArgError,
|
|
704
|
+
"endian: must be :preserve, :native, :big, or :little");
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
/* Internal recursion helper for the bulk byte-swap path. Not
|
|
708
|
+
exposed as a Ruby method; the CA_FIXLEN + data_class branches in
|
|
709
|
+
ca_byte_swap_apply / _one call this to walk into each field of a
|
|
710
|
+
struct. */
|
|
711
|
+
VALUE
|
|
712
|
+
rb_ca_swap_bytes_bang (VALUE self)
|
|
713
|
+
{
|
|
714
|
+
CArray *ca;
|
|
715
|
+
|
|
716
|
+
rb_check_frozen(self);
|
|
717
|
+
|
|
718
|
+
if ( rb_ca_is_object_type(self) ) {
|
|
719
|
+
rb_raise(rb_eCADataTypeError, "object array can't swap bytes");
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/* CA_FIXLEN with a data_class: decompose into its fields and swap each
|
|
723
|
+
(the field views write back to self). */
|
|
724
|
+
if ( rb_ca_is_fixlen_type(self) && rb_ca_has_data_class(self) ) {
|
|
725
|
+
volatile VALUE members = rb_ca_fields(self);
|
|
726
|
+
int i;
|
|
727
|
+
Check_Type(members, T_ARRAY);
|
|
728
|
+
for (i=0; i<RARRAY_LEN(members); i++) {
|
|
729
|
+
rb_ca_swap_bytes_bang(rb_ary_entry(members, i));
|
|
730
|
+
}
|
|
731
|
+
return self;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
735
|
+
ca_attach(ca);
|
|
736
|
+
ca_byte_swap_buffer(ca->data_type, ca->bytes, ca->elements, ca->ptr);
|
|
737
|
+
ca_sync(ca);
|
|
738
|
+
ca_detach(ca);
|
|
739
|
+
return self;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
void
|
|
743
|
+
Init_ca_obj_byte_swap (void)
|
|
744
|
+
{
|
|
745
|
+
rb_cCAByteSwap = rb_define_class("CAByteSwap", rb_cCAView);
|
|
746
|
+
|
|
747
|
+
ca_byte_swap_func.struct_size = sizeof(CAByteSwap);
|
|
748
|
+
ca_byte_swap_func.pool_bytes = ca_byte_swap_pool_bytes;
|
|
749
|
+
ca_byte_swap_func.pool_init = ca_byte_swap_pool_init;
|
|
750
|
+
|
|
751
|
+
CA_OBJ_BYTE_SWAP = ca_install_obj_type(rb_cCAByteSwap,
|
|
752
|
+
&cabyteswap_data_type,
|
|
753
|
+
rb_cCArrayMask,
|
|
754
|
+
&carray_mask_data_type,
|
|
755
|
+
&ca_byte_swap_func, sizeof(ca_byte_swap_func));
|
|
756
|
+
rb_define_const(rb_cObject, "CA_OBJ_BYTE_SWAP", INT2NUM(CA_OBJ_BYTE_SWAP));
|
|
757
|
+
|
|
758
|
+
rb_define_method(rb_cCArray, "swap_bytes", rb_ca_swap_bytes, 0);
|
|
759
|
+
/* `swap_bytes!` intentionally absent; the in-place idiom is
|
|
760
|
+
`ca[] = ca.swap_bytes`. */
|
|
761
|
+
rb_define_method(rb_cCArray, "endian", rb_ca_endian, 1);
|
|
762
|
+
|
|
763
|
+
rb_define_alloc_func(rb_cCAByteSwap, rb_ca_byte_swap_s_allocate);
|
|
764
|
+
rb_define_method(rb_cCAByteSwap, "initialize_copy",
|
|
765
|
+
rb_ca_byte_swap_initialize_copy, 1);
|
|
766
|
+
}
|