carray 3.0.3 → 3.0.5
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/CHANGELOG.md +469 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_array_pool.c +25 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +14 -26
- data/ext/ca_axis_group.c +27 -27
- data/ext/ca_binop_dispatch.c +1 -29
- data/ext/ca_binop_dispatch.h +0 -1
- data/ext/ca_categorical_iterator.c +231 -153
- data/ext/ca_compare.c +9 -20
- data/ext/ca_composite_dispatch.c +9 -9
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1240 -2000
- data/ext/ca_kernel_iterator.h +502 -519
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +152 -45
- data/ext/ca_obj_bincmp.c +25 -21
- data/ext/ca_obj_binop.c +16 -26
- data/ext/ca_obj_bitarray.c +8 -3
- data/ext/ca_obj_bitfield.c +63 -49
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +7 -7
- data/ext/ca_obj_const_string.c +188 -22
- data/ext/ca_obj_face.c +280 -58
- data/ext/ca_obj_face.h +19 -0
- data/ext/ca_obj_fake.c +15 -29
- data/ext/ca_obj_farray.c +6 -3
- data/ext/ca_obj_field.c +30 -8
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +455 -134
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +113 -67
- data/ext/ca_obj_object.c +210 -52
- data/ext/ca_obj_record.c +15 -7
- data/ext/ca_obj_reduce.c +17 -8
- data/ext/ca_obj_refer.c +42 -35
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +31 -10
- data/ext/ca_obj_select.c +48 -14
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +41 -7
- data/ext/ca_obj_stack.c +180 -34
- data/ext/ca_obj_stride.c +190 -134
- data/ext/ca_obj_string.c +80 -4
- data/ext/ca_obj_tile.c +32 -11
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +13 -7
- data/ext/ca_obj_triop.c +26 -32
- data/ext/ca_obj_window.c +267 -74
- data/ext/ca_op_ipower.c +4 -4
- data/ext/ca_sort_kernels.h +6 -3
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +214 -75
- data/ext/carray_access.c +200 -99
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +113 -6
- data/ext/carray_bincount.c +10 -8
- data/ext/carray_broadcast.c +13 -8
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +108 -0
- data/ext/carray_cast.c +375 -96
- data/ext/carray_cast_func.rb +90 -20
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +18 -9
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +150 -55
- data/ext/carray_count.c +56 -20
- data/ext/carray_element.c +81 -33
- data/ext/carray_factorize.c +138 -84
- data/ext/carray_generate.c +199 -52
- data/ext/carray_histogram.c +63 -18
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +348 -29
- data/ext/carray_kernels_bincmp.c +4453 -0
- data/ext/carray_kernels_binop.c +11368 -0
- data/ext/carray_kernels_init.c +1734 -0
- data/ext/carray_kernels_moncmp.c +2104 -0
- data/ext/carray_kernels_monop.c +18369 -0
- data/ext/carray_kernels_reduce_aggregate.c +23818 -0
- data/ext/carray_kernels_reduce_boolean.c +406 -0
- data/ext/carray_kernels_reduce_cumulative.c +10086 -0
- data/ext/carray_kernels_reduce_extreme.c +17634 -0
- data/ext/carray_kernels_reduce_variance.c +3849 -0
- data/ext/carray_kernels_scan.c +4302 -0
- data/ext/carray_kernels_search.c +33829 -0
- data/ext/carray_kernels_sort.c +10897 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +220 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +337 -94
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +129 -52
- data/ext/carray_order.c +604 -77
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +85 -31
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +87 -45
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +123 -37
- data/ext/carray_sort.c +259 -51
- data/ext/carray_sort_kernel.c +5 -7
- data/ext/carray_struct.c +54 -61
- data/ext/carray_test.c +26 -5
- data/ext/carray_time_text.c +4 -2
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +309 -66
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +403 -350
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +139 -22
- data/lib/carray/autoload_carray.rb +8 -31
- data/lib/carray/autoload_method_extension.rb +14 -5
- data/lib/carray/axis_group.rb +255 -106
- data/lib/carray/basics.rb +105 -17
- data/lib/carray/bincount_nd.rb +12 -2
- data/lib/carray/block_iterator.rb +126 -23
- data/lib/carray/boolean_reduce.rb +17 -17
- data/lib/carray/categorical.rb +195 -59
- data/lib/carray/categorical_iterator.rb +132 -29
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +24 -5
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +9 -1
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +48 -3
- data/lib/carray/frame/column_verbs.rb +71 -0
- data/lib/carray/frame/concat.rb +17 -3
- data/lib/carray/frame/convert.rb +69 -0
- data/lib/carray/frame/csv_parser.rb +111 -17
- data/lib/carray/frame/describe.rb +3 -2
- data/lib/carray/frame/frame.rb +252 -28
- data/lib/carray/frame/group.rb +603 -101
- data/lib/carray/frame/io.rb +117 -28
- data/lib/carray/frame/join.rb +312 -51
- data/lib/carray/frame/records.rb +83 -7
- data/lib/carray/frame/reshape.rb +42 -35
- data/lib/carray/frame/sort.rb +7 -19
- data/lib/carray/frame/verbs.rb +188 -48
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +42 -6
- data/lib/carray/fusion.rb +40 -16
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +31 -8
- data/lib/carray/iterator.rb +85 -7
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +217 -183
- data/lib/carray/mask_gap_fill.rb +63 -57
- data/lib/carray/meld_reduce.rb +12 -14
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +16 -0
- data/lib/carray/methods/bit_string.rb +1 -1
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +3 -1
- data/lib/carray/methods/gather_nd.rb +14 -5
- data/lib/carray/methods/insert_block.rb +2 -2
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +61 -37
- data/lib/carray/methods/join.rb +1 -6
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +47 -51
- data/lib/carray/methods/mode.rb +1 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/resize.rb +3 -3
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +3 -3
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +53 -8
- data/lib/carray/segment_iterator.rb +323 -88
- data/lib/carray/serialize.rb +45 -14
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/stack.rb +15 -12
- data/lib/carray/string.rb +113 -5
- data/lib/carray/string_operation_extension.rb +21 -6
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +24 -11
- data/lib/carray/time.rb +819 -158
- data/lib/carray/window_iterator.rb +122 -16
- data/lib/carray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +4 -0
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +2 -1
- data/yard-stubs/ca_obj_roll.rb +2 -2
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_transpose.rb +5 -4
- data/yard-stubs/ca_obj_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +3 -6
- data/yard-stubs/carray_cast.rb +12 -0
- data/yard-stubs/carray_conversion.rb +7 -2
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +17 -10
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +32 -3
- data/yard-stubs/carray_math.rb +41 -5
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +129 -22
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +17 -10
- data/yard-stubs/carray_slab.rb +9 -2
- data/yard-stubs/carray_sort.rb +6 -5
- data/yard-stubs/carray_test.rb +5 -3
- metadata +25 -3
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/ext/carray_cast.c
CHANGED
|
@@ -496,6 +496,7 @@ ca_decimal_object_integer (VALUE v, int *negative, uint64_t *magnitude)
|
|
|
496
496
|
/* truncate raises for a NaN or infinite BigDecimal, which reads as
|
|
497
497
|
nothing an integer can hold. */
|
|
498
498
|
int state = 0;
|
|
499
|
+
/* protect: a BigDecimal that is not finite reads as no integer; nothing is held */
|
|
499
500
|
VALUE whole = rb_protect(ca_decimal_truncate, v, &state);
|
|
500
501
|
if ( state ) {
|
|
501
502
|
rb_set_errinfo(Qnil);
|
|
@@ -589,11 +590,11 @@ ca_decimal_string_store (VALUE str, int8_t data_type, void *out)
|
|
|
589
590
|
case CA_DECIMAL_OK:
|
|
590
591
|
return;
|
|
591
592
|
case CA_DECIMAL_OUT_OF_RANGE:
|
|
592
|
-
rb_raise(rb_eRangeError, "%+"PRIsVALUE" is out of range for %s",
|
|
593
|
-
str, ca_type_name[data_type]);
|
|
593
|
+
rb_raise(rb_eRangeError, "%s: %+"PRIsVALUE" is out of range for %s",
|
|
594
|
+
ca_calling_method_name(), str, ca_type_name[data_type]);
|
|
594
595
|
default:
|
|
595
|
-
rb_raise(rb_eArgError, "%+"PRIsVALUE" cannot be read as %s",
|
|
596
|
-
str, ca_type_name[data_type]);
|
|
596
|
+
rb_raise(rb_eArgError, "%s: %+"PRIsVALUE" cannot be read as %s",
|
|
597
|
+
ca_calling_method_name(), str, ca_type_name[data_type]);
|
|
597
598
|
}
|
|
598
599
|
}
|
|
599
600
|
|
|
@@ -767,6 +768,7 @@ ca_obj2dbl_ok (VALUE val, double *out)
|
|
|
767
768
|
}
|
|
768
769
|
{
|
|
769
770
|
int state = 0;
|
|
771
|
+
/* protect: converts the caller's value and reports failure; nothing is held */
|
|
770
772
|
volatile VALUE r = rb_protect(ca_kernel_float, val, &state);
|
|
771
773
|
if ( state ) {
|
|
772
774
|
rb_set_errinfo(Qnil);
|
|
@@ -795,6 +797,7 @@ ca_obj2cmplx_ok (VALUE val, double complex *out)
|
|
|
795
797
|
if ( NIL_P(val) ) {
|
|
796
798
|
return 0;
|
|
797
799
|
}
|
|
800
|
+
/* protect: converts the caller's value and reports failure; nothing is held */
|
|
798
801
|
r = rb_protect(ca_cmplx_cell_body, val, &state);
|
|
799
802
|
if ( state ) {
|
|
800
803
|
rb_set_errinfo(Qnil);
|
|
@@ -819,6 +822,7 @@ ca_obj2integer_ok (VALUE val, int8_t wide_type, void *wide, VALUE *integer)
|
|
|
819
822
|
if ( RB_TYPE_P(val, T_STRING) ) {
|
|
820
823
|
return ca_decimal_string_to(val, wide_type, wide);
|
|
821
824
|
}
|
|
825
|
+
/* protect: converts the caller's value and reports failure; nothing is held */
|
|
822
826
|
*integer = rb_protect(ca_kernel_integer, val, &state);
|
|
823
827
|
if ( state ) {
|
|
824
828
|
rb_set_errinfo(Qnil);
|
|
@@ -1052,7 +1056,7 @@ ca_ptr2val (void *ap1, void *ptr1, int8_t data_type, void *ptr2)
|
|
|
1052
1056
|
{
|
|
1053
1057
|
CArray *ca1 = (CArray *)ap1;
|
|
1054
1058
|
static CArray dummy;
|
|
1055
|
-
|
|
1059
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type);
|
|
1056
1060
|
dummy.data_type = data_type;
|
|
1057
1061
|
ca_cast_func_table[ca1->data_type][data_type](1, ca1, ptr1, &dummy, ptr2, NULL);
|
|
1058
1062
|
return;
|
|
@@ -1063,7 +1067,7 @@ ca_val2ptr (int8_t data_type, void *ptr1, void *ap2, void *ptr2)
|
|
|
1063
1067
|
{
|
|
1064
1068
|
CArray *ca2 = (CArray *)ap2;
|
|
1065
1069
|
static CArray dummy;
|
|
1066
|
-
|
|
1070
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type);
|
|
1067
1071
|
dummy.data_type = data_type;
|
|
1068
1072
|
ca_cast_func_table[data_type][ca2->data_type](1, &dummy, ptr1, ca2, ptr2, NULL);
|
|
1069
1073
|
return;
|
|
@@ -1073,8 +1077,8 @@ void
|
|
|
1073
1077
|
ca_val2val (int8_t data_type1, void *ptr1, int8_t data_type2, void *ptr2)
|
|
1074
1078
|
{
|
|
1075
1079
|
static CArray dummy1, dummy2;
|
|
1076
|
-
|
|
1077
|
-
|
|
1080
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type1);
|
|
1081
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type2);
|
|
1078
1082
|
dummy1.data_type = data_type1;
|
|
1079
1083
|
dummy2.data_type = data_type2;
|
|
1080
1084
|
ca_cast_func_table[data_type1][data_type2](1, &dummy1, ptr1, &dummy2, ptr2, NULL);
|
|
@@ -1211,26 +1215,48 @@ typedef struct {
|
|
|
1211
1215
|
boolean8_t *scratch;
|
|
1212
1216
|
} ca_to_type_ctx_t;
|
|
1213
1217
|
|
|
1214
|
-
/*
|
|
1215
|
-
|
|
1216
|
-
|
|
1218
|
+
/* Whether a double truncates into integer type `dt`: not NaN, not an
|
|
1219
|
+
infinity, and inside the open interval of values whose integer part `dt`
|
|
1220
|
+
holds (closed below for int64: -2**63-1 rounds to -2**63 in double).
|
|
1221
|
+
The same bounds as the generated casts in carray_cast_func.rb. */
|
|
1222
|
+
static int
|
|
1223
|
+
ca_double_fits_integer (double v, int8_t dt)
|
|
1224
|
+
{
|
|
1225
|
+
switch ( dt ) {
|
|
1226
|
+
case CA_INT8: return v > -129.0 && v < 128.0;
|
|
1227
|
+
case CA_UINT8: return v > -1.0 && v < 256.0;
|
|
1228
|
+
case CA_INT16: return v > -32769.0 && v < 32768.0;
|
|
1229
|
+
case CA_UINT16: return v > -1.0 && v < 65536.0;
|
|
1230
|
+
case CA_INT32: return v > -2147483649.0 && v < 2147483648.0;
|
|
1231
|
+
case CA_UINT32: return v > -1.0 && v < 4294967296.0;
|
|
1232
|
+
case CA_INT64: return v >= -9223372036854775808.0 && v < 9223372036854775808.0;
|
|
1233
|
+
case CA_UINT64: return v > -1.0 && v < 18446744073709551616.0;
|
|
1234
|
+
default: return 1;
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
/* Marks in `m` the cells of a float or complex array that have no integer
|
|
1239
|
+
of type `dt`: NaN (in either part), an infinity, or a value out of
|
|
1240
|
+
range. C leaves their conversion undefined, and machines differ. */
|
|
1217
1241
|
static void
|
|
1218
|
-
|
|
1242
|
+
ca_mark_unconvertible (CArray *ca, boolean8_t *m, int8_t dt)
|
|
1219
1243
|
{
|
|
1220
1244
|
ca_size_t i, n = ca->elements;
|
|
1221
1245
|
switch ( ca->data_type ) {
|
|
1222
|
-
case CA_FLOAT32: {
|
|
1223
|
-
for (i=0; i<n; i++) if (
|
|
1246
|
+
case CA_FLOAT32: { ca_u_float32_t *p = (ca_u_float32_t *) ca->ptr;
|
|
1247
|
+
for (i=0; i<n; i++) if ( ! ca_double_fits_integer(p[i], dt) ) m[i] = 1;
|
|
1224
1248
|
break; }
|
|
1225
|
-
case CA_FLOAT64: {
|
|
1226
|
-
for (i=0; i<n; i++) if (
|
|
1249
|
+
case CA_FLOAT64: { ca_u_float64_t *p = (ca_u_float64_t *) ca->ptr;
|
|
1250
|
+
for (i=0; i<n; i++) if ( ! ca_double_fits_integer(p[i], dt) ) m[i] = 1;
|
|
1227
1251
|
break; }
|
|
1228
1252
|
#ifdef HAVE_COMPLEX_H
|
|
1229
|
-
case CA_CMPLX64: {
|
|
1230
|
-
for (i=0; i<n; i++)
|
|
1253
|
+
case CA_CMPLX64: { ca_u_cmplx64_t *p = (ca_u_cmplx64_t *) ca->ptr;
|
|
1254
|
+
for (i=0; i<n; i++)
|
|
1255
|
+
if ( ! ca_double_fits_integer(crealf(p[i]), dt) || isnan(cimagf(p[i])) ) m[i] = 1;
|
|
1231
1256
|
break; }
|
|
1232
|
-
case CA_CMPLX128: {
|
|
1233
|
-
for (i=0; i<n; i++)
|
|
1257
|
+
case CA_CMPLX128: { ca_u_cmplx128_t *p = (ca_u_cmplx128_t *) ca->ptr;
|
|
1258
|
+
for (i=0; i<n; i++)
|
|
1259
|
+
if ( ! ca_double_fits_integer(creal(p[i]), dt) || isnan(cimag(p[i])) ) m[i] = 1;
|
|
1234
1260
|
break; }
|
|
1235
1261
|
#endif
|
|
1236
1262
|
default:
|
|
@@ -1270,11 +1296,11 @@ ca_to_type_cast (VALUE arg)
|
|
|
1270
1296
|
else {
|
|
1271
1297
|
memset(scratch, 0, ne);
|
|
1272
1298
|
}
|
|
1273
|
-
/* float -> integer: a
|
|
1274
|
-
|
|
1275
|
-
|
|
1299
|
+
/* float -> integer: a cell with no integer of the type (NaN, an
|
|
1300
|
+
infinity, a value out of range) becomes UNDEF, as an unparseable
|
|
1301
|
+
object cell does. */
|
|
1276
1302
|
if ( from_float ) {
|
|
1277
|
-
|
|
1303
|
+
ca_mark_unconvertible(ca, scratch, cb->data_type);
|
|
1278
1304
|
memset(cb->ptr, 0, ne * cb->bytes);
|
|
1279
1305
|
}
|
|
1280
1306
|
ca_cast_block_with_mask(ne, ca, ca->ptr, cb, cb->ptr, scratch);
|
|
@@ -1767,8 +1793,11 @@ rb_ca_ptr2ptr (VALUE ra1, void *ptr1, VALUE ra2, void *ptr2)
|
|
|
1767
1793
|
}
|
|
1768
1794
|
|
|
1769
1795
|
|
|
1796
|
+
/* A cell's bytes as the value of self's data type before the last two
|
|
1797
|
+
steps of ca[i]: a boolean is 0 or 1 and a Face cell is its storage
|
|
1798
|
+
value. The element readers call this, check the mask, then decode. */
|
|
1770
1799
|
VALUE
|
|
1771
|
-
|
|
1800
|
+
rb_ca_ptr2obj_storage (VALUE self, void *ptr)
|
|
1772
1801
|
{
|
|
1773
1802
|
volatile VALUE obj;
|
|
1774
1803
|
static CArray dummy;
|
|
@@ -1784,6 +1813,20 @@ rb_ca_ptr2obj (VALUE self, void *ptr)
|
|
|
1784
1813
|
}
|
|
1785
1814
|
}
|
|
1786
1815
|
|
|
1816
|
+
VALUE
|
|
1817
|
+
rb_ca_ptr2obj (VALUE self, void *ptr)
|
|
1818
|
+
{
|
|
1819
|
+
CArray *ca;
|
|
1820
|
+
VALUE obj = rb_ca_ptr2obj_storage(self, ptr);
|
|
1821
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1822
|
+
CA_FACE_STORAGE_TO_ELEMENT_IF_FACE(obj, self, ca);
|
|
1823
|
+
if ( ca->data_type == CA_BOOLEAN &&
|
|
1824
|
+
( obj == INT2FIX(0) || obj == INT2FIX(1) ) ) {
|
|
1825
|
+
obj = ( obj == INT2FIX(1) ) ? Qtrue : Qfalse;
|
|
1826
|
+
}
|
|
1827
|
+
return obj;
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1787
1830
|
/* Surface -> storage-domain conversion for a Face store (mirror of the
|
|
1788
1831
|
storage_to_element read hook). Non-Face `ca` returns `obj` unchanged, so
|
|
1789
1832
|
the non-Face store path is untouched. For a Face, the per-obj_type C
|
|
@@ -1853,7 +1896,7 @@ rb_ca_wrap_writable (VALUE arg, VALUE rtype)
|
|
|
1853
1896
|
if ( rb_obj_is_carray(obj) ) { /* obj == carray */
|
|
1854
1897
|
TypedData_Get_Struct(obj, CArray, &carray_data_type, ca);
|
|
1855
1898
|
if ( ca_is_readonly(ca) ) {
|
|
1856
|
-
|
|
1899
|
+
ca_refuse_read_only();
|
|
1857
1900
|
}
|
|
1858
1901
|
if ( NIL_P(rtype) ) {
|
|
1859
1902
|
data_type = ca->data_type;
|
|
@@ -1891,7 +1934,7 @@ rb_ca_wrap_writable (VALUE arg, VALUE rtype)
|
|
|
1891
1934
|
}
|
|
1892
1935
|
TypedData_Get_Struct(obj, CArray, &carray_data_type, ca);
|
|
1893
1936
|
if ( ca_is_readonly(ca) ) {
|
|
1894
|
-
|
|
1937
|
+
ca_refuse_read_only();
|
|
1895
1938
|
}
|
|
1896
1939
|
if ( NIL_P(rtype) ) {
|
|
1897
1940
|
data_type = ca->data_type;
|
|
@@ -1905,12 +1948,9 @@ rb_ca_wrap_writable (VALUE arg, VALUE rtype)
|
|
|
1905
1948
|
}
|
|
1906
1949
|
}
|
|
1907
1950
|
else if ( rb_memory_view_available_p(obj) ) { /* MemoryView producer */
|
|
1908
|
-
obj =
|
|
1951
|
+
obj = ca_mv_wrap(obj, Qnil, rb_cCAWrap, -1,
|
|
1952
|
+
NIL_P(rtype) ? -1 : rb_ca_guess_type(rtype), 1);
|
|
1909
1953
|
TypedData_Get_Struct(obj, CArray, &carray_data_type, ca);
|
|
1910
|
-
if ( ca_is_readonly(ca) ) {
|
|
1911
|
-
rb_raise(rb_eRuntimeError,
|
|
1912
|
-
"MemoryView source is read-only; can't wrap as writable");
|
|
1913
|
-
}
|
|
1914
1954
|
if ( NIL_P(rtype) ) {
|
|
1915
1955
|
data_type = ca->data_type;
|
|
1916
1956
|
}
|
|
@@ -1999,7 +2039,9 @@ rb_ca_wrap_readonly (VALUE arg, VALUE rtype)
|
|
|
1999
2039
|
else {
|
|
2000
2040
|
CArray *ca_tmp;
|
|
2001
2041
|
volatile VALUE ref = obj;
|
|
2002
|
-
ca_size_t
|
|
2042
|
+
ca_size_t bytes = ca_sizeof[data_type];
|
|
2043
|
+
CA_CHECK_BYTES_GIVEN(data_type, bytes);
|
|
2044
|
+
ca_size_t dim = RSTRING_LEN(ref)/bytes;
|
|
2003
2045
|
obj = rb_carray_new(data_type, 1, &dim, 0, NULL);
|
|
2004
2046
|
TypedData_Get_Struct(obj, CArray, &carray_data_type, ca_tmp);
|
|
2005
2047
|
memcpy(ca_tmp->ptr, RSTRING_PTR(ref), dim * ca_sizeof[data_type]);
|
|
@@ -2029,7 +2071,8 @@ rb_ca_wrap_readonly (VALUE arg, VALUE rtype)
|
|
|
2029
2071
|
}
|
|
2030
2072
|
}
|
|
2031
2073
|
else if ( rb_memory_view_available_p(obj) ) { /* MemoryView producer */
|
|
2032
|
-
obj =
|
|
2074
|
+
obj = ca_mv_wrap(obj, Qnil, rb_cCAWrap, -1,
|
|
2075
|
+
NIL_P(rtype) ? -1 : rb_ca_guess_type(rtype), 0);
|
|
2033
2076
|
TypedData_Get_Struct(obj, CArray, &carray_data_type, ca);
|
|
2034
2077
|
if ( NIL_P(rtype) ) {
|
|
2035
2078
|
data_type = ca->data_type;
|
|
@@ -2131,7 +2174,15 @@ ca_fixlen_scalar_operand (volatile VALUE *scalar, VALUE reference)
|
|
|
2131
2174
|
if ( cr->data_type != CA_FIXLEN ) {
|
|
2132
2175
|
return 0;
|
|
2133
2176
|
}
|
|
2134
|
-
|
|
2177
|
+
/* A String longer than the cell keeps its length: cut to the cell, it
|
|
2178
|
+
would equal a cell it does not (a two-byte "ab" equal to "abX"). The
|
|
2179
|
+
wider scalar is then compared as two fixlen widths are. */
|
|
2180
|
+
{
|
|
2181
|
+
ca_size_t len = (ca_size_t) RSTRING_LEN(*scalar);
|
|
2182
|
+
*scalar = rb_cscalar_new_with_value(CA_FIXLEN,
|
|
2183
|
+
len > cr->bytes ? len : cr->bytes,
|
|
2184
|
+
*scalar);
|
|
2185
|
+
}
|
|
2135
2186
|
return 1;
|
|
2136
2187
|
}
|
|
2137
2188
|
|
|
@@ -2171,6 +2222,36 @@ ca_check_integer_fits (VALUE v, int8_t dt)
|
|
|
2171
2222
|
}
|
|
2172
2223
|
}
|
|
2173
2224
|
|
|
2225
|
+
/* The store reader for an integer cell: the value as an Integer, refused
|
|
2226
|
+
when it does not fit the cell's type, as an operator refuses it. A
|
|
2227
|
+
store raises where an array cast (to_type) keeps the C conversion. A
|
|
2228
|
+
non-Integer goes through Integer() (1.5 is 1; nil and NaN raise). */
|
|
2229
|
+
VALUE
|
|
2230
|
+
ca_obj2integer_fitting (VALUE v, int8_t data_type)
|
|
2231
|
+
{
|
|
2232
|
+
VALUE integer = RB_INTEGER_TYPE_P(v) ? v : rb_Integer(v);
|
|
2233
|
+
if ( FIXNUM_P(integer) ) {
|
|
2234
|
+
long x = FIX2LONG(integer);
|
|
2235
|
+
int fits;
|
|
2236
|
+
switch ( data_type ) {
|
|
2237
|
+
case CA_INT8: fits = ( x >= INT8_MIN && x <= INT8_MAX ); break;
|
|
2238
|
+
case CA_UINT8: fits = ( x >= 0 && x <= UINT8_MAX ); break;
|
|
2239
|
+
case CA_INT16: fits = ( x >= INT16_MIN && x <= INT16_MAX ); break;
|
|
2240
|
+
case CA_UINT16: fits = ( x >= 0 && x <= UINT16_MAX ); break;
|
|
2241
|
+
case CA_INT32: fits = ( x >= INT32_MIN && x <= INT32_MAX ); break;
|
|
2242
|
+
case CA_UINT32: fits = ( x >= 0 && (unsigned long) x <= UINT32_MAX ); break;
|
|
2243
|
+
case CA_INT64: fits = 1; break;
|
|
2244
|
+
case CA_UINT64: fits = ( x >= 0 ); break;
|
|
2245
|
+
default: fits = 1; break;
|
|
2246
|
+
}
|
|
2247
|
+
if ( fits ) {
|
|
2248
|
+
return integer;
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2251
|
+
ca_check_integer_fits(integer, data_type);
|
|
2252
|
+
return integer;
|
|
2253
|
+
}
|
|
2254
|
+
|
|
2174
2255
|
/* A Ruby Integer operand against an integer array is taken in the array's
|
|
2175
2256
|
own data type, refused when it does not fit (ca_check_integer_fits).
|
|
2176
2257
|
Widening instead would make the result's type depend on a scalar's
|
|
@@ -2191,6 +2272,69 @@ ca_integer_scalar_operand (volatile VALUE *scalar, VALUE reference)
|
|
|
2191
2272
|
return 1;
|
|
2192
2273
|
}
|
|
2193
2274
|
|
|
2275
|
+
/* A Ruby Array operand against a numeric or boolean array is read as its
|
|
2276
|
+
cells, as the array CArray.wrap_readonly makes of it (nested Arrays give
|
|
2277
|
+
its axes). Its data type is the
|
|
2278
|
+
one the cells would take one at a time as scalar operands of the same
|
|
2279
|
+
operation (an Integer
|
|
2280
|
+
against an integer array takes the array's type and has to fit it),
|
|
2281
|
+
promoted together. Against an object array, a Face or a fixlen array an
|
|
2282
|
+
Array stays one value. */
|
|
2283
|
+
static int
|
|
2284
|
+
ca_array_operand (volatile VALUE *ary, VALUE reference, int both)
|
|
2285
|
+
{
|
|
2286
|
+
CArray *cr;
|
|
2287
|
+
volatile VALUE flat, probe_self, probe;
|
|
2288
|
+
long i, n;
|
|
2289
|
+
int8_t type = -1, seen_fix = -1, seen_big = -1, seen_flo = -1, seen_cpx = -1,
|
|
2290
|
+
seen_bool = -1;
|
|
2291
|
+
|
|
2292
|
+
if ( ! RB_TYPE_P(*ary, T_ARRAY) || ! rb_obj_is_carray(reference) ) {
|
|
2293
|
+
return 0;
|
|
2294
|
+
}
|
|
2295
|
+
TypedData_Get_Struct(reference, CArray, &carray_data_type, cr);
|
|
2296
|
+
if ( ca_is_face(cr) || ca_is_object_type(cr) || ca_is_fixlen_type(cr) ) {
|
|
2297
|
+
return 0;
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2300
|
+
flat = rb_funcall(*ary, rb_intern("flatten"), 0);
|
|
2301
|
+
n = RARRAY_LEN(flat);
|
|
2302
|
+
for (i = 0; i < n; i++) {
|
|
2303
|
+
VALUE e = RARRAY_AREF(flat, i);
|
|
2304
|
+
int8_t *seen, t;
|
|
2305
|
+
CArray *cp;
|
|
2306
|
+
if ( FIXNUM_P(e) ) seen = &seen_fix;
|
|
2307
|
+
else if ( RB_TYPE_P(e, T_BIGNUM) ) seen = &seen_big;
|
|
2308
|
+
else if ( RB_FLOAT_TYPE_P(e) ) seen = &seen_flo;
|
|
2309
|
+
else if ( RB_TYPE_P(e, T_COMPLEX) ) seen = &seen_cpx;
|
|
2310
|
+
else if ( e == Qtrue || e == Qfalse ) seen = &seen_bool;
|
|
2311
|
+
else seen = NULL;
|
|
2312
|
+
if ( RB_INTEGER_TYPE_P(e) && ca_is_integer_type(cr) ) {
|
|
2313
|
+
ca_check_integer_fits(e, cr->data_type);
|
|
2314
|
+
}
|
|
2315
|
+
if ( seen && *seen >= 0 ) {
|
|
2316
|
+
continue;
|
|
2317
|
+
}
|
|
2318
|
+
probe_self = reference;
|
|
2319
|
+
probe = e;
|
|
2320
|
+
if ( both ) {
|
|
2321
|
+
rb_ca_cast_self_or_other(&probe_self, &probe);
|
|
2322
|
+
}
|
|
2323
|
+
else {
|
|
2324
|
+
rb_ca_cast_other((VALUE *) &probe_self, (volatile VALUE *) &probe);
|
|
2325
|
+
}
|
|
2326
|
+
TypedData_Get_Struct(probe, CArray, &carray_data_type, cp);
|
|
2327
|
+
t = cp->data_type;
|
|
2328
|
+
if ( seen ) *seen = t;
|
|
2329
|
+
type = ( type < 0 ) ? t : ca_promote_type(type, t);
|
|
2330
|
+
}
|
|
2331
|
+
if ( type < 0 ) {
|
|
2332
|
+
type = cr->data_type;
|
|
2333
|
+
}
|
|
2334
|
+
*ary = rb_ca_wrap_readonly(*ary, INT2NUM(type));
|
|
2335
|
+
return 1;
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2194
2338
|
/* CArray.cast(value) -- singleton entry delegating to rb_ca_cast, which
|
|
2195
2339
|
returns a CArray unchanged and coerces a Ruby value to a CScalar / CArray.
|
|
2196
2340
|
User doc lives in yard-stubs/carray_cast.rb. */
|
|
@@ -2255,6 +2399,10 @@ rb_ca_cast_self_or_other (volatile VALUE *self, volatile VALUE *other)
|
|
|
2255
2399
|
*other = ca_operand_from_memory_view(*other);
|
|
2256
2400
|
}
|
|
2257
2401
|
|
|
2402
|
+
if ( ! ca_array_operand(other, *self, 1) ) {
|
|
2403
|
+
ca_array_operand(self, *other, 1);
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2258
2406
|
if ( ! rb_obj_is_carray(*self) ) {
|
|
2259
2407
|
self_is_object = 1;
|
|
2260
2408
|
if ( rb_ca_is_object_type(*other) ) {
|
|
@@ -2378,12 +2526,32 @@ rb_ca_cast_self_or_other (volatile VALUE *self, volatile VALUE *other)
|
|
|
2378
2526
|
return;
|
|
2379
2527
|
}
|
|
2380
2528
|
|
|
2381
|
-
|
|
2529
|
+
/* A data type the operation does not take, as `sqrt!` on an integer
|
|
2530
|
+
array is refused (CArray::DataTypeError is a TypeError). */
|
|
2531
|
+
rb_raise(rb_eCADataTypeError,
|
|
2382
2532
|
"can't coerce carray with data_types of '%s' and '%s'",
|
|
2383
2533
|
ca_coerce_operand_name(*self, ca),
|
|
2384
2534
|
ca_coerce_operand_name(*other, cb));
|
|
2385
2535
|
}
|
|
2386
2536
|
|
|
2537
|
+
/* Refuses a pair of arrays with no common data_type in the words of
|
|
2538
|
+
rb_ca_cast_self_or_other (the eager operators'), and returns otherwise
|
|
2539
|
+
without casting either. A lazy builder calls it before it works out
|
|
2540
|
+
the kernel's data_types, so that a pair the eager operator refuses is
|
|
2541
|
+
refused the same way. */
|
|
2542
|
+
void
|
|
2543
|
+
ca_refuse_without_common_type (VALUE self, VALUE other)
|
|
2544
|
+
{
|
|
2545
|
+
CArray *ca, *cb;
|
|
2546
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
2547
|
+
TypedData_Get_Struct(other, CArray, &carray_data_type, cb);
|
|
2548
|
+
if ( ca->data_type != cb->data_type
|
|
2549
|
+
&& ca_cast_table[cb->data_type][ca->data_type] < 0
|
|
2550
|
+
&& ca_cast_table[ca->data_type][cb->data_type] < 0 ) {
|
|
2551
|
+
rb_ca_cast_self_or_other(&self, &other); /* raises */
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2554
|
+
|
|
2387
2555
|
/* CArray.cast_self_or_other(self, other) — promote self and other
|
|
2388
2556
|
* to a common data_type and return [self', other']. Wraps the
|
|
2389
2557
|
* void rb_ca_cast_self_or_other above into a class method.
|
|
@@ -2422,10 +2590,19 @@ ca_arg_to_data_type (VALUE obj)
|
|
|
2422
2590
|
/* MemoryView producer -> its format's data_type (T_STRING excluded above,
|
|
2423
2591
|
so a String never reaches here). data_type already assigned. */
|
|
2424
2592
|
}
|
|
2593
|
+
else if ( rb_memory_view_available_p(obj) ) {
|
|
2594
|
+
/* A MemoryView producer whose format says nothing usable (typeless, the
|
|
2595
|
+
other byte order) is read as the operators read it, and refused in
|
|
2596
|
+
the same words. */
|
|
2597
|
+
VALUE ca_obj = ca_operand_from_memory_view(obj);
|
|
2598
|
+
CArray *ca;
|
|
2599
|
+
TypedData_Get_Struct(ca_obj, CArray, &carray_data_type, ca);
|
|
2600
|
+
data_type = ca->data_type;
|
|
2601
|
+
}
|
|
2425
2602
|
else {
|
|
2426
2603
|
data_type = ca_value_to_data_type(obj);
|
|
2427
2604
|
}
|
|
2428
|
-
|
|
2605
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type);
|
|
2429
2606
|
if ( ! ca_valid[data_type] ) {
|
|
2430
2607
|
rb_raise(rb_eArgError,
|
|
2431
2608
|
"data type '%s' is not valid in this build",
|
|
@@ -2465,6 +2642,9 @@ int8_t
|
|
|
2465
2642
|
ca_promote_type (int8_t a, int8_t b)
|
|
2466
2643
|
{
|
|
2467
2644
|
int test;
|
|
2645
|
+
if ( a <= CA_NONE || a >= CA_NTYPE || b <= CA_NONE || b >= CA_NTYPE ) {
|
|
2646
|
+
rb_raise(rb_eArgError, "invalid data_type id (%i, %i)", (int) a, (int) b);
|
|
2647
|
+
}
|
|
2468
2648
|
if ( a == b ) {
|
|
2469
2649
|
return a;
|
|
2470
2650
|
}
|
|
@@ -2521,6 +2701,67 @@ ca_value_match_type (int8_t t, int8_t a, int8_t b)
|
|
|
2521
2701
|
}
|
|
2522
2702
|
}
|
|
2523
2703
|
|
|
2704
|
+
/* The type a value query and a reference of type `ref` are compared in,
|
|
2705
|
+
by equality or order, as `eq` compares them: the reference is read
|
|
2706
|
+
through a view of that type, so the query is never cut to the
|
|
2707
|
+
reference's type (3.9 does not match 3, -1 does not read as 255).
|
|
2708
|
+
A Float query takes the type the operators give it beside the
|
|
2709
|
+
reference; an Integer query keeps the reference's type when it fits and
|
|
2710
|
+
otherwise the type its value needs, where it matches nothing; a CArray
|
|
2711
|
+
query takes the type the two arrays match in (the common type, widened
|
|
2712
|
+
by ca_value_match_type). Beside a reference that is not a number, a
|
|
2713
|
+
scalar query keeps the reference's type. */
|
|
2714
|
+
int8_t
|
|
2715
|
+
ca_query_match_type (int8_t ref, VALUE query)
|
|
2716
|
+
{
|
|
2717
|
+
int ref_int = ( ref >= CA_INT8 && ref <= CA_UINT64 );
|
|
2718
|
+
int ref_float = ( ref == CA_FLOAT32 || ref == CA_FLOAT64 );
|
|
2719
|
+
if ( rb_obj_is_carray(query) ) {
|
|
2720
|
+
CArray *q;
|
|
2721
|
+
TypedData_Get_Struct(query, CArray, &carray_data_type, q);
|
|
2722
|
+
return ca_value_match_type(ca_promote_type(ref, q->data_type), ref,
|
|
2723
|
+
q->data_type);
|
|
2724
|
+
}
|
|
2725
|
+
if ( ! ref_int && ! ref_float && ref != CA_BOOLEAN ) {
|
|
2726
|
+
return ref;
|
|
2727
|
+
}
|
|
2728
|
+
if ( RB_FLOAT_TYPE_P(query) ) {
|
|
2729
|
+
return ca_promote_scalar_type(ref, query, CA_FLOAT64);
|
|
2730
|
+
}
|
|
2731
|
+
if ( RB_INTEGER_TYPE_P(query) ) {
|
|
2732
|
+
return ref_int ? ca_promote_scalar_type(ref, query, CA_INT64) : ref;
|
|
2733
|
+
}
|
|
2734
|
+
return ref;
|
|
2735
|
+
}
|
|
2736
|
+
|
|
2737
|
+
/* A fixlen array searched or counted for a String longer than its cells
|
|
2738
|
+
is read as cells of the String's width (NUL-padded), so the query is not
|
|
2739
|
+
cut to the cell: "abX" matches no two-byte cell, as a wider scalar does
|
|
2740
|
+
not in `eq`. Anything else is returned as given. */
|
|
2741
|
+
VALUE
|
|
2742
|
+
ca_fixlen_widen_for_query (VALUE self, VALUE query)
|
|
2743
|
+
{
|
|
2744
|
+
CArray *ca;
|
|
2745
|
+
if ( ! RB_TYPE_P(query, T_STRING) || ! rb_obj_is_carray(self) ) {
|
|
2746
|
+
return self;
|
|
2747
|
+
}
|
|
2748
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
2749
|
+
if ( ca->data_type != CA_FIXLEN || RSTRING_LEN(query) <= ca->bytes ) {
|
|
2750
|
+
return self;
|
|
2751
|
+
}
|
|
2752
|
+
return rb_ca_to_type(self, INT2NUM(CA_FIXLEN), SIZE2NUM(RSTRING_LEN(query)));
|
|
2753
|
+
}
|
|
2754
|
+
|
|
2755
|
+
/* ca.query_match_type(query) -- ca_query_match_type with self as the
|
|
2756
|
+
reference, for the set family and locate_addr. */
|
|
2757
|
+
static VALUE
|
|
2758
|
+
rb_ca_query_match_type (VALUE self, VALUE query)
|
|
2759
|
+
{
|
|
2760
|
+
CArray *ca;
|
|
2761
|
+
GetCArray(self, ca);
|
|
2762
|
+
return rb_ca_data_type_to_sym(ca_query_match_type(ca->data_type, query));
|
|
2763
|
+
}
|
|
2764
|
+
|
|
2524
2765
|
/* ca.value_match_type(t, other_type) -- ca_value_match_type with self's
|
|
2525
2766
|
data type as the first operand, for the set family and locate_addr. */
|
|
2526
2767
|
static VALUE
|
|
@@ -2546,20 +2787,30 @@ ca_arg_is_scalar (VALUE obj)
|
|
|
2546
2787
|
if ( TYPE(obj) == T_SYMBOL || TYPE(obj) == T_STRING || TYPE(obj) == T_CLASS ) {
|
|
2547
2788
|
return 0;
|
|
2548
2789
|
}
|
|
2549
|
-
return
|
|
2790
|
+
return ! rb_memory_view_available_p(obj);
|
|
2550
2791
|
}
|
|
2551
2792
|
|
|
2552
2793
|
/* The type a scalar `obj` (of type `st`) and an array of type `at` share,
|
|
2553
2794
|
by the rule the operators apply: a scalar of the same kind takes the
|
|
2554
2795
|
array's type (0.1 beside float32 is float32, 1 beside int8 is int8); one
|
|
2555
2796
|
of another kind promotes (1.5 beside int32 is float64). An Integer that
|
|
2556
|
-
does not fit the array's integer type takes
|
|
2557
|
-
|
|
2797
|
+
does not fit the array's integer type takes a type that holds it and the
|
|
2798
|
+
array's values (int64, or object where no integer type does), where an
|
|
2799
|
+
operator would raise RangeError. */
|
|
2558
2800
|
int8_t
|
|
2559
2801
|
ca_promote_scalar_type (int8_t at, VALUE obj, int8_t st)
|
|
2560
2802
|
{
|
|
2561
2803
|
if ( RB_INTEGER_TYPE_P(obj) && at >= CA_INT8 && at <= CA_UINT64 ) {
|
|
2562
|
-
|
|
2804
|
+
int8_t vt;
|
|
2805
|
+
if ( ca_integer_range_side(obj, at) == 0 ) {
|
|
2806
|
+
return at;
|
|
2807
|
+
}
|
|
2808
|
+
/* The type the value needs, widened so that the array's values are
|
|
2809
|
+
kept beside it (a uint64 array and -1 meet in object). */
|
|
2810
|
+
vt = ( ca_integer_range_side(obj, CA_INT64) == 0 ) ? CA_INT64
|
|
2811
|
+
: ( ca_integer_range_side(obj, CA_UINT64) == 0 ) ? CA_UINT64
|
|
2812
|
+
: CA_OBJECT;
|
|
2813
|
+
return ca_value_match_type(ca_promote_type(at, vt), at, vt);
|
|
2563
2814
|
}
|
|
2564
2815
|
if ( ca_cast_table2[st][at] >= 0 ) {
|
|
2565
2816
|
return at;
|
|
@@ -2606,6 +2857,8 @@ rb_ca_s_result_type (int argc, VALUE *argv, VALUE klass)
|
|
|
2606
2857
|
cur = ( cur < 0 ) ? t : ca_promote_scalar_type(cur, argv[i], t);
|
|
2607
2858
|
}
|
|
2608
2859
|
}
|
|
2860
|
+
/* argv points into rest, and classifying an argument can allocate */
|
|
2861
|
+
RB_GC_GUARD(rest);
|
|
2609
2862
|
/* Return Symbol for family consistency with
|
|
2610
2863
|
CArray.value_to_data_type and ca.data_type. */
|
|
2611
2864
|
return rb_ca_data_type_to_sym(cur);
|
|
@@ -2745,6 +2998,8 @@ rb_ca_cast_other (VALUE *self, volatile VALUE *other)
|
|
|
2745
2998
|
*other = ca_operand_from_memory_view(*other);
|
|
2746
2999
|
}
|
|
2747
3000
|
|
|
3001
|
+
ca_array_operand(other, *self, 0);
|
|
3002
|
+
|
|
2748
3003
|
if ( ! rb_obj_is_carray(*other) ) {
|
|
2749
3004
|
if ( rb_ca_is_object_type(*self) ) {
|
|
2750
3005
|
*other = rb_cscalar_new_with_value(CA_OBJECT, 0, *other);
|
|
@@ -2787,7 +3042,9 @@ rb_ca_cast_other (VALUE *self, volatile VALUE *other)
|
|
|
2787
3042
|
return;
|
|
2788
3043
|
}
|
|
2789
3044
|
|
|
2790
|
-
|
|
3045
|
+
/* A data type the operation does not take, as `sqrt!` on an integer
|
|
3046
|
+
array is refused (CArray::DataTypeError is a TypeError). */
|
|
3047
|
+
rb_raise(rb_eCADataTypeError,
|
|
2791
3048
|
"can't coerce carray with data_types of '%s' and '%s'",
|
|
2792
3049
|
ca_coerce_operand_name(*self, ca),
|
|
2793
3050
|
ca_coerce_operand_name(*other, cb));
|
|
@@ -2813,69 +3070,89 @@ rb_ca_cast_with (VALUE self, VALUE other)
|
|
|
2813
3070
|
/* -----------------------------------------------------------------------
|
|
2814
3071
|
clip_<type> family — clip into the target data type's representable
|
|
2815
3072
|
range, then cast. Sugar for `clip(lo, hi).as_<type>`.
|
|
3073
|
+
|
|
3074
|
+
A float source takes a saturating path instead. The type's maximum is
|
|
3075
|
+
not always exact in the source float (INT64_MAX and UINT64_MAX round up
|
|
3076
|
+
in float64, INT32_MAX and UINT32_MAX in float32), so clip-then-cast
|
|
3077
|
+
would hand the cast a value just past the range. Instead each cell is
|
|
3078
|
+
compared in double against the range the cast truncates into
|
|
3079
|
+
(ca_double_fits_integer) and saturates to the type's minimum or maximum
|
|
3080
|
+
outside it. A NaN that is not masked is refused.
|
|
2816
3081
|
----------------------------------------------------------------------- */
|
|
2817
3082
|
|
|
2818
|
-
|
|
3083
|
+
static VALUE
|
|
3084
|
+
ca_clip_float_to_integer (VALUE self, int8_t to_dt)
|
|
3085
|
+
{
|
|
3086
|
+
CArray *ca;
|
|
3087
|
+
GetCArray(self, ca);
|
|
3088
|
+
volatile VALUE vsrc = ( ca->data_type == CA_FLOAT64 ) ? self : rb_ca_as_float64(self);
|
|
3089
|
+
CArray *src;
|
|
3090
|
+
GetCArray(vsrc, src);
|
|
3091
|
+
volatile VALUE vout = rb_carray_new(to_dt, ca->ndim, ca->dim, 0, NULL);
|
|
3092
|
+
CArray *out;
|
|
3093
|
+
GetCArray(vout, out);
|
|
3094
|
+
ca_attach(src); /* window: nothing raises inside */
|
|
3095
|
+
double *sp = (double *) src->ptr;
|
|
3096
|
+
char *op = out->ptr;
|
|
3097
|
+
ca_size_t n = ca->elements;
|
|
3098
|
+
boolean8_t *m = ca_has_mask(src) ? (boolean8_t *) src->mask->ptr : NULL; /* attached with src */
|
|
3099
|
+
int found_nan = 0;
|
|
3100
|
+
for ( ca_size_t i = 0; i < n; i++ ) {
|
|
3101
|
+
double v = sp[i];
|
|
3102
|
+
int fits = ca_double_fits_integer(v, to_dt);
|
|
3103
|
+
if ( v != v ) { /* NaN has no integer: refused below */
|
|
3104
|
+
v = 0.0;
|
|
3105
|
+
fits = 1;
|
|
3106
|
+
if ( ! m || ! m[i] ) found_nan = 1;
|
|
3107
|
+
}
|
|
3108
|
+
#define CLIP_STORE(type, lo, hi) \
|
|
3109
|
+
((type *) op)[i] = fits ? (type) v : ( v > 0 ? (hi) : (lo) )
|
|
3110
|
+
switch ( to_dt ) {
|
|
3111
|
+
case CA_INT8: CLIP_STORE(int8_t, INT8_MIN, INT8_MAX); break;
|
|
3112
|
+
case CA_UINT8: CLIP_STORE(uint8_t, 0, UINT8_MAX); break;
|
|
3113
|
+
case CA_INT16: CLIP_STORE(int16_t, INT16_MIN, INT16_MAX); break;
|
|
3114
|
+
case CA_UINT16: CLIP_STORE(uint16_t, 0, UINT16_MAX); break;
|
|
3115
|
+
case CA_INT32: CLIP_STORE(int32_t, INT32_MIN, INT32_MAX); break;
|
|
3116
|
+
case CA_UINT32: CLIP_STORE(uint32_t, 0, UINT32_MAX); break;
|
|
3117
|
+
case CA_INT64: CLIP_STORE(int64_t, INT64_MIN, INT64_MAX); break;
|
|
3118
|
+
case CA_UINT64: CLIP_STORE(uint64_t, 0, UINT64_MAX); break;
|
|
3119
|
+
}
|
|
3120
|
+
#undef CLIP_STORE
|
|
3121
|
+
}
|
|
3122
|
+
ca_detach(src);
|
|
3123
|
+
if ( found_nan ) {
|
|
3124
|
+
rb_raise(rb_eFloatDomainError, "%s: NaN cannot be converted to %s",
|
|
3125
|
+
ca_calling_method_name(), ca_type_name[to_dt]);
|
|
3126
|
+
}
|
|
3127
|
+
if ( ca_has_mask(ca) ) {
|
|
3128
|
+
ca_copy_mask(out, ca);
|
|
3129
|
+
}
|
|
3130
|
+
return vout;
|
|
3131
|
+
}
|
|
3132
|
+
|
|
3133
|
+
#define CLIP_CAST_FUNC(name, to_dt, lo_expr, hi_expr, cast_func) \
|
|
2819
3134
|
static VALUE \
|
|
2820
3135
|
rb_ca_##name (VALUE self) \
|
|
2821
3136
|
{ \
|
|
3137
|
+
CArray *ca; \
|
|
3138
|
+
GetCArray(self, ca); \
|
|
3139
|
+
if ( ca->data_type == CA_FLOAT32 || ca->data_type == CA_FLOAT64 ) { \
|
|
3140
|
+
return ca_clip_float_to_integer(self, to_dt); \
|
|
3141
|
+
} \
|
|
2822
3142
|
return cast_func(rb_ca_clip(self, lo_expr, hi_expr)); \
|
|
2823
3143
|
}
|
|
2824
3144
|
|
|
2825
|
-
CLIP_CAST_FUNC(clip_int8, INT2NUM(-128),
|
|
2826
|
-
CLIP_CAST_FUNC(clip_int16, INT2NUM(-32768),
|
|
2827
|
-
CLIP_CAST_FUNC(clip_int32, INT2NUM(-2147483648),
|
|
2828
|
-
CLIP_CAST_FUNC(clip_int64, LL2NUM(-9223372036854775807-1),
|
|
2829
|
-
CLIP_CAST_FUNC(clip_uint8, INT2NUM(0),
|
|
2830
|
-
CLIP_CAST_FUNC(clip_uint16, INT2NUM(0),
|
|
2831
|
-
CLIP_CAST_FUNC(clip_uint32, INT2NUM(0),
|
|
3145
|
+
CLIP_CAST_FUNC(clip_int8, CA_INT8, INT2NUM(-128), INT2NUM(127), rb_ca_as_int8)
|
|
3146
|
+
CLIP_CAST_FUNC(clip_int16, CA_INT16, INT2NUM(-32768), INT2NUM(32767), rb_ca_as_int16)
|
|
3147
|
+
CLIP_CAST_FUNC(clip_int32, CA_INT32, INT2NUM(-2147483648), INT2NUM(2147483647), rb_ca_as_int32)
|
|
3148
|
+
CLIP_CAST_FUNC(clip_int64, CA_INT64, LL2NUM(-9223372036854775807-1), LL2NUM(9223372036854775807), rb_ca_as_int64)
|
|
3149
|
+
CLIP_CAST_FUNC(clip_uint8, CA_UINT8, INT2NUM(0), INT2NUM(255), rb_ca_as_uint8)
|
|
3150
|
+
CLIP_CAST_FUNC(clip_uint16, CA_UINT16, INT2NUM(0), INT2NUM(65535), rb_ca_as_uint16)
|
|
3151
|
+
CLIP_CAST_FUNC(clip_uint32, CA_UINT32, INT2NUM(0), UINT2NUM(4294967295U), rb_ca_as_uint32)
|
|
3152
|
+
CLIP_CAST_FUNC(clip_uint64, CA_UINT64, INT2NUM(0), ULL2NUM(18446744073709551615ULL), rb_ca_as_uint64)
|
|
2832
3153
|
|
|
2833
3154
|
#undef CLIP_CAST_FUNC
|
|
2834
3155
|
|
|
2835
|
-
/* CArray#clip_uint64 -- dedicated implementation.
|
|
2836
|
-
|
|
2837
|
-
UINT64_MAX (= 2^64-1) is not exactly representable in float64; the nearest
|
|
2838
|
-
double rounds up to 2^64. A generic clip-then-cast path therefore clamps
|
|
2839
|
-
an overflowing float source (e.g. 1e20) to 2^64 and the subsequent cast to
|
|
2840
|
-
uint64 wraps around to 0. For floating-point sources we take a saturating
|
|
2841
|
-
path: compare in float space against 2^64 (which IS representable) and
|
|
2842
|
-
saturate to UINT64_MAX above it and 0 below zero. Other source data types use
|
|
2843
|
-
the plain clip-then-cast path. */
|
|
2844
|
-
static VALUE
|
|
2845
|
-
rb_ca_clip_uint64 (VALUE self)
|
|
2846
|
-
{
|
|
2847
|
-
CArray *ca;
|
|
2848
|
-
GetCArray(self, ca);
|
|
2849
|
-
int dt = ca->data_type;
|
|
2850
|
-
if ( dt == CA_FLOAT32 || dt == CA_FLOAT64 ) {
|
|
2851
|
-
volatile VALUE vsrc = ( dt == CA_FLOAT64 ) ? self : rb_ca_as_float64(self);
|
|
2852
|
-
CArray *src;
|
|
2853
|
-
GetCArray(vsrc, src);
|
|
2854
|
-
volatile VALUE vout = rb_carray_new(CA_UINT64, ca->ndim, ca->dim, 0, NULL);
|
|
2855
|
-
CArray *out;
|
|
2856
|
-
GetCArray(vout, out);
|
|
2857
|
-
ca_attach(src); /* window: nothing raises inside */
|
|
2858
|
-
double *sp = (double *) src->ptr;
|
|
2859
|
-
uint64_t *op = (uint64_t *) out->ptr;
|
|
2860
|
-
ca_size_t n = ca->elements;
|
|
2861
|
-
const double LIMIT = 18446744073709551616.0; /* 2^64, exact in f64 */
|
|
2862
|
-
for ( ca_size_t i = 0; i < n; i++ ) {
|
|
2863
|
-
double v = sp[i];
|
|
2864
|
-
if ( v != v ) op[i] = 0; /* NaN -> 0 */
|
|
2865
|
-
else if ( v >= LIMIT ) op[i] = UINT64_MAX;
|
|
2866
|
-
else if ( v <= 0.0 ) op[i] = 0;
|
|
2867
|
-
else op[i] = (uint64_t) v;
|
|
2868
|
-
}
|
|
2869
|
-
ca_detach(src);
|
|
2870
|
-
if ( ca_has_mask(ca) ) {
|
|
2871
|
-
ca_copy_mask(out, ca);
|
|
2872
|
-
}
|
|
2873
|
-
return vout;
|
|
2874
|
-
}
|
|
2875
|
-
return rb_ca_as_uint64(rb_ca_clip(self, INT2NUM(0),
|
|
2876
|
-
ULL2NUM(18446744073709551615ULL)));
|
|
2877
|
-
}
|
|
2878
|
-
|
|
2879
3156
|
/* ------------------------------------------------------------------------
|
|
2880
3157
|
Global cast functions CA_INT32(data) ... CA_OBJECT(data) etc.
|
|
2881
3158
|
|
|
@@ -2889,7 +3166,7 @@ rb_ca_clip_uint64 (VALUE self)
|
|
|
2889
3166
|
Numeric -> CScalar, or #to_ca when the object answers it
|
|
2890
3167
|
String -> the whitespace / `,` / `;` / `_`->UNDEF parser, which reads
|
|
2891
3168
|
far more naturally in Ruby and so is the one branch that
|
|
2892
|
-
calls back out to it (CArray.
|
|
3169
|
+
calls back out to it (CArray.cast_string in
|
|
2893
3170
|
carray/basics.rb, eager-loaded). It receives the data_type
|
|
2894
3171
|
as a Symbol.
|
|
2895
3172
|
|
|
@@ -3541,6 +3818,8 @@ Init_carray_cast (void)
|
|
|
3541
3818
|
"result_type", rb_ca_s_result_type, -1);
|
|
3542
3819
|
rb_define_private_method(rb_cCArray,
|
|
3543
3820
|
"value_match_type", rb_ca_value_match_type, 2);
|
|
3821
|
+
rb_define_private_method(rb_cCArray,
|
|
3822
|
+
"query_match_type", rb_ca_query_match_type, 1);
|
|
3544
3823
|
|
|
3545
3824
|
rb_define_singleton_method(rb_cCArray,
|
|
3546
3825
|
"promote_list", rb_ca_s_promote_list, -1);
|
|
@@ -3554,7 +3833,7 @@ Init_carray_cast (void)
|
|
|
3554
3833
|
classes registered in ext/carray_data_type.c. */
|
|
3555
3834
|
id_new_cast = rb_intern("new");
|
|
3556
3835
|
id_guess_array_shape_cast = rb_intern("guess_array_shape");
|
|
3557
|
-
id_cast_string = rb_intern("
|
|
3836
|
+
id_cast_string = rb_intern("cast_string");
|
|
3558
3837
|
id_to_ca_cast = rb_intern("to_ca");
|
|
3559
3838
|
id_length_cast = rb_intern("length");
|
|
3560
3839
|
id_begin_cast = rb_intern("begin");
|