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
@@ -16,6 +16,18 @@
16
16
  #ifndef CARRAY_CALL_CFUNC_H
17
17
  #define CARRAY_CALL_CFUNC_H
18
18
 
19
+ /* Chunk callback for the ca_call_cslab_N family. `base` and `stride` are
20
+ one entry per operand, in the order the operands were passed; `n` is the
21
+ number of cells in this chunk; `m0` is the chunk's slice of the mask,
22
+ one byte per cell, or NULL when no INPUT carried a mask. The arity does
23
+ not appear in the signature -- the operands arrive through `base` -- so
24
+ one typedef serves every arity. */
25
+ typedef void (*ca_cslab_t) (char **base, ca_size_t *stride, ca_size_t n,
26
+ const boolean8_t *m0);
27
+
28
+ typedef void (*ca_cslab_r_t) (char **base, ca_size_t *stride, ca_size_t n,
29
+ const boolean8_t *m0, void *userdata);
30
+
19
31
  VALUE
20
32
  ca_call_cfunc_1 (void (*func)(void *p0), const char *fsync,
21
33
  VALUE rcx0);
@@ -157,4 +169,145 @@ ca_call_cfunc_3_2_r (int8_t dty1, int8_t dty2, int8_t dty3, int8_t dtx1, int8_t
157
169
  VALUE
158
170
  ca_call_cfunc_3_3_r (int8_t dty1, int8_t dty2, int8_t dty3, int8_t dtx1, int8_t dtx2, int8_t dtx3, void (*mathfunc)(void*, void*, void*, void*, void*, void*, void *userdata), volatile VALUE rx1, volatile VALUE rx2, volatile VALUE rx3, void *userdata);
159
171
 
172
+ VALUE
173
+ ca_call_cslab_1 (ca_cslab_t func, const char *fsync,
174
+ VALUE rcx0);
175
+
176
+ VALUE
177
+ ca_call_cslab_2 (ca_cslab_t func, const char *fsync,
178
+ VALUE rcx0, VALUE rcx1);
179
+
180
+ VALUE
181
+ ca_call_cslab_3 (ca_cslab_t func, const char *fsync,
182
+ VALUE rcx0, VALUE rcx1, VALUE rcx2);
183
+
184
+ VALUE
185
+ ca_call_cslab_4 (ca_cslab_t func, const char *fsync,
186
+ VALUE rcx0, VALUE rcx1, VALUE rcx2, VALUE rcx3);
187
+
188
+ VALUE
189
+ ca_call_cslab_5 (ca_cslab_t func, const char *fsync,
190
+ VALUE rcx0, VALUE rcx1, VALUE rcx2, VALUE rcx3, VALUE rcx4);
191
+
192
+ VALUE
193
+ ca_call_cslab_6 (ca_cslab_t func, const char *fsync,
194
+ VALUE rcx0, VALUE rcx1, VALUE rcx2, VALUE rcx3, VALUE rcx4, VALUE rcx5);
195
+
196
+ VALUE
197
+ ca_call_cslab_7 (ca_cslab_t func, const char *fsync,
198
+ VALUE rcx0, VALUE rcx1, VALUE rcx2, VALUE rcx3, VALUE rcx4, VALUE rcx5, VALUE rcx6);
199
+
200
+ VALUE
201
+ ca_call_cslab_1_r (ca_cslab_r_t func, const char *fsync,
202
+ VALUE rcx0,
203
+ void *userdata);
204
+
205
+ VALUE
206
+ ca_call_cslab_2_r (ca_cslab_r_t func, const char *fsync,
207
+ VALUE rcx0, VALUE rcx1,
208
+ void *userdata);
209
+
210
+ VALUE
211
+ ca_call_cslab_3_r (ca_cslab_r_t func, const char *fsync,
212
+ VALUE rcx0, VALUE rcx1, VALUE rcx2,
213
+ void *userdata);
214
+
215
+ VALUE
216
+ ca_call_cslab_4_r (ca_cslab_r_t func, const char *fsync,
217
+ VALUE rcx0, VALUE rcx1, VALUE rcx2, VALUE rcx3,
218
+ void *userdata);
219
+
220
+ VALUE
221
+ ca_call_cslab_5_r (ca_cslab_r_t func, const char *fsync,
222
+ VALUE rcx0, VALUE rcx1, VALUE rcx2, VALUE rcx3, VALUE rcx4,
223
+ void *userdata);
224
+
225
+ VALUE
226
+ ca_call_cslab_6_r (ca_cslab_r_t func, const char *fsync,
227
+ VALUE rcx0, VALUE rcx1, VALUE rcx2, VALUE rcx3, VALUE rcx4, VALUE rcx5,
228
+ void *userdata);
229
+
230
+ VALUE
231
+ ca_call_cslab_7_r (ca_cslab_r_t func, const char *fsync,
232
+ VALUE rcx0, VALUE rcx1, VALUE rcx2, VALUE rcx3, VALUE rcx4, VALUE rcx5, VALUE rcx6,
233
+ void *userdata);
234
+
235
+ VALUE
236
+ ca_call_cslab_1_1 (int8_t dty, int8_t dtx1, ca_cslab_t slabfunc, volatile VALUE rx1);
237
+
238
+ VALUE
239
+ ca_call_cslab_1_2 (int8_t dty, int8_t dtx1, int8_t dtx2, ca_cslab_t slabfunc, volatile VALUE rx1, volatile VALUE rx2);
240
+
241
+ VALUE
242
+ ca_call_cslab_1_3 (int8_t dty, int8_t dtx1, int8_t dtx2, int8_t dtx3, ca_cslab_t slabfunc, volatile VALUE rx1, volatile VALUE rx2, volatile VALUE rx3);
243
+
244
+ VALUE
245
+ ca_call_cslab_1_4 (int8_t dty, int8_t dtx1, int8_t dtx2, int8_t dtx3, int8_t dtx4, ca_cslab_t slabfunc, volatile VALUE rx1, volatile VALUE rx2, volatile VALUE rx3, volatile VALUE rx4);
246
+
247
+ VALUE
248
+ ca_call_cslab_1_5 (int8_t dty, int8_t dtx1, int8_t dtx2, int8_t dtx3, int8_t dtx4, int8_t dtx5, ca_cslab_t slabfunc, volatile VALUE rx1, volatile VALUE rx2, volatile VALUE rx3, volatile VALUE rx4, volatile VALUE rx5);
249
+
250
+ VALUE
251
+ ca_call_cslab_1_6 (int8_t dty, int8_t dtx1, int8_t dtx2, int8_t dtx3, int8_t dtx4, int8_t dtx5, int8_t dtx6, ca_cslab_t slabfunc, volatile VALUE rx1, volatile VALUE rx2, volatile VALUE rx3, volatile VALUE rx4, volatile VALUE rx5, volatile VALUE rx6);
252
+
253
+ VALUE
254
+ ca_call_cslab_2_1 (int8_t dty1, int8_t dty2, int8_t dtx1, ca_cslab_t slabfunc, volatile VALUE rx1);
255
+
256
+ VALUE
257
+ ca_call_cslab_2_2 (int8_t dty1, int8_t dty2, int8_t dtx1, int8_t dtx2, ca_cslab_t slabfunc, volatile VALUE rx1, volatile VALUE rx2);
258
+
259
+ VALUE
260
+ ca_call_cslab_2_3 (int8_t dty1, int8_t dty2, int8_t dtx1, int8_t dtx2, int8_t dtx3, ca_cslab_t slabfunc, volatile VALUE rx1, volatile VALUE rx2, volatile VALUE rx3);
261
+
262
+ VALUE
263
+ ca_call_cslab_2_4 (int8_t dty1, int8_t dty2, int8_t dtx1, int8_t dtx2, int8_t dtx3, int8_t dtx4, ca_cslab_t slabfunc, volatile VALUE rx1, volatile VALUE rx2, volatile VALUE rx3, volatile VALUE rx4);
264
+
265
+ VALUE
266
+ ca_call_cslab_3_1 (int8_t dty1, int8_t dty2, int8_t dty3, int8_t dtx1, ca_cslab_t slabfunc, volatile VALUE rx1);
267
+
268
+ VALUE
269
+ ca_call_cslab_3_2 (int8_t dty1, int8_t dty2, int8_t dty3, int8_t dtx1, int8_t dtx2, ca_cslab_t slabfunc, volatile VALUE rx1, volatile VALUE rx2);
270
+
271
+ VALUE
272
+ ca_call_cslab_3_3 (int8_t dty1, int8_t dty2, int8_t dty3, int8_t dtx1, int8_t dtx2, int8_t dtx3, ca_cslab_t slabfunc, volatile VALUE rx1, volatile VALUE rx2, volatile VALUE rx3);
273
+
274
+ VALUE
275
+ ca_call_cslab_1_1_r (int8_t dty, int8_t dtx1, ca_cslab_r_t slabfunc, volatile VALUE rx1, void *userdata);
276
+
277
+ VALUE
278
+ ca_call_cslab_1_2_r (int8_t dty, int8_t dtx1, int8_t dtx2, ca_cslab_r_t slabfunc, volatile VALUE rx1, volatile VALUE rx2, void *userdata);
279
+
280
+ VALUE
281
+ ca_call_cslab_1_3_r (int8_t dty, int8_t dtx1, int8_t dtx2, int8_t dtx3, ca_cslab_r_t slabfunc, volatile VALUE rx1, volatile VALUE rx2, volatile VALUE rx3, void *userdata);
282
+
283
+ VALUE
284
+ ca_call_cslab_1_4_r (int8_t dty, int8_t dtx1, int8_t dtx2, int8_t dtx3, int8_t dtx4, ca_cslab_r_t slabfunc, volatile VALUE rx1, volatile VALUE rx2, volatile VALUE rx3, volatile VALUE rx4, void *userdata);
285
+
286
+ VALUE
287
+ ca_call_cslab_1_5_r (int8_t dty, int8_t dtx1, int8_t dtx2, int8_t dtx3, int8_t dtx4, int8_t dtx5, ca_cslab_r_t slabfunc, volatile VALUE rx1, volatile VALUE rx2, volatile VALUE rx3, volatile VALUE rx4, volatile VALUE rx5, void *userdata);
288
+
289
+ VALUE
290
+ ca_call_cslab_1_6_r (int8_t dty, int8_t dtx1, int8_t dtx2, int8_t dtx3, int8_t dtx4, int8_t dtx5, int8_t dtx6, ca_cslab_r_t slabfunc, volatile VALUE rx1, volatile VALUE rx2, volatile VALUE rx3, volatile VALUE rx4, volatile VALUE rx5, volatile VALUE rx6, void *userdata);
291
+
292
+ VALUE
293
+ ca_call_cslab_2_1_r (int8_t dty1, int8_t dty2, int8_t dtx1, ca_cslab_r_t slabfunc, volatile VALUE rx1, void *userdata);
294
+
295
+ VALUE
296
+ ca_call_cslab_2_2_r (int8_t dty1, int8_t dty2, int8_t dtx1, int8_t dtx2, ca_cslab_r_t slabfunc, volatile VALUE rx1, volatile VALUE rx2, void *userdata);
297
+
298
+ VALUE
299
+ ca_call_cslab_2_3_r (int8_t dty1, int8_t dty2, int8_t dtx1, int8_t dtx2, int8_t dtx3, ca_cslab_r_t slabfunc, volatile VALUE rx1, volatile VALUE rx2, volatile VALUE rx3, void *userdata);
300
+
301
+ VALUE
302
+ ca_call_cslab_2_4_r (int8_t dty1, int8_t dty2, int8_t dtx1, int8_t dtx2, int8_t dtx3, int8_t dtx4, ca_cslab_r_t slabfunc, volatile VALUE rx1, volatile VALUE rx2, volatile VALUE rx3, volatile VALUE rx4, void *userdata);
303
+
304
+ VALUE
305
+ ca_call_cslab_3_1_r (int8_t dty1, int8_t dty2, int8_t dty3, int8_t dtx1, ca_cslab_r_t slabfunc, volatile VALUE rx1, void *userdata);
306
+
307
+ VALUE
308
+ ca_call_cslab_3_2_r (int8_t dty1, int8_t dty2, int8_t dty3, int8_t dtx1, int8_t dtx2, ca_cslab_r_t slabfunc, volatile VALUE rx1, volatile VALUE rx2, void *userdata);
309
+
310
+ VALUE
311
+ ca_call_cslab_3_3_r (int8_t dty1, int8_t dty2, int8_t dty3, int8_t dtx1, int8_t dtx2, int8_t dtx3, ca_cslab_r_t slabfunc, volatile VALUE rx1, volatile VALUE rx2, volatile VALUE rx3, void *userdata);
312
+
160
313
  #endif /* CARRAY_CALL_CFUNC_H */
data/ext/carray_cast.c CHANGED
@@ -2,9 +2,11 @@
2
2
 
3
3
  Cast surface (3 layers):
4
4
 
5
- to_<type> `a.to_int32` etc. Returns a fresh entity CArray
6
- of the target data_type. Independent storage from
7
- `self`.
5
+ <type> `a.int32` etc., and the general `a.to_type(:int32)`.
6
+ Returns a fresh entity CArray of the target
7
+ data_type. Independent storage from `self`. (The
8
+ C functions are named rb_ca_to_<type>, but the
9
+ methods they register carry no `to_` prefix.)
8
10
 
9
11
  as_<type> `a.as_int32` etc. Returns a writable CAMonOp view
10
12
  that reinterprets `self` cell-by-cell at the target
@@ -550,6 +552,77 @@ rb_ca_object_to_data_class (VALUE self, VALUE rtype, ca_size_t bytes)
550
552
  return obj;
551
553
  }
552
554
 
555
+ typedef struct {
556
+ CArray *ca;
557
+ CArray *cb;
558
+ boolean8_t *scratch;
559
+ } ca_to_type_ctx_t;
560
+
561
+ /* The cast proper, with `ca` attached. It can raise (a value the target
562
+ type cannot hold), so it runs under rb_ensure. */
563
+ static VALUE
564
+ ca_to_type_cast (VALUE arg)
565
+ {
566
+ ca_to_type_ctx_t *c = (ca_to_type_ctx_t *) arg;
567
+ CArray *ca = c->ca, *cb = c->cb;
568
+
569
+ if ( ca->data_type == CA_OBJECT
570
+ && ( (cb->data_type >= CA_INT8 && cb->data_type <= CA_UINT64)
571
+ || cb->data_type == CA_FLOAT32 || cb->data_type == CA_FLOAT64 ) ) {
572
+ /* object -> int/float: give the cast a mask buffer so an unparseable
573
+ cell becomes UNDEF (see ext/carray_cast_func.rb). Cast into a
574
+ scratch mask seeded from the source mask, then attach it to the
575
+ output only if some cell ended up masked -- an all-valid cast keeps
576
+ the mask-less result the legacy path produced. */
577
+ ca_size_t ne = cb->elements;
578
+ ca_size_t i;
579
+ boolean8_t any = 0;
580
+ boolean8_t *scratch;
581
+ c->scratch = scratch = ALLOC_N(boolean8_t, ne > 0 ? ne : 1);
582
+ if ( cb->mask ) {
583
+ memcpy(scratch, cb->mask->ptr, ne); /* copy of source mask */
584
+ }
585
+ else {
586
+ memset(scratch, 0, ne);
587
+ }
588
+ ca_cast_block_with_mask(ne, ca, ca->ptr, cb, cb->ptr, scratch);
589
+ for (i=0; i<ne; i++) {
590
+ if ( scratch[i] ) {
591
+ any = 1;
592
+ break;
593
+ }
594
+ }
595
+ if ( any ) {
596
+ if ( ! cb->mask ) {
597
+ ca_create_mask(cb);
598
+ }
599
+ memcpy(cb->mask->ptr, scratch, ne);
600
+ }
601
+ xfree(scratch);
602
+ c->scratch = NULL;
603
+ }
604
+ else if ( ca_has_mask(ca) ) {
605
+ ca_cast_block_with_mask(cb->elements, ca, ca->ptr, cb, cb->ptr,
606
+ (boolean8_t*)ca->mask->ptr);
607
+ }
608
+ else {
609
+ ca_cast_block(cb->elements, ca, ca->ptr, cb, cb->ptr);
610
+ }
611
+ return Qnil;
612
+ }
613
+
614
+ static VALUE
615
+ ca_to_type_release (VALUE arg)
616
+ {
617
+ ca_to_type_ctx_t *c = (ca_to_type_ctx_t *) arg;
618
+ if ( c->scratch ) {
619
+ xfree(c->scratch);
620
+ c->scratch = NULL;
621
+ }
622
+ ca_detach(c->ca);
623
+ return Qnil;
624
+ }
625
+
553
626
  /* CArray#to_type(data_type, bytes:) -- eager copy of self converted to
554
627
  data_type (a new entity owning its storage). User doc lives in
555
628
  yard-stubs/carray_cast.rb. */
@@ -559,6 +632,7 @@ rb_ca_to_type_internal (int argc, VALUE *argv, VALUE self)
559
632
  {
560
633
  volatile VALUE obj, rtype = Qnil, ropt, rbytes = Qnil;
561
634
  CArray *ca, *cb;
635
+ ca_to_type_ctx_t ctx;
562
636
  int8_t data_type;
563
637
  ca_size_t bytes;
564
638
 
@@ -599,48 +673,11 @@ rb_ca_to_type_internal (int argc, VALUE *argv, VALUE self)
599
673
 
600
674
  TypedData_Get_Struct(obj, CArray, &carray_data_type, cb);
601
675
 
676
+ ctx.ca = ca;
677
+ ctx.cb = cb;
678
+ ctx.scratch = NULL;
602
679
  ca_attach(ca);
603
- if ( ca->data_type == CA_OBJECT
604
- && ( (data_type >= CA_INT8 && data_type <= CA_UINT64)
605
- || data_type == CA_FLOAT32 || data_type == CA_FLOAT64 ) ) {
606
- /* object -> int/float: give the cast a mask buffer so an unparseable
607
- cell becomes UNDEF (see ext/carray_cast_func.rb). Cast into a
608
- scratch mask seeded from the source mask, then attach it to the
609
- output only if some cell ended up masked -- an all-valid cast keeps
610
- the mask-less result the legacy path produced. */
611
- ca_size_t ne = cb->elements;
612
- ca_size_t i;
613
- boolean8_t any = 0;
614
- boolean8_t *scratch = ALLOC_N(boolean8_t, ne > 0 ? ne : 1);
615
- if ( cb->mask ) {
616
- memcpy(scratch, cb->mask->ptr, ne); /* copy of source mask */
617
- }
618
- else {
619
- memset(scratch, 0, ne);
620
- }
621
- ca_cast_block_with_mask(ne, ca, ca->ptr, cb, cb->ptr, scratch);
622
- for (i=0; i<ne; i++) {
623
- if ( scratch[i] ) {
624
- any = 1;
625
- break;
626
- }
627
- }
628
- if ( any ) {
629
- if ( ! cb->mask ) {
630
- ca_create_mask(cb);
631
- }
632
- memcpy(cb->mask->ptr, scratch, ne);
633
- }
634
- xfree(scratch);
635
- }
636
- else if ( ca_has_mask(ca) ) {
637
- ca_cast_block_with_mask(cb->elements, ca, ca->ptr, cb, cb->ptr,
638
- (boolean8_t*)ca->mask->ptr);
639
- }
640
- else {
641
- ca_cast_block(cb->elements, ca, ca->ptr, cb, cb->ptr);
642
- }
643
- ca_detach(ca);
680
+ rb_ensure(ca_to_type_cast, (VALUE) &ctx, ca_to_type_release, (VALUE) &ctx);
644
681
 
645
682
  /* When rtype is a data_class (e.g. CAStruct subclass), wrap the
646
683
  result in CARecord so the cast output carries data_class. */
@@ -773,16 +810,62 @@ extern VALUE rb_ca_monop_build (VALUE cary, uint16_t op_id);
773
810
  /* Forward declaration: clip kernel (ext/carray_kernels.c, generated). */
774
811
  extern VALUE rb_ca_clip (VALUE self, VALUE lo, VALUE hi);
775
812
 
813
+ /* Which surface asked for a type-adapt view. A Face's cells do not mean
814
+ their storage bytes and there is no view that decodes them, so each
815
+ caller says what it does instead of reinterpreting the storage. */
816
+ enum {
817
+ CA_ADAPT_VIEW, /* as_type: the values are behind #to_type */
818
+ CA_ADAPT_READONLY, /* wrap_readonly: the eager conversion is the answer */
819
+ CA_ADAPT_WRITABLE /* wrap_writable: writes have nowhere to land */
820
+ };
821
+
776
822
  /* Routes a type-adapt view request to CAMonOp(cast_<dt>) when the
777
823
  target is a plain numeric data_type (NOT CA_FIXLEN, NOT CA_OBJECT,
778
824
  and `rtype` is not a Class). Falls back to CAFake
779
825
  (`rb_ca_fake_type`) for CA_FIXLEN sizing, CA_OBJECT, and class-rtype
780
826
  data_class overlay cases.
781
827
  Called by rb_ca_as_type_internal, rb_ca_wrap_readonly, and
782
- rb_ca_wrap_writable in this file. */
828
+ rb_ca_wrap_writable in this file.
829
+
830
+ A Face whose surface is not its storage reaches neither: reinterpreting
831
+ the storage would hand back the bytes the surface exists to hide (the
832
+ serial instead of the time, the descriptor instead of the string).
833
+ wrap_readonly, which already returns entities for its non-CArray inputs,
834
+ answers with the eager conversion #to_type performs -- the surface values,
835
+ or the Face's own #to_numeric for a numeric target. as_type and
836
+ wrap_writable have no honest answer and say so. */
783
837
  static VALUE
784
- ca_type_adapt_view (VALUE obj, VALUE rtype, int8_t data_type)
838
+ ca_type_adapt_view (VALUE obj, VALUE rtype, int8_t data_type, int mode)
785
839
  {
840
+ CArray *ca;
841
+
842
+ TypedData_Get_Struct(obj, CArray, &carray_data_type, ca);
843
+
844
+ /* Same split the eager cast makes: :object is the Face's surface for every
845
+ Face, and a NonNumeric Face (CA_FIXLEN surface) has no reading of its
846
+ storage as a number either. A Numeric Face falls through, because there
847
+ its surface *is* its storage and the ordinary cast below is right. */
848
+ if ( ca_is_face(ca) && ( data_type == CA_OBJECT
849
+ || ca->data_type == CA_FIXLEN ) ) {
850
+ VALUE args[1];
851
+ switch ( mode ) {
852
+ case CA_ADAPT_READONLY:
853
+ args[0] = rtype;
854
+ return rb_ca_to_type_internal(1, args, obj);
855
+ case CA_ADAPT_WRITABLE:
856
+ rb_raise(rb_eTypeError,
857
+ "%s has no writable view in another data_type: the writes "
858
+ "would land on the storage its surface hides -- wrap "
859
+ "#parent to reach that storage",
860
+ rb_obj_classname(obj));
861
+ default:
862
+ rb_raise(rb_eTypeError,
863
+ "%s has no view of its values in another data_type: "
864
+ "#to_type gives the values, #parent the raw storage",
865
+ rb_obj_classname(obj));
866
+ }
867
+ }
868
+
786
869
  if ( data_type != CA_FIXLEN
787
870
  && data_type != CA_OBJECT
788
871
  && TYPE(rtype) != T_CLASS ) {
@@ -815,7 +898,7 @@ rb_ca_as_type_internal (int argc, VALUE *argv, VALUE self)
815
898
  /* Natural-width cast: dispatch via helper (CAMonOp for numeric,
816
899
  CAFake for CA_FIXLEN sizing / CA_OBJECT / class-rtype). */
817
900
  if ( bytes == (ca_size_t) ca_sizeof[data_type] ) {
818
- obj = ca_type_adapt_view(self, rtype, data_type);
901
+ obj = ca_type_adapt_view(self, rtype, data_type, CA_ADAPT_VIEW);
819
902
  return obj;
820
903
  }
821
904
 
@@ -1075,7 +1158,7 @@ rb_ca_wrap_writable (VALUE arg, VALUE rtype)
1075
1158
  data_type = rb_ca_guess_type(rtype);
1076
1159
  }
1077
1160
  if ( ca->data_type != data_type ) {
1078
- obj = ca_type_adapt_view(obj, rtype, data_type);
1161
+ obj = ca_type_adapt_view(obj, rtype, data_type, CA_ADAPT_WRITABLE);
1079
1162
  }
1080
1163
  }
1081
1164
  else if ( NIL_P(obj) ) { /* obj == nil */
@@ -1113,7 +1196,8 @@ rb_ca_wrap_writable (VALUE arg, VALUE rtype)
1113
1196
  data_type = rb_ca_guess_type(rtype);
1114
1197
  }
1115
1198
  if ( ca->data_type != data_type ) {
1116
- obj = ca_type_adapt_view(obj, INT2NUM(data_type), data_type);
1199
+ obj = ca_type_adapt_view(obj, INT2NUM(data_type), data_type,
1200
+ CA_ADAPT_WRITABLE);
1117
1201
  }
1118
1202
  }
1119
1203
  else if ( rb_memory_view_available_p(obj) ) { /* MemoryView producer */
@@ -1130,7 +1214,8 @@ rb_ca_wrap_writable (VALUE arg, VALUE rtype)
1130
1214
  data_type = rb_ca_guess_type(rtype);
1131
1215
  }
1132
1216
  if ( ca->data_type != data_type ) {
1133
- obj = ca_type_adapt_view(obj, INT2NUM(data_type), data_type);
1217
+ obj = ca_type_adapt_view(obj, INT2NUM(data_type), data_type,
1218
+ CA_ADAPT_WRITABLE);
1134
1219
  }
1135
1220
  }
1136
1221
  else {
@@ -1171,7 +1256,7 @@ rb_ca_wrap_readonly (VALUE arg, VALUE rtype)
1171
1256
  data_type = rb_ca_guess_type(rtype);
1172
1257
  }
1173
1258
  if ( ca->data_type != data_type ) {
1174
- obj = ca_type_adapt_view(obj, rtype, data_type);
1259
+ obj = ca_type_adapt_view(obj, rtype, data_type, CA_ADAPT_READONLY);
1175
1260
  }
1176
1261
  }
1177
1262
  else if ( rb_obj_is_kind_of(obj, rb_cNumeric) ) { /* number */
@@ -1193,7 +1278,8 @@ rb_ca_wrap_readonly (VALUE arg, VALUE rtype)
1193
1278
  data_type = rb_ca_guess_type(rtype);
1194
1279
  }
1195
1280
  if ( ca->data_type != data_type ) {
1196
- obj = ca_type_adapt_view(obj, INT2NUM(data_type), data_type);
1281
+ obj = ca_type_adapt_view(obj, INT2NUM(data_type), data_type,
1282
+ CA_ADAPT_READONLY);
1197
1283
  }
1198
1284
  }
1199
1285
  else if ( TYPE(obj) == T_STRING ) { /* string */
@@ -1234,7 +1320,8 @@ rb_ca_wrap_readonly (VALUE arg, VALUE rtype)
1234
1320
  data_type = rb_ca_guess_type(rtype);
1235
1321
  }
1236
1322
  if ( ca->data_type != data_type ) {
1237
- obj = ca_type_adapt_view(obj, INT2NUM(data_type), data_type);
1323
+ obj = ca_type_adapt_view(obj, INT2NUM(data_type), data_type,
1324
+ CA_ADAPT_READONLY);
1238
1325
  }
1239
1326
  }
1240
1327
  else if ( rb_memory_view_available_p(obj) ) { /* MemoryView producer */
@@ -1247,7 +1334,8 @@ rb_ca_wrap_readonly (VALUE arg, VALUE rtype)
1247
1334
  data_type = rb_ca_guess_type(rtype);
1248
1335
  }
1249
1336
  if ( ca->data_type != data_type ) {
1250
- obj = ca_type_adapt_view(obj, INT2NUM(data_type), data_type);
1337
+ obj = ca_type_adapt_view(obj, INT2NUM(data_type), data_type,
1338
+ CA_ADAPT_READONLY);
1251
1339
  }
1252
1340
  }
1253
1341
  else { /* object */
@@ -1313,6 +1401,36 @@ rb_ca_cast (volatile VALUE self)
1313
1401
  return obj;
1314
1402
  }
1315
1403
 
1404
+ /* A String operand against a fixlen array is a value of that array's cell
1405
+ width. ca_value_to_data_type answers CA_OBJECT for a String, so without
1406
+ this the operand became an object scalar and the comparison ran down the
1407
+ object lane -- an rb_funcall of String#== per cell, against the cell's
1408
+ NUL-padded text. A fixlen array pads a short String on write
1409
+ (`a[i] = "be"` stores "be\0\0\0"), so that answered that an array does
1410
+ not equal the string it was written from, and did it 30x slower than the
1411
+ memcmp lane the fixlen comparison bodies are there to provide.
1412
+
1413
+ Two fixlen *arrays* of different widths keep the variable-width byte
1414
+ string semantics those bodies implement (min-width memcmp with a length
1415
+ tiebreak); this is only about a scalar standing in for a cell. */
1416
+ static int
1417
+ ca_fixlen_scalar_operand (volatile VALUE *scalar, VALUE reference)
1418
+ {
1419
+ CArray *cr;
1420
+ /* A String is the only operand that means a cell value here. A Regexp
1421
+ (match) or any other object keeps its own coercion: those are asking
1422
+ something about the bytes, not standing in for them. */
1423
+ if ( ! RB_TYPE_P(*scalar, T_STRING) || ! rb_obj_is_carray(reference) ) {
1424
+ return 0;
1425
+ }
1426
+ TypedData_Get_Struct(reference, CArray, &carray_data_type, cr);
1427
+ if ( cr->data_type != CA_FIXLEN ) {
1428
+ return 0;
1429
+ }
1430
+ *scalar = rb_cscalar_new_with_value(CA_FIXLEN, cr->bytes, *scalar);
1431
+ return 1;
1432
+ }
1433
+
1316
1434
  /* CArray.cast(value) -- singleton entry delegating to rb_ca_cast, which
1317
1435
  returns a CArray unchanged and coerces a Ruby value to a CScalar / CArray.
1318
1436
  User doc lives in yard-stubs/carray_cast.rb. */
@@ -1356,6 +1474,9 @@ rb_ca_cast_self_or_other (volatile VALUE *self, volatile VALUE *other)
1356
1474
  *self = rb_cscalar_new_with_value(CA_CMPLX128, 0, *self);
1357
1475
  }
1358
1476
  #endif
1477
+ else if ( ca_fixlen_scalar_operand(self, *other) ) {
1478
+ /* width taken from the fixlen reference; see the helper above */
1479
+ }
1359
1480
  else if ( rb_ca_is_float_type(*other) ) {
1360
1481
  *self = rb_cscalar_new_with_value(CA_FLOAT64, 0, *self);
1361
1482
  }
@@ -1384,6 +1505,9 @@ rb_ca_cast_self_or_other (volatile VALUE *self, volatile VALUE *other)
1384
1505
  *other = rb_cscalar_new_with_value(CA_CMPLX128, 0, *other);
1385
1506
  }
1386
1507
  #endif
1508
+ else if ( ca_fixlen_scalar_operand(other, *self) ) {
1509
+ /* width taken from the fixlen reference; see the helper above */
1510
+ }
1387
1511
  else if ( rb_ca_is_float_type(*self) ) {
1388
1512
  *other = rb_cscalar_new_with_value(CA_FLOAT64, 0, *other);
1389
1513
  }
@@ -1400,16 +1524,6 @@ rb_ca_cast_self_or_other (volatile VALUE *self, volatile VALUE *other)
1400
1524
  TypedData_Get_Struct(*self, CArray, &carray_data_type, ca);
1401
1525
  TypedData_Get_Struct(*other, CArray, &carray_data_type, cb);
1402
1526
 
1403
- if ( ca->obj_type == CA_OBJ_UNBOUND_REPEAT ) {
1404
- *self = ca_ubrep_bind_with(*self, *other);
1405
- TypedData_Get_Struct(*self, CArray, &carray_data_type, ca);
1406
- }
1407
-
1408
- if ( cb->obj_type == CA_OBJ_UNBOUND_REPEAT ) {
1409
- *other = ca_ubrep_bind_with(*other, *self);
1410
- TypedData_Get_Struct(*other, CArray, &carray_data_type, cb);
1411
- }
1412
-
1413
1527
  /* Implicit size-1 broadcasting (case A only). No-op if either side
1414
1528
  is scalar, ndim differs, or shapes are already equal. If shapes
1415
1529
  are incompatible (neither side is 1 nor equal on some axis), also
@@ -1781,6 +1895,9 @@ rb_ca_cast_other (VALUE *self, volatile VALUE *other)
1781
1895
  if ( rb_ca_is_object_type(*self) ) {
1782
1896
  *other = rb_cscalar_new_with_value(CA_OBJECT, 0, *other);
1783
1897
  }
1898
+ else if ( ca_fixlen_scalar_operand(other, *self) ) {
1899
+ return; /* already the receiver's data_type and width */
1900
+ }
1784
1901
  else if ( rb_ca_is_float_type(*self) ) {
1785
1902
  *other = rb_cscalar_new_with_value(CA_FLOAT64, 0, *other);
1786
1903
  }
@@ -1806,11 +1923,6 @@ rb_ca_cast_other (VALUE *self, volatile VALUE *other)
1806
1923
 
1807
1924
  TypedData_Get_Struct(*other, CArray, &carray_data_type, cb);
1808
1925
 
1809
- if ( cb->obj_type == CA_OBJ_UNBOUND_REPEAT ) {
1810
- *other = ca_ubrep_bind_with(*other, *self);
1811
- TypedData_Get_Struct(*other, CArray, &carray_data_type, cb);
1812
- }
1813
-
1814
1926
  test1 = ca_cast_table[cb->data_type][ca->data_type];
1815
1927
 
1816
1928
  if ( test1 == 0 ) {
@@ -1845,8 +1957,8 @@ rb_ca_cast_with (VALUE self, VALUE other)
1845
1957
  }
1846
1958
 
1847
1959
  /* -----------------------------------------------------------------------
1848
- clip_<dtype> family — clip into the target dtype's representable
1849
- range, then cast. Sugar for `clip(lo, hi).as_<dtype>`.
1960
+ clip_<type> family — clip into the target data type's representable
1961
+ range, then cast. Sugar for `clip(lo, hi).as_<type>`.
1850
1962
  ----------------------------------------------------------------------- */
1851
1963
 
1852
1964
  #define CLIP_CAST_FUNC(name, lo_expr, hi_expr, cast_func) \
@@ -1873,7 +1985,7 @@ CLIP_CAST_FUNC(clip_uint32, INT2NUM(0), UINT2NUM(429496729
1873
1985
  an overflowing float source (e.g. 1e20) to 2^64 and the subsequent cast to
1874
1986
  uint64 wraps around to 0. For floating-point sources we take a saturating
1875
1987
  path: compare in float space against 2^64 (which IS representable) and
1876
- saturate to UINT64_MAX above it and 0 below zero. Other source dtypes use
1988
+ saturate to UINT64_MAX above it and 0 below zero. Other source data types use
1877
1989
  the plain clip-then-cast path. */
1878
1990
  static VALUE
1879
1991
  rb_ca_clip_uint64 (VALUE self)