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.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +233 -0
  3. data/README.md +1 -1
  4. data/carray.gemspec +3 -2
  5. data/ext/ca_axis_dispatch.c +6 -0
  6. data/ext/ca_axis_group.c +1 -1
  7. data/ext/ca_categorical_iterator.c +7 -7
  8. data/ext/ca_kernel_iterator.c +116 -231
  9. data/ext/ca_kernel_iterator.h +410 -254
  10. data/ext/ca_obj_bincmp.c +9 -1
  11. data/ext/ca_obj_binop.c +10 -1
  12. data/ext/ca_obj_bitfield.c +2 -0
  13. data/ext/ca_obj_byte_swap.c +2 -0
  14. data/ext/ca_obj_face.c +2 -0
  15. data/ext/ca_obj_fake.c +3 -1
  16. data/ext/ca_obj_grid.c +167 -12
  17. data/ext/ca_obj_meld.c +69 -113
  18. data/ext/ca_obj_moncmp.c +9 -1
  19. data/ext/ca_obj_monop.c +40 -2
  20. data/ext/ca_obj_object.c +54 -20
  21. data/ext/ca_obj_reduce.c +15 -1
  22. data/ext/ca_obj_refer.c +65 -20
  23. data/ext/ca_obj_remap.c +69 -10
  24. data/ext/ca_obj_roll.c +1 -0
  25. data/ext/ca_obj_select.c +4 -1
  26. data/ext/ca_obj_select_axis.c +1 -0
  27. data/ext/ca_obj_shift.c +1 -0
  28. data/ext/ca_obj_stack.c +310 -111
  29. data/ext/ca_obj_stride.c +131 -45
  30. data/ext/ca_obj_string.c +18 -2
  31. data/ext/ca_obj_tile.c +1 -0
  32. data/ext/ca_obj_triop.c +9 -1
  33. data/ext/ca_obj_window.c +1 -0
  34. data/ext/ca_op_ipower.c +8 -8
  35. data/ext/caframe_csv_reader.c +1 -1
  36. data/ext/carray.h +2 -1
  37. data/ext/carray_access.c +27 -64
  38. data/ext/carray_address_basis.c +134 -0
  39. data/ext/carray_attribute.c +8 -0
  40. data/ext/carray_broadcast.c +3 -4
  41. data/ext/carray_build_flags.h +1 -1
  42. data/ext/carray_cast.c +8 -11
  43. data/ext/carray_conversion.c +9 -5
  44. data/ext/carray_core.c +811 -72
  45. data/ext/carray_element.c +13 -9
  46. data/ext/carray_histogram.c +25 -3
  47. data/ext/carray_internal.h +147 -12
  48. data/ext/carray_kernels_bincmp.c +2007 -3
  49. data/ext/carray_kernels_binop.c +25365 -5199
  50. data/ext/carray_kernels_init.c +8 -8
  51. data/ext/carray_kernels_monop.c +10696 -3678
  52. data/ext/carray_kernels_reduce_aggregate.c +4429 -702
  53. data/ext/carray_kernels_reduce_boolean.c +1533 -15
  54. data/ext/carray_kernels_reduce_cumulative.c +1808 -248
  55. data/ext/carray_kernels_reduce_extreme.c +4508 -511
  56. data/ext/carray_kernels_reduce_variance.c +2284 -152
  57. data/ext/carray_kernels_scan.c +240 -240
  58. data/ext/carray_kernels_search.c +4211 -264
  59. data/ext/carray_kernels_sort.c +367 -450
  60. data/ext/carray_lazy.c +47 -0
  61. data/ext/carray_loop.c +1 -1
  62. data/ext/carray_mask.c +130 -139
  63. data/ext/carray_median_percentile.c +4 -4
  64. data/ext/carray_memory_view.c +13 -7
  65. data/ext/carray_operator.c +147 -44
  66. data/ext/carray_order.c +3 -2
  67. data/ext/carray_random.c +4 -1
  68. data/ext/carray_slab.c +97 -21
  69. data/ext/carray_sort.c +1 -1
  70. data/ext/carray_test.c +74 -19
  71. data/ext/carray_time_text.c +2 -2
  72. data/ext/extconf.rb +11 -0
  73. data/ext/mkkernel.rb +346 -94
  74. data/ext/ruby_carray.c +4 -1
  75. data/ext/version.h +4 -4
  76. data/lib/carray/attribute.rb +25 -1
  77. data/lib/carray/autoload_carray.rb +3 -3
  78. data/lib/carray/autoload_method_extension.rb +5 -3
  79. data/lib/carray/axis_group.rb +13 -7
  80. data/lib/carray/basics.rb +1 -1
  81. data/lib/carray/block_iterator.rb +17 -3
  82. data/lib/carray/categorical.rb +6 -8
  83. data/lib/carray/categorical_iterator.rb +2 -2
  84. data/lib/carray/complex.rb +2 -2
  85. data/lib/carray/conditional.rb +3 -2
  86. data/lib/carray/frame/column_verbs.rb +45 -14
  87. data/lib/carray/frame/convert.rb +19 -0
  88. data/lib/carray/frame/csv_parser.rb +32 -32
  89. data/lib/carray/frame/describe.rb +4 -2
  90. data/lib/carray/frame/frame.rb +399 -78
  91. data/lib/carray/frame/group.rb +679 -53
  92. data/lib/carray/frame/io.rb +209 -71
  93. data/lib/carray/frame/join.rb +146 -37
  94. data/lib/carray/frame/records.rb +3 -3
  95. data/lib/carray/frame/reshape.rb +89 -11
  96. data/lib/carray/frame/sort.rb +57 -9
  97. data/lib/carray/frame/verbs.rb +384 -49
  98. data/lib/carray/frame/windows.rb +44 -6
  99. data/lib/carray/inspect.rb +7 -2
  100. data/lib/carray/iterator.rb +32 -0
  101. data/lib/carray/lazy.rb +17 -8
  102. data/lib/carray/mask_gap_fill.rb +37 -17
  103. data/lib/carray/meld_reduce.rb +1 -1
  104. data/lib/carray/methods/choose.rb +3 -2
  105. data/lib/carray/methods/meshgrid.rb +3 -1
  106. data/lib/carray/runtime.rb +47 -8
  107. data/lib/carray/segment_iterator.rb +23 -8
  108. data/lib/carray/serialize.rb +34 -17
  109. data/lib/carray/stack.rb +18 -6
  110. data/lib/carray/time.rb +5 -0
  111. data/lib/carray/window_iterator.rb +16 -4
  112. data/yard-stubs/ca_obj_array.rb +26 -1
  113. data/yard-stubs/carray_cast.rb +8 -5
  114. data/yard-stubs/carray_conversion.rb +8 -2
  115. data/yard-stubs/carray_mask.rb +20 -1
  116. data/yard-stubs/carray_math.rb +31 -16
  117. data/yard-stubs/carray_memory_view.rb +7 -0
  118. data/yard-stubs/carray_test.rb +7 -4
  119. 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) AND stay within that parent
282
- dim's bounds across leaf's full extent *given the base position*.
283
- Otherwise the leaf's traversal would wrap across parent dim
284
- boundaries, which is a non-strided access pattern that cannot
285
- be folded. */
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
- /* Final position in parent dim after the full leaf extent.
307
- For a forward step it must stay strictly below dim; for a
308
- backward step it must stay at or above 0. */
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 idx[CA_RANK_MAX];
690
+ ca_size_t a = addrs[i];
684
691
  ca_size_t off = ebase;
685
- ca_addr2index((CArray *) ca, addrs[i], idx);
686
- for ( k = 0; k < ca->ndim; k++ ) {
687
- off += idx[k] * esteps[k];
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. Ask the root for that span once and walk the request over
825
- it, as xfer_all does for the whole view. A PUT reads the span first so
826
- the cells between the requested ones go back unchanged. */
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
- ca_xfer_stride(root, &rlo, &rcount, &rstep, scratch, CA_XFER_PUT);
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 -- and of those,
1122
- only the ones with an xfer_stride slot can answer a region request at all.
1123
- The rest have nothing better than materialising, so they keep doing it once
1124
- under attach rather than once per transfer. */
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 ca_func[root->obj_type].xfer_stride != NULL;
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
- if ( root->ndim == 1 && ca->bytes == root->bytes ) {
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, (dir == CA_XFER_PUT) ? 1 : 0,
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 -- our view covers every root cell;
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 an entity that can be written, a value that is not a String (the
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
- ca_triop_eval (CATriOp *to, const ca_lazy_req_t *req, void *data)
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, int32_t ipow, char *ptr2)
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, int32_t ipow, char *ptr2)
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, int32_t ipow, char *ptr2)
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, int32_t ipow, char *ptr2)
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
- int32_t ipow;
198
+ int64_t ipow;
199
199
  boolean8_t *m;
200
200
 
201
- ipow = NUM2INT(other);
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
- int32_t ipow;
255
+ int64_t ipow;
256
256
  boolean8_t *m;
257
257
 
258
- ipow = NUM2INT(other);
258
+ ipow = NUM2LL(other);
259
259
 
260
260
  TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
261
261
 
@@ -1,4 +1,4 @@
1
- /* CSV body reader for CAFrame.from_csv.
1
+ /* CSV body reader for CAFrame.read_csv.
2
2
 
3
3
  CArray.__csv_read_body_as_string_cells__(text, sep, quote, ncol, keep)
4
4
  -> [ncol, cells, records]
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
- #define CA_FLAG_CYCLE_CHECK 64
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
- volatile VALUE obj = Qnil;
1561
- CArray *ca;
1562
- CAIndexInfo info;
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
- info.range_check = 0;
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
- switch ( info.type ) {
1570
- case CA_REG_ADDRESS_COMPLEX:
1571
- obj = rb_ca_fetch_addr(self, 0);
1572
- break;
1573
- case CA_REG_ADDRESS:
1574
- obj = rb_ca_fetch_addr(self, 0);
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);