carray 3.0.5 → 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 +233 -0
- data/README.md +1 -1
- data/carray.gemspec +3 -2
- data/ext/ca_axis_dispatch.c +6 -0
- data/ext/ca_axis_group.c +1 -1
- data/ext/ca_categorical_iterator.c +7 -7
- data/ext/ca_kernel_iterator.c +116 -231
- data/ext/ca_kernel_iterator.h +410 -254
- data/ext/ca_obj_bincmp.c +9 -1
- data/ext/ca_obj_binop.c +10 -1
- data/ext/ca_obj_bitfield.c +2 -0
- data/ext/ca_obj_byte_swap.c +2 -0
- data/ext/ca_obj_face.c +2 -0
- data/ext/ca_obj_fake.c +3 -1
- data/ext/ca_obj_grid.c +167 -12
- data/ext/ca_obj_meld.c +69 -113
- data/ext/ca_obj_moncmp.c +9 -1
- data/ext/ca_obj_monop.c +40 -2
- data/ext/ca_obj_object.c +54 -20
- data/ext/ca_obj_reduce.c +15 -1
- data/ext/ca_obj_refer.c +65 -20
- data/ext/ca_obj_remap.c +69 -10
- data/ext/ca_obj_roll.c +1 -0
- data/ext/ca_obj_select.c +4 -1
- data/ext/ca_obj_select_axis.c +1 -0
- data/ext/ca_obj_shift.c +1 -0
- data/ext/ca_obj_stack.c +310 -111
- data/ext/ca_obj_stride.c +131 -45
- data/ext/ca_obj_string.c +18 -2
- data/ext/ca_obj_tile.c +1 -0
- data/ext/ca_obj_triop.c +9 -1
- data/ext/ca_obj_window.c +1 -0
- data/ext/ca_op_ipower.c +8 -8
- data/ext/caframe_csv_reader.c +1 -1
- data/ext/carray.h +2 -1
- data/ext/carray_access.c +27 -64
- data/ext/carray_address_basis.c +134 -0
- data/ext/carray_attribute.c +8 -0
- data/ext/carray_broadcast.c +3 -4
- data/ext/carray_build_flags.h +1 -1
- data/ext/carray_cast.c +8 -11
- data/ext/carray_conversion.c +9 -5
- data/ext/carray_core.c +811 -72
- data/ext/carray_element.c +13 -9
- data/ext/carray_histogram.c +25 -3
- data/ext/carray_internal.h +147 -12
- data/ext/carray_kernels_bincmp.c +2007 -3
- data/ext/carray_kernels_binop.c +25365 -5199
- data/ext/carray_kernels_init.c +8 -8
- data/ext/carray_kernels_monop.c +10696 -3678
- data/ext/carray_kernels_reduce_aggregate.c +4429 -702
- data/ext/carray_kernels_reduce_boolean.c +1533 -15
- data/ext/carray_kernels_reduce_cumulative.c +1808 -248
- data/ext/carray_kernels_reduce_extreme.c +4508 -511
- data/ext/carray_kernels_reduce_variance.c +2284 -152
- data/ext/carray_kernels_scan.c +240 -240
- data/ext/carray_kernels_search.c +4211 -264
- data/ext/carray_kernels_sort.c +367 -450
- data/ext/carray_lazy.c +47 -0
- data/ext/carray_loop.c +1 -1
- data/ext/carray_mask.c +130 -139
- data/ext/carray_median_percentile.c +4 -4
- data/ext/carray_memory_view.c +13 -7
- data/ext/carray_operator.c +147 -44
- data/ext/carray_order.c +3 -2
- data/ext/carray_random.c +4 -1
- data/ext/carray_slab.c +97 -21
- data/ext/carray_sort.c +1 -1
- data/ext/carray_test.c +74 -19
- data/ext/carray_time_text.c +2 -2
- data/ext/extconf.rb +11 -0
- data/ext/mkkernel.rb +346 -94
- data/ext/ruby_carray.c +4 -1
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +25 -1
- 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 +1 -1
- data/lib/carray/block_iterator.rb +17 -3
- data/lib/carray/categorical.rb +6 -8
- data/lib/carray/categorical_iterator.rb +2 -2
- data/lib/carray/complex.rb +2 -2
- data/lib/carray/conditional.rb +3 -2
- data/lib/carray/frame/column_verbs.rb +45 -14
- 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 +399 -78
- data/lib/carray/frame/group.rb +679 -53
- data/lib/carray/frame/io.rb +209 -71
- 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/inspect.rb +7 -2
- data/lib/carray/iterator.rb +32 -0
- data/lib/carray/lazy.rb +17 -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/meshgrid.rb +3 -1
- data/lib/carray/runtime.rb +47 -8
- data/lib/carray/segment_iterator.rb +23 -8
- data/lib/carray/serialize.rb +34 -17
- data/lib/carray/stack.rb +18 -6
- data/lib/carray/time.rb +5 -0
- data/lib/carray/window_iterator.rb +16 -4
- data/yard-stubs/ca_obj_array.rb +26 -1
- data/yard-stubs/carray_cast.rb +8 -5
- data/yard-stubs/carray_conversion.rb +8 -2
- data/yard-stubs/carray_mask.rb +20 -1
- data/yard-stubs/carray_math.rb +31 -16
- data/yard-stubs/carray_memory_view.rb +7 -0
- data/yard-stubs/carray_test.rb +7 -4
- metadata +18 -4
data/ext/ca_obj_stride.c
CHANGED
|
@@ -183,6 +183,9 @@ free_ca_stride (void *ap)
|
|
|
183
183
|
{
|
|
184
184
|
CAStride *ca = (CAStride *) ap;
|
|
185
185
|
if (ca == NULL) return;
|
|
186
|
+
if ( ca_test_flag(ca, CA_FLAG_FOLDED) ) {
|
|
187
|
+
ca_fold_forget((CArray *) ca);
|
|
188
|
+
}
|
|
186
189
|
ca_free(ca->mask);
|
|
187
190
|
if (ca->_pool) {
|
|
188
191
|
/* Pool path: one xfree covers dim/strides via the pool buffer,
|
|
@@ -278,11 +281,15 @@ ca_stride_compose_through (CAStride *leaf, CAStride *parent,
|
|
|
278
281
|
|
|
279
282
|
/* Compose each leaf dim's stride.
|
|
280
283
|
Validity rule: leaf dim k must advance exactly one parent dim
|
|
281
|
-
(not cross multiple parent dims)
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
284
|
+
(not cross multiple parent dims), and every parent dim must stay
|
|
285
|
+
within its bounds across the leaf's full extent *given the base
|
|
286
|
+
position*. Several leaf dims can advance the same parent dim (a block
|
|
287
|
+
of a reshape: rows step 4 parent columns, columns step 1), so the
|
|
288
|
+
bound is on the sum of their extents, kept in lo[] / hi[]. Otherwise
|
|
289
|
+
the leaf's traversal would wrap across parent dim boundaries, which
|
|
290
|
+
is a non-strided access pattern that cannot be folded. */
|
|
291
|
+
ca_size_t lo[CA_RANK_MAX], hi[CA_RANK_MAX];
|
|
292
|
+
for (m = 0; m < parent->ndim; m++) lo[m] = hi[m] = base_idx[m];
|
|
286
293
|
for (k = 0; k < leaf->ndim; k++) {
|
|
287
294
|
if (leaf->strides[k] % parent->bytes != 0) return 0;
|
|
288
295
|
ca_size_t advance = leaf->strides[k] / parent->bytes;
|
|
@@ -302,20 +309,15 @@ ca_stride_compose_through (CAStride *leaf, CAStride *parent,
|
|
|
302
309
|
}
|
|
303
310
|
if (advance != 0) return 0;
|
|
304
311
|
if (nonzero_count > 1) return 0; /* crosses parent dims */
|
|
305
|
-
if (nonzero_count == 1) {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
ca_size_t final_pos =
|
|
310
|
-
base_idx[nonzero_dim] + (leaf->dim[k] - 1) * nonzero_step;
|
|
311
|
-
if (nonzero_step > 0) {
|
|
312
|
-
if (final_pos >= parent->dim[nonzero_dim]) return 0;
|
|
313
|
-
} else {
|
|
314
|
-
if (final_pos < 0) return 0;
|
|
315
|
-
}
|
|
312
|
+
if (nonzero_count == 1 && leaf->dim[k] > 1) {
|
|
313
|
+
ca_size_t extent = (leaf->dim[k] - 1) * nonzero_step;
|
|
314
|
+
if (extent > 0) hi[nonzero_dim] += extent;
|
|
315
|
+
else lo[nonzero_dim] += extent;
|
|
316
316
|
}
|
|
317
317
|
out_strides[k] = composed;
|
|
318
318
|
}
|
|
319
|
+
for (m = 0; m < parent->ndim; m++)
|
|
320
|
+
if (lo[m] < 0 || hi[m] >= parent->dim[m]) return 0;
|
|
319
321
|
|
|
320
322
|
/* A leaf cell wider than the remainder of its first parent element
|
|
321
323
|
(CARefer reinterpreting two float64 as one complex128) covers several
|
|
@@ -679,14 +681,20 @@ ca_stride_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
679
681
|
}
|
|
680
682
|
}
|
|
681
683
|
else {
|
|
684
|
+
/* Peel the axes from the innermost: a % dim[k] is the index on
|
|
685
|
+
axis k and a / dim[k] carries the rest outward. The outermost
|
|
686
|
+
axis takes whatever is left, so ndim-1 divisions per address. */
|
|
687
|
+
ca_size_t *dim = ca->dim;
|
|
688
|
+
int8_t ndim = ca->ndim;
|
|
682
689
|
for ( i = 0; i < n; i++ ) {
|
|
683
|
-
ca_size_t
|
|
690
|
+
ca_size_t a = addrs[i];
|
|
684
691
|
ca_size_t off = ebase;
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
off +=
|
|
692
|
+
for ( k = ndim - 1; k > 0; k-- ) {
|
|
693
|
+
ca_size_t q = a / dim[k];
|
|
694
|
+
off += ( a - q * dim[k] ) * esteps[k];
|
|
695
|
+
a = q;
|
|
688
696
|
}
|
|
689
|
-
paddrs[i] = off;
|
|
697
|
+
paddrs[i] = off + a * esteps[0];
|
|
690
698
|
}
|
|
691
699
|
}
|
|
692
700
|
ca_xfer_addrs(root, n, paddrs, data, dir);
|
|
@@ -821,9 +829,12 @@ ca_stride_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
821
829
|
|
|
822
830
|
/* A reshape over a 1-D cold root (ndim != root->ndim): the request has no
|
|
823
831
|
box in the root's single axis, but the root cells it touches lie in one
|
|
824
|
-
flat span.
|
|
825
|
-
it, as xfer_all does for the whole view. A PUT
|
|
826
|
-
the
|
|
832
|
+
flat span. A GET asks the root for that span once and walks the
|
|
833
|
+
request over it, as xfer_all does for the whole view. A PUT hands the
|
|
834
|
+
root the list of the requested cells' addresses instead: sending the
|
|
835
|
+
span back would write the cells between them too, and a root that
|
|
836
|
+
repeats its cells (CATile) would have a stale copy land after the
|
|
837
|
+
written one. */
|
|
827
838
|
if (aligned && !root->ptr && ca_func[root->obj_type].xfer_stride
|
|
828
839
|
&& ca->bytes == root->bytes && root->ndim == 1
|
|
829
840
|
&& root_base % root->bytes == 0) {
|
|
@@ -836,15 +847,33 @@ ca_stride_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
836
847
|
}
|
|
837
848
|
if ( span_lo >= 0 && span_hi <= root->elements * root->bytes ) {
|
|
838
849
|
volatile VALUE holder;
|
|
839
|
-
ca_size_t rlo = span_lo / root->bytes;
|
|
840
|
-
ca_size_t rcount = (span_hi - span_lo) / root->bytes;
|
|
841
|
-
ca_size_t rstep = root->bytes;
|
|
842
|
-
char *scratch = ALLOCV_N(char, holder, rcount * root->bytes);
|
|
843
|
-
ca_xfer_stride(root, &rlo, &rcount, &rstep, scratch, CA_XFER_GET);
|
|
844
|
-
ca_xfer_strided_walk(scratch + (root_base - span_lo), ca->bytes, ndim,
|
|
845
|
-
counts, root_stride, d, dir);
|
|
846
850
|
if ( dir == CA_XFER_PUT ) {
|
|
847
|
-
|
|
851
|
+
ca_size_t n = 1, m = 0, idx[CA_RANK_MAX];
|
|
852
|
+
ca_size_t *addrs;
|
|
853
|
+
for (k = 0; k < ndim; k++) {
|
|
854
|
+
n *= counts[k];
|
|
855
|
+
idx[k] = 0;
|
|
856
|
+
}
|
|
857
|
+
addrs = ALLOCV_N(ca_size_t, holder, n);
|
|
858
|
+
/* empty: the slot returns on an empty region at its entry */
|
|
859
|
+
while (1) {
|
|
860
|
+
ca_size_t off = root_base;
|
|
861
|
+
for (k = 0; k < ndim; k++) off += idx[k] * root_stride[k];
|
|
862
|
+
addrs[m++] = off / root->bytes;
|
|
863
|
+
k = ndim - 1;
|
|
864
|
+
while (k >= 0) { if (++idx[k] < counts[k]) break; idx[k] = 0; k--; }
|
|
865
|
+
if (k < 0) break;
|
|
866
|
+
}
|
|
867
|
+
ca_xfer_addrs(root, n, addrs, d, CA_XFER_PUT);
|
|
868
|
+
}
|
|
869
|
+
else {
|
|
870
|
+
ca_size_t rlo = span_lo / root->bytes;
|
|
871
|
+
ca_size_t rcount = (span_hi - span_lo) / root->bytes;
|
|
872
|
+
ca_size_t rstep = root->bytes;
|
|
873
|
+
char *scratch = ALLOCV_N(char, holder, rcount * root->bytes);
|
|
874
|
+
ca_xfer_stride(root, &rlo, &rcount, &rstep, scratch, CA_XFER_GET);
|
|
875
|
+
ca_xfer_strided_walk(scratch + (root_base - span_lo), ca->bytes, ndim,
|
|
876
|
+
counts, root_stride, d, dir);
|
|
848
877
|
}
|
|
849
878
|
ALLOCV_END(holder);
|
|
850
879
|
return;
|
|
@@ -1118,10 +1147,12 @@ static int ca_layout_is_contiguous (int8_t ndim, const ca_size_t *dim,
|
|
|
1118
1147
|
folds onward from itself, so the answer is the one for the root it folds
|
|
1119
1148
|
to. What is left is the
|
|
1120
1149
|
boundary views that compute or fetch their contents -- CAObject, the lazy
|
|
1121
|
-
per-element transforms, whatever a companion gem installed
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1150
|
+
per-element transforms, whatever a companion gem installed. All of them
|
|
1151
|
+
answer a region request: through their xfer_stride slot, or, when a type
|
|
1152
|
+
leaves it out, through the dispatcher's default, which hands the cells'
|
|
1153
|
+
addresses to xfer_addrs. Attaching one instead would produce all of it
|
|
1154
|
+
and write all of it back, so a cell nobody touched would go through the
|
|
1155
|
+
view's conversion both ways. */
|
|
1125
1156
|
int
|
|
1126
1157
|
ca_root_lends_no_memory (void *ap)
|
|
1127
1158
|
{
|
|
@@ -1139,7 +1170,7 @@ ca_root_lends_no_memory (void *ap)
|
|
|
1139
1170
|
ca_stride_compose_to_root((CAStride *) root, &below, cs, &base);
|
|
1140
1171
|
return ca_root_lends_no_memory(below);
|
|
1141
1172
|
}
|
|
1142
|
-
return
|
|
1173
|
+
return 1;
|
|
1143
1174
|
}
|
|
1144
1175
|
|
|
1145
1176
|
/* The same question for the parent of a view that is not itself in the
|
|
@@ -1435,8 +1466,10 @@ ca_stride_func_xfer_all (void *ap, void *data, int dir)
|
|
|
1435
1466
|
the request is exact) and ca->bytes == root->bytes (no byte
|
|
1436
1467
|
reinterpret, so the span endpoints are whole root elements). A wider
|
|
1437
1468
|
lazy root has no single strided box to ask for, so it takes the
|
|
1438
|
-
whole-root fallback below -- correct, just not partial.
|
|
1439
|
-
|
|
1469
|
+
whole-root fallback below -- correct, just not partial. Reads only:
|
|
1470
|
+
a write goes to the root as the list of its cells below, since
|
|
1471
|
+
sending the span back would write the cells between them too. */
|
|
1472
|
+
if ( dir == CA_XFER_GET && root->ndim == 1 && ca->bytes == root->bytes ) {
|
|
1440
1473
|
ca_size_t span_lo = composed_base;
|
|
1441
1474
|
ca_size_t span_hi = composed_base + ca->bytes;
|
|
1442
1475
|
int8_t k;
|
|
@@ -1453,13 +1486,10 @@ ca_stride_func_xfer_all (void *ap, void *data, int dir)
|
|
|
1453
1486
|
char *scratch = ALLOCV_N(char, holder, rcount * root->bytes);
|
|
1454
1487
|
ca_xfer_stride(root, &rlo, &rcount, &rstep, scratch, CA_XFER_GET);
|
|
1455
1488
|
ca->ptr = ptr;
|
|
1456
|
-
ca_stride_xfer_with_layout(ca,
|
|
1489
|
+
ca_stride_xfer_with_layout(ca, 0,
|
|
1457
1490
|
scratch + (composed_base - span_lo),
|
|
1458
1491
|
composed_strides);
|
|
1459
1492
|
ca->ptr = ptr0;
|
|
1460
|
-
if ( dir == CA_XFER_PUT ) {
|
|
1461
|
-
ca_xfer_stride(root, &rlo, &rcount, &rstep, scratch, CA_XFER_PUT);
|
|
1462
|
-
}
|
|
1463
1493
|
ALLOCV_END(holder);
|
|
1464
1494
|
}
|
|
1465
1495
|
return;
|
|
@@ -1585,6 +1615,51 @@ ca_stride_func_xfer_all (void *ap, void *data, int dir)
|
|
|
1585
1615
|
}
|
|
1586
1616
|
}
|
|
1587
1617
|
|
|
1618
|
+
/* Whether a layout of `ndim` axes (dims, byte strides, byte base) addresses
|
|
1619
|
+
each cell of a packed array of the same number of cells exactly once:
|
|
1620
|
+
ordered by the size of their strides, the axes longer than one must be
|
|
1621
|
+
packed (the smallest stride is `bytes`, each next one the previous times
|
|
1622
|
+
its axis length), and the lowest address must be 0. Equal counts alone
|
|
1623
|
+
do not say this: a zero or repeated stride covers fewer cells. */
|
|
1624
|
+
static int
|
|
1625
|
+
ca_stride_layout_is_permutation (int8_t ndim, const ca_size_t *dim,
|
|
1626
|
+
const ca_size_t *strides, ca_size_t base,
|
|
1627
|
+
ca_size_t bytes)
|
|
1628
|
+
{
|
|
1629
|
+
int8_t order[CA_RANK_MAX];
|
|
1630
|
+
int8_t n = 0, i, j;
|
|
1631
|
+
ca_size_t lowest = base, expect = bytes;
|
|
1632
|
+
|
|
1633
|
+
for (i=0; i<ndim; i++) {
|
|
1634
|
+
if ( dim[i] <= 1 ) {
|
|
1635
|
+
continue;
|
|
1636
|
+
}
|
|
1637
|
+
if ( strides[i] < 0 ) {
|
|
1638
|
+
lowest += (dim[i] - 1) * strides[i];
|
|
1639
|
+
}
|
|
1640
|
+
for (j=n; j>0; j--) {
|
|
1641
|
+
ca_size_t a = strides[order[j-1]], b = strides[i];
|
|
1642
|
+
if ( (a < 0 ? -a : a) <= (b < 0 ? -b : b) ) {
|
|
1643
|
+
break;
|
|
1644
|
+
}
|
|
1645
|
+
order[j] = order[j-1];
|
|
1646
|
+
}
|
|
1647
|
+
order[j] = i;
|
|
1648
|
+
n++;
|
|
1649
|
+
}
|
|
1650
|
+
if ( lowest != 0 ) {
|
|
1651
|
+
return 0;
|
|
1652
|
+
}
|
|
1653
|
+
for (i=0; i<n; i++) {
|
|
1654
|
+
ca_size_t s = strides[order[i]];
|
|
1655
|
+
if ( (s < 0 ? -s : s) != expect ) {
|
|
1656
|
+
return 0;
|
|
1657
|
+
}
|
|
1658
|
+
expect *= dim[order[i]];
|
|
1659
|
+
}
|
|
1660
|
+
return 1;
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1588
1663
|
static void
|
|
1589
1664
|
ca_stride_func_fill_data (void *ap, void *ptr)
|
|
1590
1665
|
{
|
|
@@ -1620,7 +1695,9 @@ ca_stride_func_fill_data (void *ap, void *ptr)
|
|
|
1620
1695
|
into scratch only to overwrite every byte with *ptr -- wasted
|
|
1621
1696
|
work. Delegate to root.fill_data instead.
|
|
1622
1697
|
Safety gates:
|
|
1623
|
-
(1) elements match
|
|
1698
|
+
(1) elements match and the composed layout addresses each root cell
|
|
1699
|
+
exactly once -- our view covers every root cell (a zero or
|
|
1700
|
+
repeated stride has as many cells but covers fewer);
|
|
1624
1701
|
(2) bytes match -- our cell width equals root's cell width.
|
|
1625
1702
|
Without (2), a type-reinterpreting CAStride (CAField over a
|
|
1626
1703
|
complex entity for `.real`/`.imag`) would corrupt root: root
|
|
@@ -1632,7 +1709,9 @@ ca_stride_func_fill_data (void *ap, void *ptr)
|
|
|
1632
1709
|
if ( ca_func[root->obj_type].attach != ca_stride_func.attach &&
|
|
1633
1710
|
ca_func[root->obj_type].attach != ca_window_func.attach &&
|
|
1634
1711
|
ca->elements == root->elements &&
|
|
1635
|
-
ca->bytes == root->bytes
|
|
1712
|
+
ca->bytes == root->bytes &&
|
|
1713
|
+
ca_stride_layout_is_permutation(ca->ndim, ca->dim, composed_strides,
|
|
1714
|
+
composed_base, bytes) ) {
|
|
1636
1715
|
ca_func[root->obj_type].fill_data(root, ptr);
|
|
1637
1716
|
return;
|
|
1638
1717
|
}
|
|
@@ -2094,6 +2173,13 @@ rb_cs_initialize_copy (VALUE self, VALUE other)
|
|
|
2094
2173
|
ca_stride_setup(ca, cs->obj_type, cs->parent, cs->data_type, cs->bytes,
|
|
2095
2174
|
cs->ndim, cs->dim, cs->strides, cs->base_offset);
|
|
2096
2175
|
rb_ca_set_parent(self, rb_ca_parent(other));
|
|
2176
|
+
if ( ca_test_flag(cs, CA_FLAG_FOLDED) ) {
|
|
2177
|
+
/* the copy has the same @parent, so it answers to the same source */
|
|
2178
|
+
CArray *src = ca_fold_source((CArray *) cs);
|
|
2179
|
+
if ( src ) {
|
|
2180
|
+
ca_fold_note_source((CArray *) ca, src);
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2097
2183
|
return self;
|
|
2098
2184
|
}
|
|
2099
2185
|
|
data/ext/ca_obj_string.c
CHANGED
|
@@ -217,9 +217,10 @@ ca_string_refuse_cell (VALUE v, const char *where)
|
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
/* Every cell of `parent` that is not masked is a String. Under a masked
|
|
220
|
-
cell of
|
|
220
|
+
cell of a parent that can be written, a value that is not a String (the
|
|
221
221
|
0 an object array starts with) becomes an empty String, so that the cell
|
|
222
|
-
is still a String once it is unmasked.
|
|
222
|
+
is still a String once it is unmasked. A view is written through its
|
|
223
|
+
value array, which leaves the mask as it is. */
|
|
223
224
|
static void
|
|
224
225
|
ca_string_check_cells (VALUE parent_val, CArray *parent)
|
|
225
226
|
{
|
|
@@ -247,6 +248,7 @@ ca_string_check_cells (VALUE parent_val, CArray *parent)
|
|
|
247
248
|
volatile VALUE list =
|
|
248
249
|
rb_funcall(rb_funcall(parent_val, rb_intern("flatten"), 0),
|
|
249
250
|
rb_intern("to_a"), 0);
|
|
251
|
+
volatile VALUE values = Qnil, raw = Qnil;
|
|
250
252
|
long n = RARRAY_LEN(list), j;
|
|
251
253
|
for (j = 0; j < n; j++) {
|
|
252
254
|
VALUE v = rb_ary_entry(list, j);
|
|
@@ -256,6 +258,20 @@ ca_string_check_cells (VALUE parent_val, CArray *parent)
|
|
|
256
258
|
ca_string_refuse_cell(v, where);
|
|
257
259
|
}
|
|
258
260
|
}
|
|
261
|
+
if ( ! ca_is_readonly(parent) ) {
|
|
262
|
+
for (j = 0; j < n; j++) {
|
|
263
|
+
if ( rb_ary_entry(list, j) != CA_UNDEF ) continue;
|
|
264
|
+
if ( NIL_P(values) ) {
|
|
265
|
+
values = rb_funcall(rb_funcall(parent_val, rb_intern("value"), 0),
|
|
266
|
+
rb_intern("flatten"), 0);
|
|
267
|
+
raw = rb_funcall(values, rb_intern("to_a"), 0);
|
|
268
|
+
}
|
|
269
|
+
if ( ! RB_TYPE_P(rb_ary_entry(raw, j), T_STRING) ) {
|
|
270
|
+
rb_funcall(values, rb_intern("[]="), 2, LONG2NUM(j),
|
|
271
|
+
rb_utf8_str_new("", 0));
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
259
275
|
}
|
|
260
276
|
}
|
|
261
277
|
|
data/ext/ca_obj_tile.c
CHANGED
|
@@ -643,6 +643,7 @@ Init_ca_obj_tile (void)
|
|
|
643
643
|
&catile_data_type,
|
|
644
644
|
rb_cCATileMask,
|
|
645
645
|
&catile_mask_data_type, &ca_tile_func, sizeof(ca_tile_func));
|
|
646
|
+
ca_register_cell_moving_view(CA_OBJ_TILE);
|
|
646
647
|
rb_define_const(rb_cObject, "CA_OBJ_TILE", INT2NUM(CA_OBJ_TILE));
|
|
647
648
|
|
|
648
649
|
rb_define_method(rb_cCArray, "tile", rb_ca_tile, -1);
|
data/ext/ca_obj_triop.c
CHANGED
|
@@ -267,9 +267,11 @@ pull_operand (CArray *op, int is_scalar, const ca_lazy_req_t *req,
|
|
|
267
267
|
|
|
268
268
|
/* Evaluate the cells a request names into `data` (packed, n cells). */
|
|
269
269
|
static void
|
|
270
|
-
|
|
270
|
+
ca_triop_eval_cells (void *node, const ca_lazy_req_t *req, void *data, int dir)
|
|
271
271
|
{
|
|
272
|
+
CATriOp *to = (CATriOp *) node;
|
|
272
273
|
ca_size_t slab_n = req->n;
|
|
274
|
+
(void) dir;
|
|
273
275
|
void *scratch2, *scratch3;
|
|
274
276
|
ca_size_t op2_step, op3_step;
|
|
275
277
|
|
|
@@ -316,6 +318,12 @@ ca_triop_eval (CATriOp *to, const ca_lazy_req_t *req, void *data)
|
|
|
316
318
|
ca_lazy_arena_release(scratch2);
|
|
317
319
|
}
|
|
318
320
|
|
|
321
|
+
static void
|
|
322
|
+
ca_triop_eval (CATriOp *to, const ca_lazy_req_t *req, void *data)
|
|
323
|
+
{
|
|
324
|
+
ca_lazy_eval_recorded(to, 3, to->operands, 0, NULL, ca_triop_eval_cells, req, data, CA_XFER_GET);
|
|
325
|
+
}
|
|
326
|
+
|
|
319
327
|
static void
|
|
320
328
|
ca_triop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
321
329
|
ca_size_t *strides, void *data, int dir)
|
data/ext/ca_obj_window.c
CHANGED
|
@@ -1982,6 +1982,7 @@ Init_ca_obj_window (void)
|
|
|
1982
1982
|
&cawindow_data_type,
|
|
1983
1983
|
rb_cCAWindowMask,
|
|
1984
1984
|
&cawindow_mask_data_type, &ca_window_func, sizeof(ca_window_func));
|
|
1985
|
+
ca_register_cell_moving_view(CA_OBJ_WINDOW);
|
|
1985
1986
|
rb_define_const(rb_cObject, "CA_OBJ_WINDOW", INT2NUM(CA_OBJ_WINDOW));
|
|
1986
1987
|
|
|
1987
1988
|
rb_define_method(rb_cCArray, "window", rb_ca_window, -1);
|
data/ext/ca_op_ipower.c
CHANGED
|
@@ -110,7 +110,7 @@ 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 ) {
|
|
@@ -125,7 +125,7 @@ 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 ) {
|
|
@@ -140,7 +140,7 @@ 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 ) {
|
|
@@ -155,7 +155,7 @@ 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 ) {
|
|
@@ -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/caframe_csv_reader.c
CHANGED
data/ext/carray.h
CHANGED
|
@@ -237,7 +237,8 @@ typedef ca_u_float64_t ca_u_double;
|
|
|
237
237
|
routines that walk a single ->parent test this flag and instead fold over
|
|
238
238
|
the parents[] exposed by the CAMultiParent layout convention. */
|
|
239
239
|
#define CA_FLAG_MULTI_PARENTS 32
|
|
240
|
-
|
|
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). */
|
|
241
242
|
#define CA_FLAG_IS_FACE 128
|
|
242
243
|
/* Face opt-in ordering/search flags.
|
|
243
244
|
A Face declares that its numeric storage may be descended to for kernel
|
data/ext/carray_access.c
CHANGED
|
@@ -1554,75 +1554,37 @@ rb_ca_fetch_slab_sigil (int argc, VALUE *argv, VALUE self)
|
|
|
1554
1554
|
return rb_funcall(klass, rb_intern("new"), 2, base, slab_axes);
|
|
1555
1555
|
}
|
|
1556
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
|
+
|
|
1557
1573
|
static VALUE
|
|
1558
1574
|
rb_cs_fetch_method (int argc, VALUE *argv, VALUE self)
|
|
1559
1575
|
{
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1576
|
+
rb_cs_check_index(argc, argv, "#[]");
|
|
1577
|
+
return rb_ca_fetch_addr(self, 0);
|
|
1578
|
+
}
|
|
1565
1579
|
|
|
1566
|
-
|
|
1567
|
-
rb_ca_scan_index(ca->ndim, ca->dim, ca->elements, argc, argv, &info);
|
|
1580
|
+
static VALUE rb_ca_store_method (int argc, VALUE *argv, VALUE self);
|
|
1568
1581
|
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
break;
|
|
1576
|
-
case CA_REG_FLATTEN:
|
|
1577
|
-
obj = self; /* rb_funcall(self, rb_intern("refer"), 0); */
|
|
1578
|
-
break;
|
|
1579
|
-
case CA_REG_POINT:
|
|
1580
|
-
obj = rb_ca_fetch_addr(self, 0);
|
|
1581
|
-
break;
|
|
1582
|
-
case CA_REG_ALL:
|
|
1583
|
-
obj = self; /* rb_funcall(self, rb_intern("refer"), 0); */
|
|
1584
|
-
break;
|
|
1585
|
-
case CA_REG_BLOCK:
|
|
1586
|
-
obj = self; /* rb_funcall(self, rb_intern("refer"), 0); */
|
|
1587
|
-
break;
|
|
1588
|
-
case CA_REG_SELECT:
|
|
1589
|
-
obj = rb_ca_select_new(self, argv[0]);
|
|
1590
|
-
break;
|
|
1591
|
-
case CA_REG_ITERATOR:
|
|
1592
|
-
obj = rb_ca_slab_iter_new(self, &info);
|
|
1593
|
-
break;
|
|
1594
|
-
case CA_REG_REPEAT:
|
|
1595
|
-
obj = rb_ca_repeat(argc, argv, self);
|
|
1596
|
-
break;
|
|
1597
|
-
case CA_REG_MAPPING:
|
|
1598
|
-
obj = rb_ca_fancy_index_chain(self, argv[0]);
|
|
1599
|
-
break;
|
|
1600
|
-
case CA_REG_GRID:
|
|
1601
|
-
obj = rb_ca_grid(argc, argv, self);
|
|
1602
|
-
break;
|
|
1603
|
-
case CA_REG_METHOD_CALL: {
|
|
1604
|
-
volatile VALUE idx;
|
|
1605
|
-
idx = rb_funcallv_public(self, SYM2ID(info.symbol), argc-1, argv+1);
|
|
1606
|
-
obj = rb_ca_fetch(self, idx);
|
|
1607
|
-
break;
|
|
1608
|
-
}
|
|
1609
|
-
case CA_REG_MEMBER: {
|
|
1610
|
-
volatile VALUE data_class = rb_ca_data_class(self);
|
|
1611
|
-
if ( ! NIL_P(data_class) ) {
|
|
1612
|
-
obj = rb_ca_face_field(self, info.symbol);
|
|
1613
|
-
break;
|
|
1614
|
-
}
|
|
1615
|
-
else {
|
|
1616
|
-
rb_raise(rb_eIndexError,
|
|
1617
|
-
"can't refer member of carray doesn't have data_class");
|
|
1618
|
-
}
|
|
1619
|
-
break;
|
|
1620
|
-
}
|
|
1621
|
-
default:
|
|
1622
|
-
rb_raise(rb_eIndexError, "invalid index specified");
|
|
1623
|
-
}
|
|
1624
|
-
|
|
1625
|
-
return obj;
|
|
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);
|
|
1626
1588
|
}
|
|
1627
1589
|
|
|
1628
1590
|
/* Recursively convert a store rvalue's surface value objects into
|
|
@@ -2443,6 +2405,7 @@ Init_carray_access (void)
|
|
|
2443
2405
|
rb_define_method(rb_cCArray, "[]=", rb_ca_store_method, -1);
|
|
2444
2406
|
|
|
2445
2407
|
rb_define_method(rb_cCScalar, "[]", rb_cs_fetch_method, -1);
|
|
2408
|
+
rb_define_method(rb_cCScalar, "[]=", rb_cs_store_method, -1);
|
|
2446
2409
|
|
|
2447
2410
|
rb_define_method(rb_cCArray, "fill", rb_ca_fill, 1);
|
|
2448
2411
|
rb_define_method(rb_cCArray, "fill_copy", rb_ca_fill_copy, 1);
|