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
@@ -25,6 +25,15 @@
25
25
  #define CARRAY_INTERNAL_H
26
26
 
27
27
  #include "carray.h"
28
+ #include <math.h> /* isnan, for CA_OBJ_ISNAN */
29
+
30
+ /* ---- properties a copy or a folded view must carry (ca_obj_refer.c) -------
31
+
32
+ Copies VALUE_ARRAY (dropping any mask), READ_ONLY and MASK_ARRAY from
33
+ `src` onto `view` when `src` has them, for arrays whose C parent chain
34
+ does not pass through `src`. Used by the folded reshape / flatten and by
35
+ CArray#initialize_dup / #initialize_clone. */
36
+ void ca_keep_chain_flags (CArray *view, CArray *src);
28
37
 
29
38
  /* ---- bulk bit pack / unpack (ca_obj_bitarray.c) --------------------------
30
39
 
@@ -54,13 +63,20 @@ void ca_bit_pack (const boolean8_t *src, ca_size_t elements, ca_size_t pbytes,
54
63
  The pool is global static state, so this is single-owner by construction.
55
64
  Thread-safety is a non-goal: operating on one array family from more than
56
65
  one thread is the caller's responsibility, not something this pool guards
57
- against. */
66
+ against.
67
+
68
+ A region that can raise -- one that transfers from a view, or calls Ruby
69
+ through an object lane -- goes through ca_lazy_arena_protect, never a
70
+ bare _enter / _exit pair: a skipped _exit is process-wide. */
58
71
 
59
72
  void ca_lazy_arena_enter (void);
60
73
  void ca_lazy_arena_exit (void);
61
74
  void *ca_lazy_arena_acquire (ca_size_t bytes);
62
75
  void *ca_lazy_arena_acquire_object (ca_size_t n_elements);
63
76
  void ca_lazy_arena_release (void *ptr);
77
+ VALUE ca_lazy_arena_protect (VALUE (*body)(VALUE),
78
+ VALUE (*cleanup)(VALUE), VALUE arg);
79
+ VALUE ca_lazy_arena_release_held (VALUE arg);
64
80
 
65
81
  /* ---- CA_OBJECT GC guard (carray_lazy.c) ----------------------------------
66
82
 
@@ -77,6 +93,67 @@ void ca_lazy_arena_release (void *ptr);
77
93
  int ca_gc_hold_push (void *ptr, ca_size_t n_elements);
78
94
  void ca_gc_hold_pop_to (int depth);
79
95
 
96
+ /* A buffer of object cells whose lifetime is not nested in the others' --
97
+ a kernel iterator's scratch lives from init to finish, and two walks
98
+ opened together may close in either order. Registered buffers are
99
+ marked until released, in any order; releasing one that was never
100
+ registered does nothing. The cells must be valid VALUEs when it is
101
+ registered. */
102
+ void ca_gc_hold_buffer (void *ptr, ca_size_t n_elements);
103
+ void ca_gc_release_buffer (void *ptr);
104
+
105
+ /* Copy the attributes src shows onto dst (a new entity with src's values). */
106
+ void rb_ca_inherit_attr (VALUE dst, VALUE src);
107
+
108
+ /* A String read as a decimal number of an integer or float data_type
109
+ (carray_cast.c): _to answers 1 / 0 (UNDEF), _store raises. */
110
+ int ca_decimal_string_to (VALUE str, int8_t data_type, void *out);
111
+ void ca_decimal_string_store (VALUE str, int8_t data_type, void *out);
112
+
113
+ /* Give `ca` a mask holding `m` (one byte per cell) when any cell is set,
114
+ and leave it without one otherwise. */
115
+ static inline void
116
+ ca_mask_from_bytes (CArray *ca, const boolean8_t *m)
117
+ {
118
+ ca_size_t i;
119
+ for (i = 0; i < ca->elements; i++) {
120
+ if ( m[i] ) {
121
+ ca_create_mask(ca);
122
+ memcpy(ca->mask->ptr, m, ca->elements);
123
+ return;
124
+ }
125
+ }
126
+ }
127
+
128
+ /* ---- Attaching several parents (carray_core.c) ---------------------------
129
+
130
+ ca_attach_all attaches all of list[0..n-1] or none: if one attach raises,
131
+ those already attached are detached before the raise propagates.
132
+
133
+ ca_sync_all syncs every one of list[0..n-1], carrying on past one that
134
+ raises so that the others still receive what was written, and raises
135
+ the first exception once all have been tried.
136
+
137
+ ca_attach_window opens list[0..n-1] ('r' attach, 'w' attach + sync,
138
+ 'a' allocate + sync), runs body(arg), and closes every array however body
139
+ leaves. Any window inside which Ruby runs or something raises goes
140
+ through it; see the definition for what a raise does to 'w' and 'a'. */
141
+
142
+ void ca_attach_all (CArray **list, int32_t n);
143
+ void ca_sync_all (CArray **list, int32_t n);
144
+ VALUE ca_attach_window (int32_t n, CArray **list, const char *modes,
145
+ VALUE (*body)(VALUE), VALUE arg);
146
+
147
+ /* ---- Filling a result Ruby does not own yet (carray_copy.c) ---------------
148
+
149
+ A C builder that allocates its result with carray_new / ca_template and
150
+ then reads the source into it holds a struct no Ruby object owns until
151
+ ca_wrap_struct. A read that raises (a lazy conversion) would leave it
152
+ behind. ca_fill_or_free runs fill(arg) under rb_protect and, if it
153
+ raises, frees `co` before the raise propagates. */
154
+
155
+ void ca_fill_or_free (CArray *co, VALUE (*fill)(VALUE), VALUE arg);
156
+
80
157
  /* Non-zero iff the object is an element-wise lazy view (CAMonOp / CABinOp /
81
158
  CABinCmp / CAMonCmp / CALazyMarker). The streaming branch of the
82
159
  mkkernel-generated reduction kernels tests this to decide whether it can
@@ -84,6 +161,98 @@ void ca_gc_hold_pop_to (int depth);
84
161
 
85
162
  int ca_is_lazy_view (void *ap);
86
163
 
164
+ /* The mask of an element-wise lazy operation over several operands
165
+ (CABinOp, CABinCmp, CATriOp), computed from the operands' masks on each
166
+ read so that it follows them as the values do; NULL when no operand has
167
+ a mask yet. `mode` is CA_LAZY_MASK_OR, one of the KLEENE modes for
168
+ the boolean `|` and `&`, whose masked cells an unmasked operand can
169
+ decide, or CA_LAZY_MASK_SELECT for select, masked where its condition
170
+ is or where the branch the condition chooses is (carray_lazy.c). */
171
+
172
+ #define CA_LAZY_MASK_OR 0
173
+ #define CA_LAZY_MASK_KLEENE_OR 1
174
+ #define CA_LAZY_MASK_KLEENE_AND 2
175
+ #define CA_LAZY_MASK_SELECT 3
176
+
177
+ CArray *ca_lazy_operation_mask (CArray *operation, int mode);
178
+
179
+ /* The array whose memory a view's cells live in: the entity at the end of
180
+ its parent chain, or the first view that has several parents
181
+ (carray_attribute.c). */
182
+ CArray *ca_root_array (void *ap);
183
+
184
+ /* Whether two arrays' cells live in the same root (carray_attribute.c). */
185
+ int ca_shares_root (void *ap, void *aq);
186
+
187
+ /* The create_mask slot of a view whose cells map one-to-one onto its
188
+ parent's in address order: the mask is the parent's mask seen in the
189
+ view's shape (carray_mask.c). Installed directly in operation tables. */
190
+
191
+ void ca_view_func_create_mask (void *ap);
192
+
193
+ /* Running count of the present cells of any data type along axis (Qnil:
194
+ the flattened array), read off the mask alone (carray_mask.c). The
195
+ cumcount kernel answers with it for a data type it does not load. */
196
+
197
+ VALUE rb_ca_scan_mask_count (VALUE self, VALUE axis);
198
+
199
+ /* The registered expression evaluator's answer for a lazy expression the
200
+ caller is about to compute whole, or Qnil to go on with self (see
201
+ carray_lazy.c). */
202
+
203
+ VALUE ca_lazy_evaluated (VALUE self);
204
+
205
+ /* A request to an element-wise lazy view (CAMonOp, CABinOp, CAMonCmp,
206
+ CABinCmp, CATriOp): either a region of the view's addresses -- the
207
+ xfer_stride form, strides in bytes of the view's cells -- or a list of
208
+ addresses. The view answers either with one evaluation: it pulls each
209
+ operand over the same cells with ca_lazy_req_pull and runs its kernel
210
+ once over the n cells (carray_lazy.c). */
211
+
212
+ typedef struct {
213
+ ca_size_t n;
214
+ ca_size_t *addrs; /* list form when non-NULL */
215
+ ca_size_t *starts, *counts, *strides; /* region form */
216
+ ca_size_t bytes; /* cell width the strides use */
217
+ int8_t ndim;
218
+ } ca_lazy_req_t;
219
+
220
+ void ca_lazy_req_region (ca_lazy_req_t *req, void *view, ca_size_t *starts,
221
+ ca_size_t *counts, ca_size_t *strides);
222
+ void ca_lazy_req_addrs (ca_lazy_req_t *req, ca_size_t n, ca_size_t *addrs);
223
+ int ca_lazy_req_is_packed (const ca_lazy_req_t *req, void *view);
224
+ void ca_lazy_req_pull (void *operand, const ca_lazy_req_t *req,
225
+ void *buf, int dir);
226
+ boolean8_t *ca_lazy_req_mask (const ca_lazy_req_t *req, int n, CArray **ops);
227
+ VALUE ca_lazy_settle_scalar (VALUE operand, int was_scalar);
228
+
229
+ /* Non-zero iff the array a view's cells come from -- the parent, or the
230
+ root a CAStride-family parent folds to -- computes them rather than
231
+ lending memory (ca_obj_stride.c). Depends only on what the arrays are,
232
+ never on whether they are attached, so the attach / sync / detach slots
233
+ of one view all take the same branch. */
234
+
235
+ int ca_parent_lends_no_memory (void *ap);
236
+
237
+ /* Transfers of the descriptor views (CAGrid, CASelect, CASelectAxis,
238
+ CAWindow) whose parent holds no ptr (ca_axis_dispatch.c).
239
+
240
+ ca_axis_view_xfer_all serves an xfer_all slot: `fast` is the view's
241
+ transfer against parent->ptr, and region_ok says whether the view's
242
+ xfer_stride answers a whole-view request without going cell by cell.
243
+ ca_axis_view_attach_owned / ca_axis_view_sync_owned are the attach and
244
+ sync of such a view over a parent with no memory to lend: the view owns
245
+ its buffer and the parent is never attached. attach_owned also serves
246
+ any view that owns its buffer and fills it through its own transfers
247
+ (CARemap, CAStack, CAMeld): it publishes the buffer only once filled. */
248
+
249
+ typedef void (*ca_axis_view_fast_t) (void *ap, char *data, int dir);
250
+
251
+ void ca_axis_view_xfer_all (void *ap, ca_axis_view_fast_t fast,
252
+ int region_ok, void *data, int dir);
253
+ void ca_axis_view_attach_owned (void *ap);
254
+ void ca_axis_view_sync_owned (void *ap);
255
+
87
256
  /* ---- per-obj_type view constructors --------------------------------------
88
257
 
89
258
  Constructors for view types that only carray itself builds. Ruby-side
@@ -112,6 +281,9 @@ void ca_block_sync_base_offset (CABlock *cb);
112
281
  /* ca_obj_select.c */
113
282
  VALUE rb_ca_select_new (VALUE cary, VALUE select);
114
283
  VALUE rb_ca_select_new_share (VALUE cary, VALUE select);
284
+ /* An owned, unmasked copy of a boolean selector: a masked cell becomes
285
+ false. Shared by CASelect and CASelectAxis. */
286
+ CArray *ca_select_snapshot (CArray *select);
115
287
 
116
288
  /* ca_obj_mapping.c */
117
289
  VALUE rb_ca_mapping_new (VALUE cary, CArray *mapper);
@@ -132,5 +304,232 @@ CAReduce *ca_reduce_new (CArray *carray, ca_size_t count, ca_size_t offset);
132
304
 
133
305
  /* carray_broadcast.c */
134
306
  void ca_broadcast_to_destination (VALUE dst, volatile VALUE *src);
307
+ VALUE rb_ary_flatten_for_elements (VALUE ary, ca_size_t elements, void *ap);
308
+
309
+ /* carray_utils.c */
310
+ const char *ca_calling_method_name (void);
311
+ VALUE ca_answer_as_caller (VALUE (*body)(VALUE), VALUE arg);
312
+ long ca_integer_arg (VALUE v, const char *arg, const char *name);
313
+ ca_size_t ca_shape_elements (int8_t ndim, const ca_size_t *dim, ca_size_t bytes);
314
+ void ca_check_index_array (VALUE v);
315
+ void ca_check_integer_fits (VALUE v, int8_t data_type);
316
+ int ca_integer_range_side (VALUE v, int8_t data_type);
317
+ int ca_bincmp_integer_prepare (volatile VALUE *self, volatile VALUE *other,
318
+ int op_id, int *signed_side);
319
+ int ca_bincmp_answer_when_negative (int op_id, int signed_side);
320
+ long ca_axis_integer (VALUE raxis, const char *name);
321
+ VALUE ca_fill_as (VALUE fill, int8_t data_type);
322
+ /* ---- Face MemoryView export (ca_obj_face.c) -------------------------------
323
+
324
+ A Face registers 1 when its storage bytes carry its values without the
325
+ Face (CARecord, CAFixlenString); the MemoryView producer refuses every
326
+ other Face. Unregistered Faces are refused. */
327
+
328
+ void ca_face_register_memory_view (int obj_type, int exportable);
329
+ int ca_face_memory_view_exportable (CArray *ca);
330
+
331
+ /* ---- Empty regions ---------------------------------------------------------
332
+
333
+ A region with a zero count on some axis has no cells. The per-cell walks
334
+ visit their first cell before they test the counts, so every region
335
+ transfer returns on an empty region before it walks: a zero-cell caller
336
+ buffer has no room for that first cell. */
337
+
338
+ static inline int
339
+ ca_region_is_empty (int8_t ndim, const ca_size_t *counts)
340
+ {
341
+ int8_t k;
342
+ for ( k = 0; k < ndim; k++ ) {
343
+ if ( counts[k] <= 0 ) return 1;
344
+ }
345
+ return 0;
346
+ }
347
+
348
+ /* ---- An index into n places ----------------------------------------------
349
+
350
+ A negative index counts from the end; one outside 0...n after that raises
351
+ IndexError, naming the method the user called, `what` the index is (an
352
+ "index", an "address") and the value given. Every index door decides
353
+ this here. */
354
+
355
+ /* ca_index_out_of_range is declared in carray.h (CA_CHECK_INDEX uses it). */
356
+
357
+ static inline ca_size_t
358
+ ca_index_in_range (ca_size_t idx, ca_size_t n, const char *what)
359
+ {
360
+ ca_size_t i = ( idx < 0 ) ? idx + n : idx;
361
+ if ( i < 0 || i >= n ) {
362
+ ca_index_out_of_range(idx, n, what);
363
+ }
364
+ return i;
365
+ }
366
+
367
+ /* The same for an index on axis `axis` of a multi-axis index. */
368
+ NORETURN(void ca_index_out_of_range_at (ca_size_t idx, ca_size_t n, int axis));
369
+
370
+ static inline ca_size_t
371
+ ca_index_in_range_at (ca_size_t idx, ca_size_t n, int axis)
372
+ {
373
+ ca_size_t i = ( idx < 0 ) ? idx + n : idx;
374
+ if ( i < 0 || i >= n ) {
375
+ ca_index_out_of_range_at(idx, n, axis);
376
+ }
377
+ return i;
378
+ }
379
+
380
+ /* ---- How many cells a result cell needs ---------------------------------
381
+
382
+ A reduction's result cell is UNDEF when fewer cells contribute to it than
383
+ it needs. It needs `least` cells -- 0 for an operation with an identity
384
+ (sum, prod, accumulate, count, wsum: an empty cell is the identity), 1 for
385
+ one without (mean, min, max, median, ...), 2 for a sample variance -- or
386
+ `min_count` cells when that is given and asks for more. A min_count below
387
+ zero means it was not given. Every reduction decides this here. */
388
+
389
+ static inline int
390
+ ca_too_few_present (ca_size_t present, ca_size_t min_count, ca_size_t least)
391
+ {
392
+ return present < ( min_count > least ? min_count : least );
393
+ }
394
+
395
+ long ca_min_count_arg (VALUE v, const char *name);
396
+ VALUE ca_reduce_fill (VALUE result, VALUE fill, int whole);
397
+ int ca_symbol_choice (VALUE v, const char *arg, const char *c0,
398
+ const char *c1, const char *name);
399
+
400
+ /* Return the value of `call`, keeping the array `v` reachable until the call
401
+ has returned. A kernel reads its source through the CArray pointer only,
402
+ so a view made just to be passed in (a flattened or common-type view)
403
+ would otherwise be left to a garbage collection that runs while its
404
+ cells are read: `return kernel(v, ...)` lets the compiler drop `v`. */
405
+ #define CA_RETURN_KEEPING(v, call) do { \
406
+ VALUE ca_kept_result_ = (call); \
407
+ RB_GC_GUARD(v); \
408
+ return ca_kept_result_; \
409
+ } while (0)
410
+
411
+ /* A NaN loses every contest of an extremum (min / max / minmax / the
412
+ positions / the running cummin / cummax / pmin / pmax): it never displaces
413
+ another value, the first number displaces it, and nothing but NaN answers
414
+ NaN. The two tests below are that rule for a typed cell and for an object
415
+ cell (a stored Float NaN); each says whether `v` takes the place of the
416
+ running `acc`. CMP / op is `>` for a maximum, `<` for a minimum. On an
417
+ integer type `v == v` is always true and folds away. */
418
+
419
+ #define CA_EXTREMUM_REPLACES(v, acc, CMP) \
420
+ ( (v) == (v) && ( !((acc) == (acc)) || (v) CMP (acc) ) )
421
+
422
+ #ifndef CA_OBJ_ISNAN
423
+ #define CA_OBJ_ISNAN(v) (RB_FLOAT_TYPE_P(v) && isnan(RFLOAT_VALUE(v)))
424
+ #endif
425
+
426
+ /* A pair `<=>` cannot order: ArgumentError "<method>: comparison of A with
427
+ B failed", naming the method the user called. Every object comparison
428
+ that refuses a pair raises through here. */
429
+ NORETURN(void ca_obj_compare_refused (VALUE a, VALUE b));
430
+
431
+ /* The order of two object cells, by `<=>` as Array#min and #sort take it. */
432
+ static inline int
433
+ ca_obj_cmp (VALUE a, VALUE b)
434
+ {
435
+ VALUE r = rb_funcall(a, rb_intern("<=>"), 1, b);
436
+ if ( NIL_P(r) ) {
437
+ ca_obj_compare_refused(a, b);
438
+ }
439
+ return rb_cmpint(r, a, b);
440
+ }
441
+
442
+ /* op names the contest: `<` for a minimum, `>` for a maximum. */
443
+ static inline int
444
+ ca_obj_extremum_replaces (VALUE v, VALUE acc, ID op)
445
+ {
446
+ int c;
447
+ if ( CA_OBJ_ISNAN(v) ) return 0;
448
+ if ( CA_OBJ_ISNAN(acc) ) return 1;
449
+ c = ca_obj_cmp(v, acc);
450
+ return ( op == rb_intern("<") ) ? ( c < 0 ) : ( c > 0 );
451
+ }
452
+
453
+ /* The mask a multi-parent view (CAStack, CAMeld) composes for parent `p`:
454
+ p's own mask when it has one. A parent without one gets an all-false
455
+ stand-in, stored in *standin for the view to free, so that asking the
456
+ view about its mask does not give the parent a mask. The stand-in of a
457
+ read-only (or frozen) parent is read-only. The stand-in of a value
458
+ array or a mask array, which can never carry a mask, stays in place and
459
+ takes writes; writing false into it changes nothing, and a true written
460
+ into it is refused by ca_multi_parent_mask_check. */
461
+ CArray *ca_multi_parent_mask (CArray *p, CArray **standin);
462
+
463
+ /* Let the stand-ins of a multi-parent view's mask give way to the parents'
464
+ own masks. `mask` is the view's mask (a CAStack or CAMeld over the
465
+ parents' masks), `parents` / `standins` the view's. A writable stand-in
466
+ is replaced when its parent has gained a mask, or, with for_write, by a
467
+ mask created on the parent. The mask's own transfer functions call this
468
+ on entry; it does nothing inside an attach window. */
469
+ void ca_multi_parent_mask_refresh (CArray *mask, CArray **parents,
470
+ CArray **standins, int32_t n,
471
+ int for_write);
472
+
473
+ /* After a write to a multi-parent view's mask: a true written into the
474
+ stand-in of a value array or a mask array is cleared again and refused
475
+ with the TypeError a direct write would raise. The parts of the write
476
+ that went to other parents stay written. */
477
+ void ca_multi_parent_mask_check (CArray *mask, CArray **parents,
478
+ CArray **standins, int32_t n);
479
+
480
+ /* After a write inside an attach window, which went into the stand-ins
481
+ the window was opened with: move what was written into a stand-in to a
482
+ mask created on its parent. The next refresh then reads the parent's
483
+ mask in its place. */
484
+ void ca_multi_parent_mask_settle (CArray *mask, CArray **parents,
485
+ CArray **standins, int32_t n);
486
+
487
+ /* The common-type rules the operators, result_type and the search family
488
+ share (ext/carray_cast.c): the type a scalar `obj` of type `st` takes
489
+ beside an array of type `at`, and the type two types are matched for
490
+ equality in (a mixed-sign integer pair widened so that each value is
491
+ kept). */
492
+ int8_t ca_promote_scalar_type (int8_t at, VALUE obj, int8_t st);
493
+ int8_t ca_value_match_type (int8_t t, int8_t a, int8_t b);
494
+
495
+ /* Equality of two object cells, as the float lanes answer it: Ruby's `==`,
496
+ except that a Float NaN equals nothing, itself included. rb_equal alone
497
+ answers true for the same object, so whether two NaN cells matched would
498
+ depend on whether they held one Float or two. (The value-hash family --
499
+ unique / is_in / the set operations -- folds every NaN into one value
500
+ instead, in its own hash.) */
501
+ static inline int
502
+ ca_obj_equal (VALUE a, VALUE b)
503
+ {
504
+ if ( CA_OBJ_ISNAN(a) ) return 0;
505
+ return RTEST(rb_equal(a, b));
506
+ }
507
+
508
+ /* ---- fast paths (carray_core.c) --------------------------------------------
509
+
510
+ A fast path answers what a general path also answers, by a different
511
+ algorithm. Each one tests ca_fast_paths_enabled() alongside its own
512
+ condition, so a development build run with CARRAY_GENERAL_PATH=1 in the
513
+ environment takes the general path everywhere and the test suite
514
+ compares the two. A release build has no switch: the test is the
515
+ constant 1 and costs nothing.
516
+
517
+ A branch that only lends a pointer, or drops to memcpy when the data is
518
+ contiguous, runs the same code either way and does not test this.
519
+
520
+ ---------------------------------------------------------------------------- */
521
+
522
+ #ifdef CARRAY_DEV_BUILD
523
+ extern int ca_fast_paths_on;
524
+ #define ca_fast_paths_enabled() (ca_fast_paths_on)
525
+ #else
526
+ #define ca_fast_paths_enabled() (1)
527
+ #endif
528
+
529
+ /* A logical operator between a boolean array and an object array reads the
530
+ boolean cells as true / false (carray_operator.c). Shared by the eager
531
+ binop and the lazy builder. */
532
+ void ca_binop_read_boolean_as_truth (int logical, volatile VALUE *pa,
533
+ volatile VALUE *pb);
135
534
 
136
535
  #endif /* CARRAY_INTERNAL_H */