carray 3.0.3 → 3.0.4

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 (212) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +264 -0
  3. data/README.md +3 -2
  4. data/carray.gemspec +1 -1
  5. data/ext/ca_axis_descriptor.h +27 -24
  6. data/ext/ca_axis_dispatch.c +1 -6
  7. data/ext/ca_axis_group.c +27 -27
  8. data/ext/ca_binop_dispatch.c +1 -29
  9. data/ext/ca_binop_dispatch.h +0 -1
  10. data/ext/ca_categorical_iterator.c +205 -134
  11. data/ext/ca_compare.c +7 -18
  12. data/ext/ca_group_iter.c +16 -17
  13. data/ext/ca_kernel_iterator.c +1234 -1994
  14. data/ext/ca_kernel_iterator.h +391 -437
  15. data/ext/ca_monop_dispatch.c +82 -59
  16. data/ext/ca_monop_dispatch.h +1 -0
  17. data/ext/ca_obj_array.c +96 -39
  18. data/ext/ca_obj_bincmp.c +24 -21
  19. data/ext/ca_obj_binop.c +15 -26
  20. data/ext/ca_obj_bitarray.c +3 -2
  21. data/ext/ca_obj_bitfield.c +5 -6
  22. data/ext/ca_obj_block.c +18 -9
  23. data/ext/ca_obj_byte_swap.c +5 -6
  24. data/ext/ca_obj_const_string.c +173 -19
  25. data/ext/ca_obj_face.c +238 -57
  26. data/ext/ca_obj_face.h +19 -0
  27. data/ext/ca_obj_fake.c +15 -29
  28. data/ext/ca_obj_farray.c +6 -3
  29. data/ext/ca_obj_field.c +17 -5
  30. data/ext/ca_obj_fixlen_string.c +2 -3
  31. data/ext/ca_obj_grid.c +406 -132
  32. data/ext/ca_obj_meld.c +172 -34
  33. data/ext/ca_obj_moncmp.c +23 -8
  34. data/ext/ca_obj_monop.c +67 -57
  35. data/ext/ca_obj_object.c +157 -51
  36. data/ext/ca_obj_record.c +12 -7
  37. data/ext/ca_obj_reduce.c +13 -8
  38. data/ext/ca_obj_refer.c +25 -27
  39. data/ext/ca_obj_remap.c +30 -9
  40. data/ext/ca_obj_repeat.c +9 -10
  41. data/ext/ca_obj_roll.c +6 -5
  42. data/ext/ca_obj_select.c +14 -9
  43. data/ext/ca_obj_select_axis.c +15 -47
  44. data/ext/ca_obj_shift.c +11 -1
  45. data/ext/ca_obj_stack.c +179 -34
  46. data/ext/ca_obj_stride.c +162 -115
  47. data/ext/ca_obj_string.c +71 -4
  48. data/ext/ca_obj_tile.c +6 -5
  49. data/ext/ca_obj_time.c +22 -6
  50. data/ext/ca_obj_timedelta.c +22 -6
  51. data/ext/ca_obj_transpose.c +5 -3
  52. data/ext/ca_obj_triop.c +23 -32
  53. data/ext/ca_obj_window.c +190 -26
  54. data/ext/ca_sweep_engine.c +2 -2
  55. data/ext/caframe_csv_reader.c +80 -1
  56. data/ext/carray.h +181 -75
  57. data/ext/carray_access.c +184 -96
  58. data/ext/carray_address_basis.c +343 -87
  59. data/ext/carray_attribute.c +89 -6
  60. data/ext/carray_bincount.c +10 -8
  61. data/ext/carray_broadcast.c +13 -8
  62. data/ext/carray_build_flags.h +3 -0
  63. data/ext/carray_call_cfunc.c +108 -0
  64. data/ext/carray_cast.c +142 -24
  65. data/ext/carray_cast_func.rb +46 -6
  66. data/ext/carray_class.c +4 -3
  67. data/ext/carray_config.h +28 -0
  68. data/ext/carray_conversion.c +16 -7
  69. data/ext/carray_copy.c +51 -14
  70. data/ext/carray_core.c +147 -55
  71. data/ext/carray_count.c +50 -20
  72. data/ext/carray_element.c +76 -33
  73. data/ext/carray_factorize.c +118 -64
  74. data/ext/carray_generate.c +191 -50
  75. data/ext/carray_histogram.c +62 -17
  76. data/ext/carray_hold.c +12 -15
  77. data/ext/carray_index_classifier.c +388 -176
  78. data/ext/carray_internal.h +336 -29
  79. data/ext/carray_kernels_bincmp.c +4453 -0
  80. data/ext/carray_kernels_binop.c +11368 -0
  81. data/ext/carray_kernels_init.c +1734 -0
  82. data/ext/carray_kernels_moncmp.c +2104 -0
  83. data/ext/carray_kernels_monop.c +18369 -0
  84. data/ext/carray_kernels_reduce_aggregate.c +23818 -0
  85. data/ext/carray_kernels_reduce_boolean.c +406 -0
  86. data/ext/carray_kernels_reduce_cumulative.c +10086 -0
  87. data/ext/carray_kernels_reduce_extreme.c +17634 -0
  88. data/ext/carray_kernels_reduce_variance.c +3849 -0
  89. data/ext/carray_kernels_scan.c +4302 -0
  90. data/ext/carray_kernels_search.c +33829 -0
  91. data/ext/carray_kernels_sort.c +10906 -0
  92. data/ext/carray_kernels_triop.c +1864 -0
  93. data/ext/carray_key_windows.c +216 -0
  94. data/ext/carray_lazy.c +170 -111
  95. data/ext/carray_mask.c +292 -72
  96. data/ext/carray_median_percentile.c +82 -28
  97. data/ext/carray_memory_view.c +669 -561
  98. data/ext/carray_operator.c +124 -47
  99. data/ext/carray_order.c +384 -76
  100. data/ext/carray_partition.c +28 -27
  101. data/ext/carray_random.c +67 -13
  102. data/ext/carray_round.c +273 -0
  103. data/ext/carray_scatter.c +63 -38
  104. data/ext/carray_segment.c +3 -3
  105. data/ext/carray_slab.c +91 -28
  106. data/ext/carray_sort.c +35 -35
  107. data/ext/carray_struct.c +19 -18
  108. data/ext/carray_test.c +26 -5
  109. data/ext/carray_undef.c +4 -0
  110. data/ext/carray_utils.c +246 -45
  111. data/ext/mk_call_cfunc.rb +19 -2
  112. data/ext/mkkernel.rb +198 -240
  113. data/ext/ruby_carray.c +10 -4
  114. data/ext/version.h +4 -4
  115. data/lib/carray/attribute.rb +126 -22
  116. data/lib/carray/autoload_carray.rb +8 -31
  117. data/lib/carray/autoload_method_extension.rb +14 -5
  118. data/lib/carray/axis_group.rb +255 -106
  119. data/lib/carray/basics.rb +78 -10
  120. data/lib/carray/bincount_nd.rb +12 -2
  121. data/lib/carray/block_iterator.rb +126 -23
  122. data/lib/carray/boolean_reduce.rb +17 -17
  123. data/lib/carray/categorical.rb +165 -43
  124. data/lib/carray/categorical_iterator.rb +130 -27
  125. data/lib/carray/complex.rb +5 -5
  126. data/lib/carray/conditional.rb +67 -18
  127. data/lib/carray/const_string.rb +14 -5
  128. data/lib/carray/construct.rb +15 -11
  129. data/lib/carray/data_type_extension.rb +1 -0
  130. data/lib/carray/distance_limit.rb +77 -0
  131. data/lib/carray/fixlen_string.rb +7 -1
  132. data/lib/carray/frame/column_verbs.rb +70 -0
  133. data/lib/carray/frame/convert.rb +69 -0
  134. data/lib/carray/frame/csv_parser.rb +111 -17
  135. data/lib/carray/frame/describe.rb +3 -2
  136. data/lib/carray/frame/frame.rb +246 -21
  137. data/lib/carray/frame/group.rb +510 -95
  138. data/lib/carray/frame/io.rb +115 -28
  139. data/lib/carray/frame/join.rb +312 -51
  140. data/lib/carray/frame/records.rb +83 -7
  141. data/lib/carray/frame/reshape.rb +42 -35
  142. data/lib/carray/frame/sort.rb +7 -19
  143. data/lib/carray/frame/verbs.rb +188 -48
  144. data/lib/carray/frame/windows.rb +117 -0
  145. data/lib/carray/frame.rb +2 -0
  146. data/lib/carray/fuse_source.rb +11 -4
  147. data/lib/carray/fusion.rb +40 -16
  148. data/lib/carray/histogram.rb +6 -1
  149. data/lib/carray/inspect.rb +31 -8
  150. data/lib/carray/iterator.rb +85 -7
  151. data/lib/carray/key_windows.rb +620 -0
  152. data/lib/carray/lazy.rb +182 -183
  153. data/lib/carray/mask_gap_fill.rb +63 -57
  154. data/lib/carray/meld_reduce.rb +12 -14
  155. data/lib/carray/methods/bin.rb +26 -18
  156. data/lib/carray/methods/bincount.rb +16 -0
  157. data/lib/carray/methods/bit_string.rb +1 -1
  158. data/lib/carray/methods/choose.rb +16 -3
  159. data/lib/carray/methods/composition.rb +3 -1
  160. data/lib/carray/methods/gather_nd.rb +14 -5
  161. data/lib/carray/methods/insert_block.rb +2 -2
  162. data/lib/carray/methods/is_between.rb +59 -0
  163. data/lib/carray/methods/is_in.rb +53 -36
  164. data/lib/carray/methods/join.rb +1 -6
  165. data/lib/carray/methods/lag.rb +49 -0
  166. data/lib/carray/methods/locate_addr.rb +47 -51
  167. data/lib/carray/methods/mode.rb +1 -1
  168. data/lib/carray/methods/nunique.rb +11 -6
  169. data/lib/carray/methods/resize.rb +3 -3
  170. data/lib/carray/methods/value_counts.rb +4 -11
  171. data/lib/carray/record_order.rb +3 -3
  172. data/lib/carray/rng.rb +3 -0
  173. data/lib/carray/runtime.rb +53 -8
  174. data/lib/carray/segment_iterator.rb +313 -82
  175. data/lib/carray/serialize.rb +24 -10
  176. data/lib/carray/slab_iterator.rb +50 -0
  177. data/lib/carray/string.rb +105 -5
  178. data/lib/carray/string_operation_extension.rb +8 -1
  179. data/lib/carray/struct.rb +9 -21
  180. data/lib/carray/struct_builder.rb +19 -8
  181. data/lib/carray/time.rb +726 -104
  182. data/lib/carray/window_iterator.rb +122 -16
  183. data/lib/carray.rb +7 -0
  184. data/yard-stubs/ca_obj_bitfield.rb +1 -1
  185. data/yard-stubs/ca_obj_field.rb +4 -0
  186. data/yard-stubs/ca_obj_grid.rb +21 -10
  187. data/yard-stubs/ca_obj_refer.rb +2 -1
  188. data/yard-stubs/ca_obj_roll.rb +2 -2
  189. data/yard-stubs/ca_obj_shift.rb +5 -1
  190. data/yard-stubs/ca_obj_tile.rb +1 -1
  191. data/yard-stubs/ca_obj_window.rb +8 -3
  192. data/yard-stubs/carray_access.rb +6 -1
  193. data/yard-stubs/carray_attribute.rb +0 -5
  194. data/yard-stubs/carray_cast.rb +10 -0
  195. data/yard-stubs/carray_conversion.rb +2 -1
  196. data/yard-stubs/carray_copy.rb +4 -2
  197. data/yard-stubs/carray_count.rb +4 -4
  198. data/yard-stubs/carray_element.rb +10 -4
  199. data/yard-stubs/carray_generate.rb +21 -1
  200. data/yard-stubs/carray_mask.rb +26 -2
  201. data/yard-stubs/carray_math.rb +27 -1
  202. data/yard-stubs/carray_median_percentile.rb +5 -2
  203. data/yard-stubs/carray_memory_view.rb +40 -23
  204. data/yard-stubs/carray_order.rb +29 -18
  205. data/yard-stubs/carray_random.rb +13 -4
  206. data/yard-stubs/carray_scatter.rb +14 -9
  207. data/yard-stubs/carray_slab.rb +9 -2
  208. data/yard-stubs/carray_sort.rb +6 -5
  209. data/yard-stubs/carray_test.rb +5 -3
  210. metadata +25 -3
  211. data/lib/carray/arrow_tensor.rb +0 -401
  212. data/lib/carray/table.rb +0 -108
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 76ca6c2983cbd1e07acc64daeedc7328bee9239369f56f3af661ed1cc41e0bfb
4
- data.tar.gz: 1506fa95c68148469451631fb375826e2599a979b4593db8c7508cf16d3c7545
3
+ metadata.gz: d2edeb545754cf31d330c667913471c1a0035c97de72dabad7e7b2afb4fe272b
4
+ data.tar.gz: 8b34390fcabbb04c5e1f0926ae103052345196112ec3a6a16f244fb310df5583
5
5
  SHA512:
6
- metadata.gz: 66a3078a1bdd6459ab0c7526a588cc81191a4e043a17028b769b87b5d32874a9fd20c2b4828217dfa573457871f476155d005db518da600bbef38baca5551eb8
7
- data.tar.gz: 23479b0a9b229489ff5ed1afa7fdc0a30150b9d3ba32803b089f1f9e5d7a955cd556c478c7cb5346e516830632a4ba35cb54d186f54a783b589d7cabec9498d5
6
+ metadata.gz: 0f7430ff0556faf7b609673fb8cf9ef08279e226192995ea58a5dd203e5285733582c5cff0405fc753c39cad7056acd9194f55ba26ce9eb1d1a27cf1de8e37f0
7
+ data.tar.gz: 48d35829402ba2949e865712d8aa89dd9d4228f0ca4abf62719d3b2d32280541d1c6b7b01dba3e2a68927a89e258e0d6b474a20fc6177415154e1ab57f2b380d
data/CHANGELOG.md CHANGED
@@ -34,6 +34,270 @@ and a newer one. The 1.x history, up to the 2.0.0 release, is in
34
34
  neighbour ("as well", "the producer above") or leave unnamed the
35
35
  method, class or keyword it is about. -->
36
36
 
37
+ ## 3.0.4
38
+
39
+ - New: `CAFrame#verify(rules)` judges every row against named rules (each
40
+ a callable that returns a boolean CArray) and returns the verdicts as a
41
+ frame, one column per rule; a row whose rule read a masked value is
42
+ `UNDEF`, so `count(false)` counts the rows that break it.
43
+
44
+ - New: `CAFrame#join` takes `how: :semi` and `:anti` (the left rows that
45
+ have, or have no, match), several key columns (`on: ["station",
46
+ "date"]`), and the index as a key by the row axis name.
47
+ `CAFrame#join_asof` takes the index too, and `by:` columns that must
48
+ match exactly before the nearest key is taken.
49
+
50
+ - New: a `CAFrame` grouping has more verbs. The short form of `prod`,
51
+ `accumulate`, `median`, `variance`, `stddev`, `variancep`, `stddevp`,
52
+ `first`, `last`, `nunique`, `count`, `all` and `any`, beside `sum` /
53
+ `mean` / `min` / `max`; `filter` (keep the groups a block chooses);
54
+ `lag`, `order`, `cumsum` and the other running values, and
55
+ `fill(name, :ffill)` / `:bfill`, all kept on the frame's rows; and
56
+ `to_frame`. The reductions take column names (`grp.mean("temp")` is a
57
+ CArray) and `keep_rows: true`, which gives each row its own group's
58
+ result.
59
+
60
+ - New: `CAFrame#resample` takes `by:`, columns whose groups are binned
61
+ apart: `df.resample("time", "1 day", by: "station").max("temp")`.
62
+
63
+ - New: `CArray#windows(on:, before:, after:)` bounds each window by a
64
+ width of a key (a time, a duration or a number) instead of a count of
65
+ cells, with `by:`, `exclude:`, `interval:` and `at:` (windows placed at
66
+ given points, which may overlap). The key need not be sorted, and the
67
+ value may have several columns (shape `(N, ...)`). `CAFrame#windows(on:
68
+ "time", ...)` does the same for a frame's columns.
69
+
70
+ - New: `CArray#lag(n = 1, axis:)` is the value `n` steps earlier along an
71
+ axis, `UNDEF` where there is none, so `x - x.lag` starts with `UNDEF`.
72
+
73
+ - New: the slab, block, segment, categorical and axis-group iterators
74
+ have `lag`, `order` (each cell's rank within its piece) and
75
+ `strip_mask(method: :ffill / :bfill)`; each of them works within one
76
+ piece and never takes a value from another. Every iterator has `first`,
77
+ `last` and `nunique`.
78
+
79
+ - New: `CArray#is_between(lo, hi, exclude:)` (or a Range) is true where a
80
+ value lies between two bounds; `exclude: :lower`, `:upper` or `:both`
81
+ leaves bounds out, and `nil` or an open end leaves a side unbounded.
82
+
83
+ - New: `CArray#round(ndigits)` rounds each element to `ndigits` decimal
84
+ places (negative for tens, hundreds, ...), as `Float#round` and
85
+ `Integer#round` do.
86
+
87
+ - New: `CArray#to_frame(*names, axis: -1)` shows an array as a CAFrame
88
+ whose columns are views of it, one per position along `axis`.
89
+
90
+ - New: `CACategorical#contrast(base:, full:)` gives one int8 column per
91
+ category (1 in the cell's category, the base left out unless `full:
92
+ true`), and `CAFrame#contrast_columns(name, ...)` puts those columns in
93
+ the frame in place of the categorical.
94
+
95
+ - New: `CAFrame#is_duplicate(*names, except:)` is true for the rows that
96
+ repeat an earlier row in the named columns; `except: :last` or `:none`
97
+ chooses which occurrence stays unmarked.
98
+
99
+ - New: `CAFrame#append(name, col, before:, after:)` puts the column next
100
+ to another one.
101
+
102
+ - New: a `CAFrame` carries attributes of the frame as a whole (`attr`,
103
+ `set_attr`, `attrs`, ..., and `CAFrame.new(..., attrs:)`), separate from
104
+ each column's. A row selection or a change of columns keeps them; a
105
+ summary, a join or a reshape does not.
106
+
107
+ - New: `CAFrame#to_csv(attrs: [:units, ...])` writes one line per
108
+ attribute key below the names, and `CAFrame.from_csv(attrs: [...])`
109
+ reads them back as column attributes; in a reading block,
110
+ `r.header(:units)` does the same for a line anywhere in the header.
111
+
112
+ - New: `CAFrame.from_csv` `columns:` takes a Hash that selects and names
113
+ columns, and the names `c0`, `c1`, ... of a file without a header;
114
+ `cast` and `from_csv` `types:` take `:categorical`. `CAFrame.new` takes
115
+ `types:` and `on_error:`, as `from_records` does.
116
+
117
+ - New: `CArray#delete_attr(key)` removes an attribute and returns its
118
+ value.
119
+
120
+ - New: `CATime#end_of(unit:, origin:)` (the last tick of each time's
121
+ bucket), `days_in_month`, `quarter`, and the ISO 8601 week `iso_week`
122
+ with its year `iso_year`.
123
+
124
+ - New: a time or duration array takes a single value in `+` and `-`
125
+ (`t + "3 days"`, `t - t.min`, `t - Time.utc(2024, 1, 1)`), and a month
126
+ or year duration moves a time on a day or finer grid as `Date#>>` does
127
+ (`2024-01-31 + 1 month` is `2024-02-29`). A bare number is still
128
+ refused.
129
+
130
+ - New: a time array compares with a value off its grid (`days.eq(
131
+ "2024-01-03T05:00")`, `<`, `search_nearest`, `is_in`, ...) in the finer
132
+ unit the two share, where it raised `ArgumentError`. An assignment
133
+ still raises.
134
+
135
+ - New: `CATime#pmax` / `pmin` (and `maximum` / `minimum` / `fmax` /
136
+ `fmin`) give the later / earlier time cell by cell.
137
+
138
+ - New: CArray can be used in a Ractor other than the main one, `fuse`
139
+ included, and a frozen array is shared between Ractors without
140
+ copying. See `docs/topics/Ractor.md`.
141
+
142
+ - New: C extensions: `CA_FOR_EACH_WHOLE` and `CA_FOR_EACH_WHOLE_MASKED`
143
+ hand a kernel the whole array as one contiguous run.
144
+
145
+ - Change: `CArray#rank` is removed; use `#ndim`.
146
+
147
+ - Change: `CArray::TableMethods` (`column_names=`, `column`, `row`, `rows`
148
+ and `select` on a 2-D array) is removed; use `a.to_frame("x", "y")`,
149
+ then `df["x"]` for a column or `df.to_records[i]` for a row.
150
+
151
+ - Change: `CArray.load_arrow_tensor`, `CArray#save_arrow_tensor` and
152
+ `CArray::ArrowTensor`, the experimental Arrow tensor IPC reader and
153
+ writer, are removed.
154
+
155
+ - Change: methods whose names start and end with `__` that were public
156
+ internals are now private, renamed or removed. Call the public method
157
+ they served instead.
158
+
159
+ - Change: CAFrame takes column names as Strings only. A Symbol name
160
+ (`df.drop(:a)`, `join(on: :a)`, `CAFrame.new(axis_name: :row)`) raises
161
+ `TypeError`; write `"a"`. Record keys given to `from_records` may still
162
+ be Symbols, and `df[:x]` stays the predicate syntax.
163
+
164
+ - Change: a masked cell of an integer index array keeps its place:
165
+ `x[i]`, the grid forms and `CAFrame` row selection `df[i]` give a
166
+ result shaped like `i`, `UNDEF` where `i` is masked, where they dropped
167
+ those positions. To drop them as before, index by
168
+ `i[i.is_not_masked]`.
169
+
170
+ - Change: an index beside a CArray key is read as it is without one: a
171
+ range ending before its start reads backwards (`a[i, -1..1]`), and an
172
+ Integer key drops its axis (`a[i, 1]` has the shape of `i`; add `:_`
173
+ or use `1..1` to keep it).
174
+
175
+ - Change: an index with a Float that has a fraction (`a[1.5..3]`, a step
176
+ of `0.5`) raises `IndexError`; it was cut to an integer. Convert with
177
+ `to_i` or `round` first. A Float that holds an integer, such as a count
178
+ from `sum`, is still that position.
179
+
180
+ - Change: an index step says the direction, as in Ruby: a step pointing
181
+ away from the end reads nothing (`a[(0..4).step(-1)]` read `a[0]`).
182
+
183
+ - Change: a boolean selector of more than one axis must have the array's
184
+ shape; it picked cells by flat position. Flatten both sides to keep the
185
+ old reading.
186
+
187
+ - Change: storing an integer a cell cannot hold raises `RangeError`
188
+ (`CA_INT8([300])`, `a[0] = 300`, `fill`, `scatter_add!`, a record
189
+ member); it wrapped (`300` into int8 was `44`). Storing or reading a
190
+ NaN into an integer cell (`ints[] = floats`, `as_type`, `fake`) raises
191
+ `FloatDomainError`. To keep C's conversion, use `to_type`, which is
192
+ unchanged.
193
+
194
+ - Change: `CArray.time` reads an Integer as a count of ticks of `unit:`
195
+ (`CArray.time(CA_INT64([0, 10]), unit: :m)` is 00:00 and 00:10); it
196
+ read Unix seconds. To read Unix seconds onto another unit, write
197
+ `CArray.time(secs).to_unit(:m)`.
198
+
199
+ - Change: `CArray.time` without `unit:`, and `CAFrame#parse_to_time` with
200
+ a format or `:mixed`, read the values in the finest unit they show
201
+ (dates alone `:D`, fractions of a second `:ms` / `:us` / `:ns`); it was
202
+ always `:s`. Pass `unit: :s` to keep the old unit.
203
+
204
+ - Change: adding a duration that is coarser than a time's unit and not a
205
+ whole number of its ticks (`"1 day"` on a `"7 hours"` time) raises, and
206
+ so does `CArray#time(origin:)` between two ticks of `unit:`; both were
207
+ cut to the grid. Convert the time to a unit both share first.
208
+
209
+ - Change: `order(descending: true)` puts NaN last and keeps tied cells in
210
+ their original order (`[5, 3, 5, 1, 5]` gives `[0, 3, 1, 4, 2]`, was
211
+ `[2, 3, 1, 4, 0]`); with `method: :dense` the largest value is 0 and
212
+ the ranks have no gaps. Code that used `(n - 1) - order` for the
213
+ descending rank needs that formula written out. `nlargest` no longer
214
+ returns NaN or masked cells first, and `nsmallest` / `nlargest` and
215
+ their `_index` forms break ties by position.
216
+
217
+ - Change: a CAFrame column built from Ruby values is typed by them:
218
+ Integers `int64`, numbers `float64`, Strings a text column (`CAString`),
219
+ arrays of one shape an N-D column, anything else `:object`; it was
220
+ `:object`. This holds for `CAFrame.new("x" => [...])`, `df["x"] = [...]`,
221
+ a group's `table` block and a Proc in `aggregate`. Wrap the values in
222
+ `CA_OBJECT(...)` to keep an object column. A returned array is read
223
+ from the N-D column as `col[i, nil]`.
224
+
225
+ - Change: `CAFrame#melt` names each row's source in a text column
226
+ (`CAString`); it was an object column.
227
+
228
+ - Change: `CAFrame#group_by` on several keys gives a result with no
229
+ index: each key is a column, before the reduced columns. Read the keys
230
+ with `result["station"]` and so on, where the index held tuples.
231
+
232
+ - Change: `CAFrame#data_types`, `describe` and `p df` name a Face column
233
+ by its class (`CATime[D]`, `CAString`) where they gave its storage
234
+ `data_type` (`:fixlen` for most). Read the storage through the Face's
235
+ accessor (`ticks`, `codes`, ...).
236
+
237
+ - Change: a CAFrame verb that takes a list of columns refuses a name
238
+ given twice (`select("a", "a")`, `group_by("a", "a")`) with
239
+ `ArgumentError`. `df["a", "a"]` still gives the column twice.
240
+
241
+ - Change: a CAFrame group or window reduction over a column whose type
242
+ lacks it raises `CArray::DataTypeError`; it raised `ArgumentError`.
243
+
244
+ - Change: a `CAString` holds only Strings: storing `nil`, a number or an
245
+ Array into it raises (use `UNDEF` to mask a cell). A selection among
246
+ Strings (`then_else`, `choose`, `select`, `conditional`) and a
247
+ `CAString`'s String operators give a `CAString`, where they gave an
248
+ object array.
249
+
250
+ - Change: attributes follow conversions, views and copies but not
251
+ reductions: `categorize`, `cast`, `parse_to_time`, `dup`, Marshal and a
252
+ Face's views keep them, and `first` / `last` of a grouping no longer
253
+ carry them. A joined or concatenated array shows the keys every piece
254
+ shows with the same value. An attribute value is stored frozen; change
255
+ it by setting it again.
256
+
257
+ - Change: an error names the method you called, and the common refusals
258
+ open with it ("+: shape mismatch between operands ...", "fill: can not
259
+ modify read-only array"). The exception classes are unchanged; code
260
+ that matches a message needs the new text.
261
+
262
+ - Change: `clip` refuses `UNDEF` or a masked cell as a bound with
263
+ `ArgumentError`. To mask the cells out of range, pass `UNDEF` as the
264
+ fill (`clip(0, 10, UNDEF)`).
265
+
266
+ - Change: `is_in`, `intersection`, `difference` and `union` refuse a
267
+ Range; pass an Array (`(1..3).to_a`), or use `is_between` for an
268
+ interval.
269
+
270
+ - Change: `median`, `percentile` and `quantile` along the only axis of a
271
+ 1-D array give a bare value, as `sum` does. `nunique(axis:)` naming
272
+ every axis gives an Integer; pass `keep_axis: true` to keep an array.
273
+
274
+ - Change: `valid_index?` and `valid_addr?` count a negative index from
275
+ the end, as `[]` does. `elem_fetch` on an empty array raises
276
+ `IndexError`; it returned `nil`.
277
+
278
+ - Change: `seq` / `seq!` on an integer array take a Float or Rational
279
+ start or step as `init_val + step*i` cut toward zero
280
+ (`int32.seq(0.5, 0.5)` is `[0, 1, 1, 2]`, was `[0, 0, 1, 1]`), and
281
+ raise `RangeError` for a start or Integer step the type cannot hold.
282
+
283
+ - Change: `random!` on an integer array raises for bounds the type
284
+ cannot hold or a Float bound, and clears the mask. `bin`, `bincount`,
285
+ `bincount_nd` and the histograms raise for a non-Integer count and for
286
+ edges that decrease.
287
+
288
+ - Change: MemoryView: `wrap_memory_view` refuses a boolean buffer (any
289
+ byte other than 0 or 1 cannot be told apart; use `from_memory_view`,
290
+ which reads it as true), and a wrap with a read-only `mask:` is
291
+ read-only. `CArray.memory_view_reject_reason` returns `nil` for an
292
+ object that is not a CArray.
293
+
294
+ - Change: C extensions: fifteen kernel iterator shorthand macros
295
+ (`CA_SLAB_REDUCE_F64`, `CA_SLAB_REDUCE_T_PLUS`,
296
+ `CA_L2_FOR_EACH_UNMASKED` and others) are removed; write the macro they
297
+ stood for (`CA_SLAB_REDUCE_T` with `double`, ...).
298
+ `ca_iter_state_next_slab_strided` is removed, and
299
+ `ca_iter_state_init_l2` takes `CA_SLAB_AXES` only.
300
+
37
301
  ## 3.0.3
38
302
 
39
303
  - New: `CAFrame.from_csv` reads messy tables: `types: :infer` (numbers,
data/README.md CHANGED
@@ -10,11 +10,11 @@ Ruby/CArray is an extension library for the multi-dimensional array class. It pr
10
10
 
11
11
  * Every array carries a per-element mask for missing values, respected by reductions and statistics
12
12
  * Views compose without copying — a write through the outermost view reaches the source data
13
- * MemoryView protocol on both sides: share buffers with other numerical libraries without copying
13
+ * [MemoryView protocol](guides/users/15_memory_view.md) on both sides: share buffers with other numerical libraries without copying
14
14
  * Define your own array class in pure Ruby while keeping the full CArray interface
15
15
  * Kernel-style iteration: run a Ruby block over each sub-array spanning the axes you choose
16
16
  * Faces: array types for time, strings and categories, with methods of their own on top of everything CArray does
17
- * Comes with a DataFrame (`CAFrame`) whose columns are plain CArrays, so masks and views keep working on them
17
+ * Comes with a DataFrame ([`CAFrame`](guides/dataframe/README.md)) whose columns are plain CArrays, so masks and views keep working on them
18
18
 
19
19
  Each of these is shown, briefly and with a runnable example, in [A tour of the features](docs/FeatureTour.md).
20
20
 
@@ -119,6 +119,7 @@ b.strip_mask(Float::NAN).sum(axis: 0)
119
119
  * [Views](guides/users/06_views.md) — referring to data without copying
120
120
  * [Reduction and statistics](guides/users/04_reduction_and_statistics.md) — summaries, whole or per axis
121
121
  * [Masks and missing values](guides/users/05_masks.md) — undefined elements, and how calculations treat them
122
+ * [Data frames](guides/dataframe/README.md) — tables of named columns, each column a CArray
122
123
 
123
124
  ## Contributing
124
125
 
data/carray.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "carray"
3
- s.version = "3.0.3"
3
+ s.version = "3.0.4"
4
4
  s.authors = ["himotoyoshi"]
5
5
  s.email = ["himotoyoshi@users.noreply.github.com"]
6
6
  s.summary = "Multi-dimensional numerical array class for Ruby"
@@ -2,13 +2,10 @@
2
2
 
3
3
  ca_axis_descriptor.h
4
4
 
5
- Per-axis descriptor framework (D1 + D2 + D3) — shared C-level vocabulary
6
- that lets CSA, CAGrid, CASelectAxis, CAWindow, CAShift, and future
5
+ Per-axis descriptor framework — shared C-level vocabulary that lets
6
+ CASelectAxis, CAGrid, CASelect, CAWindow, CAShift, and future
7
7
  per-axis-mixed views describe each axis the same way so a common
8
- attach dispatch engine (D3, ca_axis_dispatch.c) can drive them
9
- uniformly.
10
-
11
- See devel/PROPOSAL_AXIS_DESCRIPTOR_FRAMEWORK.md for the design.
8
+ attach dispatch engine (ca_axis_dispatch.c) can drive them uniformly.
12
9
 
13
10
  Status: TWO-TIER FREEZE CONTRACT (3.0 onward), the same split
14
11
  ca_kernel_iterator.h declares, for the same reason: this header is
@@ -50,14 +47,14 @@
50
47
  When this header is included from carray.h mid-file, those typedefs
51
48
  are already in scope by the time we reach the include site. */
52
49
 
53
- /* ---- D1: per-axis descriptor types ----------------------------------------
50
+ /* ---- per-axis descriptor types --------------------------------------------
54
51
 
55
52
  STRIDE = linear stride axis: parent index = start + i*step,
56
53
  i in [0, count). Subsumes nil / Integer / Range index args.
57
54
  INDEX = integer index axis: parent index = indices[i],
58
55
  i in [0, count). Subsumes integer-array (CAGrid)
59
56
  and boolean-mask-after-snapshot (CASelectAxis) axes.
60
- SHIFT = bound-aware stride axis (CAWindow/CAShift, Tier 2.B):
57
+ SHIFT = bound-aware stride axis (CAWindow/CAShift):
61
58
  parent index = start + i*step normalised by `policy`
62
59
  (CA_BOUNDS_FILL / PERIODIC / REFLECT / NEAREST / ...)
63
60
  against `size0` (= parent dim along this axis). When
@@ -86,16 +83,17 @@ typedef struct {
86
83
  uint8_t policy; /* CA_BOUNDS_FILL / PERIODIC / REFLECT / ... */
87
84
  } ca_axis_desc_t;
88
85
 
89
- /* ---- D2: producer interface ----------------------------------------------
86
+ /* ---- producer interface --------------------------------------------------
90
87
 
91
- Both implementations write ndim entries into `out` (caller-allocated)
92
- and `out_parent_dims` (caller-allocated, sized CA_RANK_MAX). See
93
- devel/PROPOSAL_AXIS_DESCRIPTOR_FRAMEWORK.md §5 Framework Phase 1 and
94
- devel/PROPOSAL_FLAT_INDEX_VIEWS.md §2.3 for rationale.
88
+ A producer writes one entry per descriptor axis into `out`
89
+ (caller-allocated) and `out_parent_dims` (caller-allocated, sized
90
+ CA_RANK_MAX). The producers declared here are CASelectAxis and CAGrid;
91
+ CASelect and CAWindow have their own (ca_select_describe_axes /
92
+ ca_window_describe_axes).
95
93
 
96
94
  `out_parent_dims[k]` is the **effective** parent dim along descriptor
97
- axis k — for CSA / CAGrid this is just `parent->dim[k]`, but for
98
- flat-index views (CASelect / CAMapping, Tier 2.A.3+) it is
95
+ axis k — for CASelectAxis / CAGrid this is just `parent->dim[k]`, but
96
+ for a flat-index view (CASelect) it is
99
97
  `{parent->elements}` (a single-axis flat view of parent). This
100
98
  decouples descriptor.ndim from parent.ndim so the engine can drive
101
99
  views whose iteration axes don't match the parent's physical shape.
@@ -103,13 +101,17 @@ typedef struct {
103
101
  Pointer arguments are typed `void *` here to avoid pulling the
104
102
  private CASelectAxis / CAGrid struct definitions (which live in
105
103
  their respective .c files) into this header. Each implementation
106
- casts to its concrete type inside the .c file. */
104
+ casts to its concrete type inside the .c file.
105
+
106
+ An INDEX axis has no way to say "no cell": a CAGrid index that is
107
+ masked (a hole) is written as index 0, so a caller driving a holed grid
108
+ through the engine reads and writes parent cell 0 there. */
107
109
  void ca_select_axis_describe_axes (void *ca, ca_axis_desc_t *out,
108
110
  ca_size_t *out_parent_dims);
109
111
  void ca_grid_describe_axes (void *ca, ca_axis_desc_t *out,
110
112
  ca_size_t *out_parent_dims);
111
113
 
112
- /* ---- D3: common attach engine --------------------------------------------
114
+ /* ---- common attach engine -------------------------------------------------
113
115
 
114
116
  Drives gather from `parent` into an output buffer driven by the
115
117
  per-axis descriptor array. Caller must have parent attached before
@@ -119,14 +121,15 @@ void ca_grid_describe_axes (void *ca, ca_axis_desc_t *out,
119
121
  descriptor axis (see producer interface above). The engine never
120
122
  reads `parent->dim` directly — it only reads `parent->ptr` for
121
123
  data access — which is what allows flat-index views to lie about
122
- parent's apparent shape (Tier 2.A, PROPOSAL_FLAT_INDEX_VIEWS.md).
124
+ parent's apparent shape.
123
125
 
124
126
  `bound_fill` is the bytes-wide value written into gather output
125
- cells whose SHIFT axes resolve to an out-of-bounds parent index
126
- (Tier 2.B, PROPOSAL_BOUND_AWARE_VIEWS.md). Pass NULL when no
127
- SHIFT axis is present (CSA / CAGrid / CASelect / CAMapping); the
128
- engine ignores it. On scatter, the engine simply skips parent
129
- writes for OOB cells regardless of bound_fill.
127
+ cells whose SHIFT axes resolve to an out-of-bounds parent index.
128
+ Pass NULL when no SHIFT axis is present (CASelectAxis / CAGrid /
129
+ CASelect); the engine ignores it. On scatter, the engine simply skips
130
+ parent writes for OOB cells regardless of bound_fill. A SHIFT axis
131
+ under the RUBY or STRICT policy raises IndexError part way through the
132
+ walk for an index outside the parent.
130
133
 
131
134
  _gather — caller provides out_buf (must be sized total_elements*bytes)
132
135
  _attach — wrapper that mallocs the buffer; caller xfrees
@@ -160,7 +163,7 @@ void ca_axis_dispatch_scatter (struct _CArray *parent,
160
163
  ca_size_t total_elements,
161
164
  const char *in_buf);
162
165
  /* Broadcast scatter: write the single value `val` (bytes wide) into
163
- every selected parent cell. See D6 of the framework piece.
166
+ every selected parent cell.
164
167
  (SHIFT axis OOB cells are skipped — fill semantics aren't
165
168
  meaningful for broadcast-write since the destination value already
166
169
  IS the broadcast value.) */
@@ -1158,15 +1158,10 @@ ca_axis_view_attach_owned (void *ap)
1158
1158
  CArray *ca = (CArray *) ap;
1159
1159
  char *buf = xmalloc(ca_length(ca) > 0 ? ca_length(ca) : 1);
1160
1160
  void *args[2];
1161
- int tag = 0;
1162
1161
 
1163
1162
  args[0] = ca;
1164
1163
  args[1] = buf;
1165
- rb_protect(ca_axis_view_fill_owned, (VALUE) args, &tag);
1166
- if ( tag ) {
1167
- xfree(buf);
1168
- rb_jump_tag(tag);
1169
- }
1164
+ ca_fill_or_xfree(buf, ca_axis_view_fill_owned, (VALUE) args);
1170
1165
  ca->ptr = buf;
1171
1166
  }
1172
1167
 
data/ext/ca_axis_group.c CHANGED
@@ -283,7 +283,7 @@ group_op_code (VALUE vop)
283
283
  #define GACC_XOR \
284
284
  ( ((boolean8_t *) co->ptr)[o] ^= (*(boolean8_t *)(p + gw_doff[e]) ? 1 : 0) )
285
285
 
286
- /* __axis_group_reduce__(group_axes, bundles, op) — group-reduces self along
286
+ /* __reduce_by_axis_groups__(group_axes, bundles, op) — group-reduces self along
287
287
  * the union of `group_axes` (ascending source-axis indices = the slab) into
288
288
  * composite groups described by `bundles`, preserving the band (= non-grouped)
289
289
  * axes. Internal: the Ruby surface is CAGroupIterator.
@@ -352,7 +352,7 @@ rb_ca_axis_group_reduce (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
352
352
  /* --- bundles: small per-group code tables (metadata, kept alive) --- */
353
353
  Check_Type(vbundles, T_ARRAY);
354
354
  int n_bundles = (int) RARRAY_LEN(vbundles);
355
- if ( n_bundles <= 0 || n_bundles > CA_RANK_MAX ) {
355
+ if ( n_bundles <= 0 || n_bundles > CA_RANK_MAX ) { /* rank-check: a count of key bundles */
356
356
  rb_raise(rb_eArgError, "axis_group_reduce: bad bundle count %d", n_bundles);
357
357
  }
358
358
  int32_t *bundle_codes[CA_RANK_MAX];
@@ -362,7 +362,8 @@ rb_ca_axis_group_reduce (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
362
362
  int bundle_slot[CA_RANK_MAX][CA_RANK_MAX];
363
363
  ca_size_t bundle_cstride[CA_RANK_MAX][CA_RANK_MAX];
364
364
  CArray *bundle_ca[CA_RANK_MAX];
365
- volatile VALUE keep = rb_ary_new(); /* GC-pin int32 code views */
365
+ volatile VALUE keep = rb_ary_new(); /* keeps the int32 code views alive */
366
+ volatile VALUE h_codes[CA_RANK_MAX]; /* holders of the copied code tables */
366
367
 
367
368
  ca_size_t K_total = 1;
368
369
  long consumed_total = 0;
@@ -385,18 +386,16 @@ rb_ca_axis_group_reduce (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
385
386
  and the end of the walk can raise -- a validation just below, a gather
386
387
  that cannot convert a cell, an object-lane callback into Ruby -- and a
387
388
  raise jumps over every detach, leaving the source materialised with
388
- nothing left to release it. The copy rides a temporary buffer that the
389
- unwind collects. */
389
+ nothing left to release it. The copy rides ALLOCV, a temporary buffer
390
+ that the unwind collects. Not a String: a String held only by `keep`
391
+ can be moved by compaction, taking the bytes under bundle_codes with
392
+ it. */
390
393
  VALUE v32 = rb_ca_wrap_readonly(vcodes, INT2NUM(CA_INT32));
391
394
  rb_ary_push((VALUE) keep, v32);
392
395
  GetCArray(v32, bundle_ca[bi]);
393
- {
394
- size_t nbytes = (size_t) bundle_ca[bi]->elements * sizeof(int32_t);
395
- VALUE vbuf = rb_str_tmp_new((long) nbytes);
396
- rb_ary_push((VALUE) keep, vbuf);
397
- ca_copy_data(bundle_ca[bi], RSTRING_PTR(vbuf));
398
- bundle_codes[bi] = (int32_t *) RSTRING_PTR(vbuf);
399
- }
396
+ h_codes[bi] = 0;
397
+ bundle_codes[bi] = ALLOCV_N(int32_t, h_codes[bi], bundle_ca[bi]->elements);
398
+ ca_copy_data(bundle_ca[bi], (char *) bundle_codes[bi]);
400
399
 
401
400
  int nb = (int) RARRAY_LEN(vbaxes);
402
401
  if ( nb <= 0 || nb > src->ndim ) {
@@ -682,6 +681,7 @@ rb_ca_axis_group_reduce (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
682
681
  ALLOCV_END(h_prod); ALLOCV_END(h_seen); ALLOCV_END(h_xbuf);
683
682
  ALLOCV_END(h_nz); ALLOCV_END(h_mnaddr); ALLOCV_END(h_mxaddr);
684
683
  ALLOCV_END(h_band);
684
+ for ( int bi = 0; bi < n_bundles; bi++ ) ALLOCV_END(h_codes[bi]);
685
685
 
686
686
  RB_GC_GUARD(keep);
687
687
  return vout;
@@ -983,7 +983,7 @@ group_scan_build_plan (ca_iter_state *st, boolean8_t *m,
983
983
  omask[o] = 1; \
984
984
  } while (0)
985
985
 
986
- /* The CA_OBJECT lane of __axis_group_scan__. Every cell calls into Ruby,
986
+ /* The CA_OBJECT lane of __scan_by_axis_groups__. Every cell calls into Ruby,
987
987
  so the walk can raise part way; its state lives in the caller's frame, in
988
988
  c->st, and ca_iter_ensure finishes it however this body leaves. The
989
989
  buffers are ALLOCV-backed, so the unwind collects them. */
@@ -1115,9 +1115,9 @@ group_scan_op_code (VALUE vop)
1115
1115
  rb_raise(rb_eArgError, "axis_group_scan: unsupported op :%"PRIsVALUE, rb_id2str(id));
1116
1116
  }
1117
1117
 
1118
- /* __axis_group_scan__(group_axes, bundles, op) — group-keyed segment scan of
1118
+ /* __scan_by_axis_groups__(group_axes, bundles, op) — group-keyed segment scan of
1119
1119
  * self over the union of `group_axes` into composite groups described by
1120
- * `bundles` (same argument shape as __axis_group_reduce__). Internal.
1120
+ * `bundles` (same argument shape as __reduce_by_axis_groups__). Internal.
1121
1121
  *
1122
1122
  * Unlike the reduce the grouped axes are not collapsed: the result is a new
1123
1123
  * CArray of the same shape as self, each cell holding the running statistic of
@@ -1187,7 +1187,7 @@ rb_ca_axis_group_scan (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
1187
1187
  /* --- bundles: small per-group code tables (same as reduce) --- */
1188
1188
  Check_Type(vbundles, T_ARRAY);
1189
1189
  int n_bundles = (int) RARRAY_LEN(vbundles);
1190
- if ( n_bundles <= 0 || n_bundles > CA_RANK_MAX ) {
1190
+ if ( n_bundles <= 0 || n_bundles > CA_RANK_MAX ) { /* rank-check: a count of key bundles */
1191
1191
  rb_raise(rb_eArgError, "axis_group_scan: bad bundle count %d", n_bundles);
1192
1192
  }
1193
1193
  int32_t *bundle_codes[CA_RANK_MAX];
@@ -1198,6 +1198,7 @@ rb_ca_axis_group_scan (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
1198
1198
  ca_size_t bundle_cstride[CA_RANK_MAX][CA_RANK_MAX];
1199
1199
  CArray *bundle_ca[CA_RANK_MAX];
1200
1200
  volatile VALUE keep = rb_ary_new();
1201
+ volatile VALUE h_codes[CA_RANK_MAX];
1201
1202
 
1202
1203
  ca_size_t K_total = 1;
1203
1204
  long consumed_total = 0;
@@ -1220,18 +1221,16 @@ rb_ca_axis_group_scan (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
1220
1221
  and the end of the walk can raise -- a validation just below, a gather
1221
1222
  that cannot convert a cell, an object-lane callback into Ruby -- and a
1222
1223
  raise jumps over every detach, leaving the source materialised with
1223
- nothing left to release it. The copy rides a temporary buffer that the
1224
- unwind collects. */
1224
+ nothing left to release it. The copy rides ALLOCV, a temporary buffer
1225
+ that the unwind collects. Not a String: a String held only by `keep`
1226
+ can be moved by compaction, taking the bytes under bundle_codes with
1227
+ it. */
1225
1228
  VALUE v32 = rb_ca_wrap_readonly(vcodes, INT2NUM(CA_INT32));
1226
1229
  rb_ary_push((VALUE) keep, v32);
1227
1230
  GetCArray(v32, bundle_ca[bi]);
1228
- {
1229
- size_t nbytes = (size_t) bundle_ca[bi]->elements * sizeof(int32_t);
1230
- VALUE vbuf = rb_str_tmp_new((long) nbytes);
1231
- rb_ary_push((VALUE) keep, vbuf);
1232
- ca_copy_data(bundle_ca[bi], RSTRING_PTR(vbuf));
1233
- bundle_codes[bi] = (int32_t *) RSTRING_PTR(vbuf);
1234
- }
1231
+ h_codes[bi] = 0;
1232
+ bundle_codes[bi] = ALLOCV_N(int32_t, h_codes[bi], bundle_ca[bi]->elements);
1233
+ ca_copy_data(bundle_ca[bi], (char *) bundle_codes[bi]);
1235
1234
 
1236
1235
  int nb = (int) RARRAY_LEN(vbaxes);
1237
1236
  if ( nb <= 0 || nb > src->ndim ) {
@@ -1413,6 +1412,7 @@ rb_ca_axis_group_scan (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
1413
1412
  ALLOCV_END(h_band2); ALLOCV_END(h_code); ALLOCV_END(h_doff);
1414
1413
  ALLOCV_END(h_moff); ALLOCV_END(h_addr); ALLOCV_END(h_accd);
1415
1414
  ALLOCV_END(h_accn); ALLOCV_END(h_seen); ALLOCV_END(h_acco);
1415
+ for ( int bi = 0; bi < n_bundles; bi++ ) ALLOCV_END(h_codes[bi]);
1416
1416
 
1417
1417
  RB_GC_GUARD(keep);
1418
1418
  return vout;
@@ -1421,8 +1421,8 @@ rb_ca_axis_group_scan (VALUE self, VALUE vgaxes, VALUE vbundles, VALUE vop)
1421
1421
  void
1422
1422
  Init_ca_axis_group (void)
1423
1423
  {
1424
- rb_define_method(rb_cCArray, "__axis_group_reduce__",
1424
+ rb_define_method(rb_cCArray, "__reduce_by_axis_groups__",
1425
1425
  rb_ca_axis_group_reduce, 3);
1426
- rb_define_method(rb_cCArray, "__axis_group_scan__",
1426
+ rb_define_method(rb_cCArray, "__scan_by_axis_groups__",
1427
1427
  rb_ca_axis_group_scan, 3);
1428
1428
  }
@@ -29,7 +29,7 @@
29
29
 
30
30
  /* The kernel table of each op id. The eager operators hold the tables
31
31
  themselves; ca_binop_op_id_of_table maps one back to its op id, so that
32
- both ask ca_binop_is_trapping the same question. */
32
+ both ask ca_op_raises_on_cell the same question. */
33
33
  static ca_binop_func_t * const ca_binop_tables[CA_BINOP_COUNT] = {
34
34
  [CA_BINOP_ADD] = ca_binop_add,
35
35
  [CA_BINOP_SUB] = ca_binop_sub,
@@ -116,31 +116,3 @@ ca_binop_kernel_input_data_types (uint16_t op_id, int8_t l_dt, int8_t r_dt,
116
116
  if ( out_r_in_dt ) *out_r_in_dt = common;
117
117
  }
118
118
 
119
- /* ------------------------------------------------------------------- */
120
- /* trapping-op predicate */
121
- /* ------------------------------------------------------------------- */
122
-
123
- int
124
- ca_binop_is_trapping (uint16_t op_id, int8_t common_dt)
125
- {
126
- /* An object cell calls Ruby, which can raise for any op. Integer
127
- DIV / MOD / QUO / FMOD / RCP_MUL raise on a zero divisor, and POW /
128
- IPOWER on zero to a negative power. Float division returns NaN/Inf
129
- and does not trap. */
130
- int is_integer = ( common_dt >= CA_INT8 && common_dt <= CA_UINT64 );
131
- if ( common_dt == CA_OBJECT ) return 1;
132
- if ( ! is_integer ) return 0;
133
-
134
- switch (op_id) {
135
- case CA_BINOP_DIV:
136
- case CA_BINOP_MOD:
137
- case CA_BINOP_QUO:
138
- case CA_BINOP_FMOD:
139
- case CA_BINOP_RCP_MUL:
140
- case CA_BINOP_POW:
141
- case CA_BINOP_IPOWER:
142
- return 1;
143
- default:
144
- return 0;
145
- }
146
- }
@@ -147,7 +147,6 @@ void ca_binop_kernel_input_data_types (uint16_t op_id, int8_t l_dt, int8_t r_dt,
147
147
  When trapping AND either operand has a mask, xfer_stride must pass
148
148
  a slab mask to the kernel so masked cells are skipped (otherwise
149
149
  masked-zero divisors crash with SIGFPE). See §3.4 rev3. */
150
- int ca_binop_is_trapping (uint16_t op_id, int8_t common_dt);
151
150
  int ca_binop_op_id_of_table (ca_binop_func_t table[]);
152
151
 
153
152
  #endif /* CA_BINOP_DISPATCH_H */