carray 3.0.2 → 3.0.3

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 (218) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +304 -0
  3. data/README.md +3 -4
  4. data/carray.gemspec +1 -1
  5. data/ext/ca_axis_dispatch.c +225 -0
  6. data/ext/ca_axis_group.c +177 -99
  7. data/ext/ca_binop_dispatch.c +54 -32
  8. data/ext/ca_binop_dispatch.h +1 -0
  9. data/ext/ca_categorical_iterator.c +66 -71
  10. data/ext/ca_compare.c +8 -2
  11. data/ext/ca_for_buffer.h +21 -68
  12. data/ext/ca_group_iter.c +27 -11
  13. data/ext/ca_kernel_iterator.c +663 -214
  14. data/ext/ca_kernel_iterator.h +231 -167
  15. data/ext/ca_monop_dispatch.c +4 -4
  16. data/ext/ca_monop_dispatch.h +4 -0
  17. data/ext/ca_obj_array.c +132 -22
  18. data/ext/ca_obj_bincmp.c +152 -121
  19. data/ext/ca_obj_binop.c +107 -210
  20. data/ext/ca_obj_bitarray.c +37 -24
  21. data/ext/ca_obj_bitfield.c +95 -62
  22. data/ext/ca_obj_block.c +1 -0
  23. data/ext/ca_obj_byte_swap.c +40 -40
  24. data/ext/ca_obj_const_string.c +96 -25
  25. data/ext/ca_obj_face.c +406 -64
  26. data/ext/ca_obj_face.h +92 -47
  27. data/ext/ca_obj_fake.c +21 -50
  28. data/ext/ca_obj_farray.c +1 -0
  29. data/ext/ca_obj_field.c +16 -3
  30. data/ext/ca_obj_fixlen_string.c +21 -21
  31. data/ext/ca_obj_grid.c +181 -124
  32. data/ext/ca_obj_meld.c +189 -107
  33. data/ext/ca_obj_moncmp.c +61 -61
  34. data/ext/ca_obj_monop.c +125 -107
  35. data/ext/ca_obj_object.c +543 -233
  36. data/ext/ca_obj_record.c +51 -16
  37. data/ext/ca_obj_reduce.c +5 -8
  38. data/ext/ca_obj_refer.c +117 -33
  39. data/ext/ca_obj_remap.c +57 -17
  40. data/ext/ca_obj_repeat.c +21 -5
  41. data/ext/ca_obj_roll.c +115 -11
  42. data/ext/ca_obj_select.c +47 -49
  43. data/ext/ca_obj_select_axis.c +58 -60
  44. data/ext/ca_obj_shift.c +22 -102
  45. data/ext/ca_obj_stack.c +223 -118
  46. data/ext/ca_obj_stride.c +195 -34
  47. data/ext/ca_obj_string.c +17 -18
  48. data/ext/ca_obj_tile.c +32 -16
  49. data/ext/ca_obj_time.c +23 -25
  50. data/ext/ca_obj_timedelta.c +21 -23
  51. data/ext/ca_obj_transpose.c +12 -3
  52. data/ext/ca_obj_triop.c +110 -117
  53. data/ext/ca_obj_window.c +149 -27
  54. data/ext/ca_op_ipower.c +24 -11
  55. data/ext/ca_op_powi.h +57 -30
  56. data/ext/ca_pow5_table.h +656 -0
  57. data/ext/ca_sort_kernels.h +70 -0
  58. data/ext/ca_sweep_engine.c +102 -79
  59. data/ext/ca_sweep_engine.h +7 -20
  60. data/ext/ca_triop_dispatch.c +4 -1
  61. data/ext/ca_triop_dispatch.h +5 -2
  62. data/ext/caframe_csv_reader.c +463 -0
  63. data/ext/carray.h +70 -27
  64. data/ext/carray_access.c +455 -211
  65. data/ext/carray_address_basis.c +177 -36
  66. data/ext/carray_attribute.c +45 -3
  67. data/ext/carray_bincount.c +32 -2
  68. data/ext/carray_broadcast.c +46 -14
  69. data/ext/carray_call_cfunc.c +0 -28
  70. data/ext/carray_cast.c +1444 -209
  71. data/ext/carray_cast_func.rb +34 -21
  72. data/ext/carray_conversion.c +197 -73
  73. data/ext/carray_copy.c +32 -11
  74. data/ext/carray_core.c +514 -122
  75. data/ext/carray_count.c +140 -87
  76. data/ext/carray_element.c +18 -27
  77. data/ext/carray_factorize.c +569 -277
  78. data/ext/carray_generate.c +76 -40
  79. data/ext/carray_histogram.c +152 -94
  80. data/ext/carray_hold.c +2 -1
  81. data/ext/carray_index_classifier.c +63 -96
  82. data/ext/carray_internal.h +385 -3
  83. data/ext/carray_lazy.c +834 -79
  84. data/ext/carray_loop.c +81 -65
  85. data/ext/carray_mask.c +682 -316
  86. data/ext/carray_math_kernel.h +1 -0
  87. data/ext/carray_median_percentile.c +221 -76
  88. data/ext/carray_memory_view.c +254 -248
  89. data/ext/carray_operator.c +1089 -359
  90. data/ext/carray_order.c +133 -69
  91. data/ext/carray_partition.c +102 -56
  92. data/ext/carray_random.c +273 -239
  93. data/ext/carray_scatter.c +308 -65
  94. data/ext/carray_segment.c +257 -0
  95. data/ext/carray_slab.c +170 -70
  96. data/ext/carray_sort.c +215 -218
  97. data/ext/carray_sort_kernel.c +8 -1
  98. data/ext/carray_struct.c +99 -21
  99. data/ext/carray_test.c +167 -64
  100. data/ext/carray_time_text.c +1182 -0
  101. data/ext/carray_utils.c +363 -98
  102. data/ext/extconf.rb +27 -2
  103. data/ext/mk_call_cfunc.rb +0 -2
  104. data/ext/mk_pow5_table.rb +35 -0
  105. data/ext/mkkernel.rb +1076 -846
  106. data/ext/ruby_carray.c +7 -1
  107. data/ext/version.h +4 -4
  108. data/ext/version.rb +4 -2
  109. data/lib/carray/attribute.rb +39 -0
  110. data/lib/carray/autoload_carray.rb +19 -0
  111. data/lib/carray/autoload_method_extension.rb +6 -0
  112. data/lib/carray/axis_group.rb +174 -26
  113. data/lib/carray/basics.rb +91 -25
  114. data/lib/carray/bincount_nd.rb +6 -0
  115. data/lib/carray/block_iterator.rb +118 -48
  116. data/lib/carray/boolean_reduce.rb +21 -29
  117. data/lib/carray/categorical.rb +94 -26
  118. data/lib/carray/categorical_iterator.rb +333 -826
  119. data/lib/carray/complex.rb +36 -29
  120. data/lib/carray/conditional.rb +94 -7
  121. data/lib/carray/const_string.rb +46 -0
  122. data/lib/carray/frame/concat.rb +157 -6
  123. data/lib/carray/frame/convert.rb +13 -7
  124. data/lib/carray/frame/csv_parser.rb +589 -82
  125. data/lib/carray/frame/describe.rb +79 -0
  126. data/lib/carray/frame/frame.rb +124 -25
  127. data/lib/carray/frame/group.rb +189 -63
  128. data/lib/carray/frame/io.rb +412 -72
  129. data/lib/carray/frame/join.rb +134 -46
  130. data/lib/carray/frame/records.rb +37 -16
  131. data/lib/carray/frame/reshape.rb +448 -0
  132. data/lib/carray/frame/sort.rb +26 -2
  133. data/lib/carray/frame/verbs.rb +715 -48
  134. data/lib/carray/frame.rb +2 -0
  135. data/lib/carray/fuse_source.rb +111 -2
  136. data/lib/carray/fusion.rb +229 -38
  137. data/lib/carray/inspect.rb +29 -11
  138. data/lib/carray/iterator.rb +14 -2
  139. data/lib/carray/lazy.rb +54 -30
  140. data/lib/carray/mask_gap_fill.rb +66 -52
  141. data/lib/carray/math.rb +32 -19
  142. data/lib/carray/meld_reduce.rb +40 -7
  143. data/lib/carray/methods/align_addr.rb +8 -4
  144. data/lib/carray/methods/bincount.rb +2 -2
  145. data/lib/carray/methods/bit_string.rb +14 -3
  146. data/lib/carray/methods/composition.rb +16 -10
  147. data/lib/carray/methods/factorize.rb +2 -2
  148. data/lib/carray/methods/gather_nd.rb +13 -2
  149. data/lib/carray/methods/insert_block.rb +9 -14
  150. data/lib/carray/methods/is_in.rb +117 -4
  151. data/lib/carray/methods/join.rb +1 -1
  152. data/lib/carray/methods/locate_addr.rb +177 -36
  153. data/lib/carray/methods/mode.rb +18 -1
  154. data/lib/carray/methods/repeat.rb +1 -20
  155. data/lib/carray/methods/resize.rb +21 -23
  156. data/lib/carray/methods/snap.rb +34 -12
  157. data/lib/carray/methods/unique.rb +11 -2
  158. data/lib/carray/record_order.rb +208 -0
  159. data/lib/carray/runtime.rb +14 -11
  160. data/lib/carray/segment_iterator.rb +990 -0
  161. data/lib/carray/serialize.rb +197 -27
  162. data/lib/carray/slab_iterator.rb +51 -27
  163. data/lib/carray/stack.rb +10 -4
  164. data/lib/carray/string_operation_extension.rb +4 -3
  165. data/lib/carray/struct.rb +142 -51
  166. data/lib/carray/struct_builder.rb +110 -14
  167. data/lib/carray/table.rb +2 -2
  168. data/lib/carray/time.rb +517 -103
  169. data/lib/carray/window_iterator.rb +127 -72
  170. data/lib/carray.rb +2 -2
  171. data/yard-stubs/ca_obj_array.rb +4 -4
  172. data/yard-stubs/ca_obj_bitarray.rb +7 -0
  173. data/yard-stubs/ca_obj_bitfield.rb +23 -12
  174. data/yard-stubs/ca_obj_fake.rb +1 -1
  175. data/yard-stubs/ca_obj_field.rb +1 -1
  176. data/yard-stubs/ca_obj_refer.rb +3 -3
  177. data/yard-stubs/ca_obj_roll.rb +0 -1
  178. data/yard-stubs/ca_obj_stride.rb +10 -7
  179. data/yard-stubs/ca_obj_transpose.rb +1 -1
  180. data/yard-stubs/ca_obj_window.rb +1 -2
  181. data/yard-stubs/carray_access.rb +5 -4
  182. data/yard-stubs/carray_broadcast.rb +1 -1
  183. data/yard-stubs/carray_cast.rb +78 -43
  184. data/yard-stubs/carray_conversion.rb +13 -1
  185. data/yard-stubs/carray_copy.rb +8 -3
  186. data/yard-stubs/carray_core.rb +3 -3
  187. data/yard-stubs/carray_count.rb +9 -0
  188. data/yard-stubs/carray_lazy.rb +5 -1
  189. data/yard-stubs/carray_loop.rb +4 -1
  190. data/yard-stubs/carray_mask.rb +34 -10
  191. data/yard-stubs/carray_math.rb +25 -13
  192. data/yard-stubs/carray_median_percentile.rb +10 -6
  193. data/yard-stubs/carray_order.rb +34 -13
  194. data/yard-stubs/carray_scatter.rb +10 -3
  195. data/yard-stubs/carray_segment.rb +72 -0
  196. data/yard-stubs/carray_slab.rb +2 -1
  197. data/yard-stubs/carray_sort.rb +43 -3
  198. data/yard-stubs/carray_test.rb +10 -0
  199. data/yard-stubs/carray_utils.rb +0 -26
  200. metadata +11 -19
  201. data/ext/ca_for_each_element.h +0 -239
  202. data/ext/carray_build_flags.h +0 -3
  203. data/ext/carray_config.h +0 -28
  204. data/ext/carray_kernels_bincmp.c +0 -4446
  205. data/ext/carray_kernels_binop.c +0 -11001
  206. data/ext/carray_kernels_init.c +0 -1131
  207. data/ext/carray_kernels_map.c +0 -3467
  208. data/ext/carray_kernels_moncmp.c +0 -2097
  209. data/ext/carray_kernels_monop.c +0 -18313
  210. data/ext/carray_kernels_reduce_aggregate.c +0 -26005
  211. data/ext/carray_kernels_reduce_boolean.c +0 -330
  212. data/ext/carray_kernels_reduce_cumulative.c +0 -14862
  213. data/ext/carray_kernels_reduce_extreme.c +0 -17494
  214. data/ext/carray_kernels_reduce_variance.c +0 -3910
  215. data/ext/carray_kernels_scan.c +0 -3693
  216. data/ext/carray_kernels_search.c +0 -32218
  217. data/ext/carray_kernels_sort.c +0 -10626
  218. data/ext/carray_kernels_triop.c +0 -1392
data/ext/ca_obj_repeat.c CHANGED
@@ -39,20 +39,23 @@ ca_repeat_setup (CAStride *ca, CArray *parent, int8_t ndim, ca_size_t *count)
39
39
  int8_t data_ndim = 0;
40
40
  int8_t i, j;
41
41
 
42
+ if ( ndim < 0 || ndim > CA_RANK_MAX ) {
43
+ rb_raise(rb_eArgError, "invalid ndim %d", (int) ndim);
44
+ }
42
45
  for (i = 0; i < ndim; i++) {
43
46
  if (count[i] < 0) {
44
- rb_raise(rb_eRuntimeError,
47
+ rb_raise(rb_eArgError,
45
48
  "negative size for %i-th dimension specified", i);
46
49
  }
47
50
  if (count[i]) nrpt *= count[i];
48
51
  else data_ndim += 1;
49
52
  }
50
53
  if (data_ndim != parent->ndim) {
51
- rb_raise(rb_eRuntimeError,
54
+ rb_raise(rb_eArgError,
52
55
  "mismatch in ndim between original array and determined by # of dummies");
53
56
  }
54
57
  if (((double) parent->elements) * nrpt > CA_LENGTH_MAX) {
55
- rb_raise(rb_eRuntimeError, "too large byte length");
58
+ rb_raise(rb_eArgError, "too large byte length");
56
59
  }
57
60
  (void) total_elements_d;
58
61
 
@@ -77,6 +80,12 @@ ca_repeat_setup (CAStride *ca, CArray *parent, int8_t ndim, ca_size_t *count)
77
80
  }
78
81
  }
79
82
 
83
+ /* ca == NULL asks for the checks above only, so that a constructor can
84
+ run them before it allocates. */
85
+ if ( ca == NULL ) {
86
+ return 0;
87
+ }
88
+
80
89
  ca_stride_setup(ca, CA_OBJ_REPEAT, parent,
81
90
  parent->data_type, parent->bytes,
82
91
  ndim, newdim, strides, 0);
@@ -91,7 +100,9 @@ ca_repeat_setup (CAStride *ca, CArray *parent, int8_t ndim, ca_size_t *count)
91
100
  CAStride *
92
101
  ca_repeat_new (CArray *parent, int8_t ndim, ca_size_t *count)
93
102
  {
94
- CAStride *ca = (CAStride *) ca_array_alloc(CA_OBJ_REPEAT, ndim);
103
+ CAStride *ca;
104
+ ca_repeat_setup(NULL, parent, ndim, count);
105
+ ca = (CAStride *) ca_array_alloc(CA_OBJ_REPEAT, ndim);
95
106
  ca_repeat_setup(ca, parent, ndim, count);
96
107
  return ca;
97
108
  }
@@ -155,7 +166,7 @@ rb_ca_repeat (int argc, VALUE *argv, VALUE self)
155
166
  TypedData_Get_Struct(argv[0], CArray, &carray_data_type, ct);
156
167
  }
157
168
  if ( ct->ndim < ca->ndim ) {
158
- rb_raise(rb_eRuntimeError, "invalid ndim to template");
169
+ rb_raise(rb_eArgError, "invalid ndim to template");
159
170
  }
160
171
  args = rb_ary_new();
161
172
  ndim = 0;
@@ -208,6 +219,10 @@ rb_ca_repeat (int argc, VALUE *argv, VALUE self)
208
219
  return rb_ca_repeat((int)RARRAY_LEN(args), (VALUE *)RARRAY_CONST_PTR(args), self);
209
220
  }
210
221
 
222
+ if ( argc > CA_RANK_MAX ) { /* count[] and dim[] hold CA_RANK_MAX */
223
+ rb_raise(rb_eArgError, "invalid ndim %d", argc);
224
+ }
225
+
211
226
  repeat = 1;
212
227
  for (i=0; i<argc; i++) {
213
228
  if ( rb_obj_is_kind_of(argv[i], rb_cSymbol) ) {
@@ -255,6 +270,7 @@ rb_ca_repeat_initialize_copy (VALUE self, VALUE other)
255
270
  {
256
271
  CAStride *ca, *cs;
257
272
  TypedData_Get_Struct(self, CAStride, &castride_data_type, ca);
273
+ ca_check_uninitialized(ca);
258
274
  TypedData_Get_Struct(other, CAStride, &castride_data_type, cs);
259
275
  if ( ca_func[CA_OBJ_REPEAT].pool_init ) {
260
276
  ca_array_pool_alloc(ca, CA_OBJ_REPEAT, cs->ndim);
data/ext/ca_obj_roll.c CHANGED
@@ -17,6 +17,7 @@
17
17
  ---------------------------------------------------------------------------- */
18
18
 
19
19
  #include "carray.h"
20
+ #include "carray_internal.h"
20
21
  #include "ca_composite_dispatch.h"
21
22
  #include "ca_obj_face.h"
22
23
 
@@ -90,12 +91,15 @@ ca_roll_setup (CARoll *ca, CArray *parent, ca_size_t *shift)
90
91
 
91
92
  elements = 1;
92
93
  for (i = 0; i < ndim; i++) {
93
- if ( parent->dim[i] <= 0 ) {
94
- rb_raise(rb_eIndexError, "invalid parent dim for %d-th dimension", i);
95
- }
96
94
  elements *= parent->dim[i];
97
95
  }
98
96
 
97
+ /* ca == NULL asks for the checks above only, so that a constructor can
98
+ run them before it allocates. */
99
+ if ( ca == NULL ) {
100
+ return 0;
101
+ }
102
+
99
103
  ca->obj_type = CA_OBJ_ROLL;
100
104
  ca->data_type = parent->data_type;
101
105
  ca->flags = 0;
@@ -114,8 +118,11 @@ ca_roll_setup (CARoll *ca, CArray *parent, ca_size_t *shift)
114
118
  for (i = 0; i < ndim; i++) {
115
119
  ca->dim[i] = parent->dim[i];
116
120
  /* Normalise: ((shift[i] % dim[i]) + dim[i]) % dim[i] ∈ [0, dim[i]). */
117
- ca_size_t s = shift[i] % parent->dim[i];
118
- if ( s < 0 ) s += parent->dim[i];
121
+ ca_size_t s = 0; /* an empty axis has nothing to roll */
122
+ if ( parent->dim[i] > 0 ) {
123
+ s = shift[i] % parent->dim[i];
124
+ if ( s < 0 ) s += parent->dim[i];
125
+ }
119
126
  ca->reps[i] = s;
120
127
  }
121
128
 
@@ -129,7 +136,9 @@ ca_roll_setup (CARoll *ca, CArray *parent, ca_size_t *shift)
129
136
  CARoll *
130
137
  ca_roll_new (CArray *parent, ca_size_t *shift)
131
138
  {
132
- CARoll *ca = ALLOC(CARoll);
139
+ CARoll *ca;
140
+ ca_roll_setup(NULL, parent, shift);
141
+ ca = ALLOC(CARoll);
133
142
  ca_roll_setup(ca, parent, shift);
134
143
  return ca;
135
144
  }
@@ -214,6 +223,7 @@ static void
214
223
  ca_roll_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
215
224
  ca_size_t *strides, void *data, int dir)
216
225
  {
226
+ if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
217
227
  CARoll *ca = (CARoll *) ap;
218
228
  CArray *parent = ca->parent;
219
229
  int8_t ndim = ca->ndim;
@@ -264,6 +274,95 @@ ca_roll_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
264
274
  return;
265
275
  }
266
276
 
277
+ /* The inner range is one run of a parent row, or two when it wraps, and
278
+ the rows along the next axis out are consecutive parent rows except
279
+ across that axis's wrap. So each pass over the axes further out moves
280
+ at most two strided boxes per inner run, instead of one transfer per
281
+ row. A box over an unwrapped inner range is already the request's own
282
+ layout; a box over one of two inner runs goes through a scratch whose
283
+ rows are spliced into the request's. Object cells keep the per-row
284
+ path: a scratch would hold the VALUEs a parent produces where the GC
285
+ cannot see them. */
286
+ if ( inner >= 1 ) {
287
+ int8_t m = inner - 1;
288
+ ca_size_t dim_in = parent->dim[inner];
289
+ ca_size_t p0 = starts[inner] - ca->reps[inner];
290
+ ca_size_t seg_p[2], seg_n[2], seg_i[2];
291
+ int nseg, sg;
292
+ if (p0 < 0) p0 += dim_in;
293
+ if ( p0 + counts[inner] <= dim_in ) {
294
+ nseg = 1;
295
+ seg_p[0] = p0; seg_n[0] = counts[inner]; seg_i[0] = 0;
296
+ }
297
+ else {
298
+ nseg = 2;
299
+ seg_p[0] = p0; seg_n[0] = dim_in - p0; seg_i[0] = 0;
300
+ seg_p[1] = 0; seg_n[1] = counts[inner] - seg_n[0]; seg_i[1] = seg_n[0];
301
+ }
302
+ if ( nseg == 1 || ca->data_type != CA_OBJECT ) {
303
+ volatile VALUE holder = 0;
304
+ char *tmp = NULL;
305
+ if ( nseg == 2 ) {
306
+ ca_size_t wide = seg_n[0] > seg_n[1] ? seg_n[0] : seg_n[1];
307
+ tmp = (char *) ALLOCV(holder, counts[m] * wide * ca->bytes);
308
+ }
309
+ for (k = 0; k < m; k++) o[k] = 0;
310
+ while (1) {
311
+ ca_size_t pbase = 0, doff = 0;
312
+ for (k = 0; k < m; k++) {
313
+ ca_size_t j = (starts[k] + o[k]) - ca->reps[k];
314
+ if (j < 0) j += parent->dim[k];
315
+ pbase += j * pnative[k];
316
+ doff += o[k] * dstride[k];
317
+ }
318
+ for (sg = 0; sg < nseg; sg++) {
319
+ ca_size_t r = 0;
320
+ while (r < counts[m]) {
321
+ ca_size_t pm = (starts[m] + r) - ca->reps[m];
322
+ ca_size_t run, q;
323
+ ca_size_t pstarts[CA_RANK_MAX], pcounts[CA_RANK_MAX], pstrides[CA_RANK_MAX];
324
+ char *rows = d + doff + r * dstride[m] + seg_i[sg] * ca->bytes;
325
+ ca_size_t rowb = seg_n[sg] * ca->bytes;
326
+ if (pm < 0) pm += parent->dim[m];
327
+ run = parent->dim[m] - pm;
328
+ if (run > counts[m] - r) run = counts[m] - r;
329
+ ca_addr2index((CArray *) parent,
330
+ (pbase + pm * pnative[m] + seg_p[sg] * pnative[inner])
331
+ / parent->bytes, pstarts);
332
+ for (k = 0; k < ndim; k++) { pcounts[k] = 1; pstrides[k] = 0; }
333
+ pcounts[m] = run;
334
+ pstrides[m] = pnative[m];
335
+ pcounts[inner] = seg_n[sg];
336
+ pstrides[inner] = pnative[inner];
337
+ if ( nseg == 1 ) {
338
+ ca_xfer_stride(parent, pstarts, pcounts, pstrides, rows, dir);
339
+ }
340
+ else if ( dir == CA_XFER_GET ) {
341
+ ca_xfer_stride(parent, pstarts, pcounts, pstrides, tmp, dir);
342
+ for (q = 0; q < run; q++) {
343
+ memcpy(rows + q * dstride[m], tmp + q * rowb, rowb);
344
+ }
345
+ }
346
+ else {
347
+ for (q = 0; q < run; q++) {
348
+ memcpy(tmp + q * rowb, rows + q * dstride[m], rowb);
349
+ }
350
+ ca_xfer_stride(parent, pstarts, pcounts, pstrides, tmp, dir);
351
+ }
352
+ r += run;
353
+ }
354
+ }
355
+ k = m - 1;
356
+ while (k >= 0) { if (++o[k] < counts[k]) break; o[k] = 0; k--; }
357
+ if (k < 0) break;
358
+ }
359
+ if ( tmp ) {
360
+ ALLOCV_END(holder);
361
+ }
362
+ return;
363
+ }
364
+ }
365
+
267
366
  for (k = 0; k < ndim; k++) o[k] = 0;
268
367
  while (1) {
269
368
  ca_size_t pbase = 0, doff = 0, i;
@@ -459,10 +558,13 @@ ca_roll_func_xfer_all (void *ap, void *data, int dir)
459
558
  ca_xfer_all(parent, parent_scratch, CA_XFER_GET);
460
559
  parent->ptr = parent_scratch;
461
560
  ca_roll_iterate_regions(ca, (char *) data, dir == CA_XFER_PUT);
561
+ /* Put parent->ptr back before the PUT: the PUT can raise (a lazy
562
+ backing's sync failing), and the scratch is gone once this
563
+ frame is. */
564
+ parent->ptr = parent_ptr_saved;
462
565
  if ( dir == CA_XFER_PUT ) {
463
566
  ca_xfer_all(parent, parent_scratch, CA_XFER_PUT);
464
567
  }
465
- parent->ptr = parent_ptr_saved;
466
568
  ALLOCV_END(holder);
467
569
  }
468
570
  }
@@ -480,10 +582,7 @@ static void
480
582
  ca_roll_func_create_mask (void *ap)
481
583
  {
482
584
  CARoll *ca = (CARoll *) ap;
483
- ca_update_mask(ca->parent);
484
- if ( ! ca->parent->mask ) {
485
- ca_create_mask(ca->parent);
486
- }
585
+ ca_create_mask(ca->parent);
487
586
  ca->mask = (CArray *) ca_roll_new(ca->parent->mask, ca->reps);
488
587
  }
489
588
 
@@ -557,11 +656,13 @@ rb_ca_roll_initialize_copy (VALUE self, VALUE other)
557
656
  {
558
657
  CARoll *ca, *cs;
559
658
  TypedData_Get_Struct(self, CARoll, &caroll_data_type, ca);
659
+ ca_check_uninitialized(ca);
560
660
  TypedData_Get_Struct(other, CARoll, &caroll_data_type, cs);
561
661
  ca_roll_setup(ca, cs->parent, cs->reps);
562
662
  return self;
563
663
  }
564
664
 
665
+ #ifdef CARRAY_DEV_BUILD
565
666
  /* Debug-only accessor returning the roll descriptor as a Hash
566
667
  (`shifts`, `n_regions`, `ndim`). Not part of the public surface. */
567
668
  static VALUE
@@ -583,6 +684,7 @@ rb_ca_roll_descriptor (VALUE self)
583
684
  rb_hash_aset(hash, ID2SYM(rb_intern("ndim")), INT2NUM(ca->ndim));
584
685
  return hash;
585
686
  }
687
+ #endif
586
688
 
587
689
  void
588
690
  Init_ca_obj_roll (void)
@@ -618,7 +720,9 @@ Init_ca_obj_roll (void)
618
720
  rb_define_method(rb_cCARoll, "initialize_copy",
619
721
  rb_ca_roll_initialize_copy, 1);
620
722
 
723
+ #ifdef CARRAY_DEV_BUILD
621
724
  /* Debug accessor, not part of the public surface. */
622
725
  rb_define_method(rb_cCARoll, "_roll_descriptor",
623
726
  rb_ca_roll_descriptor, 0);
727
+ #endif
624
728
  }
data/ext/ca_obj_select.c CHANGED
@@ -93,21 +93,24 @@ ca_select_snapshot_masked (VALUE arg)
93
93
  {
94
94
  CArray **pair = (CArray **) arg;
95
95
  CArray *select = pair[0], *snap = pair[1];
96
- boolean8_t *p, *q, *m;
96
+ boolean8_t *q, *m;
97
97
  ca_size_t i;
98
- ca_attach(select);
98
+ volatile VALUE holder = 0;
99
+ ca_copy_data(select, snap->ptr);
100
+ ca_update_mask(select);
101
+ m = ALLOCV_N(boolean8_t, holder, select->elements);
102
+ ca_copy_data(select->mask, (char *) m);
99
103
  q = (boolean8_t *) snap->ptr;
100
- p = (boolean8_t *) select->ptr;
101
- m = (boolean8_t *) select->mask->ptr;
102
104
  for (i = 0; i < select->elements; i++) {
103
- *q = ( *m ) ? 0 : *p;
104
- q++; p++; m++;
105
+ if ( m[i] ) {
106
+ q[i] = 0;
107
+ }
105
108
  }
106
- ca_detach(select);
109
+ ALLOCV_END(holder);
107
110
  return Qnil;
108
111
  }
109
112
 
110
- static CArray *
113
+ CArray *
111
114
  ca_select_snapshot (CArray *select)
112
115
  {
113
116
  if ( ! ca_is_boolean_type(select) ) {
@@ -352,6 +355,7 @@ static void
352
355
  ca_select_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
353
356
  ca_size_t *strides, void *data, int dir)
354
357
  {
358
+ if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
355
359
  CASelect *ca = (CASelect *) ap;
356
360
  CArray *parent = ca->parent;
357
361
  ca_size_t n = counts[0];
@@ -414,24 +418,34 @@ ca_select_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
414
418
  }
415
419
  }
416
420
 
421
+ /* A parent with no memory to lend (ca_parent_lends_no_memory) is never
422
+ attached: the view owns its buffer, filled and drained through xfer_all,
423
+ which asks the parent for the selected cells only. The predicate asks
424
+ what the parent is, not whether it is attached now, so attach, sync and
425
+ detach all take the same branch. */
426
+
417
427
  static void
418
428
  ca_select_func_allocate (void *ap)
419
429
  {
420
430
  CASelect *ca = (CASelect *) ap;
421
- ca_attach(ca->parent);
431
+ if ( ! ca_parent_lends_no_memory(ca->parent) ) {
432
+ ca_attach(ca->parent);
433
+ }
422
434
  ca->ptr = xmalloc(ca_length(ca));
423
435
  }
424
436
 
425
- /* Every attach / sync / xfer_all / xfer_stride / fill_data path
426
- dispatches through the descriptor engine with the same shape
427
- CASelectAxis uses: one axis over a flattened parent. */
428
-
429
437
  static void
430
438
  ca_select_func_attach (void *ap)
431
439
  {
432
440
  CASelect *ca = (CASelect *) ap;
433
441
  ca_axis_desc_t desc[CA_RANK_MAX];
434
442
  ca_size_t pdims[CA_RANK_MAX];
443
+
444
+ if ( ca_parent_lends_no_memory(ca->parent) ) {
445
+ ca_axis_view_attach_owned(ca);
446
+ return;
447
+ }
448
+
435
449
  ca_attach(ca->parent);
436
450
  ca_select_describe_axes(ca, desc, pdims);
437
451
  ca->ptr = ca_axis_dispatch_attach(ca->parent, pdims, desc, ca->ndim,
@@ -444,6 +458,12 @@ ca_select_func_sync (void *ap)
444
458
  CASelect *ca = (CASelect *) ap;
445
459
  ca_axis_desc_t desc[CA_RANK_MAX];
446
460
  ca_size_t pdims[CA_RANK_MAX];
461
+
462
+ if ( ca_parent_lends_no_memory(ca->parent) ) {
463
+ ca_axis_view_sync_owned(ca);
464
+ return;
465
+ }
466
+
447
467
  ca_select_describe_axes(ca, desc, pdims);
448
468
  ca_axis_dispatch_scatter(ca->parent, pdims, desc, ca->ndim, ca->bytes,
449
469
  ca->elements, ca->ptr);
@@ -454,16 +474,20 @@ static void
454
474
  ca_select_func_detach (void *ap)
455
475
  {
456
476
  CASelect *ca = (CASelect *) ap;
457
- xfree(ca->ptr);
458
- ca->ptr = NULL;
459
- ca_detach(ca->parent);
477
+ if ( ca->ptr ) {
478
+ xfree(ca->ptr);
479
+ ca->ptr = NULL;
480
+ }
481
+ if ( ! ca_parent_lends_no_memory(ca->parent) ) {
482
+ ca_detach(ca->parent);
483
+ }
460
484
  }
461
485
 
462
- /* Fast-path core used by xfer_all's attached-parent branch and the
463
- cold-parent 2-pass scratch branch below. */
486
+ /* The transfer against parent->ptr, for ca_axis_view_xfer_all. */
464
487
  static void
465
- ca_select_func_run_fast_path (CASelect *ca, char *data, int dir)
488
+ ca_select_func_run_fast_path (void *ap, char *data, int dir)
466
489
  {
490
+ CASelect *ca = (CASelect *) ap;
467
491
  ca_axis_desc_t desc[CA_RANK_MAX];
468
492
  ca_size_t pdims[CA_RANK_MAX];
469
493
  ca_select_describe_axes(ca, desc, pdims);
@@ -476,33 +500,10 @@ ca_select_func_run_fast_path (CASelect *ca, char *data, int dir)
476
500
  }
477
501
  }
478
502
 
479
- /* Cold parent is served by a 2-pass scratch (gather parent into a
480
- local buffer, dispatch through the fast path against the buffer,
481
- scatter back on PUT). Deliberately avoids ca_attach(parent) so
482
- that a silent transitive attach cannot re-enter through here. */
483
503
  static void
484
504
  ca_select_func_xfer_all (void *ap, void *data, int dir)
485
505
  {
486
- CASelect *ca = (CASelect *) ap;
487
- if ( ca->parent->ptr ) {
488
- ca_select_func_run_fast_path(ca, (char *) data, dir);
489
- return;
490
- }
491
- {
492
- volatile VALUE holder;
493
- CArray *parent = ca->parent;
494
- ca_size_t plen = parent->elements * parent->bytes;
495
- char *parent_scratch = ALLOCV_N(char, holder, plen);
496
- char *parent_ptr_saved = parent->ptr;
497
- ca_xfer_all(parent, parent_scratch, CA_XFER_GET);
498
- parent->ptr = parent_scratch;
499
- ca_select_func_run_fast_path(ca, (char *) data, dir);
500
- if ( dir == CA_XFER_PUT ) {
501
- ca_xfer_all(parent, parent_scratch, CA_XFER_PUT);
502
- }
503
- parent->ptr = parent_ptr_saved;
504
- ALLOCV_END(holder);
505
- }
506
+ ca_axis_view_xfer_all(ap, ca_select_func_run_fast_path, 1, data, dir);
506
507
  }
507
508
 
508
509
  static void
@@ -531,18 +532,14 @@ ca_select_func_fill_data (void *ap, void *ptr)
531
532
  ca_select_describe_axes(ca, desc, pdims);
532
533
  ca_axis_dispatch_fill_value(ca->parent, pdims, desc, ca->ndim, ca->bytes,
533
534
  ca->elements, ptr);
534
- ca_sync(ca->parent);
535
- ca_detach(ca->parent);
535
+ ca_sync_detach(ca->parent);
536
536
  }
537
537
 
538
538
  static void
539
539
  ca_select_func_create_mask (void *ap)
540
540
  {
541
541
  CASelect *ca = (CASelect *) ap;
542
- ca_update_mask(ca->parent);
543
- if ( ! ca->parent->mask ) {
544
- ca_create_mask(ca->parent);
545
- }
542
+ ca_create_mask(ca->parent);
546
543
  ca->mask = (CArray *) ca_select_new_share(ca->parent->mask, ca->select);
547
544
  }
548
545
 
@@ -624,6 +621,7 @@ rb_cm_initialize_copy (VALUE self, VALUE other)
624
621
  CASelect *ca, *cs;
625
622
 
626
623
  TypedData_Get_Struct(self, CASelect, &caselect_data_type, ca);
624
+ ca_check_uninitialized(ca);
627
625
  TypedData_Get_Struct(other, CASelect, &caselect_data_type, cs);
628
626
 
629
627
  /* Re-snapshot from the source's selector copy so the two views