carray 3.0.3 → 3.0.4
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 +264 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +1 -6
- 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 +205 -134
- data/ext/ca_compare.c +7 -18
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1234 -1994
- data/ext/ca_kernel_iterator.h +391 -437
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +96 -39
- data/ext/ca_obj_bincmp.c +24 -21
- data/ext/ca_obj_binop.c +15 -26
- data/ext/ca_obj_bitarray.c +3 -2
- data/ext/ca_obj_bitfield.c +5 -6
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +5 -6
- data/ext/ca_obj_const_string.c +173 -19
- data/ext/ca_obj_face.c +238 -57
- 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 +17 -5
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +406 -132
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +67 -57
- data/ext/ca_obj_object.c +157 -51
- data/ext/ca_obj_record.c +12 -7
- data/ext/ca_obj_reduce.c +13 -8
- data/ext/ca_obj_refer.c +25 -27
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +6 -5
- data/ext/ca_obj_select.c +14 -9
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +11 -1
- data/ext/ca_obj_stack.c +179 -34
- data/ext/ca_obj_stride.c +162 -115
- data/ext/ca_obj_string.c +71 -4
- data/ext/ca_obj_tile.c +6 -5
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +5 -3
- data/ext/ca_obj_triop.c +23 -32
- data/ext/ca_obj_window.c +190 -26
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +181 -75
- data/ext/carray_access.c +184 -96
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +89 -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 +142 -24
- data/ext/carray_cast_func.rb +46 -6
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +16 -7
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +147 -55
- data/ext/carray_count.c +50 -20
- data/ext/carray_element.c +76 -33
- data/ext/carray_factorize.c +118 -64
- data/ext/carray_generate.c +191 -50
- data/ext/carray_histogram.c +62 -17
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +336 -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 +10906 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +292 -72
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +124 -47
- data/ext/carray_order.c +384 -76
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +67 -13
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +63 -38
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +91 -28
- data/ext/carray_sort.c +35 -35
- data/ext/carray_struct.c +19 -18
- data/ext/carray_test.c +26 -5
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +246 -45
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +198 -240
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +126 -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 +78 -10
- 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 +165 -43
- data/lib/carray/categorical_iterator.rb +130 -27
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +14 -5
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +7 -1
- data/lib/carray/frame/column_verbs.rb +70 -0
- 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 +246 -21
- data/lib/carray/frame/group.rb +510 -95
- data/lib/carray/frame/io.rb +115 -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 +11 -4
- 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 +182 -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 +53 -36
- 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 +313 -82
- data/lib/carray/serialize.rb +24 -10
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +8 -1
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +19 -8
- data/lib/carray/time.rb +726 -104
- 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_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_cast.rb +10 -0
- data/yard-stubs/carray_conversion.rb +2 -1
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +26 -2
- data/yard-stubs/carray_math.rb +27 -1
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +29 -18
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +14 -9
- 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);
|
|
@@ -1767,8 +1771,11 @@ rb_ca_ptr2ptr (VALUE ra1, void *ptr1, VALUE ra2, void *ptr2)
|
|
|
1767
1771
|
}
|
|
1768
1772
|
|
|
1769
1773
|
|
|
1774
|
+
/* A cell's bytes as the value of self's data type before the last two
|
|
1775
|
+
steps of ca[i]: a boolean is 0 or 1 and a Face cell is its storage
|
|
1776
|
+
value. The element readers call this, check the mask, then decode. */
|
|
1770
1777
|
VALUE
|
|
1771
|
-
|
|
1778
|
+
rb_ca_ptr2obj_storage (VALUE self, void *ptr)
|
|
1772
1779
|
{
|
|
1773
1780
|
volatile VALUE obj;
|
|
1774
1781
|
static CArray dummy;
|
|
@@ -1784,6 +1791,20 @@ rb_ca_ptr2obj (VALUE self, void *ptr)
|
|
|
1784
1791
|
}
|
|
1785
1792
|
}
|
|
1786
1793
|
|
|
1794
|
+
VALUE
|
|
1795
|
+
rb_ca_ptr2obj (VALUE self, void *ptr)
|
|
1796
|
+
{
|
|
1797
|
+
CArray *ca;
|
|
1798
|
+
VALUE obj = rb_ca_ptr2obj_storage(self, ptr);
|
|
1799
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1800
|
+
CA_FACE_STORAGE_TO_ELEMENT_IF_FACE(obj, self, ca);
|
|
1801
|
+
if ( ca->data_type == CA_BOOLEAN &&
|
|
1802
|
+
( obj == INT2FIX(0) || obj == INT2FIX(1) ) ) {
|
|
1803
|
+
obj = ( obj == INT2FIX(1) ) ? Qtrue : Qfalse;
|
|
1804
|
+
}
|
|
1805
|
+
return obj;
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1787
1808
|
/* Surface -> storage-domain conversion for a Face store (mirror of the
|
|
1788
1809
|
storage_to_element read hook). Non-Face `ca` returns `obj` unchanged, so
|
|
1789
1810
|
the non-Face store path is untouched. For a Face, the per-obj_type C
|
|
@@ -1853,7 +1874,7 @@ rb_ca_wrap_writable (VALUE arg, VALUE rtype)
|
|
|
1853
1874
|
if ( rb_obj_is_carray(obj) ) { /* obj == carray */
|
|
1854
1875
|
TypedData_Get_Struct(obj, CArray, &carray_data_type, ca);
|
|
1855
1876
|
if ( ca_is_readonly(ca) ) {
|
|
1856
|
-
|
|
1877
|
+
ca_refuse_read_only();
|
|
1857
1878
|
}
|
|
1858
1879
|
if ( NIL_P(rtype) ) {
|
|
1859
1880
|
data_type = ca->data_type;
|
|
@@ -1891,7 +1912,7 @@ rb_ca_wrap_writable (VALUE arg, VALUE rtype)
|
|
|
1891
1912
|
}
|
|
1892
1913
|
TypedData_Get_Struct(obj, CArray, &carray_data_type, ca);
|
|
1893
1914
|
if ( ca_is_readonly(ca) ) {
|
|
1894
|
-
|
|
1915
|
+
ca_refuse_read_only();
|
|
1895
1916
|
}
|
|
1896
1917
|
if ( NIL_P(rtype) ) {
|
|
1897
1918
|
data_type = ca->data_type;
|
|
@@ -1905,12 +1926,9 @@ rb_ca_wrap_writable (VALUE arg, VALUE rtype)
|
|
|
1905
1926
|
}
|
|
1906
1927
|
}
|
|
1907
1928
|
else if ( rb_memory_view_available_p(obj) ) { /* MemoryView producer */
|
|
1908
|
-
obj =
|
|
1929
|
+
obj = ca_mv_wrap(obj, Qnil, rb_cCAWrap, -1,
|
|
1930
|
+
NIL_P(rtype) ? -1 : rb_ca_guess_type(rtype), 1);
|
|
1909
1931
|
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
1932
|
if ( NIL_P(rtype) ) {
|
|
1915
1933
|
data_type = ca->data_type;
|
|
1916
1934
|
}
|
|
@@ -2029,7 +2047,8 @@ rb_ca_wrap_readonly (VALUE arg, VALUE rtype)
|
|
|
2029
2047
|
}
|
|
2030
2048
|
}
|
|
2031
2049
|
else if ( rb_memory_view_available_p(obj) ) { /* MemoryView producer */
|
|
2032
|
-
obj =
|
|
2050
|
+
obj = ca_mv_wrap(obj, Qnil, rb_cCAWrap, -1,
|
|
2051
|
+
NIL_P(rtype) ? -1 : rb_ca_guess_type(rtype), 0);
|
|
2033
2052
|
TypedData_Get_Struct(obj, CArray, &carray_data_type, ca);
|
|
2034
2053
|
if ( NIL_P(rtype) ) {
|
|
2035
2054
|
data_type = ca->data_type;
|
|
@@ -2171,6 +2190,36 @@ ca_check_integer_fits (VALUE v, int8_t dt)
|
|
|
2171
2190
|
}
|
|
2172
2191
|
}
|
|
2173
2192
|
|
|
2193
|
+
/* The store reader for an integer cell: the value as an Integer, refused
|
|
2194
|
+
when it does not fit the cell's type, as an operator refuses it. A
|
|
2195
|
+
store raises where an array cast (to_type) keeps the C conversion. A
|
|
2196
|
+
non-Integer goes through Integer() (1.5 is 1; nil and NaN raise). */
|
|
2197
|
+
VALUE
|
|
2198
|
+
ca_obj2integer_fitting (VALUE v, int8_t data_type)
|
|
2199
|
+
{
|
|
2200
|
+
VALUE integer = RB_INTEGER_TYPE_P(v) ? v : rb_Integer(v);
|
|
2201
|
+
if ( FIXNUM_P(integer) ) {
|
|
2202
|
+
long x = FIX2LONG(integer);
|
|
2203
|
+
int fits;
|
|
2204
|
+
switch ( data_type ) {
|
|
2205
|
+
case CA_INT8: fits = ( x >= INT8_MIN && x <= INT8_MAX ); break;
|
|
2206
|
+
case CA_UINT8: fits = ( x >= 0 && x <= UINT8_MAX ); break;
|
|
2207
|
+
case CA_INT16: fits = ( x >= INT16_MIN && x <= INT16_MAX ); break;
|
|
2208
|
+
case CA_UINT16: fits = ( x >= 0 && x <= UINT16_MAX ); break;
|
|
2209
|
+
case CA_INT32: fits = ( x >= INT32_MIN && x <= INT32_MAX ); break;
|
|
2210
|
+
case CA_UINT32: fits = ( x >= 0 && (unsigned long) x <= UINT32_MAX ); break;
|
|
2211
|
+
case CA_INT64: fits = 1; break;
|
|
2212
|
+
case CA_UINT64: fits = ( x >= 0 ); break;
|
|
2213
|
+
default: fits = 1; break;
|
|
2214
|
+
}
|
|
2215
|
+
if ( fits ) {
|
|
2216
|
+
return integer;
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
2219
|
+
ca_check_integer_fits(integer, data_type);
|
|
2220
|
+
return integer;
|
|
2221
|
+
}
|
|
2222
|
+
|
|
2174
2223
|
/* A Ruby Integer operand against an integer array is taken in the array's
|
|
2175
2224
|
own data type, refused when it does not fit (ca_check_integer_fits).
|
|
2176
2225
|
Widening instead would make the result's type depend on a scalar's
|
|
@@ -2425,7 +2474,7 @@ ca_arg_to_data_type (VALUE obj)
|
|
|
2425
2474
|
else {
|
|
2426
2475
|
data_type = ca_value_to_data_type(obj);
|
|
2427
2476
|
}
|
|
2428
|
-
|
|
2477
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type);
|
|
2429
2478
|
if ( ! ca_valid[data_type] ) {
|
|
2430
2479
|
rb_raise(rb_eArgError,
|
|
2431
2480
|
"data type '%s' is not valid in this build",
|
|
@@ -2465,6 +2514,9 @@ int8_t
|
|
|
2465
2514
|
ca_promote_type (int8_t a, int8_t b)
|
|
2466
2515
|
{
|
|
2467
2516
|
int test;
|
|
2517
|
+
if ( a <= CA_NONE || a >= CA_NTYPE || b <= CA_NONE || b >= CA_NTYPE ) {
|
|
2518
|
+
rb_raise(rb_eArgError, "invalid data_type id (%i, %i)", (int) a, (int) b);
|
|
2519
|
+
}
|
|
2468
2520
|
if ( a == b ) {
|
|
2469
2521
|
return a;
|
|
2470
2522
|
}
|
|
@@ -2521,6 +2573,49 @@ ca_value_match_type (int8_t t, int8_t a, int8_t b)
|
|
|
2521
2573
|
}
|
|
2522
2574
|
}
|
|
2523
2575
|
|
|
2576
|
+
/* The type a value query and a reference of type `ref` are compared in,
|
|
2577
|
+
by equality or order, as `eq` compares them: the reference is read
|
|
2578
|
+
through a view of that type, so the query is never cut to the
|
|
2579
|
+
reference's type (3.9 does not match 3, -1 does not read as 255).
|
|
2580
|
+
A Float query takes the type the operators give it beside the
|
|
2581
|
+
reference; an Integer query keeps the reference's type when it fits and
|
|
2582
|
+
otherwise the type its value needs, where it matches nothing; a CArray
|
|
2583
|
+
query takes the type the two arrays match in (the common type, widened
|
|
2584
|
+
by ca_value_match_type). Beside a reference that is not a number, a
|
|
2585
|
+
scalar query keeps the reference's type. */
|
|
2586
|
+
int8_t
|
|
2587
|
+
ca_query_match_type (int8_t ref, VALUE query)
|
|
2588
|
+
{
|
|
2589
|
+
int ref_int = ( ref >= CA_INT8 && ref <= CA_UINT64 );
|
|
2590
|
+
int ref_float = ( ref == CA_FLOAT32 || ref == CA_FLOAT64 );
|
|
2591
|
+
if ( rb_obj_is_carray(query) ) {
|
|
2592
|
+
CArray *q;
|
|
2593
|
+
TypedData_Get_Struct(query, CArray, &carray_data_type, q);
|
|
2594
|
+
return ca_value_match_type(ca_promote_type(ref, q->data_type), ref,
|
|
2595
|
+
q->data_type);
|
|
2596
|
+
}
|
|
2597
|
+
if ( ! ref_int && ! ref_float && ref != CA_BOOLEAN ) {
|
|
2598
|
+
return ref;
|
|
2599
|
+
}
|
|
2600
|
+
if ( RB_FLOAT_TYPE_P(query) ) {
|
|
2601
|
+
return ca_promote_scalar_type(ref, query, CA_FLOAT64);
|
|
2602
|
+
}
|
|
2603
|
+
if ( RB_INTEGER_TYPE_P(query) ) {
|
|
2604
|
+
return ref_int ? ca_promote_scalar_type(ref, query, CA_INT64) : ref;
|
|
2605
|
+
}
|
|
2606
|
+
return ref;
|
|
2607
|
+
}
|
|
2608
|
+
|
|
2609
|
+
/* ca.query_match_type(query) -- ca_query_match_type with self as the
|
|
2610
|
+
reference, for the set family and locate_addr. */
|
|
2611
|
+
static VALUE
|
|
2612
|
+
rb_ca_query_match_type (VALUE self, VALUE query)
|
|
2613
|
+
{
|
|
2614
|
+
CArray *ca;
|
|
2615
|
+
GetCArray(self, ca);
|
|
2616
|
+
return rb_ca_data_type_to_sym(ca_query_match_type(ca->data_type, query));
|
|
2617
|
+
}
|
|
2618
|
+
|
|
2524
2619
|
/* ca.value_match_type(t, other_type) -- ca_value_match_type with self's
|
|
2525
2620
|
data type as the first operand, for the set family and locate_addr. */
|
|
2526
2621
|
static VALUE
|
|
@@ -2553,13 +2648,23 @@ ca_arg_is_scalar (VALUE obj)
|
|
|
2553
2648
|
by the rule the operators apply: a scalar of the same kind takes the
|
|
2554
2649
|
array's type (0.1 beside float32 is float32, 1 beside int8 is int8); one
|
|
2555
2650
|
of another kind promotes (1.5 beside int32 is float64). An Integer that
|
|
2556
|
-
does not fit the array's integer type takes
|
|
2557
|
-
|
|
2651
|
+
does not fit the array's integer type takes a type that holds it and the
|
|
2652
|
+
array's values (int64, or object where no integer type does), where an
|
|
2653
|
+
operator would raise RangeError. */
|
|
2558
2654
|
int8_t
|
|
2559
2655
|
ca_promote_scalar_type (int8_t at, VALUE obj, int8_t st)
|
|
2560
2656
|
{
|
|
2561
2657
|
if ( RB_INTEGER_TYPE_P(obj) && at >= CA_INT8 && at <= CA_UINT64 ) {
|
|
2562
|
-
|
|
2658
|
+
int8_t vt;
|
|
2659
|
+
if ( ca_integer_range_side(obj, at) == 0 ) {
|
|
2660
|
+
return at;
|
|
2661
|
+
}
|
|
2662
|
+
/* The type the value needs, widened so that the array's values are
|
|
2663
|
+
kept beside it (a uint64 array and -1 meet in object). */
|
|
2664
|
+
vt = ( ca_integer_range_side(obj, CA_INT64) == 0 ) ? CA_INT64
|
|
2665
|
+
: ( ca_integer_range_side(obj, CA_UINT64) == 0 ) ? CA_UINT64
|
|
2666
|
+
: CA_OBJECT;
|
|
2667
|
+
return ca_value_match_type(ca_promote_type(at, vt), at, vt);
|
|
2563
2668
|
}
|
|
2564
2669
|
if ( ca_cast_table2[st][at] >= 0 ) {
|
|
2565
2670
|
return at;
|
|
@@ -2606,6 +2711,8 @@ rb_ca_s_result_type (int argc, VALUE *argv, VALUE klass)
|
|
|
2606
2711
|
cur = ( cur < 0 ) ? t : ca_promote_scalar_type(cur, argv[i], t);
|
|
2607
2712
|
}
|
|
2608
2713
|
}
|
|
2714
|
+
/* argv points into rest, and classifying an argument can allocate */
|
|
2715
|
+
RB_GC_GUARD(rest);
|
|
2609
2716
|
/* Return Symbol for family consistency with
|
|
2610
2717
|
CArray.value_to_data_type and ca.data_type. */
|
|
2611
2718
|
return rb_ca_data_type_to_sym(cur);
|
|
@@ -2859,14 +2966,23 @@ rb_ca_clip_uint64 (VALUE self)
|
|
|
2859
2966
|
uint64_t *op = (uint64_t *) out->ptr;
|
|
2860
2967
|
ca_size_t n = ca->elements;
|
|
2861
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;
|
|
2862
2971
|
for ( ca_size_t i = 0; i < n; i++ ) {
|
|
2863
2972
|
double v = sp[i];
|
|
2864
|
-
if ( v != v )
|
|
2973
|
+
if ( v != v ) { /* NaN has no integer: refused below */
|
|
2974
|
+
op[i] = 0;
|
|
2975
|
+
if ( ! m || ! m[i] ) found_nan = 1;
|
|
2976
|
+
}
|
|
2865
2977
|
else if ( v >= LIMIT ) op[i] = UINT64_MAX;
|
|
2866
2978
|
else if ( v <= 0.0 ) op[i] = 0;
|
|
2867
2979
|
else op[i] = (uint64_t) v;
|
|
2868
2980
|
}
|
|
2869
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
|
+
}
|
|
2870
2986
|
if ( ca_has_mask(ca) ) {
|
|
2871
2987
|
ca_copy_mask(out, ca);
|
|
2872
2988
|
}
|
|
@@ -2889,7 +3005,7 @@ rb_ca_clip_uint64 (VALUE self)
|
|
|
2889
3005
|
Numeric -> CScalar, or #to_ca when the object answers it
|
|
2890
3006
|
String -> the whitespace / `,` / `;` / `_`->UNDEF parser, which reads
|
|
2891
3007
|
far more naturally in Ruby and so is the one branch that
|
|
2892
|
-
calls back out to it (CArray.
|
|
3008
|
+
calls back out to it (CArray.cast_string in
|
|
2893
3009
|
carray/basics.rb, eager-loaded). It receives the data_type
|
|
2894
3010
|
as a Symbol.
|
|
2895
3011
|
|
|
@@ -3541,6 +3657,8 @@ Init_carray_cast (void)
|
|
|
3541
3657
|
"result_type", rb_ca_s_result_type, -1);
|
|
3542
3658
|
rb_define_private_method(rb_cCArray,
|
|
3543
3659
|
"value_match_type", rb_ca_value_match_type, 2);
|
|
3660
|
+
rb_define_private_method(rb_cCArray,
|
|
3661
|
+
"query_match_type", rb_ca_query_match_type, 1);
|
|
3544
3662
|
|
|
3545
3663
|
rb_define_singleton_method(rb_cCArray,
|
|
3546
3664
|
"promote_list", rb_ca_s_promote_list, -1);
|
|
@@ -3554,7 +3672,7 @@ Init_carray_cast (void)
|
|
|
3554
3672
|
classes registered in ext/carray_data_type.c. */
|
|
3555
3673
|
id_new_cast = rb_intern("new");
|
|
3556
3674
|
id_guess_array_shape_cast = rb_intern("guess_array_shape");
|
|
3557
|
-
id_cast_string = rb_intern("
|
|
3675
|
+
id_cast_string = rb_intern("cast_string");
|
|
3558
3676
|
id_to_ca_cast = rb_intern("to_ca");
|
|
3559
3677
|
id_length_cast = rb_intern("length");
|
|
3560
3678
|
id_begin_cast = rb_intern("begin");
|
data/ext/carray_cast_func.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
data_type = []
|
|
2
|
+
type_const = {}
|
|
2
3
|
%w[
|
|
3
4
|
CA_FIXLEN
|
|
4
5
|
CA_BOOLEAN
|
|
@@ -20,6 +21,7 @@ data_type = []
|
|
|
20
21
|
].each_with_index do |name, i|
|
|
21
22
|
eval("#{name} = #{i}")
|
|
22
23
|
data_type.push(i)
|
|
24
|
+
type_const[i] = name
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
ctype = {
|
|
@@ -300,7 +302,8 @@ puts
|
|
|
300
302
|
*p2 = q;
|
|
301
303
|
}
|
|
302
304
|
else {
|
|
303
|
-
rb_raise(rb_eRangeError, "out of range to cast to boolean (0 or 1)"
|
|
305
|
+
rb_raise(rb_eRangeError, "%s: out of range to cast to boolean (0 or 1)",
|
|
306
|
+
ca_calling_method_name());
|
|
304
307
|
}
|
|
305
308
|
}
|
|
306
309
|
p1++; p2++; m++;
|
|
@@ -313,7 +316,8 @@ puts
|
|
|
313
316
|
*p2 = q;
|
|
314
317
|
}
|
|
315
318
|
else {
|
|
316
|
-
rb_raise(rb_eRangeError, "out of range to cast to boolean (0 or 1)"
|
|
319
|
+
rb_raise(rb_eRangeError, "%s: out of range to cast to boolean (0 or 1)",
|
|
320
|
+
ca_calling_method_name());
|
|
317
321
|
}
|
|
318
322
|
p1++; p2++;
|
|
319
323
|
}
|
|
@@ -332,7 +336,34 @@ puts
|
|
|
332
336
|
ctype1 = ctype[type1]
|
|
333
337
|
ctype2 = ctype[type2]
|
|
334
338
|
CA_CAST_TABLE[type1][type2] = "ca_cast_#{ctype1}_#{ctype2}"
|
|
335
|
-
|
|
339
|
+
# float / complex -> integer: a NaN has no integer and C leaves its
|
|
340
|
+
# conversion undefined. A cell that is not masked refuses it before
|
|
341
|
+
# anything is written. #to_type masks NaN cells first (UNDEF), so
|
|
342
|
+
# only a store, a view and a single cell reach the raise.
|
|
343
|
+
nan_check = ""
|
|
344
|
+
if (FLOAT+[CA_CMPLX64, CA_CMPLX128]).include?(type1) && INTEGER.include?(type2)
|
|
345
|
+
isnan = if [CA_CMPLX64, CA_CMPLX128].include?(type1)
|
|
346
|
+
"( isnan(creal(q1[k])) || isnan(cimag(q1[k])) )"
|
|
347
|
+
else
|
|
348
|
+
"isnan(q1[k])"
|
|
349
|
+
end
|
|
350
|
+
nan_check = <<-END_CHECK.gsub(/^ {6}/, '')
|
|
351
|
+
for (k=0; k<n; k++) {
|
|
352
|
+
if ( ( ! m || ! m[k] ) && #{isnan} ) {
|
|
353
|
+
rb_raise(rb_eFloatDomainError, "%s: NaN cannot be converted to %s",
|
|
354
|
+
ca_calling_method_name(), ca_type_name[#{type_const[type2]}]);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
END_CHECK
|
|
358
|
+
end
|
|
359
|
+
# int64 / uint64 -> float32 / cmplx64 goes through double, as a Ruby
|
|
360
|
+
# Integer stored into a float32 cell does (Integer#to_f). Converting in
|
|
361
|
+
# one step rounds once where the compiler keeps the loop scalar and twice
|
|
362
|
+
# where it vectorises it through double, so the answer for a value past
|
|
363
|
+
# 2**53 would depend on its place in the array.
|
|
364
|
+
via = ( [CA_INT64, CA_UINT64].include?(type1) &&
|
|
365
|
+
[CA_FLOAT32, CA_CMPLX64].include?(type2) ) ? "(double) " : ""
|
|
366
|
+
puts <<-END_DEF.gsub(/^ {6}/, '').sub("@@NAN_CHECK@@\n", nan_check).gsub("@@VIA@@", via)
|
|
336
367
|
static void
|
|
337
368
|
ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
|
|
338
369
|
{
|
|
@@ -341,6 +372,7 @@ puts
|
|
|
341
372
|
#{ctype2} *q2 = ptr2;
|
|
342
373
|
#{ctype2} *p2 = q2;
|
|
343
374
|
ca_size_t k;
|
|
375
|
+
@@NAN_CHECK@@
|
|
344
376
|
if ( m ) {
|
|
345
377
|
boolean8_t *pm = m;
|
|
346
378
|
for (k=0; k<n; k++) {
|
|
@@ -348,7 +380,7 @@ puts
|
|
|
348
380
|
if ( ! *pm ) {
|
|
349
381
|
p1 = q1 + k;
|
|
350
382
|
p2 = q2 + k;
|
|
351
|
-
*p2 = (#{ctype2})
|
|
383
|
+
*p2 = (#{ctype2}) @@VIA@@*p1;
|
|
352
384
|
}
|
|
353
385
|
}
|
|
354
386
|
}
|
|
@@ -356,7 +388,7 @@ puts
|
|
|
356
388
|
for (k=0; k<n; k++) {
|
|
357
389
|
p1 = q1 + k;
|
|
358
390
|
p2 = q2 + k;
|
|
359
|
-
*p2 = (#{ctype2})
|
|
391
|
+
*p2 = (#{ctype2}) @@VIA@@*p1;
|
|
360
392
|
}
|
|
361
393
|
}
|
|
362
394
|
return;
|
|
@@ -478,9 +510,17 @@ OBJECT.each do |type1|
|
|
|
478
510
|
read_ok = "( RB_TYPE_P(*p1, T_STRING) ? " \
|
|
479
511
|
"ca_decimal_string_to(*p1, #{type_name}, p2) : " \
|
|
480
512
|
"( #{conv_ok}(*p1, &tmp) ? ( *p2 = (#{ctype2}) tmp, 1 ) : 0 ) )"
|
|
513
|
+
# A store refuses an integer the cell cannot hold
|
|
514
|
+
# (ca_obj2integer_fitting); to_type, above, keeps the C conversion.
|
|
515
|
+
store_conv = if INTEGER.include?(type2)
|
|
516
|
+
num = [CA_UINT8, CA_UINT16, CA_UINT32, CA_UINT64].include?(type2) ? "rb_num2ull" : "NUM2LL"
|
|
517
|
+
"#{num}(ca_obj2integer_fitting(*p1, #{type_name}))"
|
|
518
|
+
else
|
|
519
|
+
"#{conv}(*p1)"
|
|
520
|
+
end
|
|
481
521
|
read = "if ( RB_TYPE_P(*p1, T_STRING) ) { " \
|
|
482
522
|
"ca_decimal_string_store(*p1, #{type_name}, p2); } " \
|
|
483
|
-
"else { *p2 = (#{ctype2}) #{
|
|
523
|
+
"else { *p2 = (#{ctype2}) #{store_conv}; }"
|
|
484
524
|
else
|
|
485
525
|
read_ok = "( #{conv_ok}(*p1, &tmp) ? ( *p2 = (#{ctype2}) tmp, 1 ) : 0 )"
|
|
486
526
|
read = "*p2 = (#{ctype2}) #{conv}(*p1);"
|
data/ext/carray_class.c
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
---------------------------------------------------------------------------- */
|
|
7
7
|
|
|
8
8
|
#include "carray.h"
|
|
9
|
+
#include "carray_internal.h" /* CA_CHECK_*_GIVEN */
|
|
9
10
|
|
|
10
11
|
/* ------------------------------------------------------------------- */
|
|
11
12
|
/* Symbol cache for data_type code → Symbol lookup.
|
|
@@ -25,7 +26,7 @@ ID ca_data_type_sym[CA_NTYPE];
|
|
|
25
26
|
VALUE
|
|
26
27
|
rb_ca_data_type_to_sym (int8_t data_type)
|
|
27
28
|
{
|
|
28
|
-
|
|
29
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type);
|
|
29
30
|
return ID2SYM(ca_data_type_sym[data_type]);
|
|
30
31
|
}
|
|
31
32
|
|
|
@@ -69,7 +70,7 @@ static VALUE
|
|
|
69
70
|
rb_ca_s_data_type_name (VALUE klass, VALUE type)
|
|
70
71
|
{
|
|
71
72
|
int8_t data_type = rb_ca_guess_type(type);
|
|
72
|
-
|
|
73
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type);
|
|
73
74
|
return rb_str_new2(ca_type_name[data_type]);
|
|
74
75
|
}
|
|
75
76
|
|
|
@@ -84,7 +85,7 @@ static VALUE
|
|
|
84
85
|
rb_ca_s_data_type_code (VALUE klass, VALUE type)
|
|
85
86
|
{
|
|
86
87
|
int8_t data_type = rb_ca_guess_type(type);
|
|
87
|
-
|
|
88
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type);
|
|
88
89
|
return INT2NUM(data_type);
|
|
89
90
|
}
|
|
90
91
|
|
data/ext/carray_config.h
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#ifndef CARRAY_CONFIG_H
|
|
2
|
+
#define CARRAY_CONFIG_H
|
|
3
|
+
#define HAVE_SYS_TYPES_H 1
|
|
4
|
+
#define HAVE_STDINT_H 1
|
|
5
|
+
#define HAVE_TYPE_INT8_T 1
|
|
6
|
+
#define HAVE_TYPE_UINT8_T 1
|
|
7
|
+
#define HAVE_TYPE_INT16_T 1
|
|
8
|
+
#define HAVE_TYPE_UINT16_T 1
|
|
9
|
+
#define HAVE_TYPE_INT32_T 1
|
|
10
|
+
#define HAVE_TYPE_UINT32_T 1
|
|
11
|
+
#define HAVE_TYPE_INT64_T 1
|
|
12
|
+
#define HAVE_TYPE_UINT64_T 1
|
|
13
|
+
#define HAVE_TYPE_LONG_LONG 1
|
|
14
|
+
#define HAVE_TYPE_FLOAT 1
|
|
15
|
+
#define HAVE_TYPE_DOUBLE 1
|
|
16
|
+
#define HAVE_COMPLEX_H 1
|
|
17
|
+
#define HAVE_TYPE_FLOAT_COMPLEX 1
|
|
18
|
+
#define HAVE_TYPE_DOUBLE_COMPLEX 1
|
|
19
|
+
#define HAVE_TGMATH_H 1
|
|
20
|
+
#define HAVE_ATAN2 1
|
|
21
|
+
#define HAVE_HYPOT 1
|
|
22
|
+
#define HAVE_LGAMMA 1
|
|
23
|
+
#define HAVE_EXPM1 1
|
|
24
|
+
#define HAVE_MERGESORT 1
|
|
25
|
+
#define HAVE_STRPTIME 1
|
|
26
|
+
#define HAVE_RB_ARITHMETIC_SEQUENCE_EXTRACT 1
|
|
27
|
+
#define HAVE_RUBY_MEMORY_VIEW_H 1
|
|
28
|
+
#endif
|
data/ext/carray_conversion.c
CHANGED
|
@@ -480,10 +480,16 @@ rb_ca_load_binary (VALUE self, VALUE io)
|
|
|
480
480
|
case T_STRING:
|
|
481
481
|
if ( ca_length(ca) != RSTRING_LEN(io) ) {
|
|
482
482
|
rb_raise(rb_eArgError,
|
|
483
|
-
"data size mismatch (got %" PRId64 " bytes, expected %" PRId64 ")",
|
|
484
|
-
(ca_size_t) RSTRING_LEN(io), (ca_size_t) ca_length(ca));
|
|
483
|
+
"%s: data size mismatch (got %" PRId64 " bytes, expected %" PRId64 ")",
|
|
484
|
+
ca_calling_method_name(), (ca_size_t) RSTRING_LEN(io), (ca_size_t) ca_length(ca));
|
|
485
|
+
}
|
|
486
|
+
if ( ca->data_type == CA_BOOLEAN ) {
|
|
487
|
+
io = rb_str_dup(io);
|
|
488
|
+
rb_str_modify(io);
|
|
489
|
+
ca_boolean_normalize_bytes(RSTRING_PTR(io), ca->elements);
|
|
485
490
|
}
|
|
486
491
|
ca_sync_data(ca, RSTRING_PTR(io));
|
|
492
|
+
RB_GC_GUARD(io);
|
|
487
493
|
return self;
|
|
488
494
|
break;
|
|
489
495
|
default:
|
|
@@ -511,6 +517,9 @@ rb_ca_load_binary (VALUE self, VALUE io)
|
|
|
511
517
|
memcpy(ca->ptr + off, RSTRING_PTR(r), want);
|
|
512
518
|
off += want;
|
|
513
519
|
}
|
|
520
|
+
if ( ca->data_type == CA_BOOLEAN ) {
|
|
521
|
+
ca_boolean_normalize_bytes(ca->ptr, ca->elements);
|
|
522
|
+
}
|
|
514
523
|
ca_sync_detach(ca);
|
|
515
524
|
}
|
|
516
525
|
else {
|
|
@@ -540,7 +549,7 @@ rb_ca_load_binary (VALUE self, VALUE io)
|
|
|
540
549
|
to float. Its digits are those of the decimal (at most 9, which a double
|
|
541
550
|
holds), so Float#to_s writes them. */
|
|
542
551
|
static double
|
|
543
|
-
|
|
552
|
+
ca_double_of_shortest_decimal_of_float32 (float x)
|
|
544
553
|
{
|
|
545
554
|
char buf[32];
|
|
546
555
|
int lo = 1, hi = 9;
|
|
@@ -576,7 +585,7 @@ ca_float32_shortest (float x)
|
|
|
576
585
|
double its shortest decimal reads as, for to_csv to write that decimal.
|
|
577
586
|
The mask is kept. */
|
|
578
587
|
static VALUE
|
|
579
|
-
|
|
588
|
+
rb_ca_widen_keeping_shortest_decimal (VALUE self)
|
|
580
589
|
{
|
|
581
590
|
volatile VALUE out, holder = 0;
|
|
582
591
|
CArray *ca, *co;
|
|
@@ -591,7 +600,7 @@ rb_ca_shortest_float64 (VALUE self)
|
|
|
591
600
|
type = CA_CMPLX128;
|
|
592
601
|
}
|
|
593
602
|
else {
|
|
594
|
-
rb_raise(rb_eCADataTypeError, "
|
|
603
|
+
rb_raise(rb_eCADataTypeError, "__widen_keeping_shortest_decimal__ takes float32 or cmplx64");
|
|
595
604
|
}
|
|
596
605
|
n = ca->elements * (ca->data_type == CA_CMPLX64 ? 2 : 1);
|
|
597
606
|
out = rb_carray_new_safe(type, ca->ndim, ca->dim, 0, NULL);
|
|
@@ -601,7 +610,7 @@ rb_ca_shortest_float64 (VALUE self)
|
|
|
601
610
|
double *dst = (double *) co->ptr;
|
|
602
611
|
ca_copy_data(ca, (char *) src);
|
|
603
612
|
for (i = 0; i < n; i++) {
|
|
604
|
-
dst[i] =
|
|
613
|
+
dst[i] = ca_double_of_shortest_decimal_of_float32(src[i]);
|
|
605
614
|
}
|
|
606
615
|
ALLOCV_END(holder);
|
|
607
616
|
}
|
|
@@ -627,7 +636,7 @@ Init_carray_conversion (void)
|
|
|
627
636
|
rb_define_method(rb_cCArray, "dump_binary", rb_ca_dump_binary, -1);
|
|
628
637
|
rb_define_method(rb_cCArray, "to_s", rb_ca_to_s, 0);
|
|
629
638
|
rb_define_method(rb_cCArray, "load_binary", rb_ca_load_binary, 1);
|
|
630
|
-
rb_define_method(rb_cCArray, "
|
|
639
|
+
rb_define_method(rb_cCArray, "__widen_keeping_shortest_decimal__", rb_ca_widen_keeping_shortest_decimal, 0);
|
|
631
640
|
|
|
632
641
|
/* CAREFUL: do not bind #to_ary — implicit array coercion in Ruby core
|
|
633
642
|
(splat / multiple assignment / Array()) then triggers on any CArray
|
data/ext/carray_copy.c
CHANGED
|
@@ -36,6 +36,42 @@ ca_fill_or_free (CArray *co, VALUE (*fill)(VALUE), VALUE arg)
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
void
|
|
40
|
+
ca_fill_or_xfree (void *buf, VALUE (*fill)(VALUE), VALUE arg)
|
|
41
|
+
{
|
|
42
|
+
int tag = 0;
|
|
43
|
+
rb_protect(fill, arg, &tag);
|
|
44
|
+
if ( tag ) {
|
|
45
|
+
xfree(buf);
|
|
46
|
+
rb_jump_tag(tag);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
void
|
|
51
|
+
ca_fill_or_detach (int n, CArray **list, VALUE (*fill)(VALUE), VALUE arg)
|
|
52
|
+
{
|
|
53
|
+
int tag = 0;
|
|
54
|
+
int k;
|
|
55
|
+
rb_protect(fill, arg, &tag);
|
|
56
|
+
if ( tag ) {
|
|
57
|
+
for ( k = 0; k < n; k++ ) {
|
|
58
|
+
ca_detach(list[k]);
|
|
59
|
+
}
|
|
60
|
+
rb_jump_tag(tag);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
VALUE
|
|
65
|
+
ca_view_inherit_mask (VALUE view)
|
|
66
|
+
{
|
|
67
|
+
CArray *ca = (CArray *) view;
|
|
68
|
+
CArray *parent = ((CAView *) ca)->parent;
|
|
69
|
+
if ( parent && ca_has_mask(parent) ) {
|
|
70
|
+
ca_create_mask(ca);
|
|
71
|
+
}
|
|
72
|
+
return Qnil;
|
|
73
|
+
}
|
|
74
|
+
|
|
39
75
|
static VALUE
|
|
40
76
|
ca_copy_fill (VALUE arg)
|
|
41
77
|
{
|
|
@@ -173,7 +209,7 @@ rb_ca_to_ca (int argc, VALUE *argv, VALUE self)
|
|
|
173
209
|
CArray *ca;
|
|
174
210
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
175
211
|
if ( ca_is_readonly(ca) ) {
|
|
176
|
-
|
|
212
|
+
ca_refuse_read_only();
|
|
177
213
|
}
|
|
178
214
|
}
|
|
179
215
|
return self;
|
|
@@ -220,7 +256,7 @@ CArray *
|
|
|
220
256
|
ca_template_safe2 (void *ap, int8_t data_type, ca_size_t bytes)
|
|
221
257
|
{
|
|
222
258
|
CArray *ca = (CArray *) ap;
|
|
223
|
-
|
|
259
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type);
|
|
224
260
|
if ( ca_is_scalar(ca) ) {
|
|
225
261
|
return (CArray*) cscalar_new(data_type, bytes, NULL);
|
|
226
262
|
}
|
|
@@ -261,6 +297,19 @@ rb_ca_template_kw (int argc, VALUE *argv, VALUE ropt, VALUE self)
|
|
|
261
297
|
obj = ca_wrap_struct(co);
|
|
262
298
|
}
|
|
263
299
|
|
|
300
|
+
/* Preserve the Face identity only for a same-type template (no explicit
|
|
301
|
+
* retype). A retype (template(:boolean)) is a different-typed buffer and
|
|
302
|
+
* must not be re-wrapped as the Face. A same-type template of a Face with
|
|
303
|
+
* a valid blank form (CARecord carries its data_class through the struct
|
|
304
|
+
* tail; identity Faces alias same-type storage) is lifted so the class is
|
|
305
|
+
* preserved. A Face with no valid blank form (CAConstString's content-
|
|
306
|
+
* defined offset+buffer) overrides `template` in Ruby to return a plain
|
|
307
|
+
* array instead of a broken same-class shell. The lift comes before the
|
|
308
|
+
* block initialiser so its values are stored through the Face. */
|
|
309
|
+
if ( NIL_P(rtype) ) {
|
|
310
|
+
CA_FACE_LIFT_IF_FACE(obj, self, ca);
|
|
311
|
+
}
|
|
312
|
+
|
|
264
313
|
if ( rb_block_given_p() ) {
|
|
265
314
|
if ( rb_proc_arity(rb_block_proc()) == 0 ) {
|
|
266
315
|
volatile VALUE rval = rb_yield_values2(0, NULL);
|
|
@@ -283,18 +332,6 @@ rb_ca_template_kw (int argc, VALUE *argv, VALUE ropt, VALUE self)
|
|
|
283
332
|
}
|
|
284
333
|
}
|
|
285
334
|
|
|
286
|
-
/* Preserve the Face identity only for a same-type template (no explicit
|
|
287
|
-
* retype). A retype (template(:boolean)) is a different-typed buffer and
|
|
288
|
-
* must not be re-wrapped as the Face. A same-type template of a Face with
|
|
289
|
-
* a valid blank form (CARecord carries its data_class through the struct
|
|
290
|
-
* tail; identity Faces alias same-type storage) is lifted so the class is
|
|
291
|
-
* preserved. A Face with no valid blank form (CAConstString's content-
|
|
292
|
-
* defined offset+buffer) overrides `template` in Ruby to return a plain
|
|
293
|
-
* array instead of a broken same-class shell. */
|
|
294
|
-
if ( NIL_P(rtype) ) {
|
|
295
|
-
CA_FACE_LIFT_IF_FACE(obj, self, ca);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
335
|
return obj;
|
|
299
336
|
}
|
|
300
337
|
|