carray 3.0.4 → 3.0.6
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 +438 -0
- data/README.md +1 -1
- data/carray.gemspec +3 -2
- data/ext/ca_array_pool.c +25 -1
- data/ext/ca_axis_dispatch.c +19 -20
- data/ext/ca_axis_group.c +1 -1
- data/ext/ca_categorical_iterator.c +34 -27
- data/ext/ca_compare.c +4 -4
- data/ext/ca_composite_dispatch.c +9 -9
- data/ext/ca_kernel_iterator.c +122 -237
- data/ext/ca_kernel_iterator.h +522 -337
- data/ext/ca_obj_array.c +69 -19
- data/ext/ca_obj_bincmp.c +10 -1
- data/ext/ca_obj_binop.c +11 -1
- data/ext/ca_obj_bitarray.c +5 -1
- data/ext/ca_obj_bitfield.c +60 -43
- data/ext/ca_obj_byte_swap.c +4 -1
- data/ext/ca_obj_const_string.c +15 -3
- data/ext/ca_obj_face.c +44 -1
- data/ext/ca_obj_fake.c +3 -1
- data/ext/ca_obj_field.c +13 -3
- data/ext/ca_obj_grid.c +219 -17
- data/ext/ca_obj_meld.c +69 -113
- data/ext/ca_obj_moncmp.c +9 -1
- data/ext/ca_obj_monop.c +86 -12
- data/ext/ca_obj_object.c +118 -32
- data/ext/ca_obj_record.c +3 -0
- data/ext/ca_obj_reduce.c +19 -1
- data/ext/ca_obj_refer.c +80 -26
- data/ext/ca_obj_remap.c +69 -10
- data/ext/ca_obj_roll.c +27 -6
- data/ext/ca_obj_select.c +38 -6
- data/ext/ca_obj_select_axis.c +1 -0
- data/ext/ca_obj_shift.c +32 -7
- data/ext/ca_obj_stack.c +311 -111
- data/ext/ca_obj_stride.c +159 -64
- data/ext/ca_obj_string.c +27 -2
- data/ext/ca_obj_tile.c +28 -7
- data/ext/ca_obj_transpose.c +8 -4
- data/ext/ca_obj_triop.c +12 -1
- data/ext/ca_obj_window.c +80 -50
- data/ext/ca_op_ipower.c +12 -12
- data/ext/ca_sort_kernels.h +6 -3
- data/ext/caframe_csv_reader.c +1 -1
- data/ext/carray.h +35 -1
- data/ext/carray_access.c +43 -67
- data/ext/carray_address_basis.c +134 -0
- data/ext/carray_attribute.c +32 -0
- data/ext/carray_broadcast.c +3 -4
- data/ext/carray_build_flags.h +1 -1
- data/ext/carray_cast.c +251 -93
- data/ext/carray_cast_func.rb +56 -26
- data/ext/carray_conversion.c +11 -7
- data/ext/carray_core.c +814 -72
- data/ext/carray_count.c +6 -0
- data/ext/carray_element.c +22 -13
- data/ext/carray_factorize.c +20 -20
- data/ext/carray_generate.c +8 -2
- data/ext/carray_histogram.c +26 -4
- data/ext/carray_index_classifier.c +4 -4
- data/ext/carray_internal.h +159 -12
- data/ext/carray_kernels_bincmp.c +2174 -170
- data/ext/carray_kernels_binop.c +25653 -5487
- data/ext/carray_kernels_init.c +8 -8
- data/ext/carray_kernels_moncmp.c +96 -96
- data/ext/carray_kernels_monop.c +12253 -5235
- data/ext/carray_kernels_reduce_aggregate.c +6150 -2423
- data/ext/carray_kernels_reduce_boolean.c +1533 -15
- data/ext/carray_kernels_reduce_cumulative.c +2442 -882
- data/ext/carray_kernels_reduce_extreme.c +5658 -1661
- data/ext/carray_kernels_reduce_variance.c +2534 -402
- data/ext/carray_kernels_scan.c +368 -368
- data/ext/carray_kernels_search.c +4551 -604
- data/ext/carray_kernels_sort.c +659 -751
- data/ext/carray_kernels_triop.c +114 -114
- data/ext/carray_key_windows.c +4 -0
- data/ext/carray_lazy.c +47 -0
- data/ext/carray_loop.c +1 -1
- data/ext/carray_mask.c +175 -161
- data/ext/carray_median_percentile.c +4 -4
- data/ext/carray_memory_view.c +15 -9
- data/ext/carray_operator.c +152 -49
- data/ext/carray_order.c +230 -10
- data/ext/carray_random.c +22 -19
- data/ext/carray_scatter.c +24 -7
- data/ext/carray_slab.c +128 -29
- data/ext/carray_sort.c +224 -16
- data/ext/carray_sort_kernel.c +5 -7
- data/ext/carray_struct.c +35 -43
- data/ext/carray_test.c +74 -19
- data/ext/carray_time_text.c +6 -4
- data/ext/carray_utils.c +63 -21
- data/ext/extconf.rb +11 -0
- data/ext/mkkernel.rb +546 -199
- data/ext/ruby_carray.c +4 -1
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +42 -5
- data/lib/carray/autoload_carray.rb +3 -3
- data/lib/carray/autoload_method_extension.rb +5 -3
- data/lib/carray/axis_group.rb +13 -7
- data/lib/carray/basics.rb +28 -8
- data/lib/carray/block_iterator.rb +17 -3
- data/lib/carray/categorical.rb +35 -23
- data/lib/carray/categorical_iterator.rb +8 -8
- data/lib/carray/complex.rb +2 -2
- data/lib/carray/conditional.rb +3 -2
- data/lib/carray/const_string.rb +10 -0
- data/lib/carray/data_type_extension.rb +8 -1
- data/lib/carray/fixlen_string.rb +41 -2
- data/lib/carray/frame/column_verbs.rb +48 -16
- data/lib/carray/frame/concat.rb +17 -3
- data/lib/carray/frame/convert.rb +19 -0
- data/lib/carray/frame/csv_parser.rb +32 -32
- data/lib/carray/frame/describe.rb +4 -2
- data/lib/carray/frame/frame.rb +405 -85
- data/lib/carray/frame/group.rb +777 -64
- data/lib/carray/frame/io.rb +212 -72
- data/lib/carray/frame/join.rb +146 -37
- data/lib/carray/frame/records.rb +3 -3
- data/lib/carray/frame/reshape.rb +89 -11
- data/lib/carray/frame/sort.rb +57 -9
- data/lib/carray/frame/verbs.rb +384 -49
- data/lib/carray/frame/windows.rb +44 -6
- data/lib/carray/fuse_source.rb +31 -2
- data/lib/carray/inspect.rb +7 -2
- data/lib/carray/iterator.rb +32 -0
- data/lib/carray/lazy.rb +52 -8
- data/lib/carray/mask_gap_fill.rb +37 -17
- data/lib/carray/meld_reduce.rb +1 -1
- data/lib/carray/methods/choose.rb +3 -2
- data/lib/carray/methods/is_in.rb +8 -1
- data/lib/carray/methods/meshgrid.rb +3 -1
- data/lib/carray/runtime.rb +47 -8
- data/lib/carray/segment_iterator.rb +35 -16
- data/lib/carray/serialize.rb +53 -19
- data/lib/carray/stack.rb +33 -18
- data/lib/carray/string.rb +8 -0
- data/lib/carray/string_operation_extension.rb +13 -5
- data/lib/carray/struct_builder.rb +5 -3
- data/lib/carray/time.rb +112 -68
- data/lib/carray/window_iterator.rb +16 -4
- data/yard-stubs/ca_obj_array.rb +26 -1
- data/yard-stubs/ca_obj_transpose.rb +5 -4
- data/yard-stubs/carray_attribute.rb +3 -1
- data/yard-stubs/carray_cast.rb +10 -5
- data/yard-stubs/carray_conversion.rb +13 -3
- data/yard-stubs/carray_element.rb +7 -6
- data/yard-stubs/carray_mask.rb +28 -4
- data/yard-stubs/carray_math.rb +45 -20
- data/yard-stubs/carray_memory_view.rb +7 -0
- data/yard-stubs/carray_order.rb +100 -4
- data/yard-stubs/carray_scatter.rb +7 -5
- data/yard-stubs/carray_test.rb +7 -4
- metadata +18 -4
data/ext/carray_build_flags.h
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/* GENERATED by extconf.rb: the flags this build's arithmetic
|
|
2
2
|
was compiled with. See CArray::BUILD_FLAGS. */
|
|
3
|
-
#define CA_BUILD_FLAGS "-O3 -fno-fast-math -fwrapv -fopenmp-simd -march=native"
|
|
3
|
+
#define CA_BUILD_FLAGS "-O3 -fno-fast-math -fwrapv -fno-math-errno -fopenmp-simd -march=native"
|
data/ext/carray_cast.c
CHANGED
|
@@ -1215,26 +1215,48 @@ typedef struct {
|
|
|
1215
1215
|
boolean8_t *scratch;
|
|
1216
1216
|
} ca_to_type_ctx_t;
|
|
1217
1217
|
|
|
1218
|
-
/*
|
|
1219
|
-
|
|
1220
|
-
|
|
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. */
|
|
1221
1241
|
static void
|
|
1222
|
-
|
|
1242
|
+
ca_mark_unconvertible (CArray *ca, boolean8_t *m, int8_t dt)
|
|
1223
1243
|
{
|
|
1224
1244
|
ca_size_t i, n = ca->elements;
|
|
1225
1245
|
switch ( ca->data_type ) {
|
|
1226
|
-
case CA_FLOAT32: {
|
|
1227
|
-
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;
|
|
1228
1248
|
break; }
|
|
1229
|
-
case CA_FLOAT64: {
|
|
1230
|
-
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;
|
|
1231
1251
|
break; }
|
|
1232
1252
|
#ifdef HAVE_COMPLEX_H
|
|
1233
|
-
case CA_CMPLX64: {
|
|
1234
|
-
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;
|
|
1235
1256
|
break; }
|
|
1236
|
-
case CA_CMPLX128: {
|
|
1237
|
-
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;
|
|
1238
1260
|
break; }
|
|
1239
1261
|
#endif
|
|
1240
1262
|
default:
|
|
@@ -1274,11 +1296,11 @@ ca_to_type_cast (VALUE arg)
|
|
|
1274
1296
|
else {
|
|
1275
1297
|
memset(scratch, 0, ne);
|
|
1276
1298
|
}
|
|
1277
|
-
/* float -> integer: a
|
|
1278
|
-
|
|
1279
|
-
|
|
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. */
|
|
1280
1302
|
if ( from_float ) {
|
|
1281
|
-
|
|
1303
|
+
ca_mark_unconvertible(ca, scratch, cb->data_type);
|
|
1282
1304
|
memset(cb->ptr, 0, ne * cb->bytes);
|
|
1283
1305
|
}
|
|
1284
1306
|
ca_cast_block_with_mask(ne, ca, ca->ptr, cb, cb->ptr, scratch);
|
|
@@ -1587,7 +1609,6 @@ static VALUE
|
|
|
1587
1609
|
rb_ca_as_type_internal (int argc, VALUE *argv, VALUE self)
|
|
1588
1610
|
{
|
|
1589
1611
|
volatile VALUE obj, rtype = Qnil, ropt, rbytes = Qnil;
|
|
1590
|
-
CArray *ca;
|
|
1591
1612
|
int8_t data_type;
|
|
1592
1613
|
ca_size_t bytes;
|
|
1593
1614
|
|
|
@@ -1596,14 +1617,12 @@ rb_ca_as_type_internal (int argc, VALUE *argv, VALUE self)
|
|
|
1596
1617
|
|
|
1597
1618
|
rb_ca_guess_type_and_bytes(rtype, rbytes, &data_type, &bytes);
|
|
1598
1619
|
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
}
|
|
1604
|
-
}
|
|
1620
|
+
rb_check_carray_object(self);
|
|
1621
|
+
|
|
1622
|
+
/* A view also when the data_type is the receiver's own: what is done to
|
|
1623
|
+
it (an attribute, a freeze) stays with it.
|
|
1605
1624
|
|
|
1606
|
-
|
|
1625
|
+
Natural-width cast: dispatch via helper (CAMonOp for numeric,
|
|
1607
1626
|
CAFake for CA_FIXLEN sizing / CA_OBJECT / class-rtype). */
|
|
1608
1627
|
if ( bytes == (ca_size_t) ca_sizeof[data_type] ) {
|
|
1609
1628
|
obj = ca_type_adapt_view(self, rtype, data_type, CA_ADAPT_VIEW);
|
|
@@ -2017,7 +2036,9 @@ rb_ca_wrap_readonly (VALUE arg, VALUE rtype)
|
|
|
2017
2036
|
else {
|
|
2018
2037
|
CArray *ca_tmp;
|
|
2019
2038
|
volatile VALUE ref = obj;
|
|
2020
|
-
ca_size_t
|
|
2039
|
+
ca_size_t bytes = ca_sizeof[data_type];
|
|
2040
|
+
CA_CHECK_BYTES_GIVEN(data_type, bytes);
|
|
2041
|
+
ca_size_t dim = RSTRING_LEN(ref)/bytes;
|
|
2021
2042
|
obj = rb_carray_new(data_type, 1, &dim, 0, NULL);
|
|
2022
2043
|
TypedData_Get_Struct(obj, CArray, &carray_data_type, ca_tmp);
|
|
2023
2044
|
memcpy(ca_tmp->ptr, RSTRING_PTR(ref), dim * ca_sizeof[data_type]);
|
|
@@ -2150,7 +2171,15 @@ ca_fixlen_scalar_operand (volatile VALUE *scalar, VALUE reference)
|
|
|
2150
2171
|
if ( cr->data_type != CA_FIXLEN ) {
|
|
2151
2172
|
return 0;
|
|
2152
2173
|
}
|
|
2153
|
-
|
|
2174
|
+
/* A String longer than the cell keeps its length: cut to the cell, it
|
|
2175
|
+
would equal a cell it does not (a two-byte "ab" equal to "abX"). The
|
|
2176
|
+
wider scalar is then compared as two fixlen widths are. */
|
|
2177
|
+
{
|
|
2178
|
+
ca_size_t len = (ca_size_t) RSTRING_LEN(*scalar);
|
|
2179
|
+
*scalar = rb_cscalar_new_with_value(CA_FIXLEN,
|
|
2180
|
+
len > cr->bytes ? len : cr->bytes,
|
|
2181
|
+
*scalar);
|
|
2182
|
+
}
|
|
2154
2183
|
return 1;
|
|
2155
2184
|
}
|
|
2156
2185
|
|
|
@@ -2240,6 +2269,69 @@ ca_integer_scalar_operand (volatile VALUE *scalar, VALUE reference)
|
|
|
2240
2269
|
return 1;
|
|
2241
2270
|
}
|
|
2242
2271
|
|
|
2272
|
+
/* A Ruby Array operand against a numeric or boolean array is read as its
|
|
2273
|
+
cells, as the array CArray.wrap_readonly makes of it (nested Arrays give
|
|
2274
|
+
its axes). Its data type is the
|
|
2275
|
+
one the cells would take one at a time as scalar operands of the same
|
|
2276
|
+
operation (an Integer
|
|
2277
|
+
against an integer array takes the array's type and has to fit it),
|
|
2278
|
+
promoted together. Against an object array, a Face or a fixlen array an
|
|
2279
|
+
Array stays one value. */
|
|
2280
|
+
static int
|
|
2281
|
+
ca_array_operand (volatile VALUE *ary, VALUE reference, int both)
|
|
2282
|
+
{
|
|
2283
|
+
CArray *cr;
|
|
2284
|
+
volatile VALUE flat, probe_self, probe;
|
|
2285
|
+
long i, n;
|
|
2286
|
+
int8_t type = -1, seen_fix = -1, seen_big = -1, seen_flo = -1, seen_cpx = -1,
|
|
2287
|
+
seen_bool = -1;
|
|
2288
|
+
|
|
2289
|
+
if ( ! RB_TYPE_P(*ary, T_ARRAY) || ! rb_obj_is_carray(reference) ) {
|
|
2290
|
+
return 0;
|
|
2291
|
+
}
|
|
2292
|
+
TypedData_Get_Struct(reference, CArray, &carray_data_type, cr);
|
|
2293
|
+
if ( ca_is_face(cr) || ca_is_object_type(cr) || ca_is_fixlen_type(cr) ) {
|
|
2294
|
+
return 0;
|
|
2295
|
+
}
|
|
2296
|
+
|
|
2297
|
+
flat = rb_funcall(*ary, rb_intern("flatten"), 0);
|
|
2298
|
+
n = RARRAY_LEN(flat);
|
|
2299
|
+
for (i = 0; i < n; i++) {
|
|
2300
|
+
VALUE e = RARRAY_AREF(flat, i);
|
|
2301
|
+
int8_t *seen, t;
|
|
2302
|
+
CArray *cp;
|
|
2303
|
+
if ( FIXNUM_P(e) ) seen = &seen_fix;
|
|
2304
|
+
else if ( RB_TYPE_P(e, T_BIGNUM) ) seen = &seen_big;
|
|
2305
|
+
else if ( RB_FLOAT_TYPE_P(e) ) seen = &seen_flo;
|
|
2306
|
+
else if ( RB_TYPE_P(e, T_COMPLEX) ) seen = &seen_cpx;
|
|
2307
|
+
else if ( e == Qtrue || e == Qfalse ) seen = &seen_bool;
|
|
2308
|
+
else seen = NULL;
|
|
2309
|
+
if ( RB_INTEGER_TYPE_P(e) && ca_is_integer_type(cr) ) {
|
|
2310
|
+
ca_check_integer_fits(e, cr->data_type);
|
|
2311
|
+
}
|
|
2312
|
+
if ( seen && *seen >= 0 ) {
|
|
2313
|
+
continue;
|
|
2314
|
+
}
|
|
2315
|
+
probe_self = reference;
|
|
2316
|
+
probe = e;
|
|
2317
|
+
if ( both ) {
|
|
2318
|
+
rb_ca_cast_self_or_other(&probe_self, &probe);
|
|
2319
|
+
}
|
|
2320
|
+
else {
|
|
2321
|
+
rb_ca_cast_other((VALUE *) &probe_self, (volatile VALUE *) &probe);
|
|
2322
|
+
}
|
|
2323
|
+
TypedData_Get_Struct(probe, CArray, &carray_data_type, cp);
|
|
2324
|
+
t = cp->data_type;
|
|
2325
|
+
if ( seen ) *seen = t;
|
|
2326
|
+
type = ( type < 0 ) ? t : ca_promote_type(type, t);
|
|
2327
|
+
}
|
|
2328
|
+
if ( type < 0 ) {
|
|
2329
|
+
type = cr->data_type;
|
|
2330
|
+
}
|
|
2331
|
+
*ary = rb_ca_wrap_readonly(*ary, INT2NUM(type));
|
|
2332
|
+
return 1;
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2243
2335
|
/* CArray.cast(value) -- singleton entry delegating to rb_ca_cast, which
|
|
2244
2336
|
returns a CArray unchanged and coerces a Ruby value to a CScalar / CArray.
|
|
2245
2337
|
User doc lives in yard-stubs/carray_cast.rb. */
|
|
@@ -2304,6 +2396,10 @@ rb_ca_cast_self_or_other (volatile VALUE *self, volatile VALUE *other)
|
|
|
2304
2396
|
*other = ca_operand_from_memory_view(*other);
|
|
2305
2397
|
}
|
|
2306
2398
|
|
|
2399
|
+
if ( ! ca_array_operand(other, *self, 1) ) {
|
|
2400
|
+
ca_array_operand(self, *other, 1);
|
|
2401
|
+
}
|
|
2402
|
+
|
|
2307
2403
|
if ( ! rb_obj_is_carray(*self) ) {
|
|
2308
2404
|
self_is_object = 1;
|
|
2309
2405
|
if ( rb_ca_is_object_type(*other) ) {
|
|
@@ -2427,12 +2523,32 @@ rb_ca_cast_self_or_other (volatile VALUE *self, volatile VALUE *other)
|
|
|
2427
2523
|
return;
|
|
2428
2524
|
}
|
|
2429
2525
|
|
|
2430
|
-
|
|
2526
|
+
/* A data type the operation does not take, as `sqrt!` on an integer
|
|
2527
|
+
array is refused (CArray::DataTypeError is a TypeError). */
|
|
2528
|
+
rb_raise(rb_eCADataTypeError,
|
|
2431
2529
|
"can't coerce carray with data_types of '%s' and '%s'",
|
|
2432
2530
|
ca_coerce_operand_name(*self, ca),
|
|
2433
2531
|
ca_coerce_operand_name(*other, cb));
|
|
2434
2532
|
}
|
|
2435
2533
|
|
|
2534
|
+
/* Refuses a pair of arrays with no common data_type in the words of
|
|
2535
|
+
rb_ca_cast_self_or_other (the eager operators'), and returns otherwise
|
|
2536
|
+
without casting either. A lazy builder calls it before it works out
|
|
2537
|
+
the kernel's data_types, so that a pair the eager operator refuses is
|
|
2538
|
+
refused the same way. */
|
|
2539
|
+
void
|
|
2540
|
+
ca_refuse_without_common_type (VALUE self, VALUE other)
|
|
2541
|
+
{
|
|
2542
|
+
CArray *ca, *cb;
|
|
2543
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
2544
|
+
TypedData_Get_Struct(other, CArray, &carray_data_type, cb);
|
|
2545
|
+
if ( ca->data_type != cb->data_type
|
|
2546
|
+
&& ca_cast_table[cb->data_type][ca->data_type] < 0
|
|
2547
|
+
&& ca_cast_table[ca->data_type][cb->data_type] < 0 ) {
|
|
2548
|
+
rb_ca_cast_self_or_other(&self, &other); /* raises */
|
|
2549
|
+
}
|
|
2550
|
+
}
|
|
2551
|
+
|
|
2436
2552
|
/* CArray.cast_self_or_other(self, other) — promote self and other
|
|
2437
2553
|
* to a common data_type and return [self', other']. Wraps the
|
|
2438
2554
|
* void rb_ca_cast_self_or_other above into a class method.
|
|
@@ -2471,6 +2587,15 @@ ca_arg_to_data_type (VALUE obj)
|
|
|
2471
2587
|
/* MemoryView producer -> its format's data_type (T_STRING excluded above,
|
|
2472
2588
|
so a String never reaches here). data_type already assigned. */
|
|
2473
2589
|
}
|
|
2590
|
+
else if ( rb_memory_view_available_p(obj) ) {
|
|
2591
|
+
/* A MemoryView producer whose format says nothing usable (typeless, the
|
|
2592
|
+
other byte order) is read as the operators read it, and refused in
|
|
2593
|
+
the same words. */
|
|
2594
|
+
VALUE ca_obj = ca_operand_from_memory_view(obj);
|
|
2595
|
+
CArray *ca;
|
|
2596
|
+
TypedData_Get_Struct(ca_obj, CArray, &carray_data_type, ca);
|
|
2597
|
+
data_type = ca->data_type;
|
|
2598
|
+
}
|
|
2474
2599
|
else {
|
|
2475
2600
|
data_type = ca_value_to_data_type(obj);
|
|
2476
2601
|
}
|
|
@@ -2606,6 +2731,24 @@ ca_query_match_type (int8_t ref, VALUE query)
|
|
|
2606
2731
|
return ref;
|
|
2607
2732
|
}
|
|
2608
2733
|
|
|
2734
|
+
/* A fixlen array searched or counted for a String longer than its cells
|
|
2735
|
+
is read as cells of the String's width (NUL-padded), so the query is not
|
|
2736
|
+
cut to the cell: "abX" matches no two-byte cell, as a wider scalar does
|
|
2737
|
+
not in `eq`. Anything else is returned as given. */
|
|
2738
|
+
VALUE
|
|
2739
|
+
ca_fixlen_widen_for_query (VALUE self, VALUE query)
|
|
2740
|
+
{
|
|
2741
|
+
CArray *ca;
|
|
2742
|
+
if ( ! RB_TYPE_P(query, T_STRING) || ! rb_obj_is_carray(self) ) {
|
|
2743
|
+
return self;
|
|
2744
|
+
}
|
|
2745
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
2746
|
+
if ( ca->data_type != CA_FIXLEN || RSTRING_LEN(query) <= ca->bytes ) {
|
|
2747
|
+
return self;
|
|
2748
|
+
}
|
|
2749
|
+
return rb_ca_to_type(self, INT2NUM(CA_FIXLEN), SIZE2NUM(RSTRING_LEN(query)));
|
|
2750
|
+
}
|
|
2751
|
+
|
|
2609
2752
|
/* ca.query_match_type(query) -- ca_query_match_type with self as the
|
|
2610
2753
|
reference, for the set family and locate_addr. */
|
|
2611
2754
|
static VALUE
|
|
@@ -2641,7 +2784,7 @@ ca_arg_is_scalar (VALUE obj)
|
|
|
2641
2784
|
if ( TYPE(obj) == T_SYMBOL || TYPE(obj) == T_STRING || TYPE(obj) == T_CLASS ) {
|
|
2642
2785
|
return 0;
|
|
2643
2786
|
}
|
|
2644
|
-
return
|
|
2787
|
+
return ! rb_memory_view_available_p(obj);
|
|
2645
2788
|
}
|
|
2646
2789
|
|
|
2647
2790
|
/* The type a scalar `obj` (of type `st`) and an array of type `at` share,
|
|
@@ -2852,6 +2995,8 @@ rb_ca_cast_other (VALUE *self, volatile VALUE *other)
|
|
|
2852
2995
|
*other = ca_operand_from_memory_view(*other);
|
|
2853
2996
|
}
|
|
2854
2997
|
|
|
2998
|
+
ca_array_operand(other, *self, 0);
|
|
2999
|
+
|
|
2855
3000
|
if ( ! rb_obj_is_carray(*other) ) {
|
|
2856
3001
|
if ( rb_ca_is_object_type(*self) ) {
|
|
2857
3002
|
*other = rb_cscalar_new_with_value(CA_OBJECT, 0, *other);
|
|
@@ -2894,7 +3039,9 @@ rb_ca_cast_other (VALUE *self, volatile VALUE *other)
|
|
|
2894
3039
|
return;
|
|
2895
3040
|
}
|
|
2896
3041
|
|
|
2897
|
-
|
|
3042
|
+
/* A data type the operation does not take, as `sqrt!` on an integer
|
|
3043
|
+
array is refused (CArray::DataTypeError is a TypeError). */
|
|
3044
|
+
rb_raise(rb_eCADataTypeError,
|
|
2898
3045
|
"can't coerce carray with data_types of '%s' and '%s'",
|
|
2899
3046
|
ca_coerce_operand_name(*self, ca),
|
|
2900
3047
|
ca_coerce_operand_name(*other, cb));
|
|
@@ -2920,78 +3067,89 @@ rb_ca_cast_with (VALUE self, VALUE other)
|
|
|
2920
3067
|
/* -----------------------------------------------------------------------
|
|
2921
3068
|
clip_<type> family — clip into the target data type's representable
|
|
2922
3069
|
range, then cast. Sugar for `clip(lo, hi).as_<type>`.
|
|
3070
|
+
|
|
3071
|
+
A float source takes a saturating path instead. The type's maximum is
|
|
3072
|
+
not always exact in the source float (INT64_MAX and UINT64_MAX round up
|
|
3073
|
+
in float64, INT32_MAX and UINT32_MAX in float32), so clip-then-cast
|
|
3074
|
+
would hand the cast a value just past the range. Instead each cell is
|
|
3075
|
+
compared in double against the range the cast truncates into
|
|
3076
|
+
(ca_double_fits_integer) and saturates to the type's minimum or maximum
|
|
3077
|
+
outside it. A NaN that is not masked is refused.
|
|
2923
3078
|
----------------------------------------------------------------------- */
|
|
2924
3079
|
|
|
2925
|
-
|
|
3080
|
+
static VALUE
|
|
3081
|
+
ca_clip_float_to_integer (VALUE self, int8_t to_dt)
|
|
3082
|
+
{
|
|
3083
|
+
CArray *ca;
|
|
3084
|
+
GetCArray(self, ca);
|
|
3085
|
+
volatile VALUE vsrc = ( ca->data_type == CA_FLOAT64 ) ? self : rb_ca_as_float64(self);
|
|
3086
|
+
CArray *src;
|
|
3087
|
+
GetCArray(vsrc, src);
|
|
3088
|
+
volatile VALUE vout = rb_carray_new(to_dt, ca->ndim, ca->dim, 0, NULL);
|
|
3089
|
+
CArray *out;
|
|
3090
|
+
GetCArray(vout, out);
|
|
3091
|
+
ca_attach(src); /* window: nothing raises inside */
|
|
3092
|
+
double *sp = (double *) src->ptr;
|
|
3093
|
+
char *op = out->ptr;
|
|
3094
|
+
ca_size_t n = ca->elements;
|
|
3095
|
+
boolean8_t *m = ca_has_mask(src) ? (boolean8_t *) src->mask->ptr : NULL; /* attached with src */
|
|
3096
|
+
int found_nan = 0;
|
|
3097
|
+
for ( ca_size_t i = 0; i < n; i++ ) {
|
|
3098
|
+
double v = sp[i];
|
|
3099
|
+
int fits = ca_double_fits_integer(v, to_dt);
|
|
3100
|
+
if ( v != v ) { /* NaN has no integer: refused below */
|
|
3101
|
+
v = 0.0;
|
|
3102
|
+
fits = 1;
|
|
3103
|
+
if ( ! m || ! m[i] ) found_nan = 1;
|
|
3104
|
+
}
|
|
3105
|
+
#define CLIP_STORE(type, lo, hi) \
|
|
3106
|
+
((type *) op)[i] = fits ? (type) v : ( v > 0 ? (hi) : (lo) )
|
|
3107
|
+
switch ( to_dt ) {
|
|
3108
|
+
case CA_INT8: CLIP_STORE(int8_t, INT8_MIN, INT8_MAX); break;
|
|
3109
|
+
case CA_UINT8: CLIP_STORE(uint8_t, 0, UINT8_MAX); break;
|
|
3110
|
+
case CA_INT16: CLIP_STORE(int16_t, INT16_MIN, INT16_MAX); break;
|
|
3111
|
+
case CA_UINT16: CLIP_STORE(uint16_t, 0, UINT16_MAX); break;
|
|
3112
|
+
case CA_INT32: CLIP_STORE(int32_t, INT32_MIN, INT32_MAX); break;
|
|
3113
|
+
case CA_UINT32: CLIP_STORE(uint32_t, 0, UINT32_MAX); break;
|
|
3114
|
+
case CA_INT64: CLIP_STORE(int64_t, INT64_MIN, INT64_MAX); break;
|
|
3115
|
+
case CA_UINT64: CLIP_STORE(uint64_t, 0, UINT64_MAX); break;
|
|
3116
|
+
}
|
|
3117
|
+
#undef CLIP_STORE
|
|
3118
|
+
}
|
|
3119
|
+
ca_detach(src);
|
|
3120
|
+
if ( found_nan ) {
|
|
3121
|
+
rb_raise(rb_eFloatDomainError, "%s: NaN cannot be converted to %s",
|
|
3122
|
+
ca_calling_method_name(), ca_type_name[to_dt]);
|
|
3123
|
+
}
|
|
3124
|
+
if ( ca_has_mask(ca) ) {
|
|
3125
|
+
ca_copy_mask(out, ca);
|
|
3126
|
+
}
|
|
3127
|
+
return vout;
|
|
3128
|
+
}
|
|
3129
|
+
|
|
3130
|
+
#define CLIP_CAST_FUNC(name, to_dt, lo_expr, hi_expr, cast_func) \
|
|
2926
3131
|
static VALUE \
|
|
2927
3132
|
rb_ca_##name (VALUE self) \
|
|
2928
3133
|
{ \
|
|
3134
|
+
CArray *ca; \
|
|
3135
|
+
GetCArray(self, ca); \
|
|
3136
|
+
if ( ca->data_type == CA_FLOAT32 || ca->data_type == CA_FLOAT64 ) { \
|
|
3137
|
+
return ca_clip_float_to_integer(self, to_dt); \
|
|
3138
|
+
} \
|
|
2929
3139
|
return cast_func(rb_ca_clip(self, lo_expr, hi_expr)); \
|
|
2930
3140
|
}
|
|
2931
3141
|
|
|
2932
|
-
CLIP_CAST_FUNC(clip_int8, INT2NUM(-128),
|
|
2933
|
-
CLIP_CAST_FUNC(clip_int16, INT2NUM(-32768),
|
|
2934
|
-
CLIP_CAST_FUNC(clip_int32, INT2NUM(-2147483648),
|
|
2935
|
-
CLIP_CAST_FUNC(clip_int64, LL2NUM(-9223372036854775807-1),
|
|
2936
|
-
CLIP_CAST_FUNC(clip_uint8, INT2NUM(0),
|
|
2937
|
-
CLIP_CAST_FUNC(clip_uint16, INT2NUM(0),
|
|
2938
|
-
CLIP_CAST_FUNC(clip_uint32, INT2NUM(0),
|
|
3142
|
+
CLIP_CAST_FUNC(clip_int8, CA_INT8, INT2NUM(-128), INT2NUM(127), rb_ca_as_int8)
|
|
3143
|
+
CLIP_CAST_FUNC(clip_int16, CA_INT16, INT2NUM(-32768), INT2NUM(32767), rb_ca_as_int16)
|
|
3144
|
+
CLIP_CAST_FUNC(clip_int32, CA_INT32, INT2NUM(-2147483648), INT2NUM(2147483647), rb_ca_as_int32)
|
|
3145
|
+
CLIP_CAST_FUNC(clip_int64, CA_INT64, LL2NUM(-9223372036854775807-1), LL2NUM(9223372036854775807), rb_ca_as_int64)
|
|
3146
|
+
CLIP_CAST_FUNC(clip_uint8, CA_UINT8, INT2NUM(0), INT2NUM(255), rb_ca_as_uint8)
|
|
3147
|
+
CLIP_CAST_FUNC(clip_uint16, CA_UINT16, INT2NUM(0), INT2NUM(65535), rb_ca_as_uint16)
|
|
3148
|
+
CLIP_CAST_FUNC(clip_uint32, CA_UINT32, INT2NUM(0), UINT2NUM(4294967295U), rb_ca_as_uint32)
|
|
3149
|
+
CLIP_CAST_FUNC(clip_uint64, CA_UINT64, INT2NUM(0), ULL2NUM(18446744073709551615ULL), rb_ca_as_uint64)
|
|
2939
3150
|
|
|
2940
3151
|
#undef CLIP_CAST_FUNC
|
|
2941
3152
|
|
|
2942
|
-
/* CArray#clip_uint64 -- dedicated implementation.
|
|
2943
|
-
|
|
2944
|
-
UINT64_MAX (= 2^64-1) is not exactly representable in float64; the nearest
|
|
2945
|
-
double rounds up to 2^64. A generic clip-then-cast path therefore clamps
|
|
2946
|
-
an overflowing float source (e.g. 1e20) to 2^64 and the subsequent cast to
|
|
2947
|
-
uint64 wraps around to 0. For floating-point sources we take a saturating
|
|
2948
|
-
path: compare in float space against 2^64 (which IS representable) and
|
|
2949
|
-
saturate to UINT64_MAX above it and 0 below zero. Other source data types use
|
|
2950
|
-
the plain clip-then-cast path. */
|
|
2951
|
-
static VALUE
|
|
2952
|
-
rb_ca_clip_uint64 (VALUE self)
|
|
2953
|
-
{
|
|
2954
|
-
CArray *ca;
|
|
2955
|
-
GetCArray(self, ca);
|
|
2956
|
-
int dt = ca->data_type;
|
|
2957
|
-
if ( dt == CA_FLOAT32 || dt == CA_FLOAT64 ) {
|
|
2958
|
-
volatile VALUE vsrc = ( dt == CA_FLOAT64 ) ? self : rb_ca_as_float64(self);
|
|
2959
|
-
CArray *src;
|
|
2960
|
-
GetCArray(vsrc, src);
|
|
2961
|
-
volatile VALUE vout = rb_carray_new(CA_UINT64, ca->ndim, ca->dim, 0, NULL);
|
|
2962
|
-
CArray *out;
|
|
2963
|
-
GetCArray(vout, out);
|
|
2964
|
-
ca_attach(src); /* window: nothing raises inside */
|
|
2965
|
-
double *sp = (double *) src->ptr;
|
|
2966
|
-
uint64_t *op = (uint64_t *) out->ptr;
|
|
2967
|
-
ca_size_t n = ca->elements;
|
|
2968
|
-
const double LIMIT = 18446744073709551616.0; /* 2^64, exact in f64 */
|
|
2969
|
-
boolean8_t *m = ca_has_mask(src) ? (boolean8_t *) src->mask->ptr : NULL; /* attached with src */
|
|
2970
|
-
int found_nan = 0;
|
|
2971
|
-
for ( ca_size_t i = 0; i < n; i++ ) {
|
|
2972
|
-
double v = sp[i];
|
|
2973
|
-
if ( v != v ) { /* NaN has no integer: refused below */
|
|
2974
|
-
op[i] = 0;
|
|
2975
|
-
if ( ! m || ! m[i] ) found_nan = 1;
|
|
2976
|
-
}
|
|
2977
|
-
else if ( v >= LIMIT ) op[i] = UINT64_MAX;
|
|
2978
|
-
else if ( v <= 0.0 ) op[i] = 0;
|
|
2979
|
-
else op[i] = (uint64_t) v;
|
|
2980
|
-
}
|
|
2981
|
-
ca_detach(src);
|
|
2982
|
-
if ( found_nan ) {
|
|
2983
|
-
rb_raise(rb_eFloatDomainError, "%s: NaN cannot be converted to uint64",
|
|
2984
|
-
ca_calling_method_name());
|
|
2985
|
-
}
|
|
2986
|
-
if ( ca_has_mask(ca) ) {
|
|
2987
|
-
ca_copy_mask(out, ca);
|
|
2988
|
-
}
|
|
2989
|
-
return vout;
|
|
2990
|
-
}
|
|
2991
|
-
return rb_ca_as_uint64(rb_ca_clip(self, INT2NUM(0),
|
|
2992
|
-
ULL2NUM(18446744073709551615ULL)));
|
|
2993
|
-
}
|
|
2994
|
-
|
|
2995
3153
|
/* ------------------------------------------------------------------------
|
|
2996
3154
|
Global cast functions CA_INT32(data) ... CA_OBJECT(data) etc.
|
|
2997
3155
|
|
|
@@ -3273,7 +3431,7 @@ rb_ca_read_text_as_number (int argc, VALUE *argv, VALUE self)
|
|
|
3273
3431
|
if ( ca->data_type != CA_OBJECT ) {
|
|
3274
3432
|
rb_raise(rb_eArgError, "decimal reading needs an object array");
|
|
3275
3433
|
}
|
|
3276
|
-
if ( ! ca_is_entity(ca) ) {
|
|
3434
|
+
if ( ! ca_is_entity(ca) || ! ca->ptr ) {
|
|
3277
3435
|
src = rb_ca_copy(src);
|
|
3278
3436
|
TypedData_Get_Struct(src, CArray, &carray_data_type, ca);
|
|
3279
3437
|
}
|
|
@@ -3410,7 +3568,7 @@ rb_ca_infer_number_type_of_text (VALUE self)
|
|
|
3410
3568
|
if ( ca->data_type != CA_OBJECT ) {
|
|
3411
3569
|
rb_raise(rb_eArgError, "type inference needs an object array");
|
|
3412
3570
|
}
|
|
3413
|
-
if ( ! ca_is_entity(ca) ) {
|
|
3571
|
+
if ( ! ca_is_entity(ca) || ! ca->ptr ) {
|
|
3414
3572
|
src = rb_ca_copy(src);
|
|
3415
3573
|
TypedData_Get_Struct(src, CArray, &carray_data_type, ca);
|
|
3416
3574
|
}
|
|
@@ -3473,7 +3631,7 @@ ca_const_string_buffer_and_ranges (VALUE cs, VALUE *buffer, CArray **ranges)
|
|
|
3473
3631
|
*buffer = rb_funcall(cs, rb_intern("buffer"), 0);
|
|
3474
3632
|
vranges = rb_ca_parent(cs);
|
|
3475
3633
|
TypedData_Get_Struct(vranges, CArray, &carray_data_type, *ranges);
|
|
3476
|
-
if ( ! ca_is_entity(*ranges) ) {
|
|
3634
|
+
if ( ! ca_is_entity(*ranges) || ! (*ranges)->ptr ) {
|
|
3477
3635
|
vranges = rb_ca_copy(vranges);
|
|
3478
3636
|
TypedData_Get_Struct(vranges, CArray, &carray_data_type, *ranges);
|
|
3479
3637
|
}
|
data/ext/carray_cast_func.rb
CHANGED
|
@@ -24,6 +24,19 @@ type_const = {}
|
|
|
24
24
|
type_const[i] = name
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
+
# The open interval (lo, hi) of doubles whose integer part a type holds:
|
|
28
|
+
# a cast truncates toward zero, so -128.5 still fits int8.
|
|
29
|
+
INTEGER_TRUNC_RANGE = {
|
|
30
|
+
CA_INT8 => ["-129.0", "128.0"],
|
|
31
|
+
CA_UINT8 => ["-1.0", "256.0"],
|
|
32
|
+
CA_INT16 => ["-32769.0", "32768.0"],
|
|
33
|
+
CA_UINT16 => ["-1.0", "65536.0"],
|
|
34
|
+
CA_INT32 => ["-2147483649.0", "2147483648.0"],
|
|
35
|
+
CA_UINT32 => ["-1.0", "4294967296.0"],
|
|
36
|
+
CA_INT64 => ["-9223372036854775808.0", "9223372036854775808.0"],
|
|
37
|
+
CA_UINT64 => ["-1.0", "18446744073709551616.0"],
|
|
38
|
+
}
|
|
39
|
+
|
|
27
40
|
ctype = {
|
|
28
41
|
CA_FIXLEN => "fixlen",
|
|
29
42
|
CA_BOOLEAN => "boolean8_t",
|
|
@@ -42,6 +55,12 @@ ctype = {
|
|
|
42
55
|
CA_OBJECT => "VALUE"
|
|
43
56
|
}
|
|
44
57
|
|
|
58
|
+
# The type a cast reads and writes a cell through. A view's cells need not
|
|
59
|
+
# be aligned to their size (a struct member at offset 1, a refer with a
|
|
60
|
+
# byte offset), so a pointer to a multi-byte cell is the unaligned typedef
|
|
61
|
+
# from carray.h; ctype stays the plain name the functions are called by.
|
|
62
|
+
utype = Hash.new { |h, c| h[c] = %w[fixlen boolean8_t int8_t uint8_t].include?(c) ? c : "ca_u_#{c}" }
|
|
63
|
+
|
|
45
64
|
obj2cval = {
|
|
46
65
|
CA_FIXLEN => nil,
|
|
47
66
|
CA_BOOLEAN => "OBJ2BOOL",
|
|
@@ -256,7 +275,7 @@ FIXLEN.each do |type1|
|
|
|
256
275
|
{
|
|
257
276
|
char *p1 = ptr1;
|
|
258
277
|
ca_size_t bytes;
|
|
259
|
-
|
|
278
|
+
ca_u_VALUE *p2 = ptr2;
|
|
260
279
|
if ( a1 == NULL ) {
|
|
261
280
|
rb_raise(rb_eRuntimeError, "[BUG] failed to cast fixlen -> object");
|
|
262
281
|
}
|
|
@@ -291,8 +310,8 @@ puts
|
|
|
291
310
|
static void
|
|
292
311
|
ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
|
|
293
312
|
{
|
|
294
|
-
#{ctype1} *p1 = ptr1;
|
|
295
|
-
#{ctype2} *p2 = ptr2;
|
|
313
|
+
#{utype[ctype1]} *p1 = ptr1;
|
|
314
|
+
#{utype[ctype2]} *p2 = ptr2;
|
|
296
315
|
#{ctype1} q;
|
|
297
316
|
if ( m ) {
|
|
298
317
|
while ( n-- ) {
|
|
@@ -336,22 +355,33 @@ puts
|
|
|
336
355
|
ctype1 = ctype[type1]
|
|
337
356
|
ctype2 = ctype[type2]
|
|
338
357
|
CA_CAST_TABLE[type1][type2] = "ca_cast_#{ctype1}_#{ctype2}"
|
|
339
|
-
# float / complex -> integer: a NaN
|
|
340
|
-
#
|
|
341
|
-
#
|
|
342
|
-
#
|
|
358
|
+
# float / complex -> integer: a NaN, an infinity, or a value whose
|
|
359
|
+
# integer part the type cannot hold has no integer, and C leaves its
|
|
360
|
+
# conversion undefined (x86 gives the type's minimum, ARM saturates). A
|
|
361
|
+
# cell that is not masked refuses it before anything is written.
|
|
362
|
+
# #to_type masks such cells first (UNDEF), so only a store, a view and a
|
|
363
|
+
# single cell reach the raise. The range is the open interval of values
|
|
364
|
+
# that truncate into the type, in double; for int64 the lower end is
|
|
365
|
+
# taken as closed, since -2**63-1 rounds to -2**63 in double.
|
|
343
366
|
nan_check = ""
|
|
344
367
|
if (FLOAT+[CA_CMPLX64, CA_CMPLX128]).include?(type1) && INTEGER.include?(type2)
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
368
|
+
complex = [CA_CMPLX64, CA_CMPLX128].include?(type1)
|
|
369
|
+
real = complex ? "creal(q1[k])" : "q1[k]"
|
|
370
|
+
lo, hi = INTEGER_TRUNC_RANGE[type2]
|
|
371
|
+
lo_cmp = ( type2 == CA_INT64 ) ? ">=" : ">"
|
|
372
|
+
fits = "( v #{lo_cmp} #{lo} && v < #{hi} )"
|
|
373
|
+
fits = "( #{fits} && ! isnan(cimag(q1[k])) )" if complex
|
|
350
374
|
nan_check = <<-END_CHECK.gsub(/^ {6}/, '')
|
|
351
375
|
for (k=0; k<n; k++) {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
376
|
+
double v = (double) #{real};
|
|
377
|
+
if ( ( ! m || ! m[k] ) && ! #{fits} ) {
|
|
378
|
+
if ( isfinite(v)#{complex ? " && ! isnan(cimag(q1[k]))" : ""} ) {
|
|
379
|
+
rb_raise(rb_eRangeError, "%s: %.17g is out of range for %s",
|
|
380
|
+
ca_calling_method_name(), v, ca_type_name[#{type_const[type2]}]);
|
|
381
|
+
}
|
|
382
|
+
rb_raise(rb_eFloatDomainError, "%s: %s cannot be converted to %s",
|
|
383
|
+
ca_calling_method_name(), isinf(v) ? "an infinity" : "NaN",
|
|
384
|
+
ca_type_name[#{type_const[type2]}]);
|
|
355
385
|
}
|
|
356
386
|
}
|
|
357
387
|
END_CHECK
|
|
@@ -367,10 +397,10 @@ puts
|
|
|
367
397
|
static void
|
|
368
398
|
ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
|
|
369
399
|
{
|
|
370
|
-
#{ctype1} *q1 = ptr1;
|
|
371
|
-
#{ctype1} *p1 = q1;
|
|
372
|
-
#{ctype2} *q2 = ptr2;
|
|
373
|
-
#{ctype2} *p2 = q2;
|
|
400
|
+
#{utype[ctype1]} *q1 = ptr1;
|
|
401
|
+
#{utype[ctype1]} *p1 = q1;
|
|
402
|
+
#{utype[ctype2]} *q2 = ptr2;
|
|
403
|
+
#{utype[ctype2]} *p2 = q2;
|
|
374
404
|
ca_size_t k;
|
|
375
405
|
@@NAN_CHECK@@
|
|
376
406
|
if ( m ) {
|
|
@@ -412,8 +442,8 @@ puts
|
|
|
412
442
|
static void
|
|
413
443
|
ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
|
|
414
444
|
{
|
|
415
|
-
#{ctype1} *p1 = ptr1;
|
|
416
|
-
|
|
445
|
+
#{utype[ctype1]} *p1 = ptr1;
|
|
446
|
+
ca_u_VALUE *p2 = ptr2;
|
|
417
447
|
if ( m ) {
|
|
418
448
|
while ( n-- ) {
|
|
419
449
|
if ( !*m ) { *p2 = (VALUE) #{conv}(*p1); }
|
|
@@ -441,7 +471,7 @@ OBJECT.each do |type1|
|
|
|
441
471
|
static void
|
|
442
472
|
ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
|
|
443
473
|
{
|
|
444
|
-
|
|
474
|
+
ca_u_VALUE *p1 = ptr1;
|
|
445
475
|
char *p2 = ptr2;
|
|
446
476
|
ca_size_t bytes;
|
|
447
477
|
if ( a2 == NULL ) {
|
|
@@ -529,8 +559,8 @@ OBJECT.each do |type1|
|
|
|
529
559
|
static void
|
|
530
560
|
ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
|
|
531
561
|
{
|
|
532
|
-
|
|
533
|
-
#{ctype2} *p2 = ptr2;
|
|
562
|
+
ca_u_VALUE *p1 = ptr1;
|
|
563
|
+
#{utype[ctype2]} *p2 = ptr2;
|
|
534
564
|
#{oktype2} tmp;
|
|
535
565
|
if ( m ) {
|
|
536
566
|
while ( n-- ) {
|
|
@@ -557,8 +587,8 @@ OBJECT.each do |type1|
|
|
|
557
587
|
static void
|
|
558
588
|
ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
|
|
559
589
|
{
|
|
560
|
-
|
|
561
|
-
#{ctype2} *p2 = ptr2;
|
|
590
|
+
ca_u_VALUE *p1 = ptr1;
|
|
591
|
+
#{utype[ctype2]} *p2 = ptr2;
|
|
562
592
|
if ( m ) {
|
|
563
593
|
while ( n-- ) {
|
|
564
594
|
if ( !*m ) { *p2 = (#{ctype2}) #{conv}(*p1); }
|