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/ca_obj_window.c
CHANGED
|
@@ -801,16 +801,40 @@ ca_window_create_bounds_mask (VALUE view)
|
|
|
801
801
|
return Qnil;
|
|
802
802
|
}
|
|
803
803
|
|
|
804
|
+
typedef struct {
|
|
805
|
+
CAWindow *ca;
|
|
806
|
+
CArray *parent;
|
|
807
|
+
ca_size_t *start;
|
|
808
|
+
ca_size_t *count;
|
|
809
|
+
uint8_t *bounds;
|
|
810
|
+
char *fill;
|
|
811
|
+
} ca_window_new_arg;
|
|
812
|
+
|
|
813
|
+
static VALUE
|
|
814
|
+
ca_window_new_setup (VALUE varg)
|
|
815
|
+
{
|
|
816
|
+
ca_window_new_arg *a = (ca_window_new_arg *) varg;
|
|
817
|
+
ca_window_setup(a->ca, a->parent, a->start, a->count, a->bounds, a->fill);
|
|
818
|
+
return Qnil;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
/* The setup allocates the fill value after the struct and its pool: when
|
|
822
|
+
that fails, the struct goes too. */
|
|
804
823
|
CAWindow *
|
|
805
824
|
ca_window_new (CArray *parent,
|
|
806
825
|
ca_size_t *start, ca_size_t *count, uint8_t *bounds, char *fill)
|
|
807
826
|
{
|
|
808
|
-
|
|
827
|
+
ca_window_new_arg a;
|
|
809
828
|
ca_window_setup(NULL, parent, start, count, bounds, fill);
|
|
810
|
-
ca
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
829
|
+
a.ca = (CAWindow *) ca_array_alloc(CA_OBJ_WINDOW, parent->ndim);
|
|
830
|
+
a.parent = parent;
|
|
831
|
+
a.start = start;
|
|
832
|
+
a.count = count;
|
|
833
|
+
a.bounds = bounds;
|
|
834
|
+
a.fill = fill;
|
|
835
|
+
ca_fill_or_free((CArray *) a.ca, ca_window_new_setup, (VALUE) &a);
|
|
836
|
+
ca_fill_or_free((CArray *) a.ca, ca_window_create_bounds_mask, (VALUE) a.ca);
|
|
837
|
+
return a.ca;
|
|
814
838
|
}
|
|
815
839
|
|
|
816
840
|
static void
|
|
@@ -1674,51 +1698,56 @@ rb_ca_window (int argc, VALUE *argv, VALUE self)
|
|
|
1674
1698
|
if ( SYMBOL_P(rbounds) ) {
|
|
1675
1699
|
rbounds = rb_sym2str(rbounds);
|
|
1676
1700
|
}
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1701
|
+
if ( ! RB_TYPE_P(rbounds, T_STRING) ) {
|
|
1702
|
+
rb_raise(rb_eTypeError,
|
|
1703
|
+
"window: bounds: must be a Symbol or a String (got %s)",
|
|
1704
|
+
rb_obj_classname(rbounds));
|
|
1705
|
+
}
|
|
1706
|
+
cbounds = StringValueCStr(rbounds);
|
|
1707
|
+
if ( ! strcmp(cbounds, "ruby") ) {
|
|
1708
|
+
bounds = CA_BOUNDS_RUBY;
|
|
1709
|
+
}
|
|
1710
|
+
else if ( ! strcmp(cbounds, "strict") ) {
|
|
1711
|
+
bounds = CA_BOUNDS_STRICT;
|
|
1712
|
+
}
|
|
1713
|
+
else if ( ! strcmp(cbounds, "nearest") ) {
|
|
1714
|
+
bounds = CA_BOUNDS_NEAREST;
|
|
1715
|
+
}
|
|
1716
|
+
else if ( ! strcmp(cbounds, "periodic") ) {
|
|
1717
|
+
rb_raise(rb_eArgError,
|
|
1718
|
+
"bounds=>'periodic' removed in 3.0; "
|
|
1719
|
+
"use CArray#roll(...) for cyclic shift "
|
|
1720
|
+
"(returns a CARoll view)");
|
|
1721
|
+
}
|
|
1722
|
+
else if ( ! strcmp(cbounds, "reflect") ) {
|
|
1723
|
+
rb_raise(rb_eArgError,
|
|
1724
|
+
"bounds=>'reflect' removed in 3.0; "
|
|
1725
|
+
"there is no view-based alternative");
|
|
1726
|
+
}
|
|
1727
|
+
else if ( ! strcmp(cbounds, "mask") ) {
|
|
1728
|
+
rb_warn("CAWindow option :bounds=>\"mask\" will be obsolete");
|
|
1729
|
+
rb_warn("use ca.window(..., fill_value: UNDEF)");
|
|
1730
|
+
bounds = CA_BOUNDS_MASK;
|
|
1731
|
+
}
|
|
1732
|
+
else if ( ! strcmp(cbounds, "fill") ) {
|
|
1733
|
+
bounds = ( rfval == CA_UNDEF ) ? CA_BOUNDS_MASK : CA_BOUNDS_FILL;
|
|
1734
|
+
}
|
|
1735
|
+
else {
|
|
1736
|
+
rb_raise(rb_eArgError,
|
|
1737
|
+
"window: unknown bounds: '%s'", cbounds);
|
|
1738
|
+
}
|
|
1739
|
+
/* A fill value says what the cells outside the array are; the other
|
|
1740
|
+
policies say something else about them. */
|
|
1741
|
+
if ( rfval != CA_UNSPECIFIED
|
|
1742
|
+
&& bounds != CA_BOUNDS_FILL && bounds != CA_BOUNDS_MASK ) {
|
|
1743
|
+
rb_raise(rb_eArgError,
|
|
1744
|
+
"window: fill_value: is for bounds: :fill, not :%s", cbounds);
|
|
1745
|
+
}
|
|
1746
|
+
if ( rfval != CA_UNSPECIFIED && rfval != CA_UNDEF
|
|
1747
|
+
&& bounds == CA_BOUNDS_MASK ) {
|
|
1748
|
+
rb_raise(rb_eArgError,
|
|
1749
|
+
"window: fill_value: %+"PRIsVALUE" conflicts with bounds: :mask "
|
|
1750
|
+
"(use fill_value: UNDEF to mask the cells outside)", rfval);
|
|
1722
1751
|
}
|
|
1723
1752
|
}
|
|
1724
1753
|
|
|
@@ -1953,6 +1982,7 @@ Init_ca_obj_window (void)
|
|
|
1953
1982
|
&cawindow_data_type,
|
|
1954
1983
|
rb_cCAWindowMask,
|
|
1955
1984
|
&cawindow_mask_data_type, &ca_window_func, sizeof(ca_window_func));
|
|
1985
|
+
ca_register_cell_moving_view(CA_OBJ_WINDOW);
|
|
1956
1986
|
rb_define_const(rb_cObject, "CA_OBJ_WINDOW", INT2NUM(CA_OBJ_WINDOW));
|
|
1957
1987
|
|
|
1958
1988
|
rb_define_method(rb_cCArray, "window", rb_ca_window, -1);
|
data/ext/ca_op_ipower.c
CHANGED
|
@@ -110,9 +110,9 @@ ca_binop_func_t ca_binop_ipower[CA_NTYPE] = {
|
|
|
110
110
|
|
|
111
111
|
static void
|
|
112
112
|
ca_ipower_float32_t (ca_size_t n, boolean8_t *m,
|
|
113
|
-
char *ptr1,
|
|
113
|
+
char *ptr1, int64_t ipow, char *ptr2)
|
|
114
114
|
{
|
|
115
|
-
|
|
115
|
+
ca_u_float32_t *p1 = (ca_u_float32_t *) ptr1, *p2 = (ca_u_float32_t *) ptr2;
|
|
116
116
|
if ( m ) {
|
|
117
117
|
while (n--) {
|
|
118
118
|
if ( ! *m++ ) { *p2 = op_powi_float32_t(*p1, ipow); }
|
|
@@ -125,9 +125,9 @@ ca_ipower_float32_t (ca_size_t n, boolean8_t *m,
|
|
|
125
125
|
|
|
126
126
|
static void
|
|
127
127
|
ca_ipower_float64_t (ca_size_t n, boolean8_t *m,
|
|
128
|
-
char *ptr1,
|
|
128
|
+
char *ptr1, int64_t ipow, char *ptr2)
|
|
129
129
|
{
|
|
130
|
-
|
|
130
|
+
ca_u_float64_t *p1 = (ca_u_float64_t *) ptr1, *p2 = (ca_u_float64_t *) ptr2;
|
|
131
131
|
if ( m ) {
|
|
132
132
|
while (n--) {
|
|
133
133
|
if ( ! *m++ ) { *p2 = op_powi_float64_t(*p1, ipow); }
|
|
@@ -140,9 +140,9 @@ ca_ipower_float64_t (ca_size_t n, boolean8_t *m,
|
|
|
140
140
|
|
|
141
141
|
static void
|
|
142
142
|
ca_ipower_cmplx64_t (ca_size_t n, boolean8_t *m,
|
|
143
|
-
char *ptr1,
|
|
143
|
+
char *ptr1, int64_t ipow, char *ptr2)
|
|
144
144
|
{
|
|
145
|
-
|
|
145
|
+
ca_u_cmplx64_t *p1 = (ca_u_cmplx64_t *) ptr1, *p2 = (ca_u_cmplx64_t *) ptr2;
|
|
146
146
|
if ( m ) {
|
|
147
147
|
while (n--) {
|
|
148
148
|
if ( ! *m++ ) { *p2 = op_powi_cmplx64_t(*p1, ipow); }
|
|
@@ -155,9 +155,9 @@ ca_ipower_cmplx64_t (ca_size_t n, boolean8_t *m,
|
|
|
155
155
|
|
|
156
156
|
static void
|
|
157
157
|
ca_ipower_cmplx128_t (ca_size_t n, boolean8_t *m,
|
|
158
|
-
char *ptr1,
|
|
158
|
+
char *ptr1, int64_t ipow, char *ptr2)
|
|
159
159
|
{
|
|
160
|
-
|
|
160
|
+
ca_u_cmplx128_t *p1 = (ca_u_cmplx128_t *) ptr1, *p2 = (ca_u_cmplx128_t *) ptr2;
|
|
161
161
|
if ( m ) {
|
|
162
162
|
while (n--) {
|
|
163
163
|
if ( ! *m++ ) { *p2 = op_powi_cmplx128_t(*p1, ipow); }
|
|
@@ -195,10 +195,10 @@ rb_ca_ipower (VALUE self, VALUE other)
|
|
|
195
195
|
{
|
|
196
196
|
volatile VALUE obj;
|
|
197
197
|
CArray *ca, *co;
|
|
198
|
-
|
|
198
|
+
int64_t ipow;
|
|
199
199
|
boolean8_t *m;
|
|
200
200
|
|
|
201
|
-
ipow =
|
|
201
|
+
ipow = NUM2LL(other);
|
|
202
202
|
|
|
203
203
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
204
204
|
|
|
@@ -252,10 +252,10 @@ static VALUE
|
|
|
252
252
|
rb_ca_ipower_bang (VALUE self, VALUE other)
|
|
253
253
|
{
|
|
254
254
|
CArray *ca;
|
|
255
|
-
|
|
255
|
+
int64_t ipow;
|
|
256
256
|
boolean8_t *m;
|
|
257
257
|
|
|
258
|
-
ipow =
|
|
258
|
+
ipow = NUM2LL(other);
|
|
259
259
|
|
|
260
260
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
261
261
|
|
data/ext/ca_sort_kernels.h
CHANGED
|
@@ -62,11 +62,14 @@ void ca_sort_merge_f64 (double *a, double *aux, ca_size_t n);
|
|
|
62
62
|
ca_size_t ca_partition_nan_f32 (float32_t *a, ca_size_t n);
|
|
63
63
|
ca_size_t ca_partition_nan_f64 (double *a, ca_size_t n);
|
|
64
64
|
|
|
65
|
-
/*
|
|
65
|
+
/* Pair variant of NaN pre-partition for float argsort kernels. scratch
|
|
66
|
+
holds n pairs; its contents on return are unspecified. */
|
|
66
67
|
struct ca_pair_f32;
|
|
67
68
|
struct ca_pair_f64;
|
|
68
|
-
ca_size_t ca_partition_nan_pair_f32 (struct ca_pair_f32 *a, ca_size_t n
|
|
69
|
-
|
|
69
|
+
ca_size_t ca_partition_nan_pair_f32 (struct ca_pair_f32 *a, ca_size_t n,
|
|
70
|
+
struct ca_pair_f32 *scratch);
|
|
71
|
+
ca_size_t ca_partition_nan_pair_f64 (struct ca_pair_f64 *a, ca_size_t n,
|
|
72
|
+
struct ca_pair_f64 *scratch);
|
|
70
73
|
|
|
71
74
|
/* P.9: value-level quickselect for partition_copy.
|
|
72
75
|
Reorders a[0..n) so that a[kth] is exact + left/right regions
|
data/ext/caframe_csv_reader.c
CHANGED
data/ext/carray.h
CHANGED
|
@@ -173,6 +173,39 @@ typedef int8_t boolean8_t;
|
|
|
173
173
|
#define CA_ALIGN_CMPLX128 offsetof(struct { char c; cmplx128_t x; }, x)
|
|
174
174
|
#define CA_ALIGN_OBJECT offsetof(struct { char c; VALUE x; }, x)
|
|
175
175
|
|
|
176
|
+
/* Cell types that may sit at any byte. A view's cells need not be aligned
|
|
177
|
+
to their size: a struct member at offset 1, a refer with a byte offset,
|
|
178
|
+
a wrapped external buffer. Reading a cell through a plain `double *`
|
|
179
|
+
there is undefined (x86 vector code may assume the alignment), so a
|
|
180
|
+
kernel reads and writes cells through these. Same size and value as the
|
|
181
|
+
plain type; only the alignment the compiler may assume is 1. */
|
|
182
|
+
#if defined(__GNUC__) || defined(__clang__)
|
|
183
|
+
# define CA_UNALIGNED __attribute__((aligned(1)))
|
|
184
|
+
#else
|
|
185
|
+
# define CA_UNALIGNED
|
|
186
|
+
#endif
|
|
187
|
+
typedef boolean8_t ca_u_boolean8_t;
|
|
188
|
+
typedef int8_t ca_u_int8_t;
|
|
189
|
+
typedef uint8_t ca_u_uint8_t;
|
|
190
|
+
typedef int16_t ca_u_int16_t CA_UNALIGNED;
|
|
191
|
+
typedef uint16_t ca_u_uint16_t CA_UNALIGNED;
|
|
192
|
+
typedef int32_t ca_u_int32_t CA_UNALIGNED;
|
|
193
|
+
typedef uint32_t ca_u_uint32_t CA_UNALIGNED;
|
|
194
|
+
typedef int64_t ca_u_int64_t CA_UNALIGNED;
|
|
195
|
+
typedef uint64_t ca_u_uint64_t CA_UNALIGNED;
|
|
196
|
+
typedef float32_t ca_u_float32_t CA_UNALIGNED;
|
|
197
|
+
typedef float64_t ca_u_float64_t CA_UNALIGNED;
|
|
198
|
+
typedef cmplx64_t ca_u_cmplx64_t CA_UNALIGNED;
|
|
199
|
+
typedef cmplx128_t ca_u_cmplx128_t CA_UNALIGNED;
|
|
200
|
+
typedef VALUE ca_u_VALUE CA_UNALIGNED;
|
|
201
|
+
|
|
202
|
+
typedef ca_u_float32_t ca_u_float;
|
|
203
|
+
typedef ca_u_float64_t ca_u_double;
|
|
204
|
+
|
|
205
|
+
/* CA_U(float64_t) is ca_u_float64_t (and CA_U(double) ca_u_double): for a
|
|
206
|
+
macro that takes the cell type. */
|
|
207
|
+
#define CA_U(type) ca_u_##type
|
|
208
|
+
|
|
176
209
|
/* -------------------------------------------------------------------- */
|
|
177
210
|
|
|
178
211
|
#define CA_OBJ_TYPE_MAX 256
|
|
@@ -204,7 +237,8 @@ typedef int8_t boolean8_t;
|
|
|
204
237
|
routines that walk a single ->parent test this flag and instead fold over
|
|
205
238
|
the parents[] exposed by the CAMultiParent layout convention. */
|
|
206
239
|
#define CA_FLAG_MULTI_PARENTS 32
|
|
207
|
-
|
|
240
|
+
/* bit 64 (formerly CA_FLAG_CYCLE_CHECK) is free: a cyclic read is found
|
|
241
|
+
without writing to the array (ca_test_cyclic_check). */
|
|
208
242
|
#define CA_FLAG_IS_FACE 128
|
|
209
243
|
/* Face opt-in ordering/search flags.
|
|
210
244
|
A Face declares that its numeric storage may be descended to for kernel
|
data/ext/carray_access.c
CHANGED
|
@@ -193,6 +193,14 @@ rb_ca_fill (VALUE self, VALUE rval)
|
|
|
193
193
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
194
194
|
|
|
195
195
|
if ( ca_is_empty(ca) ) {
|
|
196
|
+
/* No cell to fill, but a value no cell could hold is refused, as an
|
|
197
|
+
assignment to the empty array refuses it. */
|
|
198
|
+
if ( rval != CA_UNDEF && ca->bytes > 0 ) {
|
|
199
|
+
volatile VALUE holder;
|
|
200
|
+
char *fval = ALLOCV_N(char, holder, ca->bytes);
|
|
201
|
+
rb_ca_obj2ptr(self, rval, fval);
|
|
202
|
+
ALLOCV_END(holder);
|
|
203
|
+
}
|
|
196
204
|
return self; /* empty = no-op fill; return self for chaining */
|
|
197
205
|
}
|
|
198
206
|
|
|
@@ -884,9 +892,9 @@ rb_ca_index_restruct_block (int16_t *ndimp, ca_size_t *shrink, ca_size_t *dim,
|
|
|
884
892
|
|
|
885
893
|
offset = 0;
|
|
886
894
|
|
|
887
|
-
if ( idx[0] == -1 ) {
|
|
888
|
-
j =
|
|
889
|
-
|
|
895
|
+
if ( ndim0 > 0 && idx[0] == -1 ) {
|
|
896
|
+
/* j = the number of leading axes collapsed by a scalar index */
|
|
897
|
+
for (j=1; j<ndim0 && idx[j] == -1; j++) {
|
|
890
898
|
;
|
|
891
899
|
}
|
|
892
900
|
|
|
@@ -1365,6 +1373,7 @@ rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self, CArray *ca)
|
|
|
1365
1373
|
element, which is what the shape rules then hold it to. */
|
|
1366
1374
|
if ( nscalar == nclean ) {
|
|
1367
1375
|
VALUE blocks[CA_RANK_MAX];
|
|
1376
|
+
ca_check_rank_fits(nunder, NULL); /* the result has the :_ axes only */
|
|
1368
1377
|
for (i = 0; i < nclean; i++) {
|
|
1369
1378
|
blocks[i] = rb_assoc_new(clean[i], INT2FIX(1));
|
|
1370
1379
|
}
|
|
@@ -1379,6 +1388,10 @@ rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self, CArray *ca)
|
|
|
1379
1388
|
|
|
1380
1389
|
TypedData_Get_Struct(base, CArray, &carray_data_type, cb);
|
|
1381
1390
|
|
|
1391
|
+
/* The result has the base's axes and one for each :_, before any is
|
|
1392
|
+
written into final_dims. */
|
|
1393
|
+
ca_check_rank_fits((long) nunder + cb->ndim, NULL);
|
|
1394
|
+
|
|
1382
1395
|
/* Reconstruct final shape: walk original argv. :_ -> size-1, scalar
|
|
1383
1396
|
(Integer) -> dropped (skip), else -> base.dim[cursor]. A key gives one
|
|
1384
1397
|
axis, except an integer CArray read alone (a mapping), which gives as
|
|
@@ -1541,75 +1554,37 @@ rb_ca_fetch_slab_sigil (int argc, VALUE *argv, VALUE self)
|
|
|
1541
1554
|
return rb_funcall(klass, rb_intern("new"), 2, base, slab_axes);
|
|
1542
1555
|
}
|
|
1543
1556
|
|
|
1557
|
+
/* A CScalar is one cell and takes no index: s[] and s[0] name that cell,
|
|
1558
|
+
anything else is refused. */
|
|
1559
|
+
|
|
1560
|
+
static void
|
|
1561
|
+
rb_cs_check_index (int argc, VALUE *argv, const char *op)
|
|
1562
|
+
{
|
|
1563
|
+
if ( argc == 0 ) {
|
|
1564
|
+
return;
|
|
1565
|
+
}
|
|
1566
|
+
if ( argc == 1 && FIXNUM_P(argv[0]) && FIX2LONG(argv[0]) == 0 ) {
|
|
1567
|
+
return;
|
|
1568
|
+
}
|
|
1569
|
+
rb_raise(rb_eArgError,
|
|
1570
|
+
"CScalar%s takes no index other than [] or [0]", op);
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1544
1573
|
static VALUE
|
|
1545
1574
|
rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
1546
1575
|
{
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1552
|
-
|
|
1553
|
-
info.range_check = 0;
|
|
1554
|
-
rb_ca_scan_index(ca->ndim, ca->dim, ca->elements, argc, argv, &info);
|
|
1576
|
+
rb_cs_check_index(argc, argv, "#[]");
|
|
1577
|
+
return rb_ca_fetch_addr(self, 0);
|
|
1578
|
+
}
|
|
1555
1579
|
|
|
1556
|
-
|
|
1557
|
-
case CA_REG_ADDRESS_COMPLEX:
|
|
1558
|
-
obj = rb_ca_fetch_addr(self, 0);
|
|
1559
|
-
break;
|
|
1560
|
-
case CA_REG_ADDRESS:
|
|
1561
|
-
obj = rb_ca_fetch_addr(self, 0);
|
|
1562
|
-
break;
|
|
1563
|
-
case CA_REG_FLATTEN:
|
|
1564
|
-
obj = self; /* rb_funcall(self, rb_intern("refer"), 0); */
|
|
1565
|
-
break;
|
|
1566
|
-
case CA_REG_POINT:
|
|
1567
|
-
obj = rb_ca_fetch_addr(self, 0);
|
|
1568
|
-
break;
|
|
1569
|
-
case CA_REG_ALL:
|
|
1570
|
-
obj = self; /* rb_funcall(self, rb_intern("refer"), 0); */
|
|
1571
|
-
break;
|
|
1572
|
-
case CA_REG_BLOCK:
|
|
1573
|
-
obj = self; /* rb_funcall(self, rb_intern("refer"), 0); */
|
|
1574
|
-
break;
|
|
1575
|
-
case CA_REG_SELECT:
|
|
1576
|
-
obj = rb_ca_select_new(self, argv[0]);
|
|
1577
|
-
break;
|
|
1578
|
-
case CA_REG_ITERATOR:
|
|
1579
|
-
obj = rb_ca_slab_iter_new(self, &info);
|
|
1580
|
-
break;
|
|
1581
|
-
case CA_REG_REPEAT:
|
|
1582
|
-
obj = rb_ca_repeat(argc, argv, self);
|
|
1583
|
-
break;
|
|
1584
|
-
case CA_REG_MAPPING:
|
|
1585
|
-
obj = rb_ca_fancy_index_chain(self, argv[0]);
|
|
1586
|
-
break;
|
|
1587
|
-
case CA_REG_GRID:
|
|
1588
|
-
obj = rb_ca_grid(argc, argv, self);
|
|
1589
|
-
break;
|
|
1590
|
-
case CA_REG_METHOD_CALL: {
|
|
1591
|
-
volatile VALUE idx;
|
|
1592
|
-
idx = rb_funcallv_public(self, SYM2ID(info.symbol), argc-1, argv+1);
|
|
1593
|
-
obj = rb_ca_fetch(self, idx);
|
|
1594
|
-
break;
|
|
1595
|
-
}
|
|
1596
|
-
case CA_REG_MEMBER: {
|
|
1597
|
-
volatile VALUE data_class = rb_ca_data_class(self);
|
|
1598
|
-
if ( ! NIL_P(data_class) ) {
|
|
1599
|
-
obj = rb_ca_face_field(self, info.symbol);
|
|
1600
|
-
break;
|
|
1601
|
-
}
|
|
1602
|
-
else {
|
|
1603
|
-
rb_raise(rb_eIndexError,
|
|
1604
|
-
"can't refer member of carray doesn't have data_class");
|
|
1605
|
-
}
|
|
1606
|
-
break;
|
|
1607
|
-
}
|
|
1608
|
-
default:
|
|
1609
|
-
rb_raise(rb_eIndexError, "invalid index specified");
|
|
1610
|
-
}
|
|
1580
|
+
static VALUE rb_ca_store_method (int argc, VALUE *argv, VALUE self);
|
|
1611
1581
|
|
|
1612
|
-
|
|
1582
|
+
static VALUE
|
|
1583
|
+
rb_cs_store_method (int argc, VALUE *argv, VALUE self)
|
|
1584
|
+
{
|
|
1585
|
+
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
|
1586
|
+
rb_cs_check_index(argc - 1, argv, "#[]=");
|
|
1587
|
+
return rb_ca_store_method(argc, argv, self);
|
|
1613
1588
|
}
|
|
1614
1589
|
|
|
1615
1590
|
/* Recursively convert a store rvalue's surface value objects into
|
|
@@ -2430,6 +2405,7 @@ Init_carray_access (void)
|
|
|
2430
2405
|
rb_define_method(rb_cCArray, "[]=", rb_ca_store_method, -1);
|
|
2431
2406
|
|
|
2432
2407
|
rb_define_method(rb_cCScalar, "[]", rb_cs_fetch_method, -1);
|
|
2408
|
+
rb_define_method(rb_cCScalar, "[]=", rb_cs_store_method, -1);
|
|
2433
2409
|
|
|
2434
2410
|
rb_define_method(rb_cCArray, "fill", rb_ca_fill, 1);
|
|
2435
2411
|
rb_define_method(rb_cCArray, "fill_copy", rb_ca_fill_copy, 1);
|
data/ext/carray_address_basis.c
CHANGED
|
@@ -965,6 +965,139 @@ address_basis_tier (VALUE module, VALUE object)
|
|
|
965
965
|
return INT2NUM(tier_for(ca));
|
|
966
966
|
}
|
|
967
967
|
|
|
968
|
+
/* ------------------------------------------------------------------- */
|
|
969
|
+
|
|
970
|
+
/*
|
|
971
|
+
* call-seq:
|
|
972
|
+
* CArray::AddressBasis.sweep(function, fsync, arrays, *parts) -> nil
|
|
973
|
+
*
|
|
974
|
+
* Runs ca_call_cslab_N_r over `arrays` with the slab function at the address
|
|
975
|
+
* `function`, and hands it as `userdata` a table of pointers to the bytes of
|
|
976
|
+
* each of `parts`, in order.
|
|
977
|
+
*
|
|
978
|
+
* This is what a consumer did through Fiddle: copy the parts into memory
|
|
979
|
+
* from malloc, write the table in front of them, and call the family member
|
|
980
|
+
* for the arity. The copy was there because a String's bytes may be moved
|
|
981
|
+
* by GC compaction, and the sweep allocates -- so a collection can run
|
|
982
|
+
* between taking an address and the slab reading it. It is not needed
|
|
983
|
+
* here: every part is also held in an array on the machine stack for the
|
|
984
|
+
* length of this call, and an object referenced from there is pinned. The
|
|
985
|
+
* VM stack is not enough by itself -- a splat of 128 or more arguments
|
|
986
|
+
* reaches a C method as a heap array, whose elements compaction moves.
|
|
987
|
+
* The machine stack is why the parts are limited to 1024.
|
|
988
|
+
*
|
|
989
|
+
* A part that is not frozen is the slab's to write (an error slot), and is
|
|
990
|
+
* made unshared first so the write lands in that String alone. A frozen
|
|
991
|
+
* part is read only. Each part has to start on an 8-byte boundary, since a
|
|
992
|
+
* slab reads doubles and int64s out of them.
|
|
993
|
+
*/
|
|
994
|
+
static VALUE
|
|
995
|
+
address_basis_sweep (int argc, VALUE *argv, VALUE module)
|
|
996
|
+
{
|
|
997
|
+
volatile VALUE rfunction, rfsync, rarrays;
|
|
998
|
+
ca_cslab_r_t function;
|
|
999
|
+
const char *fsync;
|
|
1000
|
+
VALUE vholder = 0;
|
|
1001
|
+
void **table;
|
|
1002
|
+
VALUE *arrays;
|
|
1003
|
+
volatile VALUE *parts;
|
|
1004
|
+
int i, n, nparts;
|
|
1005
|
+
|
|
1006
|
+
rb_check_arity(argc, 3, UNLIMITED_ARGUMENTS);
|
|
1007
|
+
rfunction = argv[0];
|
|
1008
|
+
rfsync = argv[1];
|
|
1009
|
+
rarrays = argv[2];
|
|
1010
|
+
nparts = argc - 3;
|
|
1011
|
+
|
|
1012
|
+
if ( nparts > 1024 ) {
|
|
1013
|
+
rb_raise(rb_eArgError, "%s: a sweep takes at most 1024 parts, got %d",
|
|
1014
|
+
ca_calling_method_name(), nparts);
|
|
1015
|
+
}
|
|
1016
|
+
/* Held on the machine stack, which the GC scans conservatively and so
|
|
1017
|
+
pins. argv is not written: it may be the storage of a heap array. */
|
|
1018
|
+
parts = ALLOCA_N(VALUE, nparts > 0 ? nparts : 1);
|
|
1019
|
+
for ( i = 0; i < nparts; i++ ) {
|
|
1020
|
+
parts[i] = argv[3 + i];
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
Check_Type(rarrays, T_ARRAY);
|
|
1024
|
+
n = (int) RARRAY_LEN(rarrays);
|
|
1025
|
+
if ( n < 1 || n > 7 ) {
|
|
1026
|
+
rb_raise(rb_eArgError, "%s: a sweep takes 1 to 7 arrays, got %d",
|
|
1027
|
+
ca_calling_method_name(), n);
|
|
1028
|
+
}
|
|
1029
|
+
fsync = StringValueCStr(rfsync);
|
|
1030
|
+
if ( (int) strlen(fsync) != n ) {
|
|
1031
|
+
rb_raise(rb_eArgError, "%s: fsync has %d characters for %d arrays",
|
|
1032
|
+
ca_calling_method_name(), (int) strlen(fsync), n);
|
|
1033
|
+
}
|
|
1034
|
+
for ( i = 0; i < n; i++ ) {
|
|
1035
|
+
if ( fsync[i] != '0' && fsync[i] != '1' ) {
|
|
1036
|
+
rb_raise(rb_eArgError,
|
|
1037
|
+
"%s: fsync character %d is '%c', not '0' (read) or '1' (written)",
|
|
1038
|
+
ca_calling_method_name(), i, fsync[i]);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
function = (ca_cslab_r_t) (uintptr_t) NUM2ULL(rfunction);
|
|
1042
|
+
if ( ! function ) {
|
|
1043
|
+
rb_raise(rb_eArgError, "%s: the slab function's address is zero",
|
|
1044
|
+
ca_calling_method_name());
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
arrays = RARRAY_PTR(rarrays);
|
|
1048
|
+
for ( i = 0; i < n; i++ ) {
|
|
1049
|
+
if ( ! rb_obj_is_kind_of(arrays[i], rb_cCArray) ) {
|
|
1050
|
+
rb_raise(rb_eTypeError, "%s: array %d is not a CArray",
|
|
1051
|
+
ca_calling_method_name(), i);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
for ( i = 0; i < nparts; i++ ) {
|
|
1056
|
+
VALUE part = parts[i];
|
|
1057
|
+
StringValue(part);
|
|
1058
|
+
parts[i] = part;
|
|
1059
|
+
if ( ! OBJ_FROZEN(part) ) {
|
|
1060
|
+
rb_str_modify(part);
|
|
1061
|
+
}
|
|
1062
|
+
if ( (uintptr_t) RSTRING_PTR(part) & 7 ) {
|
|
1063
|
+
rb_raise(rb_eArgError, "%s: part %d does not start on an 8-byte boundary",
|
|
1064
|
+
ca_calling_method_name(), i);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
/* Taken after every check, so a refusal has nothing to free. The sweep
|
|
1069
|
+
itself can raise (a shape that will not broadcast); then the table is
|
|
1070
|
+
left to ALLOCV's own holder, which the GC reclaims. */
|
|
1071
|
+
table = ALLOCV_N(void *, vholder, nparts > 0 ? nparts : 1);
|
|
1072
|
+
for ( i = 0; i < nparts; i++ ) {
|
|
1073
|
+
table[i] = RSTRING_PTR(parts[i]);
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
switch ( n ) {
|
|
1077
|
+
case 1: ca_call_cslab_1_r(function, fsync, arrays[0], table); break;
|
|
1078
|
+
case 2: ca_call_cslab_2_r(function, fsync, arrays[0], arrays[1], table); break;
|
|
1079
|
+
case 3: ca_call_cslab_3_r(function, fsync, arrays[0], arrays[1], arrays[2],
|
|
1080
|
+
table); break;
|
|
1081
|
+
case 4: ca_call_cslab_4_r(function, fsync, arrays[0], arrays[1], arrays[2],
|
|
1082
|
+
arrays[3], table); break;
|
|
1083
|
+
case 5: ca_call_cslab_5_r(function, fsync, arrays[0], arrays[1], arrays[2],
|
|
1084
|
+
arrays[3], arrays[4], table); break;
|
|
1085
|
+
case 6: ca_call_cslab_6_r(function, fsync, arrays[0], arrays[1], arrays[2],
|
|
1086
|
+
arrays[3], arrays[4], arrays[5], table); break;
|
|
1087
|
+
case 7: ca_call_cslab_7_r(function, fsync, arrays[0], arrays[1], arrays[2],
|
|
1088
|
+
arrays[3], arrays[4], arrays[5], arrays[6],
|
|
1089
|
+
table); break;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
ALLOCV_END(vholder);
|
|
1093
|
+
for ( i = 0; i < nparts; i++ ) {
|
|
1094
|
+
RB_GC_GUARD(parts[i]);
|
|
1095
|
+
}
|
|
1096
|
+
RB_GC_GUARD(rarrays);
|
|
1097
|
+
RB_GC_GUARD(rfsync);
|
|
1098
|
+
return Qnil;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
968
1101
|
/* ------------------------------------------------------------------- */
|
|
969
1102
|
/* Init_carray_address_basis */
|
|
970
1103
|
/* ------------------------------------------------------------------- */
|
|
@@ -978,6 +1111,7 @@ Init_carray_address_basis (void)
|
|
|
978
1111
|
rb_define_singleton_method(mAddressBasis, "classify",
|
|
979
1112
|
address_basis_classify, 1);
|
|
980
1113
|
rb_define_singleton_method(mAddressBasis, "tier", address_basis_tier, 1);
|
|
1114
|
+
rb_define_singleton_method(mAddressBasis, "sweep", address_basis_sweep, -1);
|
|
981
1115
|
|
|
982
1116
|
rb_define_const(mAddressBasis, "TIER_ENTITY", INT2NUM(TIER_ENTITY));
|
|
983
1117
|
rb_define_const(mAddressBasis, "TIER_STRIDE", INT2NUM(TIER_STRIDE));
|
data/ext/carray_attribute.c
CHANGED
|
@@ -223,6 +223,14 @@ ca_is_readonly (void *ap)
|
|
|
223
223
|
return 1;
|
|
224
224
|
}
|
|
225
225
|
}
|
|
226
|
+
if ( ca_test_flag(ca, CA_FLAG_FOLDED) ) {
|
|
227
|
+
/* a folded reshape: its source is not on the parent chain */
|
|
228
|
+
CArray *src = ca_fold_source(ca);
|
|
229
|
+
if ( src && ca_is_readonly(src) ) {
|
|
230
|
+
ca_set_flag(ca, CA_FLAG_READ_ONLY);
|
|
231
|
+
return 1;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
226
234
|
return 0; /* all test -> false */
|
|
227
235
|
}
|
|
228
236
|
}
|
|
@@ -520,10 +528,34 @@ rb_ca_inherit_attr (VALUE dst, VALUE src)
|
|
|
520
528
|
it up after this (an ivar, a lift that moves it onto another parent), and
|
|
521
529
|
writes through it are refused by ca_is_readonly, which walks to the
|
|
522
530
|
frozen root and finds CA_FLAG_READ_ONLY there. */
|
|
531
|
+
static void
|
|
532
|
+
ca_note_view_of_lent (CArray *p)
|
|
533
|
+
{
|
|
534
|
+
if ( ca_test_flag(p, CA_FLAG_LENT) ) {
|
|
535
|
+
ca_set_flag(p, CA_FLAG_LENT_VIEWED);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
523
539
|
VALUE
|
|
524
540
|
rb_ca_set_parent (VALUE self, VALUE obj)
|
|
525
541
|
{
|
|
526
542
|
rb_ivar_set(self, id_parent, obj);
|
|
543
|
+
/* A view of an array lent to a CAObject hook outlives the hook: tell the
|
|
544
|
+
array, so that it keeps its cells when the hook returns. A view of
|
|
545
|
+
several arrays names one here and holds the rest in parents[]. */
|
|
546
|
+
if ( rb_obj_is_carray(obj) ) {
|
|
547
|
+
ca_note_view_of_lent((CArray *) DATA_PTR(obj));
|
|
548
|
+
}
|
|
549
|
+
if ( rb_obj_is_carray(self) ) {
|
|
550
|
+
CArray *ca = (CArray *) DATA_PTR(self);
|
|
551
|
+
if ( ca_test_flag(ca, CA_FLAG_MULTI_PARENTS) ) {
|
|
552
|
+
CAMultiParent *mp = (CAMultiParent *) ca;
|
|
553
|
+
int32_t k;
|
|
554
|
+
for ( k = 0; k < mp->n_parents; k++ ) {
|
|
555
|
+
ca_note_view_of_lent(mp->parents[k]);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
527
559
|
return obj;
|
|
528
560
|
}
|
|
529
561
|
|
data/ext/carray_broadcast.c
CHANGED
|
@@ -85,13 +85,12 @@ ca_broadcast_to_destination (VALUE dst, volatile VALUE *src)
|
|
|
85
85
|
for ( i = 0; agree && i < dst_ndim; i++ ) {
|
|
86
86
|
if ( dst_dim[i] != src_dim[i] ) agree = 0;
|
|
87
87
|
}
|
|
88
|
-
if (
|
|
89
|
-
return;
|
|
88
|
+
if ( agree ) return;
|
|
90
89
|
}
|
|
91
90
|
|
|
92
91
|
/* A size-1 axis repeated onto an axis of length 0 leaves the source
|
|
93
|
-
larger than an empty destination
|
|
94
|
-
the same. */
|
|
92
|
+
larger than an empty destination, or as large when it is empty too
|
|
93
|
+
((1,0) onto (2,0)); the axes say it is a repeat all the same. */
|
|
95
94
|
if ( ( cs->elements < cd->elements || cd->elements == 0 )
|
|
96
95
|
&& cs->ndim == cd->ndim ) {
|
|
97
96
|
int i;
|