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