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/carray_conversion.c
CHANGED
|
@@ -1,23 +1,149 @@
|
|
|
1
1
|
/* ---------------------------------------------------------------------------
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Value conversion and binary serialization: to_a / convert / dump_binary /
|
|
4
|
+
to_s / load_binary. Ruby-facing docs live in
|
|
5
|
+
yard-stubs/carray_conversion.rb.
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
Siblings:
|
|
8
|
+
carray_copy.c — CArray-to-CArray copy / template family
|
|
9
|
+
carray_element.c — element-level fetch/store (rb_ca_ptr2obj / obj2ptr)
|
|
10
|
+
carray_cast_func.c — dtype cast table used by rb_ca_ptr2obj
|
|
8
11
|
|
|
9
12
|
---------------------------------------------------------------------------- */
|
|
10
13
|
|
|
11
14
|
#include "carray.h"
|
|
12
15
|
|
|
13
|
-
#if RUBY_VERSION_CODE >= 190
|
|
14
16
|
#include "ruby/io.h"
|
|
15
|
-
#else
|
|
16
|
-
#include "rubyio.h"
|
|
17
|
-
#endif
|
|
18
17
|
|
|
18
|
+
/* to_a dispatch:
|
|
19
|
+
numeric / boolean dtype + entity or attach-able view -> fast path
|
|
20
|
+
(dtype-direct leaf loop over the attached contig buffer)
|
|
21
|
+
CA_OBJECT / CA_FIXLEN -> universal
|
|
22
|
+
(rb_ca_fetch_index per cell; ptr is VALUE or byte string, not
|
|
23
|
+
directly castable through the leaf switch)
|
|
24
|
+
|
|
25
|
+
Masked cells materialise as CA_UNDEF on both paths. */
|
|
26
|
+
|
|
27
|
+
/* Leaf macro: dtype-specialized inner loop. Produces `n` VALUE objects
|
|
28
|
+
from a contig ptr base + element width, storing into `dst` (Ruby Array). */
|
|
29
|
+
#define TO_A_LEAF_LOOP(T, TO_VALUE) do { \
|
|
30
|
+
const T *src = (const T *) base; \
|
|
31
|
+
for (li = 0; li < n; li++) { \
|
|
32
|
+
rb_ary_store(dst, li, TO_VALUE(src[li])); \
|
|
33
|
+
} \
|
|
34
|
+
} while (0)
|
|
35
|
+
|
|
36
|
+
#define TO_A_LEAF_LOOP_MASKED(T, TO_VALUE) do { \
|
|
37
|
+
const T *src = (const T *) base; \
|
|
38
|
+
for (li = 0; li < n; li++) { \
|
|
39
|
+
rb_ary_store(dst, li, mask[li] ? CA_UNDEF : TO_VALUE(src[li])); \
|
|
40
|
+
} \
|
|
41
|
+
} while (0)
|
|
42
|
+
|
|
43
|
+
#define TO_A_DISPATCH_LEAF(LOOP) do { \
|
|
44
|
+
ca_size_t li; \
|
|
45
|
+
switch ( dtype ) { \
|
|
46
|
+
case CA_FLOAT64: LOOP(double, rb_float_new); break; \
|
|
47
|
+
case CA_FLOAT32: LOOP(float, rb_float_new); break; \
|
|
48
|
+
case CA_INT64: LOOP(int64_t, LL2NUM); break; \
|
|
49
|
+
case CA_INT32: LOOP(int32_t, INT2NUM); break; \
|
|
50
|
+
case CA_INT16: LOOP(int16_t, INT2FIX); break; \
|
|
51
|
+
case CA_INT8: LOOP(int8_t, INT2FIX); break; \
|
|
52
|
+
case CA_UINT64: LOOP(uint64_t, ULL2NUM); break; \
|
|
53
|
+
case CA_UINT32: LOOP(uint32_t, UINT2NUM); break; \
|
|
54
|
+
case CA_UINT16: LOOP(uint16_t, INT2FIX); break; \
|
|
55
|
+
case CA_UINT8: LOOP(uint8_t, INT2FIX); break; \
|
|
56
|
+
case CA_BOOLEAN: \
|
|
57
|
+
/* Emit Ruby true/false. Consistent with the per-cell Ruby-land yield
|
|
58
|
+
family (a[i], each, each_with_addr, elem_fetch, CScalar value) which
|
|
59
|
+
all yield Qtrue/Qfalse since Part A. Numeric casts and serialize
|
|
60
|
+
paths keep the raw uint8 encoding via BOOL2OBJ (they do not go
|
|
61
|
+
through this leaf). */ \
|
|
62
|
+
{ \
|
|
63
|
+
const uint8_t *src = (const uint8_t *) base; \
|
|
64
|
+
for (li = 0; li < n; li++) { \
|
|
65
|
+
rb_ary_store(dst, li, src[li] ? Qtrue : Qfalse); \
|
|
66
|
+
} \
|
|
67
|
+
} \
|
|
68
|
+
break; \
|
|
69
|
+
default: \
|
|
70
|
+
rb_bug("to_a fast path: unexpected dtype %d", dtype); \
|
|
71
|
+
} \
|
|
72
|
+
} while (0)
|
|
73
|
+
|
|
74
|
+
#define TO_A_DISPATCH_LEAF_MASKED(LOOP) do { \
|
|
75
|
+
ca_size_t li; \
|
|
76
|
+
switch ( dtype ) { \
|
|
77
|
+
case CA_FLOAT64: LOOP(double, rb_float_new); break; \
|
|
78
|
+
case CA_FLOAT32: LOOP(float, rb_float_new); break; \
|
|
79
|
+
case CA_INT64: LOOP(int64_t, LL2NUM); break; \
|
|
80
|
+
case CA_INT32: LOOP(int32_t, INT2NUM); break; \
|
|
81
|
+
case CA_INT16: LOOP(int16_t, INT2FIX); break; \
|
|
82
|
+
case CA_INT8: LOOP(int8_t, INT2FIX); break; \
|
|
83
|
+
case CA_UINT64: LOOP(uint64_t, ULL2NUM); break; \
|
|
84
|
+
case CA_UINT32: LOOP(uint32_t, UINT2NUM); break; \
|
|
85
|
+
case CA_UINT16: LOOP(uint16_t, INT2FIX); break; \
|
|
86
|
+
case CA_UINT8: LOOP(uint8_t, INT2FIX); break; \
|
|
87
|
+
case CA_BOOLEAN: \
|
|
88
|
+
/* Emit Ruby true/false, matching the unmasked leaf above. */ \
|
|
89
|
+
{ \
|
|
90
|
+
const uint8_t *src = (const uint8_t *) base; \
|
|
91
|
+
for (li = 0; li < n; li++) { \
|
|
92
|
+
rb_ary_store(dst, li, mask[li] ? CA_UNDEF \
|
|
93
|
+
: (src[li] ? Qtrue : Qfalse)); \
|
|
94
|
+
} \
|
|
95
|
+
} \
|
|
96
|
+
break; \
|
|
97
|
+
default: \
|
|
98
|
+
rb_bug("to_a fast path masked: unexpected dtype %d", dtype); \
|
|
99
|
+
} \
|
|
100
|
+
} while (0)
|
|
101
|
+
|
|
102
|
+
/* Recursive multi-dim wrap: for non-leaf levels, allocate child Array and
|
|
103
|
+
recurse with adjusted base pointer. At leaf level, invoke dispatch.
|
|
104
|
+
`flat_base` is ca->ptr + cumulative byte offset for this slab. */
|
|
19
105
|
static void
|
|
20
|
-
|
|
106
|
+
to_a_fast_recurse (CArray *ca, int32_t level, const char *base,
|
|
107
|
+
const boolean8_t *mask_base, VALUE dst,
|
|
108
|
+
int dtype, ca_size_t bytes, int has_mask)
|
|
109
|
+
{
|
|
110
|
+
ca_size_t i, n, slab_elements, slab_bytes;
|
|
111
|
+
|
|
112
|
+
if ( level == ca->ndim - 1 ) {
|
|
113
|
+
n = ca->dim[level];
|
|
114
|
+
if ( has_mask ) {
|
|
115
|
+
const boolean8_t *mask = mask_base;
|
|
116
|
+
TO_A_DISPATCH_LEAF_MASKED(TO_A_LEAF_LOOP_MASKED);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
TO_A_DISPATCH_LEAF(TO_A_LEAF_LOOP);
|
|
120
|
+
}
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* Non-leaf: walk dim[level], for each i allocate child Array + recurse. */
|
|
125
|
+
n = ca->dim[level];
|
|
126
|
+
slab_elements = 1;
|
|
127
|
+
for (i = level + 1; i < ca->ndim; i++) {
|
|
128
|
+
slab_elements *= ca->dim[i];
|
|
129
|
+
}
|
|
130
|
+
slab_bytes = slab_elements * bytes;
|
|
131
|
+
|
|
132
|
+
for (i = 0; i < n; i++) {
|
|
133
|
+
volatile VALUE child = rb_ary_new2(ca->dim[level + 1]);
|
|
134
|
+
rb_ary_store(dst, i, child);
|
|
135
|
+
to_a_fast_recurse(ca, level + 1,
|
|
136
|
+
base + i * slab_bytes,
|
|
137
|
+
has_mask ? mask_base + i * slab_elements : NULL,
|
|
138
|
+
child, dtype, bytes, has_mask);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* Universal fallback for CA_OBJECT / CA_FIXLEN, where ptr-direct cast
|
|
143
|
+
through the leaf switch is not safe. Walks every cell through
|
|
144
|
+
rb_ca_fetch_index; masked cells return CA_UNDEF via the fetcher. */
|
|
145
|
+
static void
|
|
146
|
+
rb_ca_to_a_loop_universal (VALUE self, int32_t level, ca_size_t *idx, VALUE ary)
|
|
21
147
|
{
|
|
22
148
|
volatile VALUE obj;
|
|
23
149
|
CArray *ca;
|
|
@@ -35,79 +161,180 @@ rb_ca_to_a_loop (VALUE self, int32_t level, ca_size_t *idx, VALUE ary)
|
|
|
35
161
|
for (i=0; i<ca->dim[level]; i++) {
|
|
36
162
|
idx[level] = i;
|
|
37
163
|
obj = rb_ary_new2(ca->dim[level+1]);
|
|
38
|
-
|
|
164
|
+
rb_ca_to_a_loop_universal(self, level+1, idx, obj);
|
|
39
165
|
rb_ary_store(ary, i, obj);
|
|
40
166
|
}
|
|
41
167
|
}
|
|
42
168
|
}
|
|
43
169
|
|
|
44
|
-
/*
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
170
|
+
/* CArray#to_a — return a nested Ruby Array holding self's element values.
|
|
171
|
+
*
|
|
172
|
+
* ndim-1 nesting: shape [2, 3] -> 2-element Array of 3-element Arrays.
|
|
173
|
+
* Masked cells become CA_UNDEF; the mask itself is not preserved on the
|
|
174
|
+
* result. ca_attach(self) supplies a contig row-major buffer for the
|
|
175
|
+
* fast path, so all view kinds land in the dtype-direct leaf loop when
|
|
176
|
+
* the dtype is numeric or boolean; CA_OBJECT / CA_FIXLEN fall through
|
|
177
|
+
* to the universal fetch_index walk. */
|
|
52
178
|
VALUE
|
|
53
179
|
rb_ca_to_a (VALUE self)
|
|
54
180
|
{
|
|
55
181
|
volatile VALUE ary;
|
|
56
182
|
CArray *ca;
|
|
57
183
|
ca_size_t idx[CA_RANK_MAX];
|
|
184
|
+
int dtype, fast_eligible;
|
|
185
|
+
|
|
58
186
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
59
|
-
ary = rb_ary_new2(ca->dim[0]);
|
|
187
|
+
ary = rb_ca_is_empty(self) ? rb_ary_new() : rb_ary_new2(ca->dim[0]);
|
|
60
188
|
ca_attach(ca);
|
|
61
|
-
|
|
189
|
+
|
|
190
|
+
/* After ca_attach, ca->ptr is a contig row-major buffer (alias for
|
|
191
|
+
contig views, materialised otherwise) and ca->mask matches, so the
|
|
192
|
+
fast path handles every view kind. CA_OBJECT / CA_FIXLEN stay on
|
|
193
|
+
the universal path because their ptr is VALUE / byte string and
|
|
194
|
+
the leaf switch cannot cast them directly.
|
|
195
|
+
|
|
196
|
+
A Face stays on it too, whatever its storage: the fast path reads the
|
|
197
|
+
storage buffer, and a Face means something else on its surface (an
|
|
198
|
+
Element, a label). Reading the buffer would hand back the storage of a
|
|
199
|
+
numeric-storage Face -- CATimedelta serials instead of CATimedelta
|
|
200
|
+
Elements -- while ca[i] / each / to_type(:object) all decode. The
|
|
201
|
+
universal loop goes through rb_ca_fetch_addr, which decodes. */
|
|
202
|
+
dtype = ca->data_type;
|
|
203
|
+
fast_eligible = (ca->elements > 0)
|
|
204
|
+
&& ( ! ca_is_face(ca) )
|
|
205
|
+
&& (dtype == CA_FLOAT64 || dtype == CA_FLOAT32
|
|
206
|
+
|| dtype == CA_INT64 || dtype == CA_INT32
|
|
207
|
+
|| dtype == CA_INT16 || dtype == CA_INT8
|
|
208
|
+
|| dtype == CA_UINT64 || dtype == CA_UINT32
|
|
209
|
+
|| dtype == CA_UINT16 || dtype == CA_UINT8
|
|
210
|
+
|| dtype == CA_BOOLEAN);
|
|
211
|
+
|
|
212
|
+
if ( fast_eligible ) {
|
|
213
|
+
int has_mask = (ca->mask != NULL);
|
|
214
|
+
const boolean8_t *mask_base = has_mask
|
|
215
|
+
? (const boolean8_t *) ca->mask->ptr : NULL;
|
|
216
|
+
to_a_fast_recurse(ca, 0, ca->ptr, mask_base, ary,
|
|
217
|
+
dtype, ca->bytes, has_mask);
|
|
218
|
+
}
|
|
219
|
+
else if ( ca->elements > 0 ) {
|
|
220
|
+
rb_ca_to_a_loop_universal(self, 0, idx, ary);
|
|
221
|
+
}
|
|
62
222
|
ca_detach(ca);
|
|
63
223
|
return ary;
|
|
64
224
|
}
|
|
65
225
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
226
|
+
#undef TO_A_LEAF_LOOP
|
|
227
|
+
#undef TO_A_LEAF_LOOP_MASKED
|
|
228
|
+
#undef TO_A_DISPATCH_LEAF
|
|
229
|
+
#undef TO_A_DISPATCH_LEAF_MASKED
|
|
230
|
+
|
|
231
|
+
/* CArray#convert(data_type=nil, bytes: nil) { |elem| ... } — map every cell
|
|
232
|
+
* through the block, into a new array whose dtype is chosen by argv via
|
|
233
|
+
* CArray#template (shape is inherited from self).
|
|
234
|
+
*
|
|
235
|
+
* Masked cells skip the block; if the block returns CA_UNDEF, the
|
|
236
|
+
* corresponding output cell is masked instead of stored. Both self
|
|
237
|
+
* and the template result are attached symmetrically (R3-compliant) so
|
|
238
|
+
* an overridden #template returning a view stays on the in-ptr path. */
|
|
74
239
|
static VALUE
|
|
75
240
|
rb_ca_convert (int argc, VALUE *argv, VALUE self)
|
|
76
241
|
{
|
|
77
242
|
volatile VALUE obj;
|
|
78
|
-
CArray *ca;
|
|
79
|
-
ca_size_t i;
|
|
243
|
+
CArray *ca, *co;
|
|
244
|
+
ca_size_t i, n, sbytes, dbytes;
|
|
245
|
+
int has_mask;
|
|
246
|
+
const boolean8_t *src_mask = NULL;
|
|
247
|
+
boolean8_t *dst_mask = NULL;
|
|
248
|
+
const char *src_ptr;
|
|
249
|
+
char *dst_ptr;
|
|
250
|
+
|
|
251
|
+
rb_need_block();
|
|
80
252
|
|
|
81
253
|
obj = rb_apply(self, rb_intern("template"), rb_ary_new4(argc, argv));
|
|
82
254
|
|
|
83
255
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
256
|
+
TypedData_Get_Struct(obj, CArray, &carray_data_type, co);
|
|
257
|
+
|
|
258
|
+
n = ca->elements;
|
|
259
|
+
has_mask = ca_has_mask(ca);
|
|
260
|
+
sbytes = ca->bytes;
|
|
261
|
+
dbytes = co->bytes;
|
|
262
|
+
|
|
263
|
+
/* Attach every storage touched by ptr (self, obj, and either side's
|
|
264
|
+
mask) — parent → child order per the R4 attach protocol. */
|
|
84
265
|
ca_attach(ca);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
266
|
+
ca_attach(co);
|
|
267
|
+
if ( has_mask ) {
|
|
268
|
+
ca_attach(ca->mask);
|
|
269
|
+
if ( ! co->mask ) {
|
|
270
|
+
ca_create_mask(co);
|
|
271
|
+
}
|
|
272
|
+
ca_attach(co->mask);
|
|
273
|
+
src_mask = (const boolean8_t *) ca->mask->ptr;
|
|
274
|
+
dst_mask = (boolean8_t *) co->mask->ptr;
|
|
275
|
+
memset(dst_mask, 0, (size_t) n);
|
|
276
|
+
}
|
|
277
|
+
src_ptr = ca->ptr;
|
|
278
|
+
dst_ptr = co->ptr;
|
|
279
|
+
|
|
280
|
+
if ( has_mask ) {
|
|
281
|
+
for (i = 0; i < n; i++) {
|
|
282
|
+
if ( ! src_mask[i] ) {
|
|
283
|
+
VALUE val = rb_ca_ptr2obj(self, (void *) (src_ptr + i * sbytes));
|
|
284
|
+
VALUE ret = rb_yield(val);
|
|
285
|
+
if ( ret == CA_UNDEF ) {
|
|
286
|
+
dst_mask[i] = 1;
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
rb_ca_obj2ptr(obj, ret, dst_ptr + i * dbytes);
|
|
290
|
+
}
|
|
89
291
|
}
|
|
90
292
|
else {
|
|
91
|
-
|
|
293
|
+
dst_mask[i] = 1;
|
|
92
294
|
}
|
|
93
295
|
}
|
|
94
296
|
}
|
|
95
297
|
else {
|
|
96
|
-
for (i=0; i<
|
|
97
|
-
|
|
298
|
+
for (i = 0; i < n; i++) {
|
|
299
|
+
VALUE val = rb_ca_ptr2obj(self, (void *) (src_ptr + i * sbytes));
|
|
300
|
+
VALUE ret = rb_yield(val);
|
|
301
|
+
if ( ret == CA_UNDEF ) {
|
|
302
|
+
if ( ! co->mask ) {
|
|
303
|
+
ca_create_mask(co);
|
|
304
|
+
ca_attach(co->mask);
|
|
305
|
+
dst_mask = (boolean8_t *) co->mask->ptr;
|
|
306
|
+
memset(dst_mask, 0, (size_t) n);
|
|
307
|
+
}
|
|
308
|
+
dst_mask[i] = 1;
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
rb_ca_obj2ptr(obj, ret, dst_ptr + i * dbytes);
|
|
312
|
+
}
|
|
98
313
|
}
|
|
99
314
|
}
|
|
315
|
+
|
|
316
|
+
if ( co->mask ) {
|
|
317
|
+
ca_sync(co->mask);
|
|
318
|
+
ca_detach(co->mask);
|
|
319
|
+
}
|
|
320
|
+
if ( has_mask ) {
|
|
321
|
+
ca_detach(ca->mask);
|
|
322
|
+
}
|
|
323
|
+
ca_sync(co);
|
|
324
|
+
ca_detach(co);
|
|
100
325
|
ca_detach(ca);
|
|
101
326
|
|
|
102
327
|
return obj;
|
|
103
328
|
}
|
|
104
329
|
|
|
105
|
-
/*
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
330
|
+
/* CArray#dump_binary([io]) — write self's raw element bytes to io in
|
|
331
|
+
* row-major order.
|
|
332
|
+
*
|
|
333
|
+
* With no arg, returns a fresh binary String. A String arg is resized
|
|
334
|
+
* and overwritten in-place; a T_FILE writes through rb_io_bufwrite for
|
|
335
|
+
* entities (no Ruby String copy) or a scratch buffer for views; any
|
|
336
|
+
* other object must respond to #write. Rejects CA_OBJECT (data is
|
|
337
|
+
* VALUE, not portable). */
|
|
111
338
|
static VALUE
|
|
112
339
|
rb_ca_dump_binary (int argc, VALUE *argv, VALUE self)
|
|
113
340
|
{
|
|
@@ -132,43 +359,39 @@ rb_ca_dump_binary (int argc, VALUE *argv, VALUE self)
|
|
|
132
359
|
|
|
133
360
|
switch ( TYPE(io) ) {
|
|
134
361
|
case T_STRING:
|
|
362
|
+
rb_check_frozen(io);
|
|
135
363
|
if ( ca_length(ca) != RSTRING_LEN(io) ) {
|
|
136
364
|
rb_str_resize(io, ca_length(ca));
|
|
137
365
|
}
|
|
138
|
-
ca_copy_data(ca,
|
|
139
|
-
StringValuePtr(io)[ca_length(ca)] = '\0';
|
|
366
|
+
ca_copy_data(ca, RSTRING_PTR(io));
|
|
140
367
|
break;
|
|
141
|
-
#if RUBY_VERSION_CODE >= 190
|
|
142
368
|
case T_FILE: {
|
|
143
|
-
volatile VALUE str;
|
|
144
369
|
rb_io_t *iop;
|
|
370
|
+
ca_size_t total = ca_length(ca);
|
|
145
371
|
GetOpenFile(io, iop);
|
|
146
372
|
rb_io_check_writable(iop);
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if ( total < ca->elements ) {
|
|
163
|
-
rb_raise(rb_eIOError, "I/O write error in CArray#dump_binary");
|
|
373
|
+
if ( ca_is_entity(ca) ) {
|
|
374
|
+
/* Owned ca->ptr: write through the IO buffer machinery so peak
|
|
375
|
+
stays at ca_length instead of doubling via a Ruby String. */
|
|
376
|
+
ssize_t n = rb_io_bufwrite(io, ca->ptr, (size_t) total);
|
|
377
|
+
if ( n < 0 || (ca_size_t) n != total ) {
|
|
378
|
+
rb_raise(rb_eRuntimeError,
|
|
379
|
+
"short write to IO (wrote %" PRId64 " bytes, expected %" PRId64 ")",
|
|
380
|
+
(ca_size_t) (n < 0 ? 0 : n), (ca_size_t) total);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
/* View: no chunked gather API, so materialise into one buffer. */
|
|
385
|
+
volatile VALUE buf = rb_str_new(NULL, total);
|
|
386
|
+
ca_copy_data(ca, RSTRING_PTR(buf));
|
|
387
|
+
rb_io_write(io, buf);
|
|
164
388
|
}
|
|
165
389
|
break;
|
|
166
390
|
}
|
|
167
|
-
#endif
|
|
168
391
|
default:
|
|
169
392
|
if ( rb_respond_to(io, rb_intern("write") ) ) {
|
|
170
393
|
volatile VALUE buf = rb_str_new(NULL, ca_length(ca));
|
|
171
|
-
ca_copy_data(ca,
|
|
394
|
+
ca_copy_data(ca, RSTRING_PTR(buf));
|
|
172
395
|
rb_funcall(io, rb_intern("write"), 1, buf);
|
|
173
396
|
}
|
|
174
397
|
else {
|
|
@@ -179,24 +402,21 @@ rb_ca_dump_binary (int argc, VALUE *argv, VALUE self)
|
|
|
179
402
|
return io;
|
|
180
403
|
}
|
|
181
404
|
|
|
182
|
-
/*
|
|
183
|
-
|
|
184
|
-
(Conversion)
|
|
185
|
-
Dumps the value array to a string.
|
|
186
|
-
*/
|
|
187
|
-
|
|
405
|
+
/* CArray#to_s — equivalent to dump_binary with no argument. */
|
|
188
406
|
static VALUE
|
|
189
407
|
rb_ca_to_s (VALUE self)
|
|
190
408
|
{
|
|
191
409
|
return rb_ca_dump_binary(0, NULL, self);
|
|
192
410
|
}
|
|
193
411
|
|
|
194
|
-
/*
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
412
|
+
/* CArray#load_binary(io) — overwrite self's element bytes with ca_length
|
|
413
|
+
* bytes read from io in row-major order.
|
|
414
|
+
*
|
|
415
|
+
* A String arg of the exact length is used directly; anything else
|
|
416
|
+
* must respond to #read(n, buf). Entity targets read in 64 KiB
|
|
417
|
+
* chunks straight into ca->ptr (peak = ca_length + CHUNK); view
|
|
418
|
+
* targets buffer the full read and recurse via T_STRING because
|
|
419
|
+
* ca_sync_data scatters in one pass. */
|
|
200
420
|
static VALUE
|
|
201
421
|
rb_ca_load_binary (VALUE self, VALUE io)
|
|
202
422
|
{
|
|
@@ -210,280 +430,73 @@ rb_ca_load_binary (VALUE self, VALUE io)
|
|
|
210
430
|
|
|
211
431
|
switch ( TYPE(io) ) {
|
|
212
432
|
case T_STRING:
|
|
213
|
-
if ( ca_length(ca)
|
|
433
|
+
if ( ca_length(ca) != RSTRING_LEN(io) ) {
|
|
214
434
|
rb_raise(rb_eRuntimeError,
|
|
215
|
-
"data size mismatch (%
|
|
435
|
+
"data size mismatch (got %" PRId64 " bytes, expected %" PRId64 ")",
|
|
216
436
|
(ca_size_t) RSTRING_LEN(io), (ca_size_t) ca_length(ca));
|
|
217
437
|
}
|
|
218
|
-
|
|
219
|
-
memcpy(ca->ptr, StringValuePtr(io), ca_length(ca));
|
|
220
|
-
ca_sync(ca);
|
|
221
|
-
ca_detach(ca);
|
|
438
|
+
ca_sync_data(ca, RSTRING_PTR(io));
|
|
222
439
|
return self;
|
|
223
440
|
break;
|
|
224
441
|
default:
|
|
225
442
|
if ( rb_respond_to(io, rb_intern("read") ) ) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if ( ! ca_is_attached(ca) ) {
|
|
249
|
-
rb_raise(rb_eRuntimeError, "[BUG] ca_to_cptr called for detached array");
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
if ( ca->ndim == 1 ) {
|
|
253
|
-
rb_raise(rb_eRuntimeError, "[BUG] ca_to_cptr called for ndim-1 array");
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
offset[0] = 0;
|
|
257
|
-
count[0] = ca->dim[0];
|
|
258
|
-
ptr_num = count[0];
|
|
259
|
-
for (i=1; i<ca->ndim-1; i++) {
|
|
260
|
-
offset[i] = ptr_num;
|
|
261
|
-
count[i] = count[i-1] * ca->dim[i];
|
|
262
|
-
ptr_num += count[i];
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
ptr = malloc(sizeof(void*)*ptr_num);
|
|
266
|
-
|
|
267
|
-
i = ca->ndim-2;
|
|
268
|
-
p = ptr + offset[i];
|
|
269
|
-
q = (char *)ca->ptr;
|
|
270
|
-
for (j=0; j<count[i]; j++) {
|
|
271
|
-
*p = (void*)q;
|
|
272
|
-
p++; q += ca->dim[ca->ndim-1] * ca->bytes;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
for (i=ca->ndim-3; i>=0; i--) {
|
|
276
|
-
p = ptr + offset[i];
|
|
277
|
-
r = ptr + offset[i+1];
|
|
278
|
-
for (j=0; j<count[i]; j++) {
|
|
279
|
-
*p = (void*)r;
|
|
280
|
-
p++; r+=ca->dim[i+1];
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
return ptr;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
/* @overload str_format (*fmts)
|
|
289
|
-
|
|
290
|
-
(Conversion)
|
|
291
|
-
Creates object type array consist of string using the "::format" method.
|
|
292
|
-
The Multiple format strings are given, they are applied cyclic in turn.
|
|
293
|
-
*/
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
static VALUE
|
|
297
|
-
rb_ca_format (int argc, VALUE *argv, VALUE self)
|
|
298
|
-
{
|
|
299
|
-
volatile VALUE obj, elem, val;
|
|
300
|
-
CArray *ca;
|
|
301
|
-
ca_size_t i, j;
|
|
302
|
-
ID id_format = rb_intern("format");
|
|
303
|
-
|
|
304
|
-
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
305
|
-
|
|
306
|
-
obj = rb_ca_template_with_type(self, INT2NUM(CA_OBJECT), INT2NUM(0));
|
|
307
|
-
|
|
308
|
-
ca_attach(ca);
|
|
309
|
-
if ( ca_has_mask(ca) ) {
|
|
310
|
-
j = 0;
|
|
311
|
-
for (i=0; i<ca->elements; i++) {
|
|
312
|
-
val = CA_UNDEF;
|
|
313
|
-
if ( ! ca->mask->ptr[i] ) {
|
|
314
|
-
elem = rb_ca_fetch_addr(self, i);
|
|
315
|
-
val = rb_funcall(elem, id_format, 2, argv[j], elem);
|
|
316
|
-
}
|
|
317
|
-
rb_ca_store_addr(obj, i, val);
|
|
318
|
-
j++;
|
|
319
|
-
j = j % argc; /* cyclic referencing of argv */
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
else {
|
|
323
|
-
j = 0;
|
|
324
|
-
for (i=0; i<ca->elements; i++) {
|
|
325
|
-
elem = rb_ca_fetch_addr(self, i);
|
|
326
|
-
val = rb_funcall(elem, id_format, 2, argv[j], elem);
|
|
327
|
-
rb_ca_store_addr(obj, i, val);
|
|
328
|
-
j++;
|
|
329
|
-
j = j % argc; /* cyclic referencing of argv */
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
ca_detach(ca);
|
|
333
|
-
|
|
334
|
-
return obj;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
#include <time.h>
|
|
339
|
-
|
|
340
|
-
#ifdef HAVE_STRPTIME
|
|
341
|
-
|
|
342
|
-
/* @overload str_strptime (fmt)
|
|
343
|
-
|
|
344
|
-
(Conversion)
|
|
345
|
-
Creates object type array consist of Time objects
|
|
346
|
-
which are created by 'Time.strptime' applied to the elements of the object.
|
|
347
|
-
This method assumes all the elements of the objetct to be String.
|
|
348
|
-
*/
|
|
349
|
-
|
|
350
|
-
static VALUE
|
|
351
|
-
rb_ca_strptime (VALUE self, VALUE rfmt)
|
|
352
|
-
{
|
|
353
|
-
volatile VALUE obj, elem, val;
|
|
354
|
-
CArray *ca;
|
|
355
|
-
char *fmt;
|
|
356
|
-
struct tm tmv;
|
|
357
|
-
ca_size_t i;
|
|
358
|
-
|
|
359
|
-
ca = ca_wrap_readonly(self, CA_OBJECT);
|
|
360
|
-
|
|
361
|
-
if ( ! ca_is_object_type(ca) ) {
|
|
362
|
-
rb_raise(rb_eRuntimeError, "strptime can be applied only to object type.");
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
Check_Type(rfmt, T_STRING);
|
|
366
|
-
fmt = (char *) StringValuePtr(rfmt);
|
|
367
|
-
|
|
368
|
-
obj = rb_ca_template(self);
|
|
369
|
-
|
|
370
|
-
ca_attach(ca);
|
|
371
|
-
if ( ca_has_mask(ca) ) {
|
|
372
|
-
for (i=0; i<ca->elements; i++) {
|
|
373
|
-
val = CA_UNDEF;
|
|
374
|
-
if ( ! ca->mask->ptr[i] ) {
|
|
375
|
-
elem = rb_ca_fetch_addr(self, i);
|
|
376
|
-
if ( TYPE(elem) == T_STRING ) {
|
|
377
|
-
memset(&tmv, 0, sizeof(struct tm));
|
|
378
|
-
if ( strptime(StringValuePtr(elem), fmt, &tmv) ) {
|
|
379
|
-
val = rb_time_new(mktime(&tmv), 0);
|
|
380
|
-
}
|
|
443
|
+
ca_size_t total = ca_length(ca);
|
|
444
|
+
ID id_read = rb_intern("read");
|
|
445
|
+
if ( ca_is_entity(ca) ) {
|
|
446
|
+
/* Read straight into owned ca->ptr in CHUNK-sized slices. */
|
|
447
|
+
const ca_size_t CHUNK = 65536;
|
|
448
|
+
volatile VALUE scratch = rb_str_buf_new(CHUNK < total ? CHUNK : total);
|
|
449
|
+
ca_size_t off = 0;
|
|
450
|
+
ca_allocate(ca);
|
|
451
|
+
while ( off < total ) {
|
|
452
|
+
ca_size_t want = (total - off < CHUNK) ? (total - off) : CHUNK;
|
|
453
|
+
VALUE r = rb_funcall(io, id_read, 2, SIZE2NUM(want), scratch);
|
|
454
|
+
if ( NIL_P(r) || RSTRING_LEN(r) != want ) {
|
|
455
|
+
ca_detach(ca);
|
|
456
|
+
rb_raise(rb_eRuntimeError,
|
|
457
|
+
"short read from IO at offset %" PRId64 " "
|
|
458
|
+
"(got %" PRId64 " bytes, expected %" PRId64 ")",
|
|
459
|
+
(ca_size_t) off,
|
|
460
|
+
(ca_size_t) (NIL_P(r) ? 0 : RSTRING_LEN(r)),
|
|
461
|
+
(ca_size_t) want);
|
|
462
|
+
}
|
|
463
|
+
memcpy(ca->ptr + off, RSTRING_PTR(r), want);
|
|
464
|
+
off += want;
|
|
381
465
|
}
|
|
466
|
+
ca_sync(ca);
|
|
467
|
+
ca_detach(ca);
|
|
382
468
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
rb_ca_store_addr(obj, i, val);
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
ca_detach(ca);
|
|
400
|
-
|
|
401
|
-
return obj;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
#endif
|
|
405
|
-
|
|
406
|
-
/* @overload time_strftime (fmt)
|
|
407
|
-
|
|
408
|
-
(Conversion)
|
|
409
|
-
Creates object type array consist of strings
|
|
410
|
-
which are created by 'Time#strftime' applied to the elements of the object.
|
|
411
|
-
This method assumes all the elements of the objetct to be Time or DateTime.
|
|
412
|
-
*/
|
|
413
|
-
|
|
414
|
-
static VALUE
|
|
415
|
-
rb_ca_strftime (VALUE self, VALUE rfmt)
|
|
416
|
-
{
|
|
417
|
-
volatile VALUE obj, elem, val;
|
|
418
|
-
CArray *ca;
|
|
419
|
-
ca_size_t i;
|
|
420
|
-
ID id_strftime = rb_intern("strftime");
|
|
421
|
-
|
|
422
|
-
ca = ca_wrap_readonly(self, CA_OBJECT);
|
|
423
|
-
|
|
424
|
-
if ( ! ca_is_object_type(ca) ) {
|
|
425
|
-
rb_raise(rb_eRuntimeError, "strptime can be applied only to object type.");
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
obj = rb_ca_template(self);
|
|
429
|
-
|
|
430
|
-
ca_attach(ca);
|
|
431
|
-
if ( ca_has_mask(ca) ) {
|
|
432
|
-
for (i=0; i<ca->elements; i++) {
|
|
433
|
-
val = CA_UNDEF;
|
|
434
|
-
if ( ! ca->mask->ptr[i] ) {
|
|
435
|
-
elem = rb_ca_fetch_addr(self, i);
|
|
436
|
-
val = rb_funcall(elem, id_strftime, 1, rfmt);
|
|
469
|
+
else {
|
|
470
|
+
/* ca_sync_data scatters in one pass, so buffer the full read
|
|
471
|
+
and recurse via T_STRING. */
|
|
472
|
+
volatile VALUE buf = rb_funcall(io, id_read, 1, SIZE2NUM(total));
|
|
473
|
+
if ( NIL_P(buf) || RSTRING_LEN(buf) != total ) {
|
|
474
|
+
rb_raise(rb_eRuntimeError,
|
|
475
|
+
"short read from IO (got %" PRId64 " bytes, expected %" PRId64 ")",
|
|
476
|
+
(ca_size_t) (NIL_P(buf) ? 0 : RSTRING_LEN(buf)),
|
|
477
|
+
(ca_size_t) total);
|
|
478
|
+
}
|
|
479
|
+
return rb_ca_load_binary(self, buf);
|
|
437
480
|
}
|
|
438
|
-
|
|
481
|
+
return self;
|
|
439
482
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
for (i=0; i<ca->elements; i++) {
|
|
443
|
-
elem = rb_ca_fetch_addr(self, i);
|
|
444
|
-
val = rb_funcall(elem, id_strftime, 1, rfmt);
|
|
445
|
-
rb_ca_store_addr(obj, i, val);
|
|
483
|
+
else {
|
|
484
|
+
rb_raise(rb_eRuntimeError, "IO like object should have 'read' method");
|
|
446
485
|
}
|
|
447
486
|
}
|
|
448
|
-
ca_detach(ca);
|
|
449
487
|
|
|
450
|
-
return
|
|
488
|
+
return self;
|
|
451
489
|
}
|
|
452
490
|
|
|
453
|
-
/*
|
|
454
|
-
|
|
455
|
-
*/
|
|
456
|
-
|
|
457
|
-
static VALUE
|
|
458
|
-
rb_test_ca_to_cptr (VALUE self)
|
|
459
|
-
{
|
|
460
|
-
CArray *ca;
|
|
461
|
-
double ****a;
|
|
462
|
-
int i, j, k, l;
|
|
463
|
-
|
|
464
|
-
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
465
|
-
|
|
466
|
-
ca_attach(ca);
|
|
467
|
-
|
|
468
|
-
a = ca_to_cptr(ca);
|
|
469
|
-
for (i=0; i<ca->dim[0]; i++) {
|
|
470
|
-
for (j=0; j<ca->dim[1]; j++) {
|
|
471
|
-
for (k=0; k<ca->dim[2]; k++) {
|
|
472
|
-
for (l=0; l<ca->dim[3]; l++) {
|
|
473
|
-
printf("(%i, %i, %i, %i) -> %g\n", i, j, k, l, a[i][j][k][l]);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
free(a);
|
|
491
|
+
/* [MOVED] str_format (2.0-era per-element formatter) is replaced by the Ruby
|
|
492
|
+
CArray#format / CArray.format surface in lib/carray/methods/string_format.rb,
|
|
493
|
+
which yields a CAString. */
|
|
479
494
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
return Qnil;
|
|
483
|
-
}
|
|
495
|
+
/* [MOVED] time-related conversion (str_strptime / time_strftime) is
|
|
496
|
+
subsumed by CATime (see lib/carray/time.rb). */
|
|
484
497
|
|
|
485
498
|
void
|
|
486
|
-
Init_carray_conversion ()
|
|
499
|
+
Init_carray_conversion (void)
|
|
487
500
|
{
|
|
488
501
|
rb_define_method(rb_cCArray, "to_a", rb_ca_to_a, 0);
|
|
489
502
|
rb_define_method(rb_cCArray, "convert", rb_ca_convert, -1);
|
|
@@ -492,17 +505,8 @@ Init_carray_conversion ()
|
|
|
492
505
|
rb_define_method(rb_cCArray, "to_s", rb_ca_to_s, 0);
|
|
493
506
|
rb_define_method(rb_cCArray, "load_binary", rb_ca_load_binary, 1);
|
|
494
507
|
|
|
495
|
-
/*
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
rb_define_method(rb_cCArray, "
|
|
499
|
-
|
|
500
|
-
#ifdef HAVE_STRPTIME
|
|
501
|
-
rb_define_method(rb_cCArray, "str_strptime", rb_ca_strptime, 1);
|
|
502
|
-
#endif
|
|
503
|
-
|
|
504
|
-
rb_define_method(rb_cCArray, "time_strftime", rb_ca_strftime, 1);
|
|
505
|
-
|
|
506
|
-
rb_define_method(rb_cCArray, "test_ca_to_cptr", rb_test_ca_to_cptr, 0);
|
|
507
|
-
|
|
508
|
+
/* CAREFUL: do not bind #to_ary — implicit array coercion in Ruby core
|
|
509
|
+
(splat / multiple assignment / Array()) then triggers on any CArray
|
|
510
|
+
and disrupts unrelated call sites. */
|
|
511
|
+
/* rb_define_method(rb_cCArray, "to_ary", rb_ca_to_a, 0); */
|
|
508
512
|
}
|