carray 3.0.0 → 3.0.2

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 (202) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -1
  3. data/CHANGELOG.md +845 -3
  4. data/{NEWS.md → CHANGELOG.v1.md} +1 -1
  5. data/README.md +33 -33
  6. data/carray.gemspec +12 -8
  7. data/ext/ca_axis_dispatch.c +33 -4
  8. data/ext/ca_axis_group.c +256 -114
  9. data/ext/ca_binop_dispatch.c +5 -6
  10. data/ext/ca_binop_dispatch.h +0 -7
  11. data/ext/ca_categorical_iterator.c +121 -67
  12. data/ext/ca_for_each_element.h +6 -8
  13. data/ext/ca_group_iter.c +1 -1
  14. data/ext/ca_kernel_iterator.c +386 -74
  15. data/ext/ca_kernel_iterator.h +145 -45
  16. data/ext/ca_obj_array.c +62 -20
  17. data/ext/ca_obj_bincmp.c +57 -27
  18. data/ext/ca_obj_binop.c +86 -30
  19. data/ext/ca_obj_block.c +4 -4
  20. data/ext/ca_obj_const_string.c +88 -27
  21. data/ext/ca_obj_face.c +104 -0
  22. data/ext/ca_obj_face.h +48 -1
  23. data/ext/ca_obj_fake.c +11 -0
  24. data/ext/ca_obj_fixlen_string.c +21 -6
  25. data/ext/ca_obj_grid.c +11 -3
  26. data/ext/ca_obj_meld.c +125 -22
  27. data/ext/ca_obj_moncmp.c +33 -14
  28. data/ext/ca_obj_monop.c +19 -7
  29. data/ext/ca_obj_object.c +107 -4
  30. data/ext/ca_obj_record.c +3 -1
  31. data/ext/ca_obj_refer.c +30 -6
  32. data/ext/ca_obj_roll.c +13 -5
  33. data/ext/ca_obj_select.c +49 -34
  34. data/ext/ca_obj_select_axis.c +16 -6
  35. data/ext/ca_obj_shift.c +3 -3
  36. data/ext/ca_obj_stack.c +3 -8
  37. data/ext/ca_obj_stride.c +178 -24
  38. data/ext/ca_obj_string.c +11 -5
  39. data/ext/ca_obj_tile.c +13 -5
  40. data/ext/ca_obj_time.c +3 -1
  41. data/ext/ca_obj_timedelta.c +3 -1
  42. data/ext/ca_obj_transpose.c +1 -1
  43. data/ext/ca_obj_triop.c +62 -23
  44. data/ext/ca_obj_window.c +94 -19
  45. data/ext/ca_op_cmplx64.h +123 -0
  46. data/ext/ca_op_ipower.c +1 -5
  47. data/ext/ca_rng_normal.h +42 -0
  48. data/ext/ca_rng_xoshiro256pp.h +105 -0
  49. data/ext/ca_sort_kernels.h +5 -5
  50. data/ext/ca_sweep_engine.c +362 -155
  51. data/ext/ca_sweep_engine.h +39 -9
  52. data/ext/ca_transform_common.c +7 -0
  53. data/ext/carray.h +148 -132
  54. data/ext/carray_access.c +83 -49
  55. data/ext/carray_address_basis.c +590 -0
  56. data/ext/carray_bincount.c +8 -8
  57. data/ext/carray_broadcast.c +102 -9
  58. data/ext/carray_build_flags.h +3 -0
  59. data/ext/carray_call_cfunc.c +2010 -335
  60. data/ext/carray_call_cfunc.h +153 -0
  61. data/ext/carray_cast.c +184 -72
  62. data/ext/carray_conversion.c +22 -22
  63. data/ext/carray_copy.c +67 -32
  64. data/ext/carray_core.c +140 -13
  65. data/ext/carray_count.c +10 -11
  66. data/ext/carray_element.c +7 -7
  67. data/ext/carray_factorize.c +72 -51
  68. data/ext/carray_hold.c +1 -1
  69. data/ext/carray_index_classifier.c +7 -21
  70. data/ext/carray_internal.h +36 -3
  71. data/ext/carray_kernels_bincmp.c +1 -0
  72. data/ext/carray_kernels_binop.c +320 -298
  73. data/ext/carray_kernels_init.c +1095 -0
  74. data/ext/carray_kernels_map.c +1 -0
  75. data/ext/carray_kernels_moncmp.c +1 -0
  76. data/ext/carray_kernels_monop.c +412 -411
  77. data/ext/carray_kernels_reduce_aggregate.c +256 -87
  78. data/ext/carray_kernels_reduce_boolean.c +1 -0
  79. data/ext/carray_kernels_reduce_cumulative.c +324 -54
  80. data/ext/carray_kernels_reduce_extreme.c +605 -58
  81. data/ext/carray_kernels_reduce_variance.c +1 -0
  82. data/ext/carray_kernels_scan.c +5 -4
  83. data/ext/carray_kernels_search.c +187 -106
  84. data/ext/carray_kernels_sort.c +1 -0
  85. data/ext/carray_kernels_triop.c +1 -0
  86. data/ext/carray_lazy.c +175 -5
  87. data/ext/carray_loop.c +7 -1
  88. data/ext/carray_mask.c +29 -13
  89. data/ext/carray_median_percentile.c +56 -1
  90. data/ext/carray_memory_view.c +46 -21
  91. data/ext/carray_operator.c +50 -53
  92. data/ext/carray_order.c +1 -1
  93. data/ext/carray_partition.c +4 -4
  94. data/ext/carray_random.c +391 -47
  95. data/ext/carray_scatter.c +1 -1
  96. data/ext/carray_slab.c +13 -0
  97. data/ext/carray_sort.c +22 -24
  98. data/ext/carray_sort_kernel.c +10 -10
  99. data/ext/carray_test.c +1 -1
  100. data/ext/extconf.rb +18 -0
  101. data/ext/mk_call_cfunc.rb +323 -145
  102. data/ext/mkkernel.rb +651 -129
  103. data/ext/ruby_carray.c +28 -17
  104. data/ext/version.h +4 -4
  105. data/lib/carray/autoload_carray.rb +24 -3
  106. data/lib/carray/autoload_method_extension.rb +14 -1
  107. data/lib/carray/axis_group.rb +84 -7
  108. data/lib/carray/basics.rb +63 -59
  109. data/lib/carray/bincount_nd.rb +12 -12
  110. data/lib/carray/block_iterator.rb +111 -25
  111. data/lib/carray/categorical.rb +154 -37
  112. data/lib/carray/categorical_iterator.rb +300 -151
  113. data/lib/carray/conditional.rb +14 -14
  114. data/lib/carray/const_string.rb +131 -27
  115. data/lib/carray/construct.rb +61 -0
  116. data/lib/carray/core_extensions.rb +62 -5
  117. data/lib/carray/data_type_extension.rb +21 -1
  118. data/lib/carray/data_type_limits.rb +91 -0
  119. data/lib/carray/fixlen_string.rb +1 -1
  120. data/lib/carray/frame/concat.rb +3 -3
  121. data/lib/carray/frame/convert.rb +1 -1
  122. data/lib/carray/frame/csv_parser.rb +11 -4
  123. data/lib/carray/frame/frame.rb +85 -21
  124. data/lib/carray/frame/group.rb +36 -3
  125. data/lib/carray/frame/io.rb +224 -15
  126. data/lib/carray/frame/records.rb +18 -4
  127. data/lib/carray/frame/sort.rb +1 -1
  128. data/lib/carray/frame/verbs.rb +32 -12
  129. data/lib/carray/fuse_source.rb +123 -0
  130. data/lib/carray/fusion.rb +218 -0
  131. data/lib/carray/histogram.rb +16 -16
  132. data/lib/carray/inspect.rb +43 -16
  133. data/lib/carray/iterator.rb +147 -3
  134. data/lib/carray/lazy.rb +88 -73
  135. data/lib/carray/mask_gap_fill.rb +3 -1
  136. data/lib/carray/meld_reduce.rb +2 -2
  137. data/lib/carray/methods/align_addr.rb +1 -1
  138. data/lib/carray/methods/composition.rb +1 -1
  139. data/lib/carray/methods/discovery_along.rb +74 -0
  140. data/lib/carray/methods/factorize.rb +50 -0
  141. data/lib/carray/methods/is_in.rb +25 -14
  142. data/lib/carray/methods/locate_addr.rb +81 -3
  143. data/lib/carray/methods/mask_duplicates.rb +36 -2
  144. data/lib/carray/methods/meshgrid.rb +4 -5
  145. data/lib/carray/methods/mode.rb +2 -2
  146. data/lib/carray/methods/nunique.rb +23 -2
  147. data/lib/carray/methods/repeat.rb +110 -0
  148. data/lib/carray/methods/snap.rb +7 -2
  149. data/lib/carray/methods/unique.rb +44 -4
  150. data/lib/carray/methods/value_counts.rb +2 -2
  151. data/lib/carray/rng.rb +86 -0
  152. data/lib/carray/runtime.rb +0 -19
  153. data/lib/carray/slab_iterator.rb +77 -19
  154. data/lib/carray/string_operation_extension.rb +10 -6
  155. data/lib/carray/time.rb +906 -491
  156. data/lib/carray/window_iterator.rb +421 -27
  157. data/lib/carray.rb +7 -5
  158. data/yard-stubs/ca_obj_array.rb +385 -0
  159. data/yard-stubs/ca_obj_bitarray.rb +38 -0
  160. data/yard-stubs/ca_obj_bitfield.rb +43 -0
  161. data/yard-stubs/ca_obj_block.rb +68 -0
  162. data/yard-stubs/ca_obj_byte_swap.rb +56 -0
  163. data/yard-stubs/ca_obj_fake.rb +31 -0
  164. data/yard-stubs/ca_obj_farray.rb +32 -0
  165. data/yard-stubs/ca_obj_field.rb +45 -0
  166. data/yard-stubs/ca_obj_grid.rb +35 -0
  167. data/yard-stubs/ca_obj_refer.rb +72 -0
  168. data/yard-stubs/ca_obj_roll.rb +45 -0
  169. data/yard-stubs/ca_obj_shift.rb +43 -0
  170. data/yard-stubs/ca_obj_stride.rb +181 -0
  171. data/yard-stubs/ca_obj_tile.rb +29 -0
  172. data/yard-stubs/ca_obj_transpose.rb +40 -0
  173. data/yard-stubs/ca_obj_window.rb +57 -0
  174. data/yard-stubs/carray_access.rb +131 -0
  175. data/yard-stubs/carray_attribute.rb +246 -0
  176. data/yard-stubs/carray_broadcast.rb +37 -0
  177. data/yard-stubs/carray_cast.rb +489 -0
  178. data/yard-stubs/carray_class.rb +65 -0
  179. data/yard-stubs/carray_conversion.rb +76 -0
  180. data/yard-stubs/carray_copy.rb +79 -0
  181. data/yard-stubs/carray_core.rb +34 -0
  182. data/yard-stubs/carray_count.rb +84 -0
  183. data/yard-stubs/carray_element.rb +108 -0
  184. data/yard-stubs/carray_generate.rb +66 -0
  185. data/yard-stubs/carray_lazy.rb +228 -0
  186. data/yard-stubs/carray_loop.rb +140 -0
  187. data/yard-stubs/carray_mask.rb +259 -0
  188. data/yard-stubs/carray_math.rb +1615 -0
  189. data/yard-stubs/carray_mathfunc.rb +45 -0
  190. data/yard-stubs/carray_median_percentile.rb +103 -0
  191. data/yard-stubs/carray_memory_view.rb +163 -0
  192. data/yard-stubs/carray_order.rb +252 -0
  193. data/yard-stubs/carray_random.rb +89 -0
  194. data/yard-stubs/carray_scatter.rb +106 -0
  195. data/yard-stubs/carray_slab.rb +59 -0
  196. data/yard-stubs/carray_sort.rb +165 -0
  197. data/yard-stubs/carray_test.rb +85 -0
  198. data/yard-stubs/carray_undef.rb +64 -0
  199. data/yard-stubs/carray_utils.rb +97 -0
  200. data/yard-stubs/ruby_carray.rb +193 -0
  201. metadata +67 -10
  202. data/ext/ca_obj_unbound_repeat.c +0 -496
@@ -59,7 +59,7 @@
59
59
  codes : narrow unsigned CArray (uint8 / uint16 / uint32), the code
60
60
  storage; masked source cells store the type-max sentinel
61
61
  (from_codes derives the mask from it, matching categorize).
62
- levels : integer CArray (source dtype) of the k distinct values in
62
+ levels : integer CArray (source data type) of the k distinct values in
63
63
  first-appearance order.
64
64
  self.__mask_duplicates__(axis) -> boolean CArray of self.shape, true at
65
65
  each cell that duplicates an earlier-seen one along axis (per-fiber
@@ -105,13 +105,27 @@
105
105
  /* Descend `self` when it is an ORDERABLE Face; *pface keeps the pre-strip Face
106
106
  for the re-lift (Qnil when there is nothing to put back). */
107
107
  static VALUE
108
- fz_face_descend (VALUE self, volatile VALUE *pface)
108
+ fz_face_descend (VALUE self, volatile VALUE *pface, const char *name)
109
109
  {
110
110
  CArray *ca;
111
111
  GetCArray(self, ca);
112
- if ( ca_is_face(ca) && ca_test_flag(ca, CA_FLAG_FACE_ORDERABLE_STORAGE) ) {
113
- *pface = self;
114
- return rb_ca_strip_face_value(self);
112
+ if ( ca_is_face(ca) ) {
113
+ if ( ca_test_flag(ca, CA_FLAG_FACE_ORDERABLE_STORAGE) ) {
114
+ *pface = self;
115
+ return rb_ca_strip_face_value(self);
116
+ }
117
+ /* A Face that cannot be descended must not flow on undescended: whatever
118
+ reads it next reads its storage anyway, which is the encoding rather
119
+ than the values. A Face in this position normally never arrives --
120
+ CAConstString and CACategorical define their own members in Ruby -- but
121
+ the overrides only fire when the Face is the receiver, and this same
122
+ helper descends the *reference* for locate_addr, where it is the
123
+ argument. */
124
+ rb_raise(rb_eArgError,
125
+ "%s: %s is not orderable by storage (a cell encodes the value "
126
+ "rather than being it); convert it first -- #to_string for a "
127
+ "string Face -- or pass .parent to work in storage space",
128
+ name, rb_obj_classname(self));
115
129
  }
116
130
  *pface = Qnil;
117
131
  return self;
@@ -140,15 +154,7 @@ fz_face_reconcile (VALUE reference, VALUE operand, const char *name)
140
154
  rb_intern("to_comparable"),
141
155
  1, operand));
142
156
  }
143
- if ( rb_obj_is_carray(operand) ) {
144
- CArray *op;
145
- GetCArray(operand, op);
146
- if ( ca_is_face(op) ) {
147
- return rb_ca_strip_face_value(operand);
148
- }
149
- }
150
- (void) name;
151
- return operand;
157
+ return ca_face_operand_descend(operand, name);
152
158
  }
153
159
 
154
160
  /* Put the Face back on a value-carrying output. */
@@ -487,7 +493,7 @@ fz_levels_free (fz_levels *l)
487
493
  codes = narrow unsigned CArray; masked source cells store the type-max
488
494
  sentinel (0xFF / 0xFFFF / 0xFFFFFFFF), so from_codes reconstructs
489
495
  the mask exactly as the mask_duplicates path does.
490
- levels = CArray (source dtype) of the k distinct values, in first-appearance
496
+ levels = CArray (source data type) of the k distinct values, in first-appearance
491
497
  (row-major flatten) order.
492
498
  */
493
499
  static VALUE
@@ -495,7 +501,7 @@ rb_ca_factorize_appearance (VALUE self)
495
501
  {
496
502
  CArray *ca;
497
503
  volatile VALUE face;
498
- self = fz_face_descend(self, &face);
504
+ self = fz_face_descend(self, &face, "categorize");
499
505
  TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
500
506
 
501
507
  int8_t dt = ca->data_type;
@@ -508,7 +514,7 @@ rb_ca_factorize_appearance (VALUE self)
508
514
  break;
509
515
  default:
510
516
  rb_raise(rb_eCADataTypeError,
511
- "__factorize_appearance__: integer, float, object, or fixlen dtype required (got %d)", dt);
517
+ "__factorize_appearance__: integer, float, object, or fixlen data type required (got %d)", dt);
512
518
  }
513
519
  if ( ca->ndim < 1 ) {
514
520
  rb_raise(rb_eRuntimeError, "__factorize_appearance__: need ndim >= 1");
@@ -535,8 +541,8 @@ rb_ca_factorize_appearance (VALUE self)
535
541
  boolean8_t *m;
536
542
  ca_size_t n;
537
543
 
538
- /* Fiber inner loop, monomorphised per dtype. WIDEN sign- or zero-extends the
539
- element to a 64-bit key; equality within one dtype is preserved. */
544
+ /* Fiber inner loop, monomorphised per data type. WIDEN sign- or zero-extends the
545
+ element to a 64-bit key; equality within one data type is preserved. */
540
546
  #define FZ_LOOP(T, WIDEN) \
541
547
  do { \
542
548
  const T *ip = (const T *) p_in; \
@@ -664,7 +670,7 @@ rb_ca_factorize_appearance (VALUE self)
664
670
  }
665
671
  }
666
672
 
667
- /* Levels: the interned raw values, in source dtype. CA_FIXLEN carries its
673
+ /* Levels: the interned raw values, in source data type. CA_FIXLEN carries its
668
674
  element width; numeric / object use bytes = 0. */
669
675
  ca_size_t ldim[1];
670
676
  ldim[0] = k;
@@ -715,7 +721,7 @@ rb_ca_mask_duplicates (VALUE self, VALUE vaxis)
715
721
  break;
716
722
  default:
717
723
  rb_raise(rb_eCADataTypeError,
718
- "__mask_duplicates__: numeric, object, or fixlen dtype required (got %d)", dt);
724
+ "__mask_duplicates__: numeric, object, or fixlen data type required (got %d)", dt);
719
725
  }
720
726
  if ( ca->ndim < 1 ) {
721
727
  rb_raise(rb_eRuntimeError, "__mask_duplicates__: need ndim >= 1");
@@ -740,8 +746,8 @@ rb_ca_mask_duplicates (VALUE self, VALUE vaxis)
740
746
  boolean8_t *m;
741
747
  ca_size_t n;
742
748
 
743
- /* Fiber inner loop, monomorphised per dtype. WIDEN sign- or zero-extends the
744
- element to a 64-bit key; equality within one dtype is preserved. The hash
749
+ /* Fiber inner loop, monomorphised per data type. WIDEN sign- or zero-extends the
750
+ element to a 64-bit key; equality within one data type is preserved. The hash
745
751
  interns first appearances, so is_new == 0 flags a duplicate. */
746
752
  #define MD_LOOP(T, WIDEN) \
747
753
  do { \
@@ -839,7 +845,7 @@ rb_ca_mask_duplicates (VALUE self, VALUE vaxis)
839
845
 
840
846
  INTERNAL (CArray#unique). Collect the distinct values of self in
841
847
  first-appearance (row-major flatten) order, one linear pass, no sort. Returns
842
- a 1-D CArray of source dtype. Masked cells do not participate.
848
+ a 1-D CArray of source data type. Masked cells do not participate.
843
849
 
844
850
  Numeric (integer / float): distinctness follows `==` except NaN collapses to a
845
851
  single distinct value (all NaN patterns map to one canonical hash key) and
@@ -863,7 +869,7 @@ rb_ca_unique_flat (VALUE self)
863
869
  {
864
870
  CArray *ca;
865
871
  volatile VALUE face;
866
- self = fz_face_descend(self, &face);
872
+ self = fz_face_descend(self, &face, "unique");
867
873
  TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
868
874
 
869
875
  int8_t dt = ca->data_type;
@@ -876,7 +882,7 @@ rb_ca_unique_flat (VALUE self)
876
882
  break;
877
883
  default:
878
884
  rb_raise(rb_eCADataTypeError,
879
- "__unique_flat__: numeric, object, or fixlen dtype required (got %d)", dt);
885
+ "__unique_flat__: numeric, object, or fixlen data type required (got %d)", dt);
880
886
  }
881
887
  if ( ca->ndim < 1 ) {
882
888
  rb_raise(rb_eRuntimeError, "__unique_flat__: need ndim >= 1");
@@ -1098,8 +1104,8 @@ fz_intern_all (fz_hash *h, CArray *cv, fz_levels *lv)
1098
1104
  seen-set). One pass to build the set from `values`, one pass to probe self;
1099
1105
  no sort, peak memory O(distinct values).
1100
1106
 
1101
- `values` must be a CArray of the same dtype as self (the Ruby surface coerces
1102
- Array / Range / other-dtype input first). Masked cells of `values` do not
1107
+ `values` must be a CArray of the same data type as self (the Ruby surface coerces
1108
+ Array / Range / other-type input first). Masked cells of `values` do not
1103
1109
  enter the set. Masked cells of self stay masked in the output (membership is
1104
1110
  unknown), reproducing the mask propagation of the retired `contains`
1105
1111
  (self.eq(v)); their boolean payload is false.
@@ -1113,7 +1119,7 @@ rb_ca_is_in (VALUE self, VALUE rvalues)
1113
1119
  {
1114
1120
  CArray *ca, *cv;
1115
1121
  volatile VALUE face;
1116
- self = fz_face_descend(self, &face);
1122
+ self = fz_face_descend(self, &face, "is_in");
1117
1123
  rvalues = fz_face_reconcile(face, rvalues, "is_in");
1118
1124
  GetCArray(self, ca);
1119
1125
 
@@ -1127,7 +1133,7 @@ rb_ca_is_in (VALUE self, VALUE rvalues)
1127
1133
  break;
1128
1134
  default:
1129
1135
  rb_raise(rb_eCADataTypeError,
1130
- "__is_in__: numeric, object, or fixlen dtype required (got %d)", dt);
1136
+ "__is_in__: numeric, object, or fixlen data type required (got %d)", dt);
1131
1137
  }
1132
1138
  if ( ca->ndim < 1 ) {
1133
1139
  rb_raise(rb_eRuntimeError, "__is_in__: need ndim >= 1");
@@ -1137,9 +1143,16 @@ rb_ca_is_in (VALUE self, VALUE rvalues)
1137
1143
  rb_raise(rb_eArgError, "__is_in__: values must be a CArray");
1138
1144
  }
1139
1145
  GetCArray(rvalues, cv);
1140
- if ( cv->data_type != dt || (dt == CA_FIXLEN && cv->bytes != ca->bytes) ) {
1146
+ if ( cv->data_type != dt ) {
1147
+ rb_raise(rb_eCADataTypeError,
1148
+ "__is_in__: values data type (%s) must match self (%s)",
1149
+ ca_type_name[cv->data_type], ca_type_name[dt]);
1150
+ }
1151
+ if ( dt == CA_FIXLEN && cv->bytes != ca->bytes ) {
1141
1152
  rb_raise(rb_eCADataTypeError,
1142
- "__is_in__: values dtype must match self (%d)", dt);
1153
+ "__is_in__: a fixlen value is a cell-width blob, so the values "
1154
+ "must be %ld bytes wide like self, not %ld",
1155
+ (long) ca->bytes, (long) cv->bytes);
1143
1156
  }
1144
1157
  if ( cv->ndim < 1 ) {
1145
1158
  rb_raise(rb_eRuntimeError, "__is_in__: values need ndim >= 1");
@@ -1256,7 +1269,7 @@ rb_ca_is_in (VALUE self, VALUE rvalues)
1256
1269
  through the discovery-family lanes (NaN collapse, rb_hash + rb_eql, byte
1257
1270
  equality).
1258
1271
 
1259
- `ref` must be a CArray of the same dtype as self (the Ruby surface coerces
1272
+ `ref` must be a CArray of the same data type as self (the Ruby surface coerces
1260
1273
  first). Masked cells of `ref` do not enter the map but still occupy their
1261
1274
  flat address (position counts). Masked cells of self, and cells whose value
1262
1275
  is absent from `ref`, are UNDEF in the output. "First" occurrence is
@@ -1271,7 +1284,7 @@ rb_ca_locate_addr (VALUE self, VALUE rref)
1271
1284
  output is an address, so nothing is lifted back. */
1272
1285
  {
1273
1286
  volatile VALUE ref_face;
1274
- rref = fz_face_descend(rref, &ref_face);
1287
+ rref = fz_face_descend(rref, &ref_face, "locate_addr");
1275
1288
  self = fz_face_reconcile(ref_face, self, "locate_addr");
1276
1289
  }
1277
1290
  GetCArray(self, ca);
@@ -1286,7 +1299,7 @@ rb_ca_locate_addr (VALUE self, VALUE rref)
1286
1299
  break;
1287
1300
  default:
1288
1301
  rb_raise(rb_eCADataTypeError,
1289
- "__locate_addr__: numeric, object, or fixlen dtype required (got %d)", dt);
1302
+ "__locate_addr__: numeric, object, or fixlen data type required (got %d)", dt);
1290
1303
  }
1291
1304
  if ( ca->ndim < 1 ) {
1292
1305
  rb_raise(rb_eRuntimeError, "__locate_addr__: need ndim >= 1");
@@ -1297,7 +1310,7 @@ rb_ca_locate_addr (VALUE self, VALUE rref)
1297
1310
  GetCArray(rref, cr);
1298
1311
  if ( cr->data_type != dt || (dt == CA_FIXLEN && cr->bytes != ca->bytes) ) {
1299
1312
  rb_raise(rb_eCADataTypeError,
1300
- "__locate_addr__: ref dtype must match self (%d)", dt);
1313
+ "__locate_addr__: ref data type must match self (%d)", dt);
1301
1314
  }
1302
1315
  if ( cr->ndim < 1 ) {
1303
1316
  rb_raise(rb_eRuntimeError, "__locate_addr__: ref need ndim >= 1");
@@ -1521,7 +1534,7 @@ rb_ca_locate_addr (VALUE self, VALUE rref)
1521
1534
  /* Shared body of __intersection__ (keep_when_hit = 1) and __difference__
1522
1535
  (keep_when_hit = 0): the distinct values of self that are (resp. are not)
1523
1536
  present in `other`, in self's first-appearance order, as a 1-D CArray of
1524
- self's dtype. Two seen-sets: `hoth` built from `other` is the probe set;
1537
+ self's data type. Two seen-sets: `hoth` built from `other` is the probe set;
1525
1538
  `hself` dedups self so each distinct value is decided once. Masked cells of
1526
1539
  either array do not participate. Distinctness is the discovery family's per
1527
1540
  lane (numeric `==` + NaN collapse + -0.0 == +0.0, object hash/eql? + NaN
@@ -1531,7 +1544,7 @@ fz_set_relation (VALUE self, VALUE rother, int keep_when_hit)
1531
1544
  {
1532
1545
  CArray *ca, *co;
1533
1546
  volatile VALUE face;
1534
- self = fz_face_descend(self, &face);
1547
+ self = fz_face_descend(self, &face, "set relation");
1535
1548
  rother = fz_face_reconcile(face, rother, "set relation");
1536
1549
  GetCArray(self, ca);
1537
1550
 
@@ -1545,7 +1558,7 @@ fz_set_relation (VALUE self, VALUE rother, int keep_when_hit)
1545
1558
  break;
1546
1559
  default:
1547
1560
  rb_raise(rb_eCADataTypeError,
1548
- "set relation: numeric, object, or fixlen dtype required (got %d)", dt);
1561
+ "set relation: numeric, object, or fixlen data type required (got %d)", dt);
1549
1562
  }
1550
1563
  if ( ca->ndim < 1 ) {
1551
1564
  rb_raise(rb_eRuntimeError, "set relation: need ndim >= 1");
@@ -1554,8 +1567,16 @@ fz_set_relation (VALUE self, VALUE rother, int keep_when_hit)
1554
1567
  rb_raise(rb_eArgError, "set relation: other must be a CArray");
1555
1568
  }
1556
1569
  GetCArray(rother, co);
1557
- if ( co->data_type != dt || (dt == CA_FIXLEN && co->bytes != ca->bytes) ) {
1558
- rb_raise(rb_eCADataTypeError, "set relation: other dtype must match self (%d)", dt);
1570
+ if ( co->data_type != dt ) {
1571
+ rb_raise(rb_eCADataTypeError,
1572
+ "set relation: other data type (%s) must match self (%s)",
1573
+ ca_type_name[co->data_type], ca_type_name[dt]);
1574
+ }
1575
+ if ( dt == CA_FIXLEN && co->bytes != ca->bytes ) {
1576
+ rb_raise(rb_eCADataTypeError,
1577
+ "set relation: a fixlen value is a cell-width blob, so other "
1578
+ "must be %ld bytes wide like self, not %ld",
1579
+ (long) ca->bytes, (long) co->bytes);
1559
1580
  }
1560
1581
  if ( co->ndim < 1 ) {
1561
1582
  rb_raise(rb_eRuntimeError, "set relation: other need ndim >= 1");
@@ -1716,7 +1737,7 @@ rb_ca_set_union (VALUE self, VALUE rother)
1716
1737
  {
1717
1738
  CArray *ca, *co;
1718
1739
  volatile VALUE face;
1719
- self = fz_face_descend(self, &face);
1740
+ self = fz_face_descend(self, &face, "union");
1720
1741
  rother = fz_face_reconcile(face, rother, "union");
1721
1742
  GetCArray(self, ca);
1722
1743
 
@@ -1730,7 +1751,7 @@ rb_ca_set_union (VALUE self, VALUE rother)
1730
1751
  break;
1731
1752
  default:
1732
1753
  rb_raise(rb_eCADataTypeError,
1733
- "__union__: numeric, object, or fixlen dtype required (got %d)", dt);
1754
+ "__union__: numeric, object, or fixlen data type required (got %d)", dt);
1734
1755
  }
1735
1756
  if ( ca->ndim < 1 ) {
1736
1757
  rb_raise(rb_eRuntimeError, "__union__: need ndim >= 1");
@@ -1740,7 +1761,7 @@ rb_ca_set_union (VALUE self, VALUE rother)
1740
1761
  }
1741
1762
  GetCArray(rother, co);
1742
1763
  if ( co->data_type != dt || (dt == CA_FIXLEN && co->bytes != ca->bytes) ) {
1743
- rb_raise(rb_eCADataTypeError, "__union__: other dtype must match self (%d)", dt);
1764
+ rb_raise(rb_eCADataTypeError, "__union__: other data type must match self (%d)", dt);
1744
1765
  }
1745
1766
  if ( co->ndim < 1 ) {
1746
1767
  rb_raise(rb_eRuntimeError, "__union__: other need ndim >= 1");
@@ -1779,7 +1800,7 @@ rb_ca_set_union (VALUE self, VALUE rother)
1779
1800
  first-appearance (row-major flatten) order together with the number of times
1780
1801
  each occurs, one linear pass, no sort.
1781
1802
  Returns [levels, counts]:
1782
- levels = 1-D CArray of source dtype, the k distinct values in appearance
1803
+ levels = 1-D CArray of source data type, the k distinct values in appearance
1783
1804
  order (identical to __unique_flat__).
1784
1805
  counts = 1-D CA_INT64 of length k, counts[i] = occurrences of levels[i].
1785
1806
  Masked cells do not participate (skipped, not counted). Numeric distinctness
@@ -1793,7 +1814,7 @@ rb_ca_value_counts_flat (VALUE self)
1793
1814
  {
1794
1815
  CArray *ca;
1795
1816
  volatile VALUE face;
1796
- self = fz_face_descend(self, &face);
1817
+ self = fz_face_descend(self, &face, "value_counts");
1797
1818
  TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
1798
1819
 
1799
1820
  int8_t dt = ca->data_type;
@@ -1806,7 +1827,7 @@ rb_ca_value_counts_flat (VALUE self)
1806
1827
  break;
1807
1828
  default:
1808
1829
  rb_raise(rb_eCADataTypeError,
1809
- "__value_counts_flat__: numeric, object, or fixlen dtype required (got %d)", dt);
1830
+ "__value_counts_flat__: numeric, object, or fixlen data type required (got %d)", dt);
1810
1831
  }
1811
1832
  if ( ca->ndim < 1 ) {
1812
1833
  rb_raise(rb_eRuntimeError, "__value_counts_flat__: need ndim >= 1");
@@ -1979,7 +2000,7 @@ rb_ca_nunique (VALUE self, VALUE vaxis, VALUE vkeep)
1979
2000
  break;
1980
2001
  default:
1981
2002
  rb_raise(rb_eCADataTypeError,
1982
- "__nunique__: numeric, object, or fixlen dtype required (got %d)", dt);
2003
+ "__nunique__: numeric, object, or fixlen data type required (got %d)", dt);
1983
2004
  }
1984
2005
  if ( ca->ndim < 1 ) {
1985
2006
  rb_raise(rb_eRuntimeError, "__nunique__: need ndim >= 1");
@@ -2126,7 +2147,7 @@ rb_ca_is_mode (VALUE self, VALUE vaxis)
2126
2147
  break;
2127
2148
  default:
2128
2149
  rb_raise(rb_eCADataTypeError,
2129
- "__is_mode__: numeric, object, or fixlen dtype required (got %d)", dt);
2150
+ "__is_mode__: numeric, object, or fixlen data type required (got %d)", dt);
2130
2151
  }
2131
2152
  if ( ca->ndim < 1 ) {
2132
2153
  rb_raise(rb_eRuntimeError, "__is_mode__: need ndim >= 1");
@@ -2332,7 +2353,7 @@ rb_ca_mode_axis (VALUE self, VALUE vaxis)
2332
2353
  {
2333
2354
  CArray *ca;
2334
2355
  volatile VALUE face;
2335
- self = fz_face_descend(self, &face);
2356
+ self = fz_face_descend(self, &face, "mode");
2336
2357
  TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
2337
2358
 
2338
2359
  int8_t dt = ca->data_type;
@@ -2344,7 +2365,7 @@ rb_ca_mode_axis (VALUE self, VALUE vaxis)
2344
2365
  break;
2345
2366
  default:
2346
2367
  rb_raise(rb_eCADataTypeError,
2347
- "__mode_axis__: numeric dtype required (got %d)", dt);
2368
+ "__mode_axis__: numeric data type required (got %d)", dt);
2348
2369
  }
2349
2370
  if ( ca->ndim < 1 ) {
2350
2371
  rb_raise(rb_eRuntimeError, "__mode_axis__: need ndim >= 1");
data/ext/carray_hold.c CHANGED
@@ -5,7 +5,7 @@
5
5
  (see devel/PROPOSAL_UNMASK_FILL_METHOD.md).
6
6
 
7
7
  Hold copies a cell's bytes into masked cells with no arithmetic and no
8
- per-dtype behavior, so a single ca->bytes-width memcpy walk covers every
8
+ per-type behavior, so a single ca->bytes-width memcpy walk covers every
9
9
  data_type -- numeric, complex, bool, object (VALUE-slot byte copy of an
10
10
  already-live value), fixlen, and Face storage. This native does forward
11
11
  hold along one axis only and returns a fresh same-shape entity; the
@@ -37,7 +37,6 @@ static ID ca_classifier_id_excl_end = 0;
37
37
  /* Symbol cache — see the range-macro comment above for why this
38
38
  file keeps its own copy independent of carray_access.c. */
39
39
 
40
- static VALUE ca_classifier_sym_star = Qundef;
41
40
  static VALUE ca_classifier_sym_perc = Qundef;
42
41
  static VALUE ca_classifier_sym_under = Qundef;
43
42
  static VALUE ca_classifier_sym_gt = Qundef; /* :> slab-iterator marker */
@@ -46,8 +45,7 @@ static VALUE ca_classifier_sym_tilde = Qundef; /* :~ rubber-dim alias for `fal
46
45
  static inline void
47
46
  ca_classifier_sym_cache_init (void)
48
47
  {
49
- if ( ca_classifier_sym_star == Qundef ) {
50
- ca_classifier_sym_star = ID2SYM(rb_intern("*"));
48
+ if ( ca_classifier_sym_perc == Qundef ) {
51
49
  ca_classifier_sym_perc = ID2SYM(rb_intern("%"));
52
50
  ca_classifier_sym_under = ID2SYM(rb_intern("_"));
53
51
  ca_classifier_sym_gt = ID2SYM(rb_intern(">"));
@@ -166,7 +164,7 @@ ca_classifier_try_address_fast_path (ca_classifier_ctx_t *ctx)
166
164
  /* Single-character alphabetic Symbols (`:a`-`:z` / `:A`-`:Z`) are
167
165
  reserved for future contraction notation. Raises
168
166
  NotImplementedError rather than the generic IndexError. The
169
- caller passes any Symbol that is not `:_` / `:*` / `:%`; a
167
+ caller passes any Symbol that is not `:_` / `:%`; a
170
168
  non-reserved Symbol returns without action. */
171
169
  static inline void
172
170
  ca_classifier_check_reserved_contraction_symbol (VALUE sym)
@@ -763,12 +761,6 @@ ca_classifier_try_argc1_special (ca_classifier_ctx_t *ctx)
763
761
  ca_type_name[cs->data_type]);
764
762
  }
765
763
 
766
- /* :* → UNBOUND_REPEAT. */
767
- if ( arg == ca_classifier_sym_star ) {
768
- info->type = CA_REG_UNBOUND_REPEAT;
769
- return 1;
770
- }
771
-
772
764
  /* ndim > 1 with Integer → ADDRESS. Fixnum was caught by the
773
765
  fast path; this branch handles Bignum. */
774
766
  if ( ctx->ca_ndim > 1 && rb_obj_is_kind_of(arg, rb_cInteger) ) {
@@ -832,7 +824,7 @@ rb_ca_scan_index_v2 (int ca_ndim, ca_size_t *ca_dim, ca_size_t ca_elements,
832
824
  }
833
825
 
834
826
  /* argv[0] = multi-char Symbol → METHOD_CALL. Single-char
835
- specials (:_ / :* / :%) fall through the strlen check and are
827
+ specials (:_ / :%) fall through the strlen check and are
836
828
  handled downstream (argc == 1 special / fast paths / main
837
829
  loop). Single-char alphabetic reserved-contraction Symbols
838
830
  also fall through here and are raised later by the per-axis
@@ -859,20 +851,15 @@ rb_ca_scan_index_v2 (int ca_ndim, ca_size_t *ca_dim, ca_size_t ca_elements,
859
851
  when argc == 1 && ndim == 1 falls through to the POINT 1-D
860
852
  classification below. */
861
853
 
862
- /* CAREFUL: pre-scan for :% / :*. Either Symbol at any position
863
- pins the final REG and short-circuits both the main loop and
864
- the argc / ndim validation below — skipping the pre-scan lets
865
- the ndim mismatch check fire before the Symbol is
866
- recognised. */
854
+ /* CAREFUL: pre-scan for :%. The Symbol at any position pins the
855
+ final REG and short-circuits both the main loop and the argc /
856
+ ndim validation below — skipping the pre-scan lets the ndim
857
+ mismatch check fire before the Symbol is recognised. */
867
858
  for (i = 0; i < ctx.argc; i++) {
868
859
  if ( ctx.argv[i] == ca_classifier_sym_perc ) {
869
860
  info->type = CA_REG_REPEAT;
870
861
  return;
871
862
  }
872
- if ( ctx.argv[i] == ca_classifier_sym_star ) {
873
- info->type = CA_REG_UNBOUND_REPEAT;
874
- return;
875
- }
876
863
  }
877
864
 
878
865
  ca_classifier_expand_rubber_dim(&ctx);
@@ -941,7 +928,6 @@ rb_ca_s_scan_index_v2 (VALUE self, VALUE rdim, VALUE ridx)
941
928
  case CA_REG_GRID:
942
929
  case CA_REG_MAPPING:
943
930
  case CA_REG_METHOD_CALL:
944
- case CA_REG_UNBOUND_REPEAT:
945
931
  case CA_REG_MEMBER:
946
932
  case CA_REG_ATTRIBUTE:
947
933
  break;
@@ -59,8 +59,41 @@ void ca_bit_pack (const boolean8_t *src, ca_size_t elements, ca_size_t pbytes,
59
59
  void ca_lazy_arena_enter (void);
60
60
  void ca_lazy_arena_exit (void);
61
61
  void *ca_lazy_arena_acquire (ca_size_t bytes);
62
+ void *ca_lazy_arena_acquire_object (ca_size_t n_elements);
62
63
  void ca_lazy_arena_release (void *ptr);
63
64
 
65
+ /* ---- CA_OBJECT GC guard (carray_lazy.c) ----------------------------------
66
+
67
+ A CA_OBJECT cell is a VALUE, and a materialise writes those cells into a
68
+ buffer no Ruby object owns. Object-lane kernels call rb_funcall per cell,
69
+ so a collection can happen halfway through and free what has been written
70
+ so far. Hold the buffer while it is exposed like that, and after the
71
+ materialise until a Ruby object takes ownership of it.
72
+
73
+ The cells must already be valid VALUEs, so a fresh buffer is Qnil-filled
74
+ before it is held. ca_gc_hold_push returns the depth to hand back to
75
+ ca_gc_hold_pop_to, so nested holds unwind in order. */
76
+
77
+ int ca_gc_hold_push (void *ptr, ca_size_t n_elements);
78
+ void ca_gc_hold_pop_to (int depth);
79
+
80
+ /* ---- Attaching several parents (carray_core.c) ---------------------------
81
+
82
+ Attach all of list[0..n-1] or none: if one attach raises, those already
83
+ attached are detached before the raise propagates. */
84
+
85
+ void ca_attach_all (CArray **list, int32_t n);
86
+
87
+ /* ---- Filling a result Ruby does not own yet (carray_copy.c) ---------------
88
+
89
+ A C builder that allocates its result with carray_new / ca_template and
90
+ then reads the source into it holds a struct no Ruby object owns until
91
+ ca_wrap_struct. A read that raises (a lazy conversion) would leave it
92
+ behind. ca_fill_or_free runs fill(arg) under rb_protect and, if it
93
+ raises, frees `co` before the raise propagates. */
94
+
95
+ void ca_fill_or_free (CArray *co, VALUE (*fill)(VALUE), VALUE arg);
96
+
64
97
  /* Non-zero iff the object is an element-wise lazy view (CAMonOp / CABinOp /
65
98
  CABinCmp / CAMonCmp / CALazyMarker). The streaming branch of the
66
99
  mkkernel-generated reduction kernels tests this to decide whether it can
@@ -111,10 +144,10 @@ VALUE rb_ca_fake_new (VALUE cary, int8_t data_type, ca_size_t bytes);
111
144
  CARepeat *ca_repeat_new (CArray *carray, int8_t ndim, ca_size_t *count);
112
145
  VALUE rb_ca_repeat_new (VALUE cary, int8_t ndim, ca_size_t *count);
113
146
 
114
- /* ca_obj_unbound_repeat.c */
115
- VALUE rb_ca_ubrep_new (VALUE cary, int32_t rep_ndim, ca_size_t *rep_dim);
116
-
117
147
  /* ca_obj_reduce.c */
118
148
  CAReduce *ca_reduce_new (CArray *carray, ca_size_t count, ca_size_t offset);
119
149
 
150
+ /* carray_broadcast.c */
151
+ void ca_broadcast_to_destination (VALUE dst, volatile VALUE *src);
152
+
120
153
  #endif /* CARRAY_INTERNAL_H */
@@ -34,6 +34,7 @@ static inline VALUE BOOL2VAL (boolean8_t x) { return x ? Qtrue : Qfalse; }
34
34
  #endif
35
35
 
36
36
  #include "ca_op_powi.h"
37
+ #include "ca_op_cmplx64.h"
37
38
 
38
39
  /* ===== bincmp feq ============================================ */
39
40