carray 3.0.1 → 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 (229) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +824 -0
  3. data/README.md +5 -6
  4. data/carray.gemspec +1 -1
  5. data/ext/ca_axis_dispatch.c +258 -4
  6. data/ext/ca_axis_group.c +368 -184
  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 +90 -41
  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 +960 -245
  14. data/ext/ca_kernel_iterator.h +352 -181
  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 +194 -42
  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 +5 -4
  23. data/ext/ca_obj_byte_swap.c +40 -40
  24. data/ext/ca_obj_const_string.c +180 -50
  25. data/ext/ca_obj_face.c +428 -62
  26. data/ext/ca_obj_face.h +107 -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 +39 -26
  31. data/ext/ca_obj_grid.c +181 -124
  32. data/ext/ca_obj_meld.c +235 -55
  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 +551 -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 +88 -75
  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 -123
  46. data/ext/ca_obj_stride.c +267 -35
  47. data/ext/ca_obj_string.c +25 -22
  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 +157 -29
  54. data/ext/ca_op_ipower.c +25 -13
  55. data/ext/ca_op_powi.h +57 -30
  56. data/ext/ca_pow5_table.h +656 -0
  57. data/ext/ca_rng_normal.h +42 -0
  58. data/ext/ca_rng_xoshiro256pp.h +105 -0
  59. data/ext/ca_sort_kernels.h +70 -0
  60. data/ext/ca_sweep_engine.c +385 -198
  61. data/ext/ca_sweep_engine.h +31 -23
  62. data/ext/ca_triop_dispatch.c +4 -1
  63. data/ext/ca_triop_dispatch.h +5 -2
  64. data/ext/caframe_csv_reader.c +463 -0
  65. data/ext/carray.h +90 -28
  66. data/ext/carray_access.c +487 -231
  67. data/ext/carray_address_basis.c +731 -0
  68. data/ext/carray_attribute.c +45 -3
  69. data/ext/carray_bincount.c +32 -2
  70. data/ext/carray_broadcast.c +49 -17
  71. data/ext/carray_call_cfunc.c +667 -511
  72. data/ext/carray_cast.c +1556 -247
  73. data/ext/carray_cast_func.rb +34 -21
  74. data/ext/carray_conversion.c +197 -73
  75. data/ext/carray_copy.c +84 -38
  76. data/ext/carray_core.c +591 -119
  77. data/ext/carray_count.c +148 -96
  78. data/ext/carray_element.c +18 -27
  79. data/ext/carray_factorize.c +604 -291
  80. data/ext/carray_generate.c +76 -40
  81. data/ext/carray_histogram.c +152 -94
  82. data/ext/carray_hold.c +2 -1
  83. data/ext/carray_index_classifier.c +63 -96
  84. data/ext/carray_internal.h +400 -1
  85. data/ext/carray_lazy.c +834 -79
  86. data/ext/carray_loop.c +88 -66
  87. data/ext/carray_mask.c +705 -324
  88. data/ext/carray_math_kernel.h +1 -0
  89. data/ext/carray_median_percentile.c +263 -63
  90. data/ext/carray_memory_view.c +254 -248
  91. data/ext/carray_operator.c +1093 -363
  92. data/ext/carray_order.c +133 -69
  93. data/ext/carray_partition.c +102 -56
  94. data/ext/carray_random.c +582 -204
  95. data/ext/carray_scatter.c +308 -65
  96. data/ext/carray_segment.c +257 -0
  97. data/ext/carray_slab.c +183 -70
  98. data/ext/carray_sort.c +235 -240
  99. data/ext/carray_sort_kernel.c +8 -1
  100. data/ext/carray_struct.c +99 -21
  101. data/ext/carray_test.c +167 -64
  102. data/ext/carray_time_text.c +1182 -0
  103. data/ext/carray_utils.c +363 -98
  104. data/ext/extconf.rb +27 -2
  105. data/ext/mk_call_cfunc.rb +103 -118
  106. data/ext/mk_pow5_table.rb +35 -0
  107. data/ext/mkkernel.rb +1349 -851
  108. data/ext/ruby_carray.c +17 -2
  109. data/ext/version.h +4 -4
  110. data/ext/version.rb +4 -2
  111. data/lib/carray/attribute.rb +39 -0
  112. data/lib/carray/autoload_carray.rb +24 -3
  113. data/lib/carray/autoload_method_extension.rb +18 -0
  114. data/lib/carray/axis_group.rb +245 -20
  115. data/lib/carray/basics.rb +95 -25
  116. data/lib/carray/bincount_nd.rb +6 -0
  117. data/lib/carray/block_iterator.rb +200 -54
  118. data/lib/carray/boolean_reduce.rb +21 -29
  119. data/lib/carray/categorical.rb +244 -59
  120. data/lib/carray/categorical_iterator.rb +391 -757
  121. data/lib/carray/complex.rb +36 -29
  122. data/lib/carray/conditional.rb +94 -7
  123. data/lib/carray/const_string.rb +177 -27
  124. data/lib/carray/construct.rb +40 -0
  125. data/lib/carray/data_type_extension.rb +3 -0
  126. data/lib/carray/data_type_limits.rb +91 -0
  127. data/lib/carray/fixlen_string.rb +1 -1
  128. data/lib/carray/frame/concat.rb +157 -6
  129. data/lib/carray/frame/convert.rb +13 -7
  130. data/lib/carray/frame/csv_parser.rb +590 -76
  131. data/lib/carray/frame/describe.rb +79 -0
  132. data/lib/carray/frame/frame.rb +205 -35
  133. data/lib/carray/frame/group.rb +199 -40
  134. data/lib/carray/frame/io.rb +452 -60
  135. data/lib/carray/frame/join.rb +134 -46
  136. data/lib/carray/frame/records.rb +54 -19
  137. data/lib/carray/frame/reshape.rb +448 -0
  138. data/lib/carray/frame/sort.rb +26 -2
  139. data/lib/carray/frame/verbs.rb +726 -56
  140. data/lib/carray/frame.rb +2 -0
  141. data/lib/carray/fuse_source.rb +111 -2
  142. data/lib/carray/fusion.rb +229 -38
  143. data/lib/carray/inspect.rb +71 -20
  144. data/lib/carray/iterator.rb +157 -2
  145. data/lib/carray/lazy.rb +54 -67
  146. data/lib/carray/mask_gap_fill.rb +66 -50
  147. data/lib/carray/math.rb +32 -19
  148. data/lib/carray/meld_reduce.rb +40 -7
  149. data/lib/carray/methods/align_addr.rb +8 -4
  150. data/lib/carray/methods/bincount.rb +2 -2
  151. data/lib/carray/methods/bit_string.rb +14 -3
  152. data/lib/carray/methods/composition.rb +16 -10
  153. data/lib/carray/methods/discovery_along.rb +74 -0
  154. data/lib/carray/methods/factorize.rb +50 -0
  155. data/lib/carray/methods/gather_nd.rb +13 -2
  156. data/lib/carray/methods/insert_block.rb +9 -14
  157. data/lib/carray/methods/is_in.rb +130 -6
  158. data/lib/carray/methods/join.rb +1 -1
  159. data/lib/carray/methods/locate_addr.rb +235 -21
  160. data/lib/carray/methods/mask_duplicates.rb +35 -1
  161. data/lib/carray/methods/mode.rb +18 -1
  162. data/lib/carray/methods/nunique.rb +22 -1
  163. data/lib/carray/methods/repeat.rb +91 -0
  164. data/lib/carray/methods/resize.rb +21 -23
  165. data/lib/carray/methods/snap.rb +34 -12
  166. data/lib/carray/methods/unique.rb +52 -3
  167. data/lib/carray/record_order.rb +208 -0
  168. data/lib/carray/rng.rb +86 -0
  169. data/lib/carray/runtime.rb +14 -11
  170. data/lib/carray/segment_iterator.rb +990 -0
  171. data/lib/carray/serialize.rb +197 -27
  172. data/lib/carray/slab_iterator.rb +109 -40
  173. data/lib/carray/stack.rb +10 -4
  174. data/lib/carray/string_operation_extension.rb +9 -4
  175. data/lib/carray/struct.rb +142 -51
  176. data/lib/carray/struct_builder.rb +110 -14
  177. data/lib/carray/table.rb +2 -2
  178. data/lib/carray/time.rb +535 -105
  179. data/lib/carray/window_iterator.rb +259 -82
  180. data/lib/carray.rb +4 -2
  181. data/yard-stubs/ca_obj_array.rb +4 -4
  182. data/yard-stubs/ca_obj_bitarray.rb +7 -0
  183. data/yard-stubs/ca_obj_bitfield.rb +23 -12
  184. data/yard-stubs/ca_obj_block.rb +2 -7
  185. data/yard-stubs/ca_obj_fake.rb +1 -1
  186. data/yard-stubs/ca_obj_field.rb +1 -1
  187. data/yard-stubs/ca_obj_refer.rb +3 -3
  188. data/yard-stubs/ca_obj_roll.rb +0 -1
  189. data/yard-stubs/ca_obj_stride.rb +10 -7
  190. data/yard-stubs/ca_obj_transpose.rb +1 -1
  191. data/yard-stubs/ca_obj_window.rb +11 -4
  192. data/yard-stubs/carray_access.rb +6 -5
  193. data/yard-stubs/carray_broadcast.rb +2 -2
  194. data/yard-stubs/carray_cast.rb +78 -43
  195. data/yard-stubs/carray_conversion.rb +13 -1
  196. data/yard-stubs/carray_copy.rb +8 -3
  197. data/yard-stubs/carray_core.rb +3 -83
  198. data/yard-stubs/carray_count.rb +16 -2
  199. data/yard-stubs/carray_lazy.rb +210 -1
  200. data/yard-stubs/carray_loop.rb +4 -1
  201. data/yard-stubs/carray_mask.rb +34 -10
  202. data/yard-stubs/carray_math.rb +1499 -4
  203. data/yard-stubs/carray_median_percentile.rb +26 -8
  204. data/yard-stubs/carray_order.rb +43 -82
  205. data/yard-stubs/carray_scatter.rb +10 -3
  206. data/yard-stubs/carray_segment.rb +72 -0
  207. data/yard-stubs/carray_slab.rb +11 -8
  208. data/yard-stubs/carray_sort.rb +50 -8
  209. data/yard-stubs/carray_test.rb +10 -0
  210. data/yard-stubs/carray_utils.rb +0 -26
  211. metadata +19 -19
  212. data/ext/ca_for_each_element.h +0 -239
  213. data/ext/carray_build_flags.h +0 -3
  214. data/ext/carray_config.h +0 -28
  215. data/ext/carray_kernels_bincmp.c +0 -4446
  216. data/ext/carray_kernels_binop.c +0 -11001
  217. data/ext/carray_kernels_init.c +0 -1131
  218. data/ext/carray_kernels_map.c +0 -3467
  219. data/ext/carray_kernels_moncmp.c +0 -2097
  220. data/ext/carray_kernels_monop.c +0 -18313
  221. data/ext/carray_kernels_reduce_aggregate.c +0 -25837
  222. data/ext/carray_kernels_reduce_boolean.c +0 -330
  223. data/ext/carray_kernels_reduce_cumulative.c +0 -14593
  224. data/ext/carray_kernels_reduce_extreme.c +0 -16948
  225. data/ext/carray_kernels_reduce_variance.c +0 -3910
  226. data/ext/carray_kernels_scan.c +0 -3693
  227. data/ext/carray_kernels_search.c +0 -32138
  228. data/ext/carray_kernels_sort.c +0 -10626
  229. data/ext/carray_kernels_triop.c +0 -1392
data/ext/ca_obj_tile.c CHANGED
@@ -16,6 +16,7 @@
16
16
  ---------------------------------------------------------------------------- */
17
17
 
18
18
  #include "carray.h"
19
+ #include "carray_internal.h"
19
20
  #include "ca_composite_dispatch.h"
20
21
  #include "ca_obj_face.h" /* CA_FACE_LIFT_IF_FACE */
21
22
 
@@ -75,17 +76,24 @@ ca_tile_setup (CATile *ca, CArray *parent, ca_size_t *reps)
75
76
  ndim = parent->ndim;
76
77
  bytes = parent->bytes;
77
78
 
78
- elements = 1;
79
- for (i = 0; i < ndim; i++) {
80
- if ( reps[i] <= 0 ) {
81
- rb_raise(rb_eIndexError,
82
- "invalid reps for %d-th dimension (must be positive)", i);
83
- }
84
- if ( parent->dim[i] <= 0 ) {
85
- rb_raise(rb_eIndexError,
86
- "invalid parent dim for %d-th dimension", i);
79
+ {
80
+ ca_size_t tiled[CA_RANK_MAX];
81
+ for (i = 0; i < ndim; i++) {
82
+ if ( reps[i] <= 0 ) {
83
+ rb_raise(rb_eIndexError,
84
+ "invalid reps for %d-th dimension (must be positive)", i);
85
+ }
86
+ if ( __builtin_mul_overflow(parent->dim[i], reps[i], &tiled[i]) ) {
87
+ rb_raise(rb_eArgError, "too large byte length");
88
+ }
87
89
  }
88
- elements *= parent->dim[i] * reps[i];
90
+ elements = ca_shape_elements(ndim, tiled, bytes);
91
+ }
92
+
93
+ /* ca == NULL asks for the checks above only, so that a constructor can
94
+ run them before it allocates. */
95
+ if ( ca == NULL ) {
96
+ return 0;
89
97
  }
90
98
 
91
99
  ca->obj_type = CA_OBJ_TILE;
@@ -118,7 +126,9 @@ ca_tile_setup (CATile *ca, CArray *parent, ca_size_t *reps)
118
126
  CATile *
119
127
  ca_tile_new (CArray *parent, ca_size_t *reps)
120
128
  {
121
- CATile *ca = ALLOC(CATile);
129
+ CATile *ca;
130
+ ca_tile_setup(NULL, parent, reps);
131
+ ca = ALLOC(CATile);
122
132
  ca_tile_setup(ca, parent, reps);
123
133
  return ca;
124
134
  }
@@ -196,6 +206,7 @@ static void
196
206
  ca_tile_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
197
207
  ca_size_t *strides, void *data, int dir)
198
208
  {
209
+ if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
199
210
  CATile *ca = (CATile *) ap;
200
211
  CArray *parent = ca->parent;
201
212
  int8_t ndim = ca->ndim;
@@ -445,10 +456,13 @@ ca_tile_func_xfer_all (void *ap, void *data, int dir)
445
456
  parent->ptr = parent_scratch;
446
457
  if ( dir == CA_XFER_GET ) ca_tile_attach_into(ca, (char *) data);
447
458
  else ca_tile_sync_from(ca, (char *) data);
459
+ /* Put parent->ptr back before the PUT: the PUT can raise (a lazy
460
+ backing's sync failing), and the scratch is gone once this
461
+ frame is. */
462
+ parent->ptr = parent_ptr_saved;
448
463
  if ( dir == CA_XFER_PUT ) {
449
464
  ca_xfer_all(parent, parent_scratch, CA_XFER_PUT);
450
465
  }
451
- parent->ptr = parent_ptr_saved;
452
466
  ALLOCV_END(holder);
453
467
  }
454
468
  }
@@ -466,10 +480,7 @@ static void
466
480
  ca_tile_func_create_mask (void *ap)
467
481
  {
468
482
  CATile *ca = (CATile *) ap;
469
- ca_update_mask(ca->parent);
470
- if ( ! ca->parent->mask ) {
471
- ca_create_mask(ca->parent);
472
- }
483
+ ca_create_mask(ca->parent);
473
484
  ca->mask = (CArray *) ca_tile_new(ca->parent->mask, ca->reps);
474
485
  }
475
486
 
@@ -571,11 +582,13 @@ rb_ca_tile_initialize_copy (VALUE self, VALUE other)
571
582
  {
572
583
  CATile *ca, *cs;
573
584
  TypedData_Get_Struct(self, CATile, &catile_data_type, ca);
585
+ ca_check_uninitialized(ca);
574
586
  TypedData_Get_Struct(other, CATile, &catile_data_type, cs);
575
587
  ca_tile_setup(ca, cs->parent, cs->reps);
576
588
  return self;
577
589
  }
578
590
 
591
+ #ifdef CARRAY_DEV_BUILD
579
592
  /* Debug-only accessor returning the tile descriptor as a Hash.
580
593
  Naming: leading underscore signals internal use. */
581
594
  static VALUE
@@ -597,6 +610,7 @@ rb_ca_tile_descriptor (VALUE self)
597
610
  rb_hash_aset(hash, ID2SYM(rb_intern("ndim")), INT2NUM(ca->ndim));
598
611
  return hash;
599
612
  }
613
+ #endif
600
614
 
601
615
  void
602
616
  Init_ca_obj_tile (void)
@@ -616,7 +630,9 @@ Init_ca_obj_tile (void)
616
630
  rb_define_method(rb_cCATile, "initialize_copy",
617
631
  rb_ca_tile_initialize_copy, 1);
618
632
 
633
+ #ifdef CARRAY_DEV_BUILD
619
634
  /* Debug-only descriptor accessor. */
620
635
  rb_define_method(rb_cCATile, "_tile_descriptor",
621
636
  rb_ca_tile_descriptor, 0);
637
+ #endif
622
638
  }
data/ext/ca_obj_time.c CHANGED
@@ -14,6 +14,7 @@
14
14
  --------------------------------------------------------------------------- */
15
15
 
16
16
  #include "carray.h"
17
+ #include "carray_internal.h"
17
18
  #include "ca_obj_face.h"
18
19
 
19
20
  /* unit enum (base epoch is 1970-01-01) */
@@ -36,7 +37,7 @@ enum {
36
37
  typedef struct {
37
38
  /* === CAView prefix === */
38
39
  int16_t obj_type;
39
- int8_t data_type; /* fixed to CA_INT64 */
40
+ int8_t data_type; /* surface: CA_FIXLEN (storage is the int64 parent) */
40
41
  int8_t ndim;
41
42
  int32_t flags; /* CA_FLAG_IS_FACE set */
42
43
  ca_size_t bytes; /* fixed to sizeof(int64_t) */
@@ -182,6 +183,12 @@ ca_time_setup (CATime *ca, CArray *parent, int8_t unit, int64_t count)
182
183
  "CATime requires int64 storage (parent.data_type != CA_INT64)");
183
184
  }
184
185
 
186
+ /* ca == NULL asks for the checks above only, so that a constructor can
187
+ run them before it allocates. */
188
+ if ( ca == NULL ) {
189
+ return 0;
190
+ }
191
+
185
192
  ca->obj_type = CA_OBJ_TIME;
186
193
  /* The surface data_type is CA_FIXLEN, not CA_INT64: this routes
187
194
  mkkernel dispatch onto the ca_*_not_implement stubs so numeric
@@ -227,7 +234,9 @@ ca_time_setup (CATime *ca, CArray *parent, int8_t unit, int64_t count)
227
234
  CATime *
228
235
  ca_time_new (CArray *parent, int8_t unit, int64_t count)
229
236
  {
230
- CATime *ca = (CATime *) ca_array_alloc(CA_OBJ_TIME, parent->ndim);
237
+ CATime *ca;
238
+ ca_time_setup(NULL, parent, unit, count);
239
+ ca = (CATime *) ca_array_alloc(CA_OBJ_TIME, parent->ndim);
231
240
  ca_time_setup(ca, parent, unit, count);
232
241
  return ca;
233
242
  }
@@ -266,18 +275,6 @@ ca_time_func_allocate (void *ap)
266
275
  ca->ptr = ca->parent->ptr;
267
276
  }
268
277
 
269
- static void
270
- ca_time_func_create_mask (void *ap)
271
- {
272
- CATime *ca = (CATime *) ap;
273
- ca_update_mask(ca->parent);
274
- if ( ! ca->parent->mask ) {
275
- ca_create_mask(ca->parent);
276
- }
277
- ca->mask = (CArray *) ca_refer_new(ca->parent->mask,
278
- CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
279
- }
280
-
281
278
  ca_operation_function_t ca_time_func = {
282
279
  -1, /* CA_OBJ_TIME — filled by ca_install_obj_type */
283
280
  CA_VIEW_ARRAY,
@@ -288,7 +285,7 @@ ca_operation_function_t ca_time_func = {
288
285
  ca_face_sync,
289
286
  ca_face_detach,
290
287
  ca_face_fill_data,
291
- ca_time_func_create_mask,
288
+ ca_view_func_create_mask,
292
289
  ca_face_xfer_index,
293
290
  ca_face_xfer_addrs,
294
291
  NULL, /* fold_stride: identity Face is not foldable */
@@ -422,16 +419,16 @@ rb_ca_time_unit (VALUE self)
422
419
  return ca_time_resolution(ca->count, ca->unit);
423
420
  }
424
421
 
425
- /* storage_to_scalar implemented in C to avoid per-cell Ruby method dispatch
426
- on the fetch hot path. CAREFUL: there must be no Ruby `storage_to_scalar`
422
+ /* storage_to_element implemented in C to avoid per-cell Ruby method dispatch
423
+ on the fetch hot path. CAREFUL: there must be no Ruby `storage_to_element`
427
424
  def in lib/carray/time.rb — require order would let a Ruby version
428
- shadow this C method (the Ruby `scalar_to_storage` write hook is a
425
+ shadow this C method (the Ruby `element_to_storage` write hook is a
429
426
  distinct method and does not collide).
430
427
  Since the Face surface is CA_FIXLEN, fetch delivers an 8-byte raw
431
428
  String. Decode it as the parent int64 (= storage), then construct
432
429
  CATime::Element(epoch, unit). */
433
430
  static VALUE
434
- rb_ca_time_storage_to_scalar (VALUE self, VALUE raw)
431
+ rb_ca_time_storage_to_element (VALUE self, VALUE raw)
435
432
  {
436
433
  CATime *ca;
437
434
  CATimeElement *s;
@@ -443,7 +440,7 @@ rb_ca_time_storage_to_scalar (VALUE self, VALUE raw)
443
440
  if ( TYPE(raw) == T_STRING ) {
444
441
  if ( RSTRING_LEN(raw) != (long) sizeof(int64_t) ) {
445
442
  rb_raise(rb_eArgError,
446
- "CATime#storage_to_scalar: expected %lu bytes, got %ld",
443
+ "CATime#storage_to_element: expected %lu bytes, got %ld",
447
444
  (unsigned long) sizeof(int64_t), RSTRING_LEN(raw));
448
445
  }
449
446
  memcpy(&epoch, RSTRING_PTR(raw), sizeof(int64_t));
@@ -476,6 +473,7 @@ rb_ca_time_initialize_copy (VALUE self, VALUE other)
476
473
  {
477
474
  CATime *ca, *cs;
478
475
  TypedData_Get_Struct(self, CATime, &catime_data_type, ca);
476
+ ca_check_uninitialized(ca);
479
477
  TypedData_Get_Struct(other, CATime, &catime_data_type, cs);
480
478
  if ( ca_func[CA_OBJ_TIME].pool_init ) {
481
479
  ca_array_pool_alloc(ca, CA_OBJ_TIME, cs->parent->ndim);
@@ -517,12 +515,12 @@ Init_ca_obj_time (void)
517
515
  rb_define_singleton_method(rb_cCATime, "__wrap__",
518
516
  rb_ca_time_wrap_method, 2);
519
517
  rb_define_method(rb_cCATime, "unit", rb_ca_time_unit, 0);
520
- rb_define_method(rb_cCATime, "storage_to_scalar",
521
- rb_ca_time_storage_to_scalar, 1);
522
- /* Registers the C-level fast path so CA_FACE_STORAGE_TO_SCALAR_IF_FACE can
518
+ rb_define_method(rb_cCATime, "storage_to_element",
519
+ rb_ca_time_storage_to_element, 1);
520
+ /* Registers the C-level fast path so CA_FACE_STORAGE_TO_ELEMENT_IF_FACE can
523
521
  skip rb_funcall on the hot path. */
524
- ca_face_register_storage_to_scalar(CA_OBJ_TIME,
525
- rb_ca_time_storage_to_scalar);
522
+ ca_face_register_storage_to_element(CA_OBJ_TIME,
523
+ rb_ca_time_storage_to_element);
526
524
  ca_face_register_state_compatible(CA_OBJ_TIME,
527
525
  ca_time_state_compatible);
528
526
  /* unit is pure metadata (= no per-parent buffer), so the Face wrap can
@@ -14,6 +14,7 @@
14
14
  --------------------------------------------------------------------------- */
15
15
 
16
16
  #include "carray.h"
17
+ #include "carray_internal.h"
17
18
  #include "ca_obj_face.h"
18
19
 
19
20
  /* The unit enum is shared with CATime (= same unit system).
@@ -26,7 +27,7 @@ extern void ca_time_extract_unit (VALUE unit, int8_t *base, int64_t *count);
26
27
  typedef struct {
27
28
  /* === CAView prefix === */
28
29
  int16_t obj_type;
29
- int8_t data_type; /* fixed to CA_INT64 */
30
+ int8_t data_type; /* surface: CA_FIXLEN (storage is the int64 parent) */
30
31
  int8_t ndim;
31
32
  int32_t flags; /* CA_FLAG_IS_FACE set */
32
33
  ca_size_t bytes; /* fixed to sizeof(int64_t) */
@@ -161,6 +162,12 @@ ca_timedelta_setup (CATimedelta *ca, CArray *parent, int8_t unit, int64_t count)
161
162
  "CATimedelta requires int64 storage (parent.data_type != CA_INT64)");
162
163
  }
163
164
 
165
+ /* ca == NULL asks for the checks above only, so that a constructor can
166
+ run them before it allocates. */
167
+ if ( ca == NULL ) {
168
+ return 0;
169
+ }
170
+
164
171
  ca->obj_type = CA_OBJ_TIMEDELTA;
165
172
  /* NonNumeric surface (the FIXLEN gate), like CATime: the storage is a
166
173
  count of `count x unit` ticks, and letting the numeric kernels read it
@@ -208,7 +215,9 @@ ca_timedelta_setup (CATimedelta *ca, CArray *parent, int8_t unit, int64_t count)
208
215
  CATimedelta *
209
216
  ca_timedelta_new (CArray *parent, int8_t unit, int64_t count)
210
217
  {
211
- CATimedelta *ca = (CATimedelta *) ca_array_alloc(CA_OBJ_TIMEDELTA, parent->ndim);
218
+ CATimedelta *ca;
219
+ ca_timedelta_setup(NULL, parent, unit, count);
220
+ ca = (CATimedelta *) ca_array_alloc(CA_OBJ_TIMEDELTA, parent->ndim);
212
221
  ca_timedelta_setup(ca, parent, unit, count);
213
222
  return ca;
214
223
  }
@@ -246,18 +255,6 @@ ca_timedelta_func_allocate (void *ap)
246
255
  ca->ptr = ca->parent->ptr;
247
256
  }
248
257
 
249
- static void
250
- ca_timedelta_func_create_mask (void *ap)
251
- {
252
- CATimedelta *ca = (CATimedelta *) ap;
253
- ca_update_mask(ca->parent);
254
- if ( ! ca->parent->mask ) {
255
- ca_create_mask(ca->parent);
256
- }
257
- ca->mask = (CArray *) ca_refer_new(ca->parent->mask,
258
- CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
259
- }
260
-
261
258
  ca_operation_function_t ca_timedelta_func = {
262
259
  -1, /* CA_OBJ_TIMEDELTA — filled by ca_install_obj_type */
263
260
  CA_VIEW_ARRAY,
@@ -268,7 +265,7 @@ ca_operation_function_t ca_timedelta_func = {
268
265
  ca_face_sync,
269
266
  ca_face_detach,
270
267
  ca_face_fill_data,
271
- ca_timedelta_func_create_mask,
268
+ ca_view_func_create_mask,
272
269
  ca_face_xfer_index,
273
270
  ca_face_xfer_addrs,
274
271
  NULL, /* fold_stride */
@@ -330,6 +327,7 @@ rb_ca_timedelta_initialize_copy (VALUE self, VALUE other)
330
327
  {
331
328
  CATimedelta *ca, *cs;
332
329
  TypedData_Get_Struct(self, CATimedelta, &catimedelta_data_type, ca);
330
+ ca_check_uninitialized(ca);
333
331
  TypedData_Get_Struct(other, CATimedelta, &catimedelta_data_type, cs);
334
332
  if ( ca_func[CA_OBJ_TIMEDELTA].pool_init ) {
335
333
  ca_array_pool_alloc(ca, CA_OBJ_TIMEDELTA, cs->parent->ndim);
@@ -338,12 +336,12 @@ rb_ca_timedelta_initialize_copy (VALUE self, VALUE other)
338
336
  return self;
339
337
  }
340
338
 
341
- /* storage_to_scalar implemented in C to avoid per-cell Ruby method dispatch
339
+ /* storage_to_element implemented in C to avoid per-cell Ruby method dispatch
342
340
  on the fetch hot path. Accepts either an Integer (INT64 surface fetch)
343
341
  or an 8-byte String (FIXLEN surface fetch); decodes the parent int64
344
342
  and constructs CATimedelta::Element(value, unit). */
345
343
  static VALUE
346
- rb_ca_timedelta_storage_to_scalar (VALUE self, VALUE raw)
344
+ rb_ca_timedelta_storage_to_element (VALUE self, VALUE raw)
347
345
  {
348
346
  CATimedelta *ca;
349
347
  CATimedeltaElement *s;
@@ -355,7 +353,7 @@ rb_ca_timedelta_storage_to_scalar (VALUE self, VALUE raw)
355
353
  if ( TYPE(raw) == T_STRING ) {
356
354
  if ( RSTRING_LEN(raw) != (long) sizeof(int64_t) ) {
357
355
  rb_raise(rb_eArgError,
358
- "CATimedelta#storage_to_scalar: expected %lu bytes, got %ld",
356
+ "CATimedelta#storage_to_element: expected %lu bytes, got %ld",
359
357
  (unsigned long) sizeof(int64_t), RSTRING_LEN(raw));
360
358
  }
361
359
  memcpy(&value, RSTRING_PTR(raw), sizeof(int64_t));
@@ -408,17 +406,17 @@ Init_ca_obj_timedelta (void)
408
406
  rb_define_singleton_method(rb_cCATimedelta, "__wrap__",
409
407
  rb_ca_timedelta_wrap_method, 2);
410
408
  rb_define_method(rb_cCATimedelta, "unit", rb_ca_timedelta_unit, 0);
411
- rb_define_method(rb_cCATimedelta, "storage_to_scalar",
412
- rb_ca_timedelta_storage_to_scalar, 1);
413
- /* Registers the state-compatibility predicate so CA_FACE_STORAGE_TO_SCALAR_IF_FACE
409
+ rb_define_method(rb_cCATimedelta, "storage_to_element",
410
+ rb_ca_timedelta_storage_to_element, 1);
411
+ /* Registers the state-compatibility predicate so CA_FACE_STORAGE_TO_ELEMENT_IF_FACE
414
412
  can skip rb_funcall on the hot path. */
415
413
  ca_face_register_state_compatible(CA_OBJ_TIMEDELTA,
416
414
  ca_timedelta_state_compatible);
417
415
  /* unit is pure metadata, no per-parent buffer; multi-parent Face lift
418
416
  is safe (portable = 1). */
419
417
  ca_face_register_state_portable(CA_OBJ_TIMEDELTA, 1);
420
- ca_face_register_storage_to_scalar(CA_OBJ_TIMEDELTA,
421
- rb_ca_timedelta_storage_to_scalar);
418
+ ca_face_register_storage_to_element(CA_OBJ_TIMEDELTA,
419
+ rb_ca_timedelta_storage_to_element);
422
420
 
423
421
  /* CATimedelta::Element as a C-backed TypedData class. The Ruby-side
424
422
  definition in lib/carray/time.rb keeps Comparable + to_seconds /
@@ -37,11 +37,11 @@ ca_trans_setup (CAStride *ca, CArray *parent, ca_size_t *imap)
37
37
  for (i = 0; i < ndim; i++) {
38
38
  idim = imap[i];
39
39
  if (idim < 0 || idim >= ndim) {
40
- rb_raise(rb_eRuntimeError,
40
+ rb_raise(rb_eArgError,
41
41
  "specified %i-th dimension number out of range", i);
42
42
  }
43
43
  if (map[idim] != -1) {
44
- rb_raise(rb_eRuntimeError,
44
+ rb_raise(rb_eArgError,
45
45
  "specified %i-th dimension number is duplicated", i);
46
46
  }
47
47
  map[idim] = i;
@@ -58,6 +58,12 @@ ca_trans_setup (CAStride *ca, CArray *parent, ca_size_t *imap)
58
58
  strides[i] = parent_byte_stride[imap[i]];
59
59
  }
60
60
 
61
+ /* ca == NULL asks for the checks above only, so that a constructor can
62
+ run them before it allocates. */
63
+ if ( ca == NULL ) {
64
+ return 0;
65
+ }
66
+
61
67
  ca_stride_setup(ca, CA_OBJ_TRANSPOSE, parent,
62
68
  parent->data_type, parent->bytes,
63
69
  ndim, newdim, strides, 0);
@@ -67,7 +73,9 @@ ca_trans_setup (CAStride *ca, CArray *parent, ca_size_t *imap)
67
73
  CAStride *
68
74
  ca_trans_new (CArray *parent, ca_size_t *imap)
69
75
  {
70
- CAStride *ca = (CAStride *) ca_array_alloc(CA_OBJ_TRANSPOSE, parent->ndim);
76
+ CAStride *ca;
77
+ ca_trans_setup(NULL, parent, imap);
78
+ ca = (CAStride *) ca_array_alloc(CA_OBJ_TRANSPOSE, parent->ndim);
71
79
  ca_trans_setup(ca, parent, imap);
72
80
  return ca;
73
81
  }
@@ -126,6 +134,7 @@ rb_ca_trans_initialize_copy (VALUE self, VALUE other)
126
134
  {
127
135
  CAStride *ca, *cs;
128
136
  TypedData_Get_Struct(self, CAStride, &castride_data_type, ca);
137
+ ca_check_uninitialized(ca);
129
138
  TypedData_Get_Struct(other, CAStride, &castride_data_type, cs);
130
139
  if ( ca_func[CA_OBJ_TRANSPOSE].pool_init ) {
131
140
  ca_array_pool_alloc(ca, CA_OBJ_TRANSPOSE, cs->ndim);