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_cast.c
CHANGED
|
@@ -1,14 +1,37 @@
|
|
|
1
1
|
/* ---------------------------------------------------------------------------
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
Cast surface (3 layers):
|
|
4
|
+
|
|
5
|
+
to_<type> `a.to_int32` etc. Returns a fresh entity CArray
|
|
6
|
+
of the target data_type. Independent storage from
|
|
7
|
+
`self`.
|
|
8
|
+
|
|
9
|
+
as_<type> `a.as_int32` etc. Returns a writable CAMonOp view
|
|
10
|
+
that reinterprets `self` cell-by-cell at the target
|
|
11
|
+
data_type. No new storage.
|
|
12
|
+
|
|
13
|
+
CA_<TYPE>(data)
|
|
14
|
+
`CA_INT32(data)`, `CA_FLOAT64(data)`, ...,
|
|
15
|
+
`CA_OBJECT(data)`, `CA_FIXLEN(...)` — global
|
|
16
|
+
polymorphic cast functions (registered at file
|
|
17
|
+
bottom via rb_define_global_function). Coerce
|
|
18
|
+
`data` (Numeric / Array / CArray / Range /
|
|
19
|
+
String / nil / object responding to `to_ca` /
|
|
20
|
+
`to_a`) into a CArray of the target data_type,
|
|
21
|
+
dispatching on `data`'s Ruby class. Type-name
|
|
22
|
+
aliases (CA_BYTE / CA_INT / CA_FLOAT / CA_SIZE /
|
|
23
|
+
...) reuse the canonical entry.
|
|
24
|
+
|
|
25
|
+
Sibling of ext/carray_data_type.c (type-tag class shells +
|
|
26
|
+
data_type id <-> class mapping); the CA_<TYPE>(data) functions
|
|
27
|
+
here pair with the typed classes registered there.
|
|
8
28
|
|
|
9
29
|
---------------------------------------------------------------------------- */
|
|
10
30
|
|
|
11
31
|
#include "carray.h"
|
|
32
|
+
#include "ruby/memory_view.h"
|
|
33
|
+
#include "ca_monop_dispatch.h" /* CA_MONOP_CAST_BASE for as_type routing */
|
|
34
|
+
#include "ca_obj_face.h" /* ca_strip_face for write path lift */
|
|
12
35
|
|
|
13
36
|
boolean8_t
|
|
14
37
|
OBJ2BOOL (VALUE v)
|
|
@@ -38,6 +61,36 @@ BOOL2OBJ (boolean8_t x)
|
|
|
38
61
|
return ( x != 0 ) ? INT2NUM(1) : INT2NUM(0);
|
|
39
62
|
}
|
|
40
63
|
|
|
64
|
+
/* Recognise an explicit non-finite float literal. `str` must already be
|
|
65
|
+
whitespace-stripped. The whole token is matched case-insensitively as an
|
|
66
|
+
exact match (not a prefix): only nan / inf / infinity with an optional
|
|
67
|
+
+/- sign map to a non-finite value. Returns 1 and sets *out on a match,
|
|
68
|
+
0 otherwise -- so "nancy" / "info" / "inflation" fall through to the
|
|
69
|
+
numeric parser instead of being read as NaN/Infinity. */
|
|
70
|
+
static int
|
|
71
|
+
ca_str_nonfinite (const char *str, double *out)
|
|
72
|
+
{
|
|
73
|
+
if ( ! strcasecmp(str, "nan")
|
|
74
|
+
|| ! strcasecmp(str, "+nan")
|
|
75
|
+
|| ! strcasecmp(str, "-nan") ) {
|
|
76
|
+
*out = 0.0/0.0;
|
|
77
|
+
return 1;
|
|
78
|
+
}
|
|
79
|
+
else if ( ! strcasecmp(str, "inf")
|
|
80
|
+
|| ! strcasecmp(str, "+inf")
|
|
81
|
+
|| ! strcasecmp(str, "infinity")
|
|
82
|
+
|| ! strcasecmp(str, "+infinity") ) {
|
|
83
|
+
*out = 1.0/0.0;
|
|
84
|
+
return 1;
|
|
85
|
+
}
|
|
86
|
+
else if ( ! strcasecmp(str, "-inf")
|
|
87
|
+
|| ! strcasecmp(str, "-infinity") ) {
|
|
88
|
+
*out = -1.0/0.0;
|
|
89
|
+
return 1;
|
|
90
|
+
}
|
|
91
|
+
return 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
41
94
|
double
|
|
42
95
|
OBJ2DBL (VALUE val)
|
|
43
96
|
{
|
|
@@ -46,30 +99,160 @@ OBJ2DBL (VALUE val)
|
|
|
46
99
|
return NUM2DBL(val);
|
|
47
100
|
case T_NIL:
|
|
48
101
|
return 0.0/0.0;
|
|
49
|
-
/* rb_raise(rb_eTypeError, "no implicit conversion to float from nil"); */
|
|
50
|
-
break;
|
|
51
102
|
case T_STRING: {
|
|
103
|
+
double d;
|
|
52
104
|
volatile VALUE rstr = rb_funcall(val, rb_intern("strip"), 0);
|
|
53
105
|
char *str = StringValuePtr(rstr);
|
|
54
|
-
if (
|
|
55
|
-
return
|
|
106
|
+
if ( ca_str_nonfinite(str, &d) ) {
|
|
107
|
+
return d;
|
|
56
108
|
}
|
|
57
|
-
|
|
58
|
-
|
|
109
|
+
return rb_cstr_to_dbl(str, 0);
|
|
110
|
+
}
|
|
111
|
+
default:
|
|
112
|
+
return NUM2DBL(rb_Float(val));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* rb_protect bodies: Kernel#Float / Kernel#Integer applied to one value.
|
|
117
|
+
Used by the mask-aware object->numeric parsers below so a conversion
|
|
118
|
+
error is caught (and turned into a masked cell) rather than raised. */
|
|
119
|
+
static VALUE
|
|
120
|
+
ca_kernel_float (VALUE v)
|
|
121
|
+
{
|
|
122
|
+
return rb_Float(v);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
static VALUE
|
|
126
|
+
ca_kernel_integer (VALUE v)
|
|
127
|
+
{
|
|
128
|
+
return rb_Integer(v);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/* Object -> double with parse-failure signalling. Returns 1 and sets *out
|
|
132
|
+
on success; returns 0 when the cell cannot be parsed, in which case the
|
|
133
|
+
caller writes UNDEF (mask) for that cell. nil and unparseable
|
|
134
|
+
strings/objects fail; already-numeric values and explicit nan/inf
|
|
135
|
+
literals succeed. Strictness mirrors Ruby Float() (whitespace strip,
|
|
136
|
+
"1e3" ok, ...) but a bad token masks instead of raising. */
|
|
137
|
+
int
|
|
138
|
+
ca_obj2dbl_ok (VALUE val, double *out)
|
|
139
|
+
{
|
|
140
|
+
if ( NIL_P(val) ) {
|
|
141
|
+
return 0;
|
|
142
|
+
}
|
|
143
|
+
if ( RB_FLOAT_TYPE_P(val) || RB_INTEGER_TYPE_P(val) ) {
|
|
144
|
+
*out = NUM2DBL(val);
|
|
145
|
+
return 1;
|
|
146
|
+
}
|
|
147
|
+
if ( RB_TYPE_P(val, T_STRING) ) {
|
|
148
|
+
volatile VALUE rstr = rb_funcall(val, rb_intern("strip"), 0);
|
|
149
|
+
if ( ca_str_nonfinite(StringValuePtr(rstr), out) ) {
|
|
150
|
+
return 1;
|
|
59
151
|
}
|
|
60
|
-
|
|
61
|
-
|
|
152
|
+
}
|
|
153
|
+
{
|
|
154
|
+
int state = 0;
|
|
155
|
+
volatile VALUE r = rb_protect(ca_kernel_float, val, &state);
|
|
156
|
+
if ( state ) {
|
|
157
|
+
rb_set_errinfo(Qnil);
|
|
158
|
+
return 0;
|
|
62
159
|
}
|
|
63
|
-
|
|
64
|
-
|
|
160
|
+
*out = NUM2DBL(r);
|
|
161
|
+
return 1;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* Object -> integer with parse-failure signalling (int/long lane). Same
|
|
166
|
+
contract as ca_obj2dbl_ok: 1 + *out on success, 0 (mask) on failure.
|
|
167
|
+
Strictness mirrors Ruby Integer() -- a non-integer string ("1.5") fails
|
|
168
|
+
(no truncation), nil fails, "0xff"/"1_000" parse. A valid Integer that
|
|
169
|
+
overflows the widest C integer still raises (a domain error, not a parse
|
|
170
|
+
failure). */
|
|
171
|
+
int
|
|
172
|
+
rb_obj2long_ok (VALUE val, long *out)
|
|
173
|
+
{
|
|
174
|
+
if ( NIL_P(val) ) {
|
|
175
|
+
return 0;
|
|
176
|
+
}
|
|
177
|
+
if ( RB_TYPE_P(val, T_FIXNUM) ) {
|
|
178
|
+
*out = NUM2LONG(val);
|
|
179
|
+
return 1;
|
|
180
|
+
}
|
|
181
|
+
{
|
|
182
|
+
int state = 0;
|
|
183
|
+
volatile VALUE r = rb_protect(ca_kernel_integer, val, &state);
|
|
184
|
+
if ( state ) {
|
|
185
|
+
rb_set_errinfo(Qnil);
|
|
186
|
+
return 0;
|
|
65
187
|
}
|
|
66
|
-
|
|
67
|
-
|
|
188
|
+
*out = NUM2LONG(r);
|
|
189
|
+
return 1;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
int
|
|
194
|
+
rb_obj2ulong_ok (VALUE val, unsigned long *out)
|
|
195
|
+
{
|
|
196
|
+
if ( NIL_P(val) ) {
|
|
197
|
+
return 0;
|
|
198
|
+
}
|
|
199
|
+
if ( RB_TYPE_P(val, T_FIXNUM) ) {
|
|
200
|
+
*out = NUM2ULONG(val);
|
|
201
|
+
return 1;
|
|
202
|
+
}
|
|
203
|
+
{
|
|
204
|
+
int state = 0;
|
|
205
|
+
volatile VALUE r = rb_protect(ca_kernel_integer, val, &state);
|
|
206
|
+
if ( state ) {
|
|
207
|
+
rb_set_errinfo(Qnil);
|
|
208
|
+
return 0;
|
|
68
209
|
}
|
|
69
|
-
|
|
210
|
+
*out = NUM2ULONG(r);
|
|
211
|
+
return 1;
|
|
70
212
|
}
|
|
71
|
-
|
|
72
|
-
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
int
|
|
216
|
+
rb_obj2ll_ok (VALUE val, long long *out)
|
|
217
|
+
{
|
|
218
|
+
if ( NIL_P(val) ) {
|
|
219
|
+
return 0;
|
|
220
|
+
}
|
|
221
|
+
if ( RB_TYPE_P(val, T_FIXNUM) ) {
|
|
222
|
+
*out = NUM2LL(val);
|
|
223
|
+
return 1;
|
|
224
|
+
}
|
|
225
|
+
{
|
|
226
|
+
int state = 0;
|
|
227
|
+
volatile VALUE r = rb_protect(ca_kernel_integer, val, &state);
|
|
228
|
+
if ( state ) {
|
|
229
|
+
rb_set_errinfo(Qnil);
|
|
230
|
+
return 0;
|
|
231
|
+
}
|
|
232
|
+
*out = NUM2LL(r);
|
|
233
|
+
return 1;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
int
|
|
238
|
+
rb_obj2ull_ok (VALUE val, unsigned long long *out)
|
|
239
|
+
{
|
|
240
|
+
if ( NIL_P(val) ) {
|
|
241
|
+
return 0;
|
|
242
|
+
}
|
|
243
|
+
if ( RB_TYPE_P(val, T_FIXNUM) ) {
|
|
244
|
+
*out = NUM2ULL(val);
|
|
245
|
+
return 1;
|
|
246
|
+
}
|
|
247
|
+
{
|
|
248
|
+
int state = 0;
|
|
249
|
+
volatile VALUE r = rb_protect(ca_kernel_integer, val, &state);
|
|
250
|
+
if ( state ) {
|
|
251
|
+
rb_set_errinfo(Qnil);
|
|
252
|
+
return 0;
|
|
253
|
+
}
|
|
254
|
+
*out = rb_num2ull(r);
|
|
255
|
+
return 1;
|
|
73
256
|
}
|
|
74
257
|
}
|
|
75
258
|
|
|
@@ -112,7 +295,7 @@ rb_obj2ll (VALUE val)
|
|
|
112
295
|
case T_FIXNUM:
|
|
113
296
|
return NUM2LONG(val);
|
|
114
297
|
case T_NIL:
|
|
115
|
-
rb_raise(rb_eTypeError, "no implicit conversion
|
|
298
|
+
rb_raise(rb_eTypeError, "no implicit conversion from nil to integer");
|
|
116
299
|
break;
|
|
117
300
|
default:
|
|
118
301
|
return NUM2LL(rb_Integer(val));
|
|
@@ -133,6 +316,26 @@ rb_obj2ull (VALUE val)
|
|
|
133
316
|
}
|
|
134
317
|
}
|
|
135
318
|
|
|
319
|
+
/* Face has surface != storage; cast operates on the storage
|
|
320
|
+
* data_type, which lives at the parent chain bottom (the first
|
|
321
|
+
* non-Face ancestor). This predicate is defensive: stack-allocated
|
|
322
|
+
* dummy CArrays may have an uninitialised obj_type, so we additionally
|
|
323
|
+
* require obj_type to fall in the valid range before treating `ca`
|
|
324
|
+
* as a Face. */
|
|
325
|
+
static inline int
|
|
326
|
+
ca_face_safe_check (CArray *ca)
|
|
327
|
+
{
|
|
328
|
+
return ca && ca_is_face(ca)
|
|
329
|
+
&& ca->obj_type >= 0 && ca->obj_type < CA_OBJ_TYPE_MAX;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
static inline int8_t
|
|
333
|
+
ca_storage_type_of (CArray *ca)
|
|
334
|
+
{
|
|
335
|
+
while (ca_face_safe_check(ca)) ca = ((CAView *) ca)->parent;
|
|
336
|
+
return ca ? ca->data_type : CA_FIXLEN;
|
|
337
|
+
}
|
|
338
|
+
|
|
136
339
|
void
|
|
137
340
|
ca_cast_block (ca_size_t n, void *ap1, void *ptr1,
|
|
138
341
|
void *ap2, void *ptr2)
|
|
@@ -140,7 +343,7 @@ ca_cast_block (ca_size_t n, void *ap1, void *ptr1,
|
|
|
140
343
|
CArray *ca1 = (CArray *) ap1;
|
|
141
344
|
CArray *ca2 = (CArray *) ap2;
|
|
142
345
|
if ( n < 0 ) {
|
|
143
|
-
rb_raise(rb_eRuntimeError,
|
|
346
|
+
rb_raise(rb_eRuntimeError,
|
|
144
347
|
"[BUG] in ca_cast_block(): negative count");
|
|
145
348
|
}
|
|
146
349
|
ca_cast_func_table[ca1->data_type][ca2->data_type](n, ca1, ptr1, ca2, ptr2, NULL);
|
|
@@ -153,7 +356,7 @@ ca_cast_block_with_mask (ca_size_t n, void *ap1, void *ptr1,
|
|
|
153
356
|
CArray *ca1 = (CArray *) ap1;
|
|
154
357
|
CArray *ca2 = (CArray *) ap2;
|
|
155
358
|
if ( n < 0 ) {
|
|
156
|
-
rb_raise(rb_eRuntimeError,
|
|
359
|
+
rb_raise(rb_eRuntimeError,
|
|
157
360
|
"[BUG] in ca_cast_block_with_mask(): negative count");
|
|
158
361
|
}
|
|
159
362
|
ca_cast_func_table[ca1->data_type][ca2->data_type](n, ca1, ptr1, ca2, ptr2, m);
|
|
@@ -225,12 +428,20 @@ ca_val2val (int8_t data_type1, void *ptr1, int8_t data_type2, void *ptr2)
|
|
|
225
428
|
|
|
226
429
|
/* --------------------------------------------------------------------- */
|
|
227
430
|
|
|
431
|
+
/* Cast to CA_OBJECT for an array whose cells mean something other than their
|
|
432
|
+
storage bytes: a data_class array (CARecord / CAStruct) or a Face (CATime,
|
|
433
|
+
CAConstString, CACategorical, ...). Both decode per cell -- rb_ca_fetch_addr
|
|
434
|
+
goes through the data_class decode and CA_FACE_STORAGE_TO_SCALAR_IF_FACE --
|
|
435
|
+
so the object array holds the *surface* values (labels, not codes;
|
|
436
|
+
CATime::Element, not serials; the string, not the descriptor bytes). Reading
|
|
437
|
+
the storage instead is `.parent`, which stays available and explicit. Mask
|
|
438
|
+
and shape carry. */
|
|
228
439
|
static VALUE
|
|
229
|
-
|
|
440
|
+
rb_ca_surface_to_object (VALUE self)
|
|
230
441
|
{
|
|
231
442
|
volatile VALUE obj;
|
|
232
443
|
CArray *ca;
|
|
233
|
-
|
|
444
|
+
ca_size_t i;
|
|
234
445
|
|
|
235
446
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
236
447
|
|
|
@@ -244,10 +455,71 @@ rb_ca_data_class_to_object (VALUE self)
|
|
|
244
455
|
for (i=0; i<ca->elements; i++) {
|
|
245
456
|
rb_ca_store_addr(obj, i, rb_ca_fetch_addr(self, i));
|
|
246
457
|
}
|
|
247
|
-
|
|
458
|
+
|
|
248
459
|
return obj;
|
|
249
460
|
}
|
|
250
461
|
|
|
462
|
+
/* Cast a NonNumeric Face (= one whose surface declares CA_FIXLEN, so the
|
|
463
|
+
numeric kernel dispatch is gated off) to a type other than :object.
|
|
464
|
+
|
|
465
|
+
Reading the storage would hand back the bytes the surface exists to hide,
|
|
466
|
+
and there is no way for the core to guess how a surface becomes a number:
|
|
467
|
+
a fixed-point cell is its storage over a scale, a categorical cell is a
|
|
468
|
+
label, a time cell is not a number at all. So the Face declares it, with
|
|
469
|
+
#to_numeric returning a plain CArray of its values, and everything else is
|
|
470
|
+
an ordinary cast of that. A Face that declares nothing raises: it is the
|
|
471
|
+
Face saying "my values are not numbers", which is information, unlike an
|
|
472
|
+
array of UNDEF.
|
|
473
|
+
|
|
474
|
+
The projection is array-level on purpose. Going through the surface cell
|
|
475
|
+
by cell (to_type(:object) and Ruby #to_f) measured 449 ms against 1.45 ms
|
|
476
|
+
for the vectorised expression the author writes anyway (1M cells,
|
|
477
|
+
CAFixedPoint = parent.float64 / scale). */
|
|
478
|
+
static VALUE
|
|
479
|
+
rb_ca_face_numeric_projection (VALUE self, CArray *ca)
|
|
480
|
+
{
|
|
481
|
+
static ID id_to_numeric = 0;
|
|
482
|
+
VALUE num;
|
|
483
|
+
CArray *cn;
|
|
484
|
+
|
|
485
|
+
if ( id_to_numeric == 0 ) {
|
|
486
|
+
id_to_numeric = rb_intern("to_numeric");
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
if ( ! rb_respond_to(self, id_to_numeric) ) {
|
|
490
|
+
rb_raise(rb_eTypeError,
|
|
491
|
+
"%s declares no numeric conversion: define #to_numeric to say "
|
|
492
|
+
"how its values become numbers, or take the surface with "
|
|
493
|
+
"to_type(:object) / the storage with #parent",
|
|
494
|
+
rb_obj_classname(self));
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
num = rb_funcall(self, id_to_numeric, 0);
|
|
498
|
+
|
|
499
|
+
if ( ! rb_obj_is_carray(num) ) {
|
|
500
|
+
rb_raise(rb_eTypeError,
|
|
501
|
+
"%s#to_numeric must return a CArray (got %s)",
|
|
502
|
+
rb_obj_classname(self), rb_obj_classname(num));
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
TypedData_Get_Struct(num, CArray, &carray_data_type, cn);
|
|
506
|
+
|
|
507
|
+
if ( ca_is_face(cn) ) {
|
|
508
|
+
rb_raise(rb_eTypeError,
|
|
509
|
+
"%s#to_numeric must return a plain CArray, not a Face (got %s)",
|
|
510
|
+
rb_obj_classname(self), rb_obj_classname(num));
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if ( cn->elements != ca->elements ) {
|
|
514
|
+
rb_raise(rb_eArgError,
|
|
515
|
+
"%s#to_numeric returned %lld elements, expected %lld",
|
|
516
|
+
rb_obj_classname(self),
|
|
517
|
+
(long long) cn->elements, (long long) ca->elements);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
return num;
|
|
521
|
+
}
|
|
522
|
+
|
|
251
523
|
static VALUE
|
|
252
524
|
rb_ca_object_to_data_class (VALUE self, VALUE rtype, ca_size_t bytes)
|
|
253
525
|
{
|
|
@@ -264,7 +536,6 @@ rb_ca_object_to_data_class (VALUE self, VALUE rtype, ca_size_t bytes)
|
|
|
264
536
|
else {
|
|
265
537
|
obj = rb_carray_new(CA_FIXLEN, ca->ndim, ca->dim, bytes, ca->mask);
|
|
266
538
|
}
|
|
267
|
-
rb_ca_data_type_import(obj, rtype);
|
|
268
539
|
|
|
269
540
|
for (i=0; i<ca->elements; i++) {
|
|
270
541
|
rval = rb_ca_fetch_addr(self, i);
|
|
@@ -279,11 +550,9 @@ rb_ca_object_to_data_class (VALUE self, VALUE rtype, ca_size_t bytes)
|
|
|
279
550
|
return obj;
|
|
280
551
|
}
|
|
281
552
|
|
|
282
|
-
/*
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
to the given data type from the object.
|
|
286
|
-
*/
|
|
553
|
+
/* CArray#to_type(data_type, bytes:) -- eager copy of self converted to
|
|
554
|
+
data_type (a new entity owning its storage). User doc lives in
|
|
555
|
+
yard-stubs/carray_cast.rb. */
|
|
287
556
|
|
|
288
557
|
static VALUE
|
|
289
558
|
rb_ca_to_type_internal (int argc, VALUE *argv, VALUE self)
|
|
@@ -300,14 +569,24 @@ rb_ca_to_type_internal (int argc, VALUE *argv, VALUE self)
|
|
|
300
569
|
|
|
301
570
|
rb_ca_guess_type_and_bytes(rtype, rbytes, &data_type, &bytes);
|
|
302
571
|
|
|
303
|
-
if ( rb_ca_has_data_class(self) && data_type == CA_OBJECT ) {
|
|
304
|
-
return
|
|
572
|
+
if ( ( rb_ca_has_data_class(self) || ca_is_face(ca) ) && data_type == CA_OBJECT ) {
|
|
573
|
+
return rb_ca_surface_to_object(self);
|
|
305
574
|
}
|
|
306
575
|
|
|
307
576
|
if ( rb_ca_is_object_type(self) && rb_obj_is_data_class(rtype) ) {
|
|
308
577
|
return rb_ca_object_to_data_class(self, rtype, bytes);
|
|
309
578
|
}
|
|
310
579
|
|
|
580
|
+
/* NonNumeric Face (CA_FIXLEN surface = the numeric gate) to anything but
|
|
581
|
+
:object: the values come from the Face's own #to_numeric, and the
|
|
582
|
+
request is then served by an ordinary cast of that plain array. A
|
|
583
|
+
Numeric Face is not routed here -- its surface *is* its storage, so the
|
|
584
|
+
ordinary cast below is already right. */
|
|
585
|
+
if ( ca_is_face(ca) && ca->data_type == CA_FIXLEN ) {
|
|
586
|
+
return rb_ca_to_type_internal(argc, argv,
|
|
587
|
+
rb_ca_face_numeric_projection(self, ca));
|
|
588
|
+
}
|
|
589
|
+
|
|
311
590
|
ca_update_mask(ca);
|
|
312
591
|
|
|
313
592
|
if ( ca_is_scalar(ca) ) {
|
|
@@ -317,13 +596,45 @@ rb_ca_to_type_internal (int argc, VALUE *argv, VALUE self)
|
|
|
317
596
|
obj = rb_carray_new(data_type, ca->ndim, ca->dim, bytes, ca->mask);
|
|
318
597
|
}
|
|
319
598
|
|
|
320
|
-
rb_ca_data_type_import(obj, rtype);
|
|
321
599
|
|
|
322
600
|
TypedData_Get_Struct(obj, CArray, &carray_data_type, cb);
|
|
323
601
|
|
|
324
602
|
ca_attach(ca);
|
|
325
|
-
if (
|
|
326
|
-
|
|
603
|
+
if ( ca->data_type == CA_OBJECT
|
|
604
|
+
&& ( (data_type >= CA_INT8 && data_type <= CA_UINT64)
|
|
605
|
+
|| data_type == CA_FLOAT32 || data_type == CA_FLOAT64 ) ) {
|
|
606
|
+
/* object -> int/float: give the cast a mask buffer so an unparseable
|
|
607
|
+
cell becomes UNDEF (see ext/carray_cast_func.rb). Cast into a
|
|
608
|
+
scratch mask seeded from the source mask, then attach it to the
|
|
609
|
+
output only if some cell ended up masked -- an all-valid cast keeps
|
|
610
|
+
the mask-less result the legacy path produced. */
|
|
611
|
+
ca_size_t ne = cb->elements;
|
|
612
|
+
ca_size_t i;
|
|
613
|
+
boolean8_t any = 0;
|
|
614
|
+
boolean8_t *scratch = ALLOC_N(boolean8_t, ne > 0 ? ne : 1);
|
|
615
|
+
if ( cb->mask ) {
|
|
616
|
+
memcpy(scratch, cb->mask->ptr, ne); /* copy of source mask */
|
|
617
|
+
}
|
|
618
|
+
else {
|
|
619
|
+
memset(scratch, 0, ne);
|
|
620
|
+
}
|
|
621
|
+
ca_cast_block_with_mask(ne, ca, ca->ptr, cb, cb->ptr, scratch);
|
|
622
|
+
for (i=0; i<ne; i++) {
|
|
623
|
+
if ( scratch[i] ) {
|
|
624
|
+
any = 1;
|
|
625
|
+
break;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
if ( any ) {
|
|
629
|
+
if ( ! cb->mask ) {
|
|
630
|
+
ca_create_mask(cb);
|
|
631
|
+
}
|
|
632
|
+
memcpy(cb->mask->ptr, scratch, ne);
|
|
633
|
+
}
|
|
634
|
+
xfree(scratch);
|
|
635
|
+
}
|
|
636
|
+
else if ( ca_has_mask(ca) ) {
|
|
637
|
+
ca_cast_block_with_mask(cb->elements, ca, ca->ptr, cb, cb->ptr,
|
|
327
638
|
(boolean8_t*)ca->mask->ptr);
|
|
328
639
|
}
|
|
329
640
|
else {
|
|
@@ -331,6 +642,13 @@ rb_ca_to_type_internal (int argc, VALUE *argv, VALUE self)
|
|
|
331
642
|
}
|
|
332
643
|
ca_detach(ca);
|
|
333
644
|
|
|
645
|
+
/* When rtype is a data_class (e.g. CAStruct subclass), wrap the
|
|
646
|
+
result in CARecord so the cast output carries data_class. */
|
|
647
|
+
if ( rb_obj_is_data_class(rtype) ) {
|
|
648
|
+
obj = rb_funcall(rb_const_get(rb_cObject, rb_intern("CARecord")),
|
|
649
|
+
rb_intern("wrap"), 2, obj, rtype);
|
|
650
|
+
}
|
|
651
|
+
|
|
334
652
|
return obj;
|
|
335
653
|
}
|
|
336
654
|
|
|
@@ -349,161 +667,97 @@ rb_ca_to_type (VALUE self, VALUE rtype, VALUE rbytes)
|
|
|
349
667
|
return rb_ca_to_type_internal(1, &rcode, self); \
|
|
350
668
|
}
|
|
351
669
|
|
|
352
|
-
/*
|
|
353
|
-
|
|
354
|
-
(Conversion) Short-Hand of "CArray#to_type(:fixlen, bytes:)"
|
|
355
|
-
*/
|
|
670
|
+
/* CArray#fixlen(bytes:) -- short-hand of to_type(:fixlen, bytes:). */
|
|
356
671
|
|
|
357
672
|
VALUE
|
|
358
673
|
rb_ca_to_fixlen (int argc, VALUE *argv, VALUE self)
|
|
359
674
|
{
|
|
360
675
|
volatile VALUE ropt = rb_pop_options(&argc, &argv);
|
|
361
676
|
VALUE list[2];
|
|
362
|
-
// rb_scan_args(argc, argv, "0");
|
|
363
677
|
list[0] = INT2NUM(CA_FIXLEN);
|
|
364
678
|
list[1] = ropt;
|
|
365
679
|
return rb_ca_to_type_internal(2, list, self);
|
|
366
680
|
}
|
|
367
681
|
|
|
368
|
-
/*
|
|
369
|
-
|
|
370
|
-
(Conversion) Short-Hand of "CArray#to_type(:boolean)"
|
|
371
|
-
*/
|
|
682
|
+
/* CArray#boolean -- short-hand of to_type(:boolean). */
|
|
372
683
|
VALUE rb_ca_to_boolean (VALUE self)
|
|
373
684
|
{
|
|
374
685
|
rb_ca_to_type_method_body(CA_BOOLEAN);
|
|
375
686
|
}
|
|
376
687
|
|
|
377
|
-
/*
|
|
378
|
-
|
|
379
|
-
(Conversion) Short-Hand of "CArray#to_type(:int8)"
|
|
380
|
-
*/
|
|
688
|
+
/* CArray#int8 -- short-hand of to_type(:int8). */
|
|
381
689
|
VALUE rb_ca_to_int8 (VALUE self)
|
|
382
690
|
{
|
|
383
691
|
rb_ca_to_type_method_body(CA_INT8);
|
|
384
692
|
}
|
|
385
693
|
|
|
386
|
-
/*
|
|
387
|
-
|
|
388
|
-
(Conversion) Short-Hand of "CArray#to_type(:uint8)"
|
|
389
|
-
*/
|
|
694
|
+
/* CArray#uint8 -- short-hand of to_type(:uint8). */
|
|
390
695
|
VALUE rb_ca_to_uint8 (VALUE self)
|
|
391
696
|
{
|
|
392
697
|
rb_ca_to_type_method_body(CA_UINT8);
|
|
393
698
|
}
|
|
394
699
|
|
|
395
|
-
/*
|
|
396
|
-
|
|
397
|
-
(Conversion) Short-Hand of "CArray#to_type(:int16)"
|
|
398
|
-
*/
|
|
700
|
+
/* CArray#int16 -- short-hand of to_type(:int16). */
|
|
399
701
|
VALUE rb_ca_to_int16 (VALUE self)
|
|
400
702
|
{
|
|
401
703
|
rb_ca_to_type_method_body(CA_INT16);
|
|
402
704
|
}
|
|
403
705
|
|
|
404
|
-
/*
|
|
405
|
-
|
|
406
|
-
(Conversion) Short-Hand of "CArray#to_type(:uint16)"
|
|
407
|
-
*/
|
|
706
|
+
/* CArray#uint16 -- short-hand of to_type(:uint16). */
|
|
408
707
|
VALUE rb_ca_to_uint16 (VALUE self)
|
|
409
708
|
{
|
|
410
709
|
rb_ca_to_type_method_body(CA_UINT16);
|
|
411
710
|
}
|
|
412
711
|
|
|
413
|
-
/*
|
|
414
|
-
|
|
415
|
-
(Conversion) Short-Hand of "CArray#to_type(:int32)"
|
|
416
|
-
*/
|
|
712
|
+
/* CArray#int32 -- short-hand of to_type(:int32). */
|
|
417
713
|
VALUE rb_ca_to_int32 (VALUE self)
|
|
418
714
|
{
|
|
419
715
|
rb_ca_to_type_method_body(CA_INT32);
|
|
420
716
|
}
|
|
421
717
|
|
|
422
|
-
/*
|
|
423
|
-
|
|
424
|
-
(Conversion) Short-Hand of "CArray#to_type(:uint32)"
|
|
425
|
-
*/
|
|
718
|
+
/* CArray#uint32 -- short-hand of to_type(:uint32). */
|
|
426
719
|
VALUE rb_ca_to_uint32 (VALUE self)
|
|
427
720
|
{
|
|
428
721
|
rb_ca_to_type_method_body(CA_UINT32);
|
|
429
722
|
}
|
|
430
723
|
|
|
431
|
-
/*
|
|
432
|
-
|
|
433
|
-
(Conversion) Short-Hand of "CArray#to_type(:int64)"
|
|
434
|
-
*/
|
|
724
|
+
/* CArray#int64 -- short-hand of to_type(:int64). */
|
|
435
725
|
VALUE rb_ca_to_int64 (VALUE self)
|
|
436
726
|
{
|
|
437
727
|
rb_ca_to_type_method_body(CA_INT64);
|
|
438
728
|
}
|
|
439
729
|
|
|
440
|
-
/*
|
|
441
|
-
|
|
442
|
-
(Conversion) Short-Hand of "CArray#to_type(:uint64)"
|
|
443
|
-
*/
|
|
730
|
+
/* CArray#uint64 -- short-hand of to_type(:uint64). */
|
|
444
731
|
VALUE rb_ca_to_uint64 (VALUE self)
|
|
445
732
|
{
|
|
446
733
|
rb_ca_to_type_method_body(CA_UINT64);
|
|
447
734
|
}
|
|
448
735
|
|
|
449
|
-
/*
|
|
450
|
-
|
|
451
|
-
(Conversion) Short-Hand of "CArray#to_type(:float32)"
|
|
452
|
-
*/
|
|
736
|
+
/* CArray#float32 -- short-hand of to_type(:float32). */
|
|
453
737
|
VALUE rb_ca_to_float32 (VALUE self)
|
|
454
738
|
{
|
|
455
739
|
rb_ca_to_type_method_body(CA_FLOAT32);
|
|
456
740
|
}
|
|
457
741
|
|
|
458
|
-
/*
|
|
459
|
-
|
|
460
|
-
(Conversion) Short-Hand of "CArray#to_type(:float64)"
|
|
461
|
-
*/
|
|
742
|
+
/* CArray#float64 -- short-hand of to_type(:float64). */
|
|
462
743
|
VALUE rb_ca_to_float64 (VALUE self)
|
|
463
744
|
{
|
|
464
745
|
rb_ca_to_type_method_body(CA_FLOAT64);
|
|
465
746
|
}
|
|
466
747
|
|
|
467
|
-
/*
|
|
468
|
-
|
|
469
|
-
(Conversion) Short-Hand of "CArray#to_type(:float128)"
|
|
470
|
-
*/
|
|
471
|
-
VALUE rb_ca_to_float128 (VALUE self)
|
|
472
|
-
{
|
|
473
|
-
rb_ca_to_type_method_body(CA_FLOAT128);
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
/* @overload cmplx64
|
|
477
|
-
|
|
478
|
-
(Conversion) Short-Hand of "CArray#to_type(:cmplx64)"
|
|
479
|
-
*/
|
|
748
|
+
/* CArray#cmplx64 -- short-hand of to_type(:cmplx64). */
|
|
480
749
|
VALUE rb_ca_to_cmplx64 (VALUE self)
|
|
481
750
|
{
|
|
482
751
|
rb_ca_to_type_method_body(CA_CMPLX64);
|
|
483
752
|
}
|
|
484
753
|
|
|
485
|
-
/*
|
|
486
|
-
|
|
487
|
-
(Conversion) Short-Hand of "CArray#to_type(:cmplx128)"
|
|
488
|
-
*/
|
|
754
|
+
/* CArray#cmplx128 -- short-hand of to_type(:cmplx128). */
|
|
489
755
|
VALUE rb_ca_to_cmplx128 (VALUE self)
|
|
490
756
|
{
|
|
491
757
|
rb_ca_to_type_method_body(CA_CMPLX128);
|
|
492
758
|
}
|
|
493
759
|
|
|
494
|
-
/*
|
|
495
|
-
|
|
496
|
-
(Conversion) Short-Hand of "CArray#to_type(:cmplx256)"
|
|
497
|
-
*/
|
|
498
|
-
VALUE rb_ca_to_cmplx256 (VALUE self)
|
|
499
|
-
{
|
|
500
|
-
rb_ca_to_type_method_body(CA_CMPLX256);
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
/* @overload object
|
|
504
|
-
|
|
505
|
-
(Conversion) Short-Hand of "CArray#to_type(:object)"
|
|
506
|
-
*/
|
|
760
|
+
/* CArray#object -- short-hand of to_type(:object). */
|
|
507
761
|
VALUE rb_ca_to_VALUE (VALUE self)
|
|
508
762
|
{
|
|
509
763
|
rb_ca_to_type_method_body(CA_OBJECT);
|
|
@@ -513,6 +767,31 @@ VALUE rb_ca_to_VALUE (VALUE self)
|
|
|
513
767
|
|
|
514
768
|
/* CArray#as_type */
|
|
515
769
|
|
|
770
|
+
/* Forward declaration: CAMonOp builder (ext/ca_obj_monop.c). */
|
|
771
|
+
extern VALUE rb_ca_monop_build (VALUE cary, uint16_t op_id);
|
|
772
|
+
|
|
773
|
+
/* Forward declaration: clip kernel (ext/carray_kernels.c, generated). */
|
|
774
|
+
extern VALUE rb_ca_clip (VALUE self, VALUE lo, VALUE hi);
|
|
775
|
+
|
|
776
|
+
/* Routes a type-adapt view request to CAMonOp(cast_<dt>) when the
|
|
777
|
+
target is a plain numeric data_type (NOT CA_FIXLEN, NOT CA_OBJECT,
|
|
778
|
+
and `rtype` is not a Class). Falls back to CAFake
|
|
779
|
+
(`rb_ca_fake_type`) for CA_FIXLEN sizing, CA_OBJECT, and class-rtype
|
|
780
|
+
data_class overlay cases.
|
|
781
|
+
Called by rb_ca_as_type_internal, rb_ca_wrap_readonly, and
|
|
782
|
+
rb_ca_wrap_writable in this file. */
|
|
783
|
+
static VALUE
|
|
784
|
+
ca_type_adapt_view (VALUE obj, VALUE rtype, int8_t data_type)
|
|
785
|
+
{
|
|
786
|
+
if ( data_type != CA_FIXLEN
|
|
787
|
+
&& data_type != CA_OBJECT
|
|
788
|
+
&& TYPE(rtype) != T_CLASS ) {
|
|
789
|
+
uint16_t cast_op_id = (uint16_t)(CA_MONOP_CAST_BASE + data_type);
|
|
790
|
+
return rb_ca_monop_build(obj, cast_op_id);
|
|
791
|
+
}
|
|
792
|
+
return rb_ca_fake_type(obj, rtype, Qnil);
|
|
793
|
+
}
|
|
794
|
+
|
|
516
795
|
static VALUE
|
|
517
796
|
rb_ca_as_type_internal (int argc, VALUE *argv, VALUE self)
|
|
518
797
|
{
|
|
@@ -533,16 +812,23 @@ rb_ca_as_type_internal (int argc, VALUE *argv, VALUE self)
|
|
|
533
812
|
}
|
|
534
813
|
}
|
|
535
814
|
|
|
815
|
+
/* Natural-width cast: dispatch via helper (CAMonOp for numeric,
|
|
816
|
+
CAFake for CA_FIXLEN sizing / CA_OBJECT / class-rtype). */
|
|
817
|
+
if ( bytes == (ca_size_t) ca_sizeof[data_type] ) {
|
|
818
|
+
obj = ca_type_adapt_view(self, rtype, data_type);
|
|
819
|
+
return obj;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
/* Byte-reinterpret variant (bytes != natural for non-FIXLEN, or
|
|
823
|
+
explicit fixlen sizing): CAFake. */
|
|
536
824
|
obj = rb_ca_fake_type(self, rtype, rbytes);
|
|
537
|
-
rb_ca_data_type_import(obj, rtype);
|
|
538
825
|
|
|
539
826
|
return obj;
|
|
540
827
|
}
|
|
541
828
|
|
|
542
|
-
/*
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
*/
|
|
829
|
+
/* CArray#as_type(data_type, bytes:) -- CAFake view of self reinterpreted
|
|
830
|
+
as data_type (no copy; reads/writes cast on the fly through the shared
|
|
831
|
+
parent storage). User doc lives in yard-stubs/carray_cast.rb. */
|
|
546
832
|
|
|
547
833
|
VALUE
|
|
548
834
|
rb_ca_as_type (VALUE self, VALUE rtype, VALUE rbytes)
|
|
@@ -559,10 +845,7 @@ rb_ca_as_type (VALUE self, VALUE rtype, VALUE rbytes)
|
|
|
559
845
|
return rb_ca_as_type_internal(1, &rcode, self); \
|
|
560
846
|
}
|
|
561
847
|
|
|
562
|
-
/*
|
|
563
|
-
|
|
564
|
-
(Reference) Short-Hand of `CArray#as_type(:fixlen, bytes: nil)`
|
|
565
|
-
*/
|
|
848
|
+
/* CArray#as_fixlen(bytes:) -- short-hand of as_type(:fixlen, bytes:). */
|
|
566
849
|
VALUE
|
|
567
850
|
rb_ca_as_fixlen (int argc, VALUE *argv, VALUE self)
|
|
568
851
|
{
|
|
@@ -574,145 +857,97 @@ rb_ca_as_fixlen (int argc, VALUE *argv, VALUE self)
|
|
|
574
857
|
return rb_ca_as_type_internal(2, list, self);
|
|
575
858
|
}
|
|
576
859
|
|
|
577
|
-
/*
|
|
578
|
-
|
|
579
|
-
(Reference) Short-Hand of `CArray#as_type(:boolean)`
|
|
580
|
-
*/
|
|
860
|
+
/* CArray#as_boolean -- short-hand of as_type(:boolean). */
|
|
581
861
|
VALUE rb_ca_as_boolean (VALUE self)
|
|
582
862
|
{
|
|
583
863
|
rb_ca_as_type_method_body(CA_BOOLEAN);
|
|
584
864
|
}
|
|
585
865
|
|
|
586
|
-
/*
|
|
587
|
-
|
|
588
|
-
(Reference) Short-Hand of `CArray#as_type(:int8)`
|
|
589
|
-
*/
|
|
866
|
+
/* CArray#as_int8 -- short-hand of as_type(:int8). */
|
|
590
867
|
VALUE rb_ca_as_int8 (VALUE self)
|
|
591
868
|
{
|
|
592
869
|
rb_ca_as_type_method_body(CA_INT8);
|
|
593
870
|
}
|
|
594
871
|
|
|
595
|
-
/*
|
|
596
|
-
|
|
597
|
-
(Reference) Short-Hand of `CArray#as_type(:uint8)`
|
|
598
|
-
*/
|
|
872
|
+
/* CArray#as_uint8 -- short-hand of as_type(:uint8). */
|
|
599
873
|
VALUE rb_ca_as_uint8 (VALUE self)
|
|
600
874
|
{
|
|
601
875
|
rb_ca_as_type_method_body(CA_UINT8);
|
|
602
876
|
}
|
|
603
877
|
|
|
604
|
-
/*
|
|
605
|
-
|
|
606
|
-
(Reference) Short-Hand of `CArray#as_type(:int16)`
|
|
607
|
-
*/
|
|
878
|
+
/* CArray#as_int16 -- short-hand of as_type(:int16). */
|
|
608
879
|
VALUE rb_ca_as_int16 (VALUE self)
|
|
609
880
|
{
|
|
610
881
|
rb_ca_as_type_method_body(CA_INT16);
|
|
611
882
|
}
|
|
612
883
|
|
|
613
|
-
/*
|
|
614
|
-
|
|
615
|
-
(Reference) Short-Hand of `CArray#as_type(:uint16)`
|
|
616
|
-
*/
|
|
884
|
+
/* CArray#as_uint16 -- short-hand of as_type(:uint16). */
|
|
617
885
|
VALUE rb_ca_as_uint16 (VALUE self)
|
|
618
886
|
{
|
|
619
887
|
rb_ca_as_type_method_body(CA_UINT16);
|
|
620
888
|
}
|
|
621
889
|
|
|
622
|
-
/*
|
|
623
|
-
|
|
624
|
-
(Reference) Short-Hand of `CArray#as_type(:int32)`
|
|
625
|
-
*/
|
|
890
|
+
/* CArray#as_int32 -- short-hand of as_type(:int32). */
|
|
626
891
|
VALUE rb_ca_as_int32 (VALUE self)
|
|
627
892
|
{
|
|
628
893
|
rb_ca_as_type_method_body(CA_INT32);
|
|
629
894
|
}
|
|
630
895
|
|
|
631
|
-
/*
|
|
632
|
-
|
|
633
|
-
(Reference) Short-Hand of `CArray#as_type(:uint32)`
|
|
634
|
-
*/
|
|
896
|
+
/* CArray#as_uint32 -- short-hand of as_type(:uint32). */
|
|
635
897
|
VALUE rb_ca_as_uint32 (VALUE self)
|
|
636
898
|
{
|
|
637
899
|
rb_ca_as_type_method_body(CA_UINT32);
|
|
638
900
|
}
|
|
639
901
|
|
|
640
|
-
/*
|
|
641
|
-
|
|
642
|
-
(Reference) Short-Hand of `CArray#as_type(:int64)`
|
|
643
|
-
*/
|
|
902
|
+
/* CArray#as_int64 -- short-hand of as_type(:int64). */
|
|
644
903
|
VALUE rb_ca_as_int64 (VALUE self)
|
|
645
904
|
{
|
|
646
905
|
rb_ca_as_type_method_body(CA_INT64);
|
|
647
906
|
}
|
|
648
907
|
|
|
649
|
-
/*
|
|
650
|
-
|
|
651
|
-
(Reference) Short-Hand of `CArray#as_type(:uint64)`
|
|
652
|
-
*/
|
|
908
|
+
/* CArray#as_uint64 -- short-hand of as_type(:uint64). */
|
|
653
909
|
VALUE rb_ca_as_uint64 (VALUE self)
|
|
654
910
|
{
|
|
655
911
|
rb_ca_as_type_method_body(CA_UINT64);
|
|
656
912
|
}
|
|
657
913
|
|
|
658
|
-
/*
|
|
659
|
-
|
|
660
|
-
(Reference) Short-Hand of `CArray#as_type(:float32)`
|
|
661
|
-
*/
|
|
914
|
+
/* CArray#as_float32 -- short-hand of as_type(:float32). */
|
|
662
915
|
VALUE rb_ca_as_float32 (VALUE self)
|
|
663
916
|
{
|
|
664
917
|
rb_ca_as_type_method_body(CA_FLOAT32);
|
|
665
918
|
}
|
|
666
919
|
|
|
667
|
-
/*
|
|
668
|
-
|
|
669
|
-
(Reference) Short-Hand of `CArray#as_type(:float64)`
|
|
670
|
-
*/
|
|
920
|
+
/* CArray#as_float64 -- short-hand of as_type(:float64). */
|
|
671
921
|
VALUE rb_ca_as_float64 (VALUE self)
|
|
672
922
|
{
|
|
673
923
|
rb_ca_as_type_method_body(CA_FLOAT64);
|
|
674
924
|
}
|
|
675
925
|
|
|
676
|
-
/*
|
|
677
|
-
|
|
678
|
-
(Reference) Short-Hand of `CArray#as_type(:float128)`
|
|
679
|
-
*/
|
|
926
|
+
/* CArray#as_float128 -- short-hand of as_type(:float128). */
|
|
680
927
|
VALUE rb_ca_as_float128 (VALUE self)
|
|
681
928
|
{
|
|
682
929
|
rb_ca_as_type_method_body(CA_FLOAT128);
|
|
683
930
|
}
|
|
684
931
|
|
|
685
|
-
/*
|
|
686
|
-
|
|
687
|
-
(Reference) Short-Hand of `CArray#as_type(:cmplx64)`
|
|
688
|
-
*/
|
|
932
|
+
/* CArray#as_cmplx64 -- short-hand of as_type(:cmplx64). */
|
|
689
933
|
VALUE rb_ca_as_cmplx64 (VALUE self)
|
|
690
934
|
{
|
|
691
935
|
rb_ca_as_type_method_body(CA_CMPLX64);
|
|
692
936
|
}
|
|
693
937
|
|
|
694
|
-
/*
|
|
695
|
-
|
|
696
|
-
(Reference) Short-Hand of `CArray#as_type(:cmplx128)`
|
|
697
|
-
*/
|
|
938
|
+
/* CArray#as_cmplx128 -- short-hand of as_type(:cmplx128). */
|
|
698
939
|
VALUE rb_ca_as_cmplx128 (VALUE self)
|
|
699
940
|
{
|
|
700
941
|
rb_ca_as_type_method_body(CA_CMPLX128);
|
|
701
942
|
}
|
|
702
943
|
|
|
703
|
-
/*
|
|
704
|
-
|
|
705
|
-
(Reference) Short-Hand of `CArray#as_type(:cmplx256)`
|
|
706
|
-
*/
|
|
944
|
+
/* CArray#as_cmplx256 -- short-hand of as_type(:cmplx256). */
|
|
707
945
|
VALUE rb_ca_as_cmplx256 (VALUE self)
|
|
708
946
|
{
|
|
709
947
|
rb_ca_as_type_method_body(CA_CMPLX256);
|
|
710
948
|
}
|
|
711
949
|
|
|
712
|
-
/*
|
|
713
|
-
|
|
714
|
-
(Reference) Short-Hand of `CArray#as_type(:object)`
|
|
715
|
-
*/
|
|
950
|
+
/* CArray#as_object -- short-hand of as_type(:object). */
|
|
716
951
|
VALUE rb_ca_as_VALUE (VALUE self)
|
|
717
952
|
{
|
|
718
953
|
rb_ca_as_type_method_body(CA_OBJECT);
|
|
@@ -762,6 +997,36 @@ rb_ca_ptr2obj (VALUE self, void *ptr)
|
|
|
762
997
|
}
|
|
763
998
|
}
|
|
764
999
|
|
|
1000
|
+
/* Surface -> storage-domain conversion for a Face store (mirror of the
|
|
1001
|
+
storage_to_scalar read hook). Non-Face `ca` returns `obj` unchanged, so
|
|
1002
|
+
the non-Face store path is untouched. For a Face, the per-obj_type C
|
|
1003
|
+
table is consulted first (fast path); if none is registered, the Ruby
|
|
1004
|
+
`scalar_to_storage` method is called when defined. A Face that recognizes
|
|
1005
|
+
`obj` returns a storage-domain value (e.g. an Integer in its unit); a bare
|
|
1006
|
+
Integer / String falls through unchanged to the storage cast. */
|
|
1007
|
+
VALUE
|
|
1008
|
+
ca_face_scalar_to_storage (VALUE self, CArray *ca, VALUE obj)
|
|
1009
|
+
{
|
|
1010
|
+
ca_face_scalar_to_storage_fn fn;
|
|
1011
|
+
if ( ! ca_face_safe_check(ca) || obj == CA_UNDEF ) {
|
|
1012
|
+
return obj;
|
|
1013
|
+
}
|
|
1014
|
+
fn = ca_face_scalar_to_storage_table[ca->obj_type];
|
|
1015
|
+
if ( fn != NULL ) {
|
|
1016
|
+
return fn(self, obj);
|
|
1017
|
+
}
|
|
1018
|
+
else {
|
|
1019
|
+
static ID id_scalar_to_storage = 0;
|
|
1020
|
+
if ( id_scalar_to_storage == 0 ) {
|
|
1021
|
+
id_scalar_to_storage = rb_intern("scalar_to_storage");
|
|
1022
|
+
}
|
|
1023
|
+
if ( rb_respond_to(self, id_scalar_to_storage) ) {
|
|
1024
|
+
return rb_funcall(self, id_scalar_to_storage, 1, obj);
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
return obj;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
765
1030
|
VALUE
|
|
766
1031
|
rb_ca_obj2ptr (VALUE self, VALUE obj, void *ptr)
|
|
767
1032
|
{
|
|
@@ -772,9 +1037,21 @@ rb_ca_obj2ptr (VALUE self, VALUE obj, void *ptr)
|
|
|
772
1037
|
memset(ptr, 0, ca->bytes);
|
|
773
1038
|
}
|
|
774
1039
|
else {
|
|
775
|
-
|
|
1040
|
+
/* Face surfaces as FIXLEN but its storage is the parent chain
|
|
1041
|
+
bottom (e.g. int64); the obj -> bytes conversion must use the
|
|
1042
|
+
storage data_type, not the Face surface. */
|
|
1043
|
+
int8_t convert_type = ca->data_type;
|
|
1044
|
+
if ( ca_face_safe_check(ca) ) {
|
|
1045
|
+
/* Face write hook: turn a surface value object (Scalar / Time /
|
|
1046
|
+
DateTime) into a storage-domain value the cast below consumes. */
|
|
1047
|
+
obj = ca_face_scalar_to_storage(self, ca, obj);
|
|
1048
|
+
convert_type = ca_storage_type_of(ca);
|
|
1049
|
+
}
|
|
1050
|
+
if ( convert_type == CA_FIXLEN ) {
|
|
1051
|
+
obj = rb_ca_data_class_encode(self, obj);
|
|
1052
|
+
}
|
|
776
1053
|
dummy.data_type = CA_OBJECT;
|
|
777
|
-
ca_cast_func_table[CA_OBJECT][
|
|
1054
|
+
ca_cast_func_table[CA_OBJECT][convert_type](1, &dummy, &obj, ca, ptr, NULL);
|
|
778
1055
|
}
|
|
779
1056
|
return Qnil;
|
|
780
1057
|
}
|
|
@@ -798,7 +1075,7 @@ rb_ca_wrap_writable (VALUE arg, VALUE rtype)
|
|
|
798
1075
|
data_type = rb_ca_guess_type(rtype);
|
|
799
1076
|
}
|
|
800
1077
|
if ( ca->data_type != data_type ) {
|
|
801
|
-
obj =
|
|
1078
|
+
obj = ca_type_adapt_view(obj, rtype, data_type);
|
|
802
1079
|
}
|
|
803
1080
|
}
|
|
804
1081
|
else if ( NIL_P(obj) ) { /* obj == nil */
|
|
@@ -810,9 +1087,25 @@ rb_ca_wrap_writable (VALUE arg, VALUE rtype)
|
|
|
810
1087
|
}
|
|
811
1088
|
obj = rb_cscalar_new(data_type, 0, NULL);
|
|
812
1089
|
}
|
|
813
|
-
else if ( rb_respond_to(obj, rb_intern("
|
|
814
|
-
|
|
1090
|
+
else if ( rb_respond_to(obj, rb_intern("to_ca")) ) { /* respond_to obj.to_ca */
|
|
1091
|
+
/* `writable: true` is the caller's half of the bargain: it says the
|
|
1092
|
+
result has to be one whose writes reach `obj`, and a to_ca that can
|
|
1093
|
+
only produce a copy raises rather than swallowing them. An object
|
|
1094
|
+
whose to_ca predates the keyword raises ArgumentError here, which is
|
|
1095
|
+
the honest report that it does not implement writable intake. */
|
|
1096
|
+
volatile VALUE kw = rb_hash_new();
|
|
1097
|
+
rb_hash_aset(kw, ID2SYM(rb_intern("writable")), Qtrue);
|
|
1098
|
+
obj = rb_funcallv_kw(obj, rb_intern("to_ca"), 1, (VALUE *) &kw,
|
|
1099
|
+
RB_PASS_KEYWORDS);
|
|
1100
|
+
if ( ! rb_obj_is_carray(obj) ) {
|
|
1101
|
+
volatile VALUE inspect = rb_inspect(CLASS_OF(arg));
|
|
1102
|
+
rb_raise(rb_eTypeError,
|
|
1103
|
+
"%s#to_ca did not return a CArray", StringValuePtr(inspect));
|
|
1104
|
+
}
|
|
815
1105
|
TypedData_Get_Struct(obj, CArray, &carray_data_type, ca);
|
|
1106
|
+
if ( ca_is_readonly(ca) ) {
|
|
1107
|
+
rb_raise(rb_eRuntimeError, "can't modify read-only carray");
|
|
1108
|
+
}
|
|
816
1109
|
if ( NIL_P(rtype) ) {
|
|
817
1110
|
data_type = ca->data_type;
|
|
818
1111
|
}
|
|
@@ -820,7 +1113,24 @@ rb_ca_wrap_writable (VALUE arg, VALUE rtype)
|
|
|
820
1113
|
data_type = rb_ca_guess_type(rtype);
|
|
821
1114
|
}
|
|
822
1115
|
if ( ca->data_type != data_type ) {
|
|
823
|
-
obj =
|
|
1116
|
+
obj = ca_type_adapt_view(obj, INT2NUM(data_type), data_type);
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
else if ( rb_memory_view_available_p(obj) ) { /* MemoryView producer */
|
|
1120
|
+
obj = rb_funcall(rb_cCArray, rb_intern("wrap_memory_view"), 1, obj);
|
|
1121
|
+
TypedData_Get_Struct(obj, CArray, &carray_data_type, ca);
|
|
1122
|
+
if ( ca_is_readonly(ca) ) {
|
|
1123
|
+
rb_raise(rb_eRuntimeError,
|
|
1124
|
+
"MemoryView source is read-only; can't wrap as writable");
|
|
1125
|
+
}
|
|
1126
|
+
if ( NIL_P(rtype) ) {
|
|
1127
|
+
data_type = ca->data_type;
|
|
1128
|
+
}
|
|
1129
|
+
else {
|
|
1130
|
+
data_type = rb_ca_guess_type(rtype);
|
|
1131
|
+
}
|
|
1132
|
+
if ( ca->data_type != data_type ) {
|
|
1133
|
+
obj = ca_type_adapt_view(obj, INT2NUM(data_type), data_type);
|
|
824
1134
|
}
|
|
825
1135
|
}
|
|
826
1136
|
else {
|
|
@@ -833,10 +1143,9 @@ rb_ca_wrap_writable (VALUE arg, VALUE rtype)
|
|
|
833
1143
|
return obj;
|
|
834
1144
|
}
|
|
835
1145
|
|
|
836
|
-
/*
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
*/
|
|
1146
|
+
/* CArray.wrap_writable(other, data_type = nil) -- singleton entry that
|
|
1147
|
+
scans (other, data_type) and delegates to rb_ca_wrap_writable.
|
|
1148
|
+
User doc lives in yard-stubs/carray_cast.rb. */
|
|
840
1149
|
|
|
841
1150
|
static VALUE
|
|
842
1151
|
rb_ca_s_wrap_writable (int argc, VALUE *argv, VALUE klass)
|
|
@@ -862,7 +1171,7 @@ rb_ca_wrap_readonly (VALUE arg, VALUE rtype)
|
|
|
862
1171
|
data_type = rb_ca_guess_type(rtype);
|
|
863
1172
|
}
|
|
864
1173
|
if ( ca->data_type != data_type ) {
|
|
865
|
-
obj =
|
|
1174
|
+
obj = ca_type_adapt_view(obj, rtype, data_type);
|
|
866
1175
|
}
|
|
867
1176
|
}
|
|
868
1177
|
else if ( rb_obj_is_kind_of(obj, rb_cNumeric) ) { /* number */
|
|
@@ -884,7 +1193,7 @@ rb_ca_wrap_readonly (VALUE arg, VALUE rtype)
|
|
|
884
1193
|
data_type = rb_ca_guess_type(rtype);
|
|
885
1194
|
}
|
|
886
1195
|
if ( ca->data_type != data_type ) {
|
|
887
|
-
obj =
|
|
1196
|
+
obj = ca_type_adapt_view(obj, INT2NUM(data_type), data_type);
|
|
888
1197
|
}
|
|
889
1198
|
}
|
|
890
1199
|
else if ( TYPE(obj) == T_STRING ) { /* string */
|
|
@@ -898,14 +1207,12 @@ rb_ca_wrap_readonly (VALUE arg, VALUE rtype)
|
|
|
898
1207
|
obj = rb_cscalar_new_with_value(data_type, 0, obj);
|
|
899
1208
|
}
|
|
900
1209
|
else {
|
|
1210
|
+
CArray *ca_tmp;
|
|
901
1211
|
volatile VALUE ref = obj;
|
|
902
|
-
if ( ! RB_OBJ_FROZEN(ref) ) {
|
|
903
|
-
ref = rb_obj_dup(ref);
|
|
904
|
-
rb_obj_freeze(ref);
|
|
905
|
-
}
|
|
906
1212
|
ca_size_t dim = RSTRING_LEN(ref)/ca_sizeof[data_type];
|
|
907
|
-
obj =
|
|
908
|
-
|
|
1213
|
+
obj = rb_carray_new(data_type, 1, &dim, 0, NULL);
|
|
1214
|
+
TypedData_Get_Struct(obj, CArray, &carray_data_type, ca_tmp);
|
|
1215
|
+
memcpy(ca_tmp->ptr, RSTRING_PTR(ref), dim * ca_sizeof[data_type]);
|
|
909
1216
|
}
|
|
910
1217
|
}
|
|
911
1218
|
else if ( NIL_P(obj) ) { /* nil */
|
|
@@ -917,8 +1224,8 @@ rb_ca_wrap_readonly (VALUE arg, VALUE rtype)
|
|
|
917
1224
|
}
|
|
918
1225
|
obj = rb_cscalar_new(data_type, 0, NULL);
|
|
919
1226
|
}
|
|
920
|
-
else if ( rb_respond_to(obj, rb_intern("
|
|
921
|
-
obj = rb_funcall(obj, rb_intern("
|
|
1227
|
+
else if ( rb_respond_to(obj, rb_intern("to_ca")) ) {
|
|
1228
|
+
obj = rb_funcall(obj, rb_intern("to_ca"), 0);
|
|
922
1229
|
TypedData_Get_Struct(obj, CArray, &carray_data_type, ca);
|
|
923
1230
|
if ( NIL_P(rtype) ) {
|
|
924
1231
|
data_type = ca->data_type;
|
|
@@ -927,11 +1234,11 @@ rb_ca_wrap_readonly (VALUE arg, VALUE rtype)
|
|
|
927
1234
|
data_type = rb_ca_guess_type(rtype);
|
|
928
1235
|
}
|
|
929
1236
|
if ( ca->data_type != data_type ) {
|
|
930
|
-
obj =
|
|
1237
|
+
obj = ca_type_adapt_view(obj, INT2NUM(data_type), data_type);
|
|
931
1238
|
}
|
|
932
1239
|
}
|
|
933
|
-
else if (
|
|
934
|
-
obj = rb_funcall(
|
|
1240
|
+
else if ( rb_memory_view_available_p(obj) ) { /* MemoryView producer */
|
|
1241
|
+
obj = rb_funcall(rb_cCArray, rb_intern("wrap_memory_view"), 1, obj);
|
|
935
1242
|
TypedData_Get_Struct(obj, CArray, &carray_data_type, ca);
|
|
936
1243
|
if ( NIL_P(rtype) ) {
|
|
937
1244
|
data_type = ca->data_type;
|
|
@@ -940,7 +1247,7 @@ rb_ca_wrap_readonly (VALUE arg, VALUE rtype)
|
|
|
940
1247
|
data_type = rb_ca_guess_type(rtype);
|
|
941
1248
|
}
|
|
942
1249
|
if ( ca->data_type != data_type ) {
|
|
943
|
-
obj =
|
|
1250
|
+
obj = ca_type_adapt_view(obj, INT2NUM(data_type), data_type);
|
|
944
1251
|
}
|
|
945
1252
|
}
|
|
946
1253
|
else { /* object */
|
|
@@ -956,10 +1263,9 @@ rb_ca_wrap_readonly (VALUE arg, VALUE rtype)
|
|
|
956
1263
|
return obj;
|
|
957
1264
|
}
|
|
958
1265
|
|
|
959
|
-
/*
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
*/
|
|
1266
|
+
/* CArray.wrap_readonly(other, data_type = nil) -- singleton entry that
|
|
1267
|
+
scans (other, data_type) and delegates to rb_ca_wrap_readonly.
|
|
1268
|
+
User doc lives in yard-stubs/carray_cast.rb. */
|
|
963
1269
|
|
|
964
1270
|
static VALUE
|
|
965
1271
|
rb_ca_s_wrap_readonly (int argc, VALUE *argv, VALUE klass)
|
|
@@ -995,7 +1301,7 @@ rb_ca_cast (volatile VALUE self)
|
|
|
995
1301
|
break;
|
|
996
1302
|
}
|
|
997
1303
|
#ifdef HAVE_COMPLEX_H
|
|
998
|
-
if (
|
|
1304
|
+
if ( RB_TYPE_P(obj, T_COMPLEX) ) {
|
|
999
1305
|
obj = rb_cscalar_new_with_value(CA_CMPLX128, 0, obj);
|
|
1000
1306
|
break;
|
|
1001
1307
|
}
|
|
@@ -1007,10 +1313,9 @@ rb_ca_cast (volatile VALUE self)
|
|
|
1007
1313
|
return obj;
|
|
1008
1314
|
}
|
|
1009
1315
|
|
|
1010
|
-
/*
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
*/
|
|
1316
|
+
/* CArray.cast(value) -- singleton entry delegating to rb_ca_cast, which
|
|
1317
|
+
returns a CArray unchanged and coerces a Ruby value to a CScalar / CArray.
|
|
1318
|
+
User doc lives in yard-stubs/carray_cast.rb. */
|
|
1014
1319
|
|
|
1015
1320
|
static VALUE
|
|
1016
1321
|
rb_ca_s_cast (VALUE klass, VALUE val)
|
|
@@ -1026,11 +1331,31 @@ rb_ca_cast_self_or_other (volatile VALUE *self, volatile VALUE *other)
|
|
|
1026
1331
|
int self_is_object = 0;
|
|
1027
1332
|
int other_is_object = 0;
|
|
1028
1333
|
|
|
1334
|
+
/* Promote MemoryView-aware operands to CArray (CAWrap or CAStride).
|
|
1335
|
+
Excludes T_STRING which has its own legacy interpretation. */
|
|
1336
|
+
if ( ! rb_obj_is_carray(*self) && TYPE(*self) != T_STRING &&
|
|
1337
|
+
rb_memory_view_available_p(*self) ) {
|
|
1338
|
+
*self = rb_funcall(rb_cCArray, rb_intern("wrap_memory_view"), 1, *self);
|
|
1339
|
+
}
|
|
1340
|
+
if ( ! rb_obj_is_carray(*other) && TYPE(*other) != T_STRING &&
|
|
1341
|
+
rb_memory_view_available_p(*other) ) {
|
|
1342
|
+
*other = rb_funcall(rb_cCArray, rb_intern("wrap_memory_view"), 1, *other);
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1029
1345
|
if ( ! rb_obj_is_carray(*self) ) {
|
|
1030
1346
|
self_is_object = 1;
|
|
1031
1347
|
if ( rb_ca_is_object_type(*other) ) {
|
|
1032
1348
|
*self = rb_cscalar_new_with_value(CA_OBJECT, 0, *self);
|
|
1033
1349
|
}
|
|
1350
|
+
#ifdef HAVE_COMPLEX_H
|
|
1351
|
+
/* A Complex scalar with a non-object non-complex CArray on the other
|
|
1352
|
+
side must wrap as CA_CMPLX128; falling into the float branch below
|
|
1353
|
+
would NUM2DBL(Complex) and raise. Downstream promotion lifts the
|
|
1354
|
+
other operand to cmplx128. */
|
|
1355
|
+
else if ( RB_TYPE_P(*self, T_COMPLEX) ) {
|
|
1356
|
+
*self = rb_cscalar_new_with_value(CA_CMPLX128, 0, *self);
|
|
1357
|
+
}
|
|
1358
|
+
#endif
|
|
1034
1359
|
else if ( rb_ca_is_float_type(*other) ) {
|
|
1035
1360
|
*self = rb_cscalar_new_with_value(CA_FLOAT64, 0, *self);
|
|
1036
1361
|
}
|
|
@@ -1040,27 +1365,7 @@ rb_ca_cast_self_or_other (volatile VALUE *self, volatile VALUE *other)
|
|
|
1040
1365
|
}
|
|
1041
1366
|
#endif
|
|
1042
1367
|
else {
|
|
1043
|
-
|
|
1044
|
-
case T_FIXNUM:
|
|
1045
|
-
*self = rb_cscalar_new_with_value(CA_INT64, 0, *self);
|
|
1046
|
-
break;
|
|
1047
|
-
case T_FLOAT:
|
|
1048
|
-
*self = rb_cscalar_new_with_value(CA_FLOAT64, 0, *self);
|
|
1049
|
-
break;
|
|
1050
|
-
case T_TRUE:
|
|
1051
|
-
case T_FALSE:
|
|
1052
|
-
*self = rb_cscalar_new_with_value(CA_BOOLEAN, 0, *self);
|
|
1053
|
-
break;
|
|
1054
|
-
default:
|
|
1055
|
-
#ifdef HAVE_COMPLEX_H
|
|
1056
|
-
if ( rb_obj_is_kind_of(*self, rb_cCComplex) ) {
|
|
1057
|
-
*self = rb_cscalar_new_with_value(CA_CMPLX128, 0, *self);
|
|
1058
|
-
break;
|
|
1059
|
-
}
|
|
1060
|
-
#endif
|
|
1061
|
-
*self = rb_cscalar_new_with_value(CA_OBJECT, 0, *self);
|
|
1062
|
-
break;
|
|
1063
|
-
}
|
|
1368
|
+
*self = rb_cscalar_new_with_value(ca_value_to_data_type(*self), 0, *self);
|
|
1064
1369
|
}
|
|
1065
1370
|
}
|
|
1066
1371
|
|
|
@@ -1070,6 +1375,15 @@ rb_ca_cast_self_or_other (volatile VALUE *self, volatile VALUE *other)
|
|
|
1070
1375
|
if ( rb_ca_is_object_type(*self) ) {
|
|
1071
1376
|
*other = rb_cscalar_new_with_value(CA_OBJECT, 0, *other);
|
|
1072
1377
|
}
|
|
1378
|
+
#ifdef HAVE_COMPLEX_H
|
|
1379
|
+
/* Symmetric to the self-branch above: Complex scalar wraps as
|
|
1380
|
+
cmplx128 regardless of the CArray operand's numeric width, so
|
|
1381
|
+
float64_array + Complex(0, 1) promotes rather than raising in
|
|
1382
|
+
NUM2DBL(Complex). */
|
|
1383
|
+
else if ( RB_TYPE_P(*other, T_COMPLEX) ) {
|
|
1384
|
+
*other = rb_cscalar_new_with_value(CA_CMPLX128, 0, *other);
|
|
1385
|
+
}
|
|
1386
|
+
#endif
|
|
1073
1387
|
else if ( rb_ca_is_float_type(*self) ) {
|
|
1074
1388
|
*other = rb_cscalar_new_with_value(CA_FLOAT64, 0, *other);
|
|
1075
1389
|
}
|
|
@@ -1079,28 +1393,7 @@ rb_ca_cast_self_or_other (volatile VALUE *self, volatile VALUE *other)
|
|
|
1079
1393
|
}
|
|
1080
1394
|
#endif
|
|
1081
1395
|
else {
|
|
1082
|
-
|
|
1083
|
-
case T_FIXNUM:
|
|
1084
|
-
case T_BIGNUM:
|
|
1085
|
-
*other = rb_cscalar_new_with_value(CA_INT64, 0, *other);
|
|
1086
|
-
break;
|
|
1087
|
-
case T_FLOAT:
|
|
1088
|
-
*other = rb_cscalar_new_with_value(CA_FLOAT64, 0, *other);
|
|
1089
|
-
break;
|
|
1090
|
-
case T_TRUE:
|
|
1091
|
-
case T_FALSE:
|
|
1092
|
-
*other = rb_cscalar_new_with_value(CA_BOOLEAN, 0, *other);
|
|
1093
|
-
break;
|
|
1094
|
-
default:
|
|
1095
|
-
#ifdef HAVE_COMPLEX_H
|
|
1096
|
-
if ( rb_obj_is_kind_of(*other, rb_cCComplex) ) {
|
|
1097
|
-
*other = rb_cscalar_new_with_value(CA_CMPLX128, 0, *other);
|
|
1098
|
-
break;
|
|
1099
|
-
}
|
|
1100
|
-
#endif
|
|
1101
|
-
*other = rb_cscalar_new_with_value(CA_OBJECT, 0, *other);
|
|
1102
|
-
break;
|
|
1103
|
-
}
|
|
1396
|
+
*other = rb_cscalar_new_with_value(ca_value_to_data_type(*other), 0, *other);
|
|
1104
1397
|
}
|
|
1105
1398
|
}
|
|
1106
1399
|
|
|
@@ -1117,8 +1410,17 @@ rb_ca_cast_self_or_other (volatile VALUE *self, volatile VALUE *other)
|
|
|
1117
1410
|
TypedData_Get_Struct(*other, CArray, &carray_data_type, cb);
|
|
1118
1411
|
}
|
|
1119
1412
|
|
|
1120
|
-
|
|
1121
|
-
|
|
1413
|
+
/* Implicit size-1 broadcasting (case A only). No-op if either side
|
|
1414
|
+
is scalar, ndim differs, or shapes are already equal. If shapes
|
|
1415
|
+
are incompatible (neither side is 1 nor equal on some axis), also
|
|
1416
|
+
no-op — the downstream element-count check in ca_set_iterator
|
|
1417
|
+
raises with the existing message. */
|
|
1418
|
+
ca_broadcast_pair(self, other);
|
|
1419
|
+
TypedData_Get_Struct(*self, CArray, &carray_data_type, ca);
|
|
1420
|
+
TypedData_Get_Struct(*other, CArray, &carray_data_type, cb);
|
|
1421
|
+
|
|
1422
|
+
if ( ca_is_scalar(ca) ^ ca_is_scalar(cb) ||
|
|
1423
|
+
self_is_object ||
|
|
1122
1424
|
other_is_object ) {
|
|
1123
1425
|
if ( other_is_object ||
|
|
1124
1426
|
( ( ! other_is_object ) && ca_is_scalar(cb) ) ) {
|
|
@@ -1167,10 +1469,10 @@ rb_ca_cast_self_or_other (volatile VALUE *self, volatile VALUE *other)
|
|
|
1167
1469
|
ca_type_name[cb->data_type]);
|
|
1168
1470
|
}
|
|
1169
1471
|
|
|
1170
|
-
/*
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
*/
|
|
1472
|
+
/* CArray.cast_self_or_other(self, other) — promote self and other
|
|
1473
|
+
* to a common data_type and return [self', other']. Wraps the
|
|
1474
|
+
* void rb_ca_cast_self_or_other above into a class method.
|
|
1475
|
+
*/
|
|
1174
1476
|
|
|
1175
1477
|
VALUE
|
|
1176
1478
|
rb_ca_s_cast_self_or_other (VALUE klass, VALUE self, VALUE other)
|
|
@@ -1179,6 +1481,286 @@ rb_ca_s_cast_self_or_other (VALUE klass, VALUE self, VALUE other)
|
|
|
1179
1481
|
return rb_assoc_new(self, other);
|
|
1180
1482
|
}
|
|
1181
1483
|
|
|
1484
|
+
/* Extract a data_type code (0..CA_NTYPE-1) from an argument.
|
|
1485
|
+
Dispatch:
|
|
1486
|
+
- CArray instance -> its data_type
|
|
1487
|
+
- Symbol / String / Class -> data_type representation (name lookup)
|
|
1488
|
+
- other (Integer / Float / Complex / true / false / nil / Object)
|
|
1489
|
+
-> value semantic via ca_value_to_data_type
|
|
1490
|
+
(e.g. an Integer like `3` is interpreted
|
|
1491
|
+
as a value -> :int64, not as a data_type
|
|
1492
|
+
code). */
|
|
1493
|
+
static int8_t
|
|
1494
|
+
ca_arg_to_data_type (VALUE obj)
|
|
1495
|
+
{
|
|
1496
|
+
int8_t data_type;
|
|
1497
|
+
if ( rb_obj_is_carray(obj) ) {
|
|
1498
|
+
CArray *ca;
|
|
1499
|
+
TypedData_Get_Struct(obj, CArray, &carray_data_type, ca);
|
|
1500
|
+
data_type = ca->data_type;
|
|
1501
|
+
}
|
|
1502
|
+
else if ( TYPE(obj) == T_SYMBOL || TYPE(obj) == T_STRING ||
|
|
1503
|
+
TYPE(obj) == T_CLASS ) {
|
|
1504
|
+
data_type = rb_ca_guess_type(obj);
|
|
1505
|
+
}
|
|
1506
|
+
else if ( ( data_type = ca_mv_probe_data_type(obj) ) >= 0 ) {
|
|
1507
|
+
/* MemoryView producer -> its format's data_type (T_STRING excluded above,
|
|
1508
|
+
so a String never reaches here). data_type already assigned. */
|
|
1509
|
+
}
|
|
1510
|
+
else {
|
|
1511
|
+
data_type = ca_value_to_data_type(obj);
|
|
1512
|
+
}
|
|
1513
|
+
CA_CHECK_DATA_TYPE(data_type);
|
|
1514
|
+
if ( ! ca_valid[data_type] ) {
|
|
1515
|
+
rb_raise(rb_eArgError,
|
|
1516
|
+
"data type '%s' is not valid in this build",
|
|
1517
|
+
ca_type_name[data_type]);
|
|
1518
|
+
}
|
|
1519
|
+
return data_type;
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
/* Infer a data_type code from a Ruby *value* (literal Numeric, true/false,
|
|
1523
|
+
Complex, etc.). See declaration in carray.h for the contract. */
|
|
1524
|
+
int8_t
|
|
1525
|
+
ca_value_to_data_type (VALUE obj)
|
|
1526
|
+
{
|
|
1527
|
+
switch ( TYPE(obj) ) {
|
|
1528
|
+
case T_FIXNUM:
|
|
1529
|
+
case T_BIGNUM: return CA_INT64;
|
|
1530
|
+
case T_FLOAT: return CA_FLOAT64;
|
|
1531
|
+
case T_TRUE:
|
|
1532
|
+
case T_FALSE: return CA_BOOLEAN;
|
|
1533
|
+
case T_NIL: return CA_OBJECT;
|
|
1534
|
+
default:
|
|
1535
|
+
#ifdef HAVE_COMPLEX_H
|
|
1536
|
+
if ( RB_TYPE_P(obj, T_COMPLEX) ) return CA_CMPLX128;
|
|
1537
|
+
#endif
|
|
1538
|
+
return CA_OBJECT;
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
/* Promote two data_type codes according to ca_cast_table.
|
|
1543
|
+
Returns the higher (= the type both can be cast to without loss
|
|
1544
|
+
under the table's policy). Raises if incompatible.
|
|
1545
|
+
|
|
1546
|
+
Externally callable so the lazy view layer (CABinOp constructor)
|
|
1547
|
+
can compute its output_data_type using the same single-source
|
|
1548
|
+
promotion rule as the eager binop path. */
|
|
1549
|
+
int8_t
|
|
1550
|
+
ca_promote_type (int8_t a, int8_t b)
|
|
1551
|
+
{
|
|
1552
|
+
int test;
|
|
1553
|
+
if ( a == b ) {
|
|
1554
|
+
return a;
|
|
1555
|
+
}
|
|
1556
|
+
test = ca_cast_table[a][b];
|
|
1557
|
+
if ( test == 0 ) {
|
|
1558
|
+
return b;
|
|
1559
|
+
}
|
|
1560
|
+
else if ( test > 0 ) {
|
|
1561
|
+
/* a should be cast to b */
|
|
1562
|
+
return b;
|
|
1563
|
+
}
|
|
1564
|
+
/* test < 0: try the other direction */
|
|
1565
|
+
test = ca_cast_table[b][a];
|
|
1566
|
+
if ( test > 0 ) {
|
|
1567
|
+
/* b should be cast to a */
|
|
1568
|
+
return a;
|
|
1569
|
+
}
|
|
1570
|
+
rb_raise(rb_eRuntimeError,
|
|
1571
|
+
"can't promote data_types '%s' and '%s' to a common type",
|
|
1572
|
+
ca_type_name[a], ca_type_name[b]);
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
/* CArray.result_type(*args) -- common data_type each operand promotes to
|
|
1576
|
+
under ca_cast_table. Each arg is classified by ca_arg_to_data_type: a
|
|
1577
|
+
CArray / Symbol / String / Class gives a data_type representation, a
|
|
1578
|
+
Numeric / bool / nil / Object gives a value whose data_type is inferred.
|
|
1579
|
+
Folds pairwise via ca_promote_type; returns a Symbol. User doc (with
|
|
1580
|
+
the value-vs-code distinction and examples) lives in
|
|
1581
|
+
yard-stubs/carray_cast.rb. */
|
|
1582
|
+
|
|
1583
|
+
static VALUE
|
|
1584
|
+
rb_ca_s_result_type (int argc, VALUE *argv, VALUE klass)
|
|
1585
|
+
{
|
|
1586
|
+
int8_t cur;
|
|
1587
|
+
int i;
|
|
1588
|
+
|
|
1589
|
+
if ( argc < 1 ) {
|
|
1590
|
+
rb_raise(rb_eArgError, "result_type requires at least one argument");
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
cur = ca_arg_to_data_type(argv[0]);
|
|
1594
|
+
for ( i = 1; i < argc; i++ ) {
|
|
1595
|
+
int8_t next = ca_arg_to_data_type(argv[i]);
|
|
1596
|
+
cur = ca_promote_type(cur, next);
|
|
1597
|
+
}
|
|
1598
|
+
/* Return Symbol for family consistency with
|
|
1599
|
+
CArray.value_to_data_type and ca.data_type. */
|
|
1600
|
+
return rb_ca_data_type_to_sym(cur);
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
/* CArray.promote_list(list, data_type: nil) -- reconcile an Array of
|
|
1604
|
+
CArray instances into a uniformly-handleable representation (same Face
|
|
1605
|
+
class, or same primitive data_type) suitable for multi-parent
|
|
1606
|
+
constructors like CArray.stack. User doc lives in
|
|
1607
|
+
yard-stubs/carray_cast.rb; the dispatch branches are:
|
|
1608
|
+
|
|
1609
|
+
Auto-detect (data_type: nil):
|
|
1610
|
+
- All elements Face (= ca_is_face) and same Face class:
|
|
1611
|
+
- Reject if the class is not portable (= CAConstString)
|
|
1612
|
+
- Reject on pairwise state mismatch (= CATime with different units)
|
|
1613
|
+
- Otherwise pass through (= CAStack will lift)
|
|
1614
|
+
- All elements primitive: promote via result_type + wrap_readonly
|
|
1615
|
+
- Mixed Face + non-Face: reject (= ambiguous; user must strip Face
|
|
1616
|
+
manually with .parent if the storage-level layout is intended)
|
|
1617
|
+
- Heterogeneous Face classes: reject (= no semantics for mixing Faces)
|
|
1618
|
+
|
|
1619
|
+
Explicit data_type (Symbol):
|
|
1620
|
+
- All primitive elements: wrap_readonly to the requested type
|
|
1621
|
+
- Any Face element: reject (= Face cannot be coerced into a primitive
|
|
1622
|
+
without losing identity; the user must strip Face manually)
|
|
1623
|
+
|
|
1624
|
+
Explicit data_type (Class / non-Symbol):
|
|
1625
|
+
- Reject. Class-shaped targets (CARecord, Face subclasses, etc.) are
|
|
1626
|
+
not valid promotion destinations; use auto-detect or pass a primitive
|
|
1627
|
+
Symbol. Future work may relax this once Face-as-target promotion is
|
|
1628
|
+
designed.
|
|
1629
|
+
|
|
1630
|
+
Raises ArgumentError on empty list or any of the reject cases above. */
|
|
1631
|
+
static VALUE
|
|
1632
|
+
rb_ca_s_promote_list (int argc, VALUE *argv, VALUE klass)
|
|
1633
|
+
{
|
|
1634
|
+
VALUE list, kwargs, data_type = Qnil;
|
|
1635
|
+
long n, i;
|
|
1636
|
+
int all_face = 1, any_face = 0, all_primitive = 1;
|
|
1637
|
+
VALUE face_class = Qnil;
|
|
1638
|
+
CArray *ref_face = NULL;
|
|
1639
|
+
int8_t common = -1;
|
|
1640
|
+
|
|
1641
|
+
rb_scan_args(argc, argv, "1:", &list, &kwargs);
|
|
1642
|
+
Check_Type(list, T_ARRAY);
|
|
1643
|
+
rb_scan_options(kwargs, "data_type", &data_type);
|
|
1644
|
+
|
|
1645
|
+
n = RARRAY_LEN(list);
|
|
1646
|
+
if ( n <= 0 ) {
|
|
1647
|
+
rb_raise(rb_eArgError, "promote_list: list must not be empty");
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
/* Explicit data_type validation: reject Class / non-Symbol targets up
|
|
1651
|
+
front so the rest of the function only deals with `nil` or a
|
|
1652
|
+
primitive-shaped Symbol/String/Integer. */
|
|
1653
|
+
if ( ! NIL_P(data_type) ) {
|
|
1654
|
+
if ( RB_TYPE_P(data_type, T_CLASS) || RB_TYPE_P(data_type, T_MODULE) ) {
|
|
1655
|
+
rb_raise(rb_eArgError,
|
|
1656
|
+
"promote_list: data_type must be a primitive Symbol "
|
|
1657
|
+
"(Class targets are not supported; use auto-detect or "
|
|
1658
|
+
"strip Face manually)");
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
/* Classify each element: Face / primitive CArray. Detect Face-class
|
|
1663
|
+
homogeneity as we go. */
|
|
1664
|
+
for ( i = 0; i < n; i++ ) {
|
|
1665
|
+
VALUE elem = rb_ary_entry(list, i);
|
|
1666
|
+
CArray *ca;
|
|
1667
|
+
rb_check_carray_object(elem);
|
|
1668
|
+
TypedData_Get_Struct(elem, CArray, &carray_data_type, ca);
|
|
1669
|
+
if ( ca_is_face(ca) ) {
|
|
1670
|
+
any_face = 1;
|
|
1671
|
+
all_primitive = 0;
|
|
1672
|
+
if ( NIL_P(face_class) ) {
|
|
1673
|
+
face_class = rb_obj_class(elem);
|
|
1674
|
+
ref_face = ca;
|
|
1675
|
+
} else if ( rb_obj_class(elem) != face_class ) {
|
|
1676
|
+
all_face = 0; /* will be caught after the loop */
|
|
1677
|
+
} else if ( all_face ) {
|
|
1678
|
+
if ( ! ca_face_state_compatible(rb_ary_entry(list, 0), ref_face,
|
|
1679
|
+
elem, ca) ) {
|
|
1680
|
+
rb_raise(rb_eArgError,
|
|
1681
|
+
"promote_list: Face state mismatch across elements "
|
|
1682
|
+
"(= %s instance at index %ld differs from index 0)",
|
|
1683
|
+
rb_class2name(face_class), i);
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
} else {
|
|
1687
|
+
all_face = 0;
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
/* Explicit data_type path: primitive Symbol, all elements must be
|
|
1692
|
+
primitive. Reject if any Face in list. */
|
|
1693
|
+
if ( ! NIL_P(data_type) ) {
|
|
1694
|
+
if ( any_face ) {
|
|
1695
|
+
rb_raise(rb_eArgError,
|
|
1696
|
+
"promote_list: data_type %s cannot be applied to a list "
|
|
1697
|
+
"containing Face elements (= Face cannot be coerced to "
|
|
1698
|
+
"a primitive without losing identity)",
|
|
1699
|
+
RSTRING_PTR(rb_inspect(data_type)));
|
|
1700
|
+
}
|
|
1701
|
+
{
|
|
1702
|
+
VALUE out = rb_ary_new_capa(n);
|
|
1703
|
+
static ID id_wrap_readonly = 0;
|
|
1704
|
+
if ( id_wrap_readonly == 0 ) id_wrap_readonly = rb_intern("wrap_readonly");
|
|
1705
|
+
for ( i = 0; i < n; i++ ) {
|
|
1706
|
+
VALUE coerced = rb_funcall(klass, id_wrap_readonly, 2,
|
|
1707
|
+
rb_ary_entry(list, i), data_type);
|
|
1708
|
+
rb_ary_push(out, coerced);
|
|
1709
|
+
}
|
|
1710
|
+
return out;
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
/* Auto-detect path. */
|
|
1715
|
+
if ( any_face && ! all_face ) {
|
|
1716
|
+
if ( all_primitive == 0 && any_face ) {
|
|
1717
|
+
/* Mixed: at least one Face and at least one non-Face,
|
|
1718
|
+
OR mixed Face classes. Both are rejected. */
|
|
1719
|
+
rb_raise(rb_eArgError,
|
|
1720
|
+
"promote_list: cannot mix Face and non-Face (or heterogeneous "
|
|
1721
|
+
"Face classes); pass a homogeneous Face list, or strip Face "
|
|
1722
|
+
"manually with .parent for the storage-level layout");
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
if ( all_face ) {
|
|
1727
|
+
/* Homogeneous Face: validate portability, then pass through. */
|
|
1728
|
+
if ( n > 1 && ! ca_face_state_portable(ref_face->obj_type, face_class) ) {
|
|
1729
|
+
rb_raise(rb_eArgError,
|
|
1730
|
+
"promote_list: %s state is not portable across multiple "
|
|
1731
|
+
"elements (= per-parent storage like CAConstString's buffer); "
|
|
1732
|
+
"strip Face manually with .parent for a storage-level list",
|
|
1733
|
+
rb_class2name(face_class));
|
|
1734
|
+
}
|
|
1735
|
+
/* Return a fresh Array so callers can mutate without aliasing. */
|
|
1736
|
+
{
|
|
1737
|
+
VALUE out = rb_ary_new_capa(n);
|
|
1738
|
+
for ( i = 0; i < n; i++ ) rb_ary_push(out, rb_ary_entry(list, i));
|
|
1739
|
+
return out;
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
/* All primitive: result_type to determine common data_type, then
|
|
1744
|
+
wrap_readonly each element. */
|
|
1745
|
+
common = ca_arg_to_data_type(rb_ary_entry(list, 0));
|
|
1746
|
+
for ( i = 1; i < n; i++ ) {
|
|
1747
|
+
int8_t next = ca_arg_to_data_type(rb_ary_entry(list, i));
|
|
1748
|
+
common = ca_promote_type(common, next);
|
|
1749
|
+
}
|
|
1750
|
+
{
|
|
1751
|
+
VALUE common_sym = rb_ca_data_type_to_sym(common);
|
|
1752
|
+
VALUE out = rb_ary_new_capa(n);
|
|
1753
|
+
static ID id_wrap_readonly = 0;
|
|
1754
|
+
if ( id_wrap_readonly == 0 ) id_wrap_readonly = rb_intern("wrap_readonly");
|
|
1755
|
+
for ( i = 0; i < n; i++ ) {
|
|
1756
|
+
VALUE coerced = rb_funcall(klass, id_wrap_readonly, 2,
|
|
1757
|
+
rb_ary_entry(list, i), common_sym);
|
|
1758
|
+
rb_ary_push(out, coerced);
|
|
1759
|
+
}
|
|
1760
|
+
return out;
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1182
1764
|
void
|
|
1183
1765
|
rb_ca_cast_other (VALUE *self, volatile VALUE *other)
|
|
1184
1766
|
{
|
|
@@ -1188,6 +1770,13 @@ rb_ca_cast_other (VALUE *self, volatile VALUE *other)
|
|
|
1188
1770
|
|
|
1189
1771
|
TypedData_Get_Struct(*self, CArray, &carray_data_type, ca);
|
|
1190
1772
|
|
|
1773
|
+
/* Promote MemoryView-aware operand to CArray (CAWrap or CAStride).
|
|
1774
|
+
Excludes T_STRING which has its own legacy interpretation. */
|
|
1775
|
+
if ( ! rb_obj_is_carray(*other) && TYPE(*other) != T_STRING &&
|
|
1776
|
+
rb_memory_view_available_p(*other) ) {
|
|
1777
|
+
*other = rb_funcall(rb_cCArray, rb_intern("wrap_memory_view"), 1, *other);
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1191
1780
|
if ( ! rb_obj_is_carray(*other) ) {
|
|
1192
1781
|
if ( rb_ca_is_object_type(*self) ) {
|
|
1193
1782
|
*other = rb_cscalar_new_with_value(CA_OBJECT, 0, *other);
|
|
@@ -1202,30 +1791,9 @@ rb_ca_cast_other (VALUE *self, volatile VALUE *other)
|
|
|
1202
1791
|
}
|
|
1203
1792
|
#endif
|
|
1204
1793
|
else {
|
|
1205
|
-
|
|
1206
|
-
case T_FIXNUM:
|
|
1207
|
-
case T_BIGNUM:
|
|
1208
|
-
*other = rb_cscalar_new_with_value(CA_INT64, 0, *other);
|
|
1209
|
-
break;
|
|
1210
|
-
case T_FLOAT:
|
|
1211
|
-
*other = rb_cscalar_new_with_value(CA_FLOAT64, 0, *other);
|
|
1212
|
-
break;
|
|
1213
|
-
case T_TRUE:
|
|
1214
|
-
case T_FALSE:
|
|
1215
|
-
*other = rb_cscalar_new_with_value(CA_BOOLEAN, 0, *other);
|
|
1216
|
-
break;
|
|
1217
|
-
default:
|
|
1218
|
-
#ifdef HAVE_COMPLEX_H
|
|
1219
|
-
if ( rb_obj_is_kind_of(*other, rb_cCComplex) ) {
|
|
1220
|
-
*other = rb_cscalar_new_with_value(CA_CMPLX128, 0, *other);
|
|
1221
|
-
break;
|
|
1222
|
-
}
|
|
1223
|
-
#endif
|
|
1224
|
-
*other = rb_cscalar_new_with_value(CA_OBJECT, 0, *other);
|
|
1225
|
-
break;
|
|
1226
|
-
}
|
|
1794
|
+
*other = rb_cscalar_new_with_value(ca_value_to_data_type(*other), 0, *other);
|
|
1227
1795
|
}
|
|
1228
|
-
|
|
1796
|
+
|
|
1229
1797
|
TypedData_Get_Struct(*other, CScalar, &cscalar_data_type, cs);
|
|
1230
1798
|
|
|
1231
1799
|
test0 = ca_cast_table2[cs->data_type][ca->data_type];
|
|
@@ -1259,10 +1827,10 @@ rb_ca_cast_other (VALUE *self, volatile VALUE *other)
|
|
|
1259
1827
|
ca_type_name[cb->data_type]);
|
|
1260
1828
|
}
|
|
1261
1829
|
|
|
1262
|
-
/*
|
|
1263
|
-
|
|
1264
|
-
[
|
|
1265
|
-
*/
|
|
1830
|
+
/* CArray#cast_with(other) -- coerce self and other to a common
|
|
1831
|
+
representation via rb_ca_cast_self_or_other and return them as a
|
|
1832
|
+
two-element [self, other] array. User doc lives in
|
|
1833
|
+
yard-stubs/carray_cast.rb. */
|
|
1266
1834
|
|
|
1267
1835
|
VALUE
|
|
1268
1836
|
rb_ca_cast_with (VALUE self, VALUE other)
|
|
@@ -1276,8 +1844,289 @@ rb_ca_cast_with (VALUE self, VALUE other)
|
|
|
1276
1844
|
return rb_assoc_new(self, other);
|
|
1277
1845
|
}
|
|
1278
1846
|
|
|
1847
|
+
/* -----------------------------------------------------------------------
|
|
1848
|
+
clip_<dtype> family — clip into the target dtype's representable
|
|
1849
|
+
range, then cast. Sugar for `clip(lo, hi).as_<dtype>`.
|
|
1850
|
+
----------------------------------------------------------------------- */
|
|
1851
|
+
|
|
1852
|
+
#define CLIP_CAST_FUNC(name, lo_expr, hi_expr, cast_func) \
|
|
1853
|
+
static VALUE \
|
|
1854
|
+
rb_ca_##name (VALUE self) \
|
|
1855
|
+
{ \
|
|
1856
|
+
return cast_func(rb_ca_clip(self, lo_expr, hi_expr)); \
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
CLIP_CAST_FUNC(clip_int8, INT2NUM(-128), INT2NUM(127), rb_ca_as_int8)
|
|
1860
|
+
CLIP_CAST_FUNC(clip_int16, INT2NUM(-32768), INT2NUM(32767), rb_ca_as_int16)
|
|
1861
|
+
CLIP_CAST_FUNC(clip_int32, INT2NUM(-2147483648), INT2NUM(2147483647), rb_ca_as_int32)
|
|
1862
|
+
CLIP_CAST_FUNC(clip_int64, LL2NUM(-9223372036854775807-1), LL2NUM(9223372036854775807), rb_ca_as_int64)
|
|
1863
|
+
CLIP_CAST_FUNC(clip_uint8, INT2NUM(0), INT2NUM(255), rb_ca_as_uint8)
|
|
1864
|
+
CLIP_CAST_FUNC(clip_uint16, INT2NUM(0), INT2NUM(65535), rb_ca_as_uint16)
|
|
1865
|
+
CLIP_CAST_FUNC(clip_uint32, INT2NUM(0), UINT2NUM(4294967295U), rb_ca_as_uint32)
|
|
1866
|
+
|
|
1867
|
+
#undef CLIP_CAST_FUNC
|
|
1868
|
+
|
|
1869
|
+
/* CArray#clip_uint64 -- dedicated implementation.
|
|
1870
|
+
|
|
1871
|
+
UINT64_MAX (= 2^64-1) is not exactly representable in float64; the nearest
|
|
1872
|
+
double rounds up to 2^64. A generic clip-then-cast path therefore clamps
|
|
1873
|
+
an overflowing float source (e.g. 1e20) to 2^64 and the subsequent cast to
|
|
1874
|
+
uint64 wraps around to 0. For floating-point sources we take a saturating
|
|
1875
|
+
path: compare in float space against 2^64 (which IS representable) and
|
|
1876
|
+
saturate to UINT64_MAX above it and 0 below zero. Other source dtypes use
|
|
1877
|
+
the plain clip-then-cast path. */
|
|
1878
|
+
static VALUE
|
|
1879
|
+
rb_ca_clip_uint64 (VALUE self)
|
|
1880
|
+
{
|
|
1881
|
+
CArray *ca;
|
|
1882
|
+
GetCArray(self, ca);
|
|
1883
|
+
int dt = ca->data_type;
|
|
1884
|
+
if ( dt == CA_FLOAT32 || dt == CA_FLOAT64 ) {
|
|
1885
|
+
volatile VALUE vsrc = ( dt == CA_FLOAT64 ) ? self : rb_ca_as_float64(self);
|
|
1886
|
+
CArray *src;
|
|
1887
|
+
GetCArray(vsrc, src);
|
|
1888
|
+
volatile VALUE vout = rb_carray_new(CA_UINT64, ca->ndim, ca->dim, 0, NULL);
|
|
1889
|
+
CArray *out;
|
|
1890
|
+
GetCArray(vout, out);
|
|
1891
|
+
ca_attach(src);
|
|
1892
|
+
double *sp = (double *) src->ptr;
|
|
1893
|
+
uint64_t *op = (uint64_t *) out->ptr;
|
|
1894
|
+
ca_size_t n = ca->elements;
|
|
1895
|
+
const double LIMIT = 18446744073709551616.0; /* 2^64, exact in f64 */
|
|
1896
|
+
for ( ca_size_t i = 0; i < n; i++ ) {
|
|
1897
|
+
double v = sp[i];
|
|
1898
|
+
if ( v != v ) op[i] = 0; /* NaN -> 0 */
|
|
1899
|
+
else if ( v >= LIMIT ) op[i] = UINT64_MAX;
|
|
1900
|
+
else if ( v <= 0.0 ) op[i] = 0;
|
|
1901
|
+
else op[i] = (uint64_t) v;
|
|
1902
|
+
}
|
|
1903
|
+
ca_detach(src);
|
|
1904
|
+
if ( ca_has_mask(ca) ) {
|
|
1905
|
+
ca_copy_mask(out, ca);
|
|
1906
|
+
}
|
|
1907
|
+
return vout;
|
|
1908
|
+
}
|
|
1909
|
+
return rb_ca_as_uint64(rb_ca_clip(self, INT2NUM(0),
|
|
1910
|
+
ULL2NUM(18446744073709551615ULL)));
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
/* ------------------------------------------------------------------------
|
|
1914
|
+
Global cast functions CA_INT32(data) ... CA_OBJECT(data) etc.
|
|
1915
|
+
|
|
1916
|
+
Polymorphic cast (NOT a fresh allocator): `data` is coerced into a CArray
|
|
1917
|
+
of the target data_type, dispatching on its Ruby class:
|
|
1918
|
+
|
|
1919
|
+
Array -> shape-guessed CArray, element-wise store (C fast path)
|
|
1920
|
+
CArray -> copy if same data_type, else #to_type (C fast path)
|
|
1921
|
+
nil -> empty CArray (C fast path)
|
|
1922
|
+
Range / String / Numeric / #to_ca responder (Ruby fallback)
|
|
1923
|
+
|
|
1924
|
+
The cold / Ruby-natural branches (arange arithmetic, the whitespace/`,`/`;`
|
|
1925
|
+
string parser, generic coercion) stay in Ruby as `CArray.__cast_rest__`
|
|
1926
|
+
(carray/basics.rb, eager-loaded). `type` is passed to the fallback as the
|
|
1927
|
+
data_type Symbol so the Ruby side keeps its original `type == CA_OBJECT`
|
|
1928
|
+
style comparisons.
|
|
1929
|
+
------------------------------------------------------------------------ */
|
|
1930
|
+
|
|
1931
|
+
static ID id_new_cast = 0, id_guess_array_shape_cast = 0, id_cast_string = 0,
|
|
1932
|
+
id_to_ca_cast = 0, id_length_cast = 0,
|
|
1933
|
+
id_begin_cast = 0, id_end_cast = 0, id_to_a_cast = 0,
|
|
1934
|
+
id_exclude_end_p_cast = 0, id_abs_cast = 0, id_floor_cast = 0,
|
|
1935
|
+
id_op_minus = 0, id_op_div = 0, id_op_plus = 0,
|
|
1936
|
+
id_op_le = 0, id_op_eq = 0, id_op_uminus = 0;
|
|
1937
|
+
|
|
1938
|
+
/* Cross-type cast helper: v.to_type(sym) with no bytes (= in-file call to
|
|
1939
|
+
the #to_type implementation, no Ruby method dispatch). */
|
|
1940
|
+
static VALUE
|
|
1941
|
+
ca_cast_to_type1 (VALUE v, VALUE sym)
|
|
1942
|
+
{
|
|
1943
|
+
VALUE list[1];
|
|
1944
|
+
list[0] = sym;
|
|
1945
|
+
return rb_ca_to_type_internal(1, list, v);
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
static VALUE
|
|
1949
|
+
ca_cast_impl (int8_t data_type, int argc, VALUE *argv)
|
|
1950
|
+
{
|
|
1951
|
+
VALUE v = ( argc >= 1 ) ? argv[0] : Qnil;
|
|
1952
|
+
VALUE sym = ID2SYM(ca_data_type_sym[data_type]);
|
|
1953
|
+
|
|
1954
|
+
if ( TYPE(v) == T_ARRAY ) {
|
|
1955
|
+
volatile VALUE shape, obj;
|
|
1956
|
+
shape = rb_funcall(rb_cCArray, id_guess_array_shape_cast, 1, v);
|
|
1957
|
+
obj = rb_funcall(rb_cCArray, id_new_cast, 2, sym, shape);
|
|
1958
|
+
rb_ca_store_all(obj, v);
|
|
1959
|
+
return obj;
|
|
1960
|
+
}
|
|
1961
|
+
else if ( RTEST(rb_obj_is_kind_of(v, rb_cCArray)) ) {
|
|
1962
|
+
CArray *ca;
|
|
1963
|
+
TypedData_Get_Struct(v, CArray, &carray_data_type, ca);
|
|
1964
|
+
if ( ca->data_type == data_type ) {
|
|
1965
|
+
return rb_ca_copy(v);
|
|
1966
|
+
}
|
|
1967
|
+
return ca_cast_to_type1(v, sym);
|
|
1968
|
+
}
|
|
1969
|
+
else if ( NIL_P(v) ) {
|
|
1970
|
+
ca_size_t dim0 = 0;
|
|
1971
|
+
return rb_carray_new(data_type, 1, &dim0, 0, NULL);
|
|
1972
|
+
}
|
|
1973
|
+
else if ( RTEST(rb_obj_is_kind_of(v, rb_cRange)) ) {
|
|
1974
|
+
/* arange: n = ((end - begin).abs / step).floor (+1 unless exclude_end),
|
|
1975
|
+
then seq(begin, sign * step.abs). */
|
|
1976
|
+
volatile VALUE vbeg, vend, step, n;
|
|
1977
|
+
int sign;
|
|
1978
|
+
ca_size_t dn;
|
|
1979
|
+
VALUE obj, step_abs, signed_step;
|
|
1980
|
+
|
|
1981
|
+
vbeg = rb_funcall(v, id_begin_cast, 0);
|
|
1982
|
+
vend = rb_funcall(v, id_end_cast, 0);
|
|
1983
|
+
step = ( argc >= 2 ) ? argv[1] : Qnil;
|
|
1984
|
+
if ( RTEST(step) && RTEST(rb_funcall(step, id_op_eq, 1, INT2FIX(0))) ) {
|
|
1985
|
+
rb_raise(rb_eRuntimeError, "step should not be 0");
|
|
1986
|
+
}
|
|
1987
|
+
if ( data_type == CA_OBJECT && !RTEST(step) ) {
|
|
1988
|
+
VALUE va = rb_funcall(v, id_to_a_cast, 0); /* CA_OBJECT(v.to_a) */
|
|
1989
|
+
return ca_cast_impl(CA_OBJECT, 1, &va);
|
|
1990
|
+
}
|
|
1991
|
+
if ( !RTEST(step) ) step = INT2FIX(1);
|
|
1992
|
+
n = rb_funcall(vend, id_op_minus, 1, vbeg);
|
|
1993
|
+
n = rb_funcall(n, id_abs_cast, 0);
|
|
1994
|
+
n = rb_funcall(n, id_op_div, 1, step);
|
|
1995
|
+
n = rb_funcall(n, id_floor_cast, 0);
|
|
1996
|
+
if ( !RTEST(rb_funcall(v, id_exclude_end_p_cast, 0)) ) {
|
|
1997
|
+
n = rb_funcall(n, id_op_plus, 1, INT2FIX(1));
|
|
1998
|
+
}
|
|
1999
|
+
sign = RTEST(rb_funcall(vbeg, id_op_le, 1, vend)) ? 1 : -1;
|
|
2000
|
+
dn = NUM2SIZE(n);
|
|
2001
|
+
obj = rb_carray_new(data_type, 1, &dn, 0, NULL);
|
|
2002
|
+
step_abs = rb_funcall(step, id_abs_cast, 0);
|
|
2003
|
+
signed_step = ( sign == 1 ) ? step_abs : rb_funcall(step_abs, id_op_uminus, 0);
|
|
2004
|
+
return rb_ca_seq(obj, vbeg, signed_step);
|
|
2005
|
+
}
|
|
2006
|
+
else if ( TYPE(v) == T_STRING ) {
|
|
2007
|
+
/* The whitespace / `,` / `;` / `_`->UNDEF parser is far more natural in
|
|
2008
|
+
Ruby; only this branch stays there (carray/basics.rb). */
|
|
2009
|
+
return rb_funcall(rb_cCArray, id_cast_string, 2, sym, v);
|
|
2010
|
+
}
|
|
2011
|
+
else {
|
|
2012
|
+
/* Numeric / #to_ca responder */
|
|
2013
|
+
if ( rb_respond_to(v, id_to_ca_cast) ) {
|
|
2014
|
+
VALUE ca = rb_funcall(v, id_to_ca_cast, 0);
|
|
2015
|
+
CArray *cap;
|
|
2016
|
+
TypedData_Get_Struct(ca, CArray, &carray_data_type, cap);
|
|
2017
|
+
return ( cap->data_type == data_type ) ? ca : ca_cast_to_type1(ca, sym);
|
|
2018
|
+
}
|
|
2019
|
+
return rb_cscalar_new_with_value(data_type, 0, v);
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
2022
|
+
|
|
2023
|
+
#define DEFINE_CA_CAST(cfunc, dt) \
|
|
2024
|
+
static VALUE \
|
|
2025
|
+
cfunc (int argc, VALUE *argv, VALUE self) \
|
|
2026
|
+
{ \
|
|
2027
|
+
return ca_cast_impl((dt), argc, argv); \
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2030
|
+
DEFINE_CA_CAST(rb_ca_cast_boolean, CA_BOOLEAN)
|
|
2031
|
+
DEFINE_CA_CAST(rb_ca_cast_int8, CA_INT8)
|
|
2032
|
+
DEFINE_CA_CAST(rb_ca_cast_uint8, CA_UINT8)
|
|
2033
|
+
DEFINE_CA_CAST(rb_ca_cast_int16, CA_INT16)
|
|
2034
|
+
DEFINE_CA_CAST(rb_ca_cast_uint16, CA_UINT16)
|
|
2035
|
+
DEFINE_CA_CAST(rb_ca_cast_int32, CA_INT32)
|
|
2036
|
+
DEFINE_CA_CAST(rb_ca_cast_uint32, CA_UINT32)
|
|
2037
|
+
DEFINE_CA_CAST(rb_ca_cast_int64, CA_INT64)
|
|
2038
|
+
DEFINE_CA_CAST(rb_ca_cast_uint64, CA_UINT64)
|
|
2039
|
+
DEFINE_CA_CAST(rb_ca_cast_float32, CA_FLOAT32)
|
|
2040
|
+
DEFINE_CA_CAST(rb_ca_cast_float64, CA_FLOAT64)
|
|
2041
|
+
DEFINE_CA_CAST(rb_ca_cast_cmplx64, CA_CMPLX64)
|
|
2042
|
+
DEFINE_CA_CAST(rb_ca_cast_cmplx128, CA_CMPLX128)
|
|
2043
|
+
DEFINE_CA_CAST(rb_ca_cast_object, CA_OBJECT)
|
|
2044
|
+
DEFINE_CA_CAST(rb_ca_cast_size, CA_SIZE)
|
|
2045
|
+
|
|
2046
|
+
#undef DEFINE_CA_CAST
|
|
2047
|
+
|
|
2048
|
+
/* to_type(:fixlen, bytes: bytes_v) via in-file #to_type implementation. */
|
|
2049
|
+
static VALUE
|
|
2050
|
+
ca_cast_to_fixlen (VALUE v, VALUE fixlen_sym, VALUE bytes_v)
|
|
2051
|
+
{
|
|
2052
|
+
VALUE list[2], ropt;
|
|
2053
|
+
ropt = rb_hash_new();
|
|
2054
|
+
rb_hash_aset(ropt, ID2SYM(rb_intern("bytes")), bytes_v);
|
|
2055
|
+
list[0] = fixlen_sym;
|
|
2056
|
+
list[1] = ropt;
|
|
2057
|
+
return rb_ca_to_type_internal(2, list, v);
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
/* CA_FIXLEN(data, bytes: N) -- fully in C (no String-regex branch to keep in
|
|
2061
|
+
Ruby, unlike the numeric casts).
|
|
2062
|
+
Array -> bytes defaults to max top-level element #length; new + store
|
|
2063
|
+
CArray -> copy if already fixlen, else #to_type(:fixlen, bytes:)
|
|
2064
|
+
nil -> empty fixlen (bytes 0 when omitted, matching the old default)
|
|
2065
|
+
other -> #to_ca coerce, else CScalar.new(:fixlen, bytes:) { data } */
|
|
2066
|
+
static VALUE
|
|
2067
|
+
rb_ca_cast_fixlen (int argc, VALUE *argv, VALUE self)
|
|
2068
|
+
{
|
|
2069
|
+
VALUE v, opts = Qnil, bytes_v = Qnil;
|
|
2070
|
+
VALUE fixlen_sym = ID2SYM(ca_data_type_sym[CA_FIXLEN]);
|
|
2071
|
+
|
|
2072
|
+
rb_scan_args(argc, argv, "11", &v, &opts);
|
|
2073
|
+
rb_scan_options(opts, "bytes", &bytes_v);
|
|
2074
|
+
|
|
2075
|
+
if ( RTEST(rb_obj_is_kind_of(v, rb_cCArray)) ) {
|
|
2076
|
+
CArray *ca;
|
|
2077
|
+
TypedData_Get_Struct(v, CArray, &carray_data_type, ca);
|
|
2078
|
+
if ( ca->data_type == CA_FIXLEN ) {
|
|
2079
|
+
return rb_ca_copy(v);
|
|
2080
|
+
}
|
|
2081
|
+
return ca_cast_to_fixlen(v, fixlen_sym, bytes_v);
|
|
2082
|
+
}
|
|
2083
|
+
else if ( TYPE(v) == T_ARRAY ) {
|
|
2084
|
+
volatile VALUE shape;
|
|
2085
|
+
ca_size_t dim[CA_RANK_MAX];
|
|
2086
|
+
long ndim, i;
|
|
2087
|
+
ca_size_t bytes;
|
|
2088
|
+
VALUE obj;
|
|
2089
|
+
if ( NIL_P(bytes_v) ) {
|
|
2090
|
+
/* bytes = v.map{|s| s.length}.max (top-level #length, duck-typed) */
|
|
2091
|
+
long len = RARRAY_LEN(v);
|
|
2092
|
+
ca_size_t maxlen = 0;
|
|
2093
|
+
for ( i = 0; i < len; i++ ) {
|
|
2094
|
+
ca_size_t l = NUM2SIZE(rb_funcall(rb_ary_entry(v, i), id_length_cast, 0));
|
|
2095
|
+
if ( l > maxlen ) maxlen = l;
|
|
2096
|
+
}
|
|
2097
|
+
bytes = maxlen;
|
|
2098
|
+
} else {
|
|
2099
|
+
bytes = NUM2SIZE(bytes_v);
|
|
2100
|
+
}
|
|
2101
|
+
shape = rb_funcall(rb_cCArray, id_guess_array_shape_cast, 1, v);
|
|
2102
|
+
ndim = RARRAY_LEN(shape);
|
|
2103
|
+
for ( i = 0; i < ndim; i++ ) dim[i] = NUM2SIZE(rb_ary_entry(shape, i));
|
|
2104
|
+
obj = rb_carray_new(CA_FIXLEN, (int8_t) ndim, dim, bytes, NULL);
|
|
2105
|
+
rb_ca_store_all(obj, v);
|
|
2106
|
+
return obj;
|
|
2107
|
+
}
|
|
2108
|
+
else if ( NIL_P(v) ) {
|
|
2109
|
+
ca_size_t dim0 = 0;
|
|
2110
|
+
ca_size_t bytes = NIL_P(bytes_v) ? 0 : NUM2SIZE(bytes_v);
|
|
2111
|
+
return rb_carray_new(CA_FIXLEN, 1, &dim0, bytes, NULL);
|
|
2112
|
+
}
|
|
2113
|
+
else {
|
|
2114
|
+
if ( rb_respond_to(v, id_to_ca_cast) ) {
|
|
2115
|
+
VALUE ca = rb_funcall(v, id_to_ca_cast, 0);
|
|
2116
|
+
CArray *cap;
|
|
2117
|
+
TypedData_Get_Struct(ca, CArray, &carray_data_type, cap);
|
|
2118
|
+
return ( cap->data_type == CA_FIXLEN )
|
|
2119
|
+
? ca : ca_cast_to_fixlen(ca, fixlen_sym, bytes_v);
|
|
2120
|
+
}
|
|
2121
|
+
{
|
|
2122
|
+
ca_size_t bytes = NIL_P(bytes_v) ? 0 : NUM2SIZE(bytes_v);
|
|
2123
|
+
return rb_cscalar_new_with_value(CA_FIXLEN, bytes, v);
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
|
|
1279
2128
|
void
|
|
1280
|
-
Init_carray_cast ()
|
|
2129
|
+
Init_carray_cast (void)
|
|
1281
2130
|
{
|
|
1282
2131
|
/* CArray data_type conversion */
|
|
1283
2132
|
|
|
@@ -1295,10 +2144,8 @@ Init_carray_cast ()
|
|
|
1295
2144
|
rb_define_method(rb_cCArray, "uint64", rb_ca_to_uint64, 0);
|
|
1296
2145
|
rb_define_method(rb_cCArray, "float32", rb_ca_to_float32, 0);
|
|
1297
2146
|
rb_define_method(rb_cCArray, "float64", rb_ca_to_float64, 0);
|
|
1298
|
-
rb_define_method(rb_cCArray, "float128", rb_ca_to_float128, 0);
|
|
1299
2147
|
rb_define_method(rb_cCArray, "cmplx64", rb_ca_to_cmplx64, 0);
|
|
1300
2148
|
rb_define_method(rb_cCArray, "cmplx128", rb_ca_to_cmplx128, 0);
|
|
1301
|
-
rb_define_method(rb_cCArray, "cmplx256", rb_ca_to_cmplx256, 0);
|
|
1302
2149
|
rb_define_method(rb_cCArray, "object", rb_ca_to_VALUE, 0);
|
|
1303
2150
|
|
|
1304
2151
|
rb_define_alias(rb_cCArray, "byte", "uint8");
|
|
@@ -1345,7 +2192,71 @@ Init_carray_cast ()
|
|
|
1345
2192
|
"cast", rb_ca_s_cast, 1);
|
|
1346
2193
|
rb_define_singleton_method(rb_cCArray,
|
|
1347
2194
|
"cast_self_or_other", rb_ca_s_cast_self_or_other, 2);
|
|
2195
|
+
rb_define_singleton_method(rb_cCArray,
|
|
2196
|
+
"result_type", rb_ca_s_result_type, -1);
|
|
2197
|
+
|
|
2198
|
+
rb_define_singleton_method(rb_cCArray,
|
|
2199
|
+
"promote_list", rb_ca_s_promote_list, -1);
|
|
2200
|
+
|
|
2201
|
+
/* Global polymorphic cast functions: CA_INT32(data), CA_FLOAT64(data),
|
|
2202
|
+
... CA_OBJECT(data), CA_FIXLEN(...). Implementation is the
|
|
2203
|
+
ca_cast_impl family above; dispatch on `data`'s Ruby class.
|
|
2204
|
+
Type-name aliases (CA_BYTE / CA_SHORT / CA_INT / CA_FLOAT /
|
|
2205
|
+
CA_DOUBLE / CA_COMPLEX / CA_DCOMPLEX / CA_SIZE) reuse the same C
|
|
2206
|
+
function as their canonical data_type. Paired with the type-tag
|
|
2207
|
+
classes registered in ext/carray_data_type.c. */
|
|
2208
|
+
id_new_cast = rb_intern("new");
|
|
2209
|
+
id_guess_array_shape_cast = rb_intern("guess_array_shape");
|
|
2210
|
+
id_cast_string = rb_intern("__cast_string__");
|
|
2211
|
+
id_to_ca_cast = rb_intern("to_ca");
|
|
2212
|
+
id_length_cast = rb_intern("length");
|
|
2213
|
+
id_begin_cast = rb_intern("begin");
|
|
2214
|
+
id_end_cast = rb_intern("end");
|
|
2215
|
+
id_to_a_cast = rb_intern("to_a");
|
|
2216
|
+
id_exclude_end_p_cast = rb_intern("exclude_end?");
|
|
2217
|
+
id_abs_cast = rb_intern("abs");
|
|
2218
|
+
id_floor_cast = rb_intern("floor");
|
|
2219
|
+
id_op_minus = rb_intern("-");
|
|
2220
|
+
id_op_div = rb_intern("/");
|
|
2221
|
+
id_op_plus = rb_intern("+");
|
|
2222
|
+
id_op_le = rb_intern("<=");
|
|
2223
|
+
id_op_eq = rb_intern("==");
|
|
2224
|
+
id_op_uminus = rb_intern("-@");
|
|
2225
|
+
|
|
2226
|
+
rb_define_global_function("CA_BOOLEAN", rb_ca_cast_boolean, -1);
|
|
2227
|
+
rb_define_global_function("CA_INT8", rb_ca_cast_int8, -1);
|
|
2228
|
+
rb_define_global_function("CA_UINT8", rb_ca_cast_uint8, -1);
|
|
2229
|
+
rb_define_global_function("CA_INT16", rb_ca_cast_int16, -1);
|
|
2230
|
+
rb_define_global_function("CA_UINT16", rb_ca_cast_uint16, -1);
|
|
2231
|
+
rb_define_global_function("CA_INT32", rb_ca_cast_int32, -1);
|
|
2232
|
+
rb_define_global_function("CA_UINT32", rb_ca_cast_uint32, -1);
|
|
2233
|
+
rb_define_global_function("CA_INT64", rb_ca_cast_int64, -1);
|
|
2234
|
+
rb_define_global_function("CA_UINT64", rb_ca_cast_uint64, -1);
|
|
2235
|
+
rb_define_global_function("CA_FLOAT32", rb_ca_cast_float32, -1);
|
|
2236
|
+
rb_define_global_function("CA_FLOAT64", rb_ca_cast_float64, -1);
|
|
2237
|
+
rb_define_global_function("CA_CMPLX64", rb_ca_cast_cmplx64, -1);
|
|
2238
|
+
rb_define_global_function("CA_CMPLX128", rb_ca_cast_cmplx128, -1);
|
|
2239
|
+
rb_define_global_function("CA_OBJECT", rb_ca_cast_object, -1);
|
|
2240
|
+
/* type-name aliases */
|
|
2241
|
+
rb_define_global_function("CA_BYTE", rb_ca_cast_uint8, -1);
|
|
2242
|
+
rb_define_global_function("CA_SHORT", rb_ca_cast_int16, -1);
|
|
2243
|
+
rb_define_global_function("CA_INT", rb_ca_cast_int32, -1);
|
|
2244
|
+
rb_define_global_function("CA_FLOAT", rb_ca_cast_float32, -1);
|
|
2245
|
+
rb_define_global_function("CA_DOUBLE", rb_ca_cast_float64, -1);
|
|
2246
|
+
rb_define_global_function("CA_COMPLEX", rb_ca_cast_cmplx64, -1);
|
|
2247
|
+
rb_define_global_function("CA_DCOMPLEX", rb_ca_cast_cmplx128, -1);
|
|
2248
|
+
rb_define_global_function("CA_SIZE", rb_ca_cast_size, -1);
|
|
2249
|
+
rb_define_global_function("CA_FIXLEN", rb_ca_cast_fixlen, -1);
|
|
1348
2250
|
|
|
1349
2251
|
rb_define_method(rb_cCArray, "cast_with", rb_ca_cast_with, 1);
|
|
2252
|
+
|
|
2253
|
+
rb_define_method(rb_cCArray, "clip_int8", rb_ca_clip_int8, 0);
|
|
2254
|
+
rb_define_method(rb_cCArray, "clip_int16", rb_ca_clip_int16, 0);
|
|
2255
|
+
rb_define_method(rb_cCArray, "clip_int32", rb_ca_clip_int32, 0);
|
|
2256
|
+
rb_define_method(rb_cCArray, "clip_int64", rb_ca_clip_int64, 0);
|
|
2257
|
+
rb_define_method(rb_cCArray, "clip_uint8", rb_ca_clip_uint8, 0);
|
|
2258
|
+
rb_define_method(rb_cCArray, "clip_uint16", rb_ca_clip_uint16, 0);
|
|
2259
|
+
rb_define_method(rb_cCArray, "clip_uint32", rb_ca_clip_uint32, 0);
|
|
2260
|
+
rb_define_method(rb_cCArray, "clip_uint64", rb_ca_clip_uint64, 0);
|
|
1350
2261
|
}
|
|
1351
2262
|
|