carray 3.0.2 → 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 (247) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +568 -0
  3. data/README.md +6 -6
  4. data/carray.gemspec +1 -1
  5. data/ext/ca_axis_descriptor.h +27 -24
  6. data/ext/ca_axis_dispatch.c +220 -0
  7. data/ext/ca_axis_group.c +201 -123
  8. data/ext/ca_binop_dispatch.c +46 -52
  9. data/ext/ca_binop_dispatch.h +1 -1
  10. data/ext/ca_categorical_iterator.c +249 -183
  11. data/ext/ca_compare.c +7 -12
  12. data/ext/ca_for_buffer.h +21 -68
  13. data/ext/ca_group_iter.c +38 -23
  14. data/ext/ca_kernel_iterator.c +1765 -2076
  15. data/ext/ca_kernel_iterator.h +584 -566
  16. data/ext/ca_monop_dispatch.c +86 -63
  17. data/ext/ca_monop_dispatch.h +5 -0
  18. data/ext/ca_obj_array.c +223 -56
  19. data/ext/ca_obj_bincmp.c +172 -138
  20. data/ext/ca_obj_binop.c +116 -230
  21. data/ext/ca_obj_bitarray.c +40 -26
  22. data/ext/ca_obj_bitfield.c +100 -68
  23. data/ext/ca_obj_block.c +19 -9
  24. data/ext/ca_obj_byte_swap.c +45 -46
  25. data/ext/ca_obj_const_string.c +269 -44
  26. data/ext/ca_obj_face.c +612 -89
  27. data/ext/ca_obj_face.h +111 -47
  28. data/ext/ca_obj_fake.c +36 -79
  29. data/ext/ca_obj_farray.c +7 -3
  30. data/ext/ca_obj_field.c +33 -8
  31. data/ext/ca_obj_fixlen_string.c +23 -24
  32. data/ext/ca_obj_grid.c +541 -210
  33. data/ext/ca_obj_meld.c +331 -111
  34. data/ext/ca_obj_moncmp.c +80 -65
  35. data/ext/ca_obj_monop.c +177 -149
  36. data/ext/ca_obj_object.c +664 -248
  37. data/ext/ca_obj_record.c +63 -23
  38. data/ext/ca_obj_reduce.c +18 -16
  39. data/ext/ca_obj_refer.c +140 -58
  40. data/ext/ca_obj_remap.c +85 -24
  41. data/ext/ca_obj_repeat.c +24 -9
  42. data/ext/ca_obj_roll.c +121 -16
  43. data/ext/ca_obj_select.c +61 -58
  44. data/ext/ca_obj_select_axis.c +73 -107
  45. data/ext/ca_obj_shift.c +32 -102
  46. data/ext/ca_obj_stack.c +372 -122
  47. data/ext/ca_obj_stride.c +348 -140
  48. data/ext/ca_obj_string.c +88 -22
  49. data/ext/ca_obj_tile.c +38 -21
  50. data/ext/ca_obj_time.c +45 -31
  51. data/ext/ca_obj_timedelta.c +43 -29
  52. data/ext/ca_obj_transpose.c +17 -6
  53. data/ext/ca_obj_triop.c +125 -141
  54. data/ext/ca_obj_window.c +330 -44
  55. data/ext/ca_op_ipower.c +24 -11
  56. data/ext/ca_op_powi.h +57 -30
  57. data/ext/ca_pow5_table.h +656 -0
  58. data/ext/ca_sort_kernels.h +70 -0
  59. data/ext/ca_sweep_engine.c +104 -81
  60. data/ext/ca_sweep_engine.h +7 -20
  61. data/ext/ca_triop_dispatch.c +4 -1
  62. data/ext/ca_triop_dispatch.h +5 -2
  63. data/ext/caframe_csv_reader.c +542 -0
  64. data/ext/carray.h +241 -92
  65. data/ext/carray_access.c +608 -276
  66. data/ext/carray_address_basis.c +494 -97
  67. data/ext/carray_attribute.c +129 -4
  68. data/ext/carray_bincount.c +39 -7
  69. data/ext/carray_broadcast.c +56 -19
  70. data/ext/carray_build_flags.h +1 -1
  71. data/ext/carray_call_cfunc.c +108 -28
  72. data/ext/carray_cast.c +1576 -223
  73. data/ext/carray_cast_func.rb +77 -24
  74. data/ext/carray_class.c +4 -3
  75. data/ext/carray_conversion.c +208 -75
  76. data/ext/carray_copy.c +82 -24
  77. data/ext/carray_core.c +646 -162
  78. data/ext/carray_count.c +171 -88
  79. data/ext/carray_element.c +94 -60
  80. data/ext/carray_factorize.c +670 -324
  81. data/ext/carray_generate.c +260 -83
  82. data/ext/carray_histogram.c +209 -106
  83. data/ext/carray_hold.c +14 -16
  84. data/ext/carray_index_classifier.c +422 -243
  85. data/ext/carray_internal.h +692 -3
  86. data/ext/carray_kernels_bincmp.c +7 -0
  87. data/ext/carray_kernels_binop.c +487 -120
  88. data/ext/carray_kernels_init.c +653 -50
  89. data/ext/carray_kernels_moncmp.c +15 -8
  90. data/ext/carray_kernels_monop.c +99 -43
  91. data/ext/carray_kernels_reduce_aggregate.c +3925 -6112
  92. data/ext/carray_kernels_reduce_boolean.c +112 -36
  93. data/ext/carray_kernels_reduce_cumulative.c +2127 -6903
  94. data/ext/carray_kernels_reduce_extreme.c +3032 -2892
  95. data/ext/carray_kernels_reduce_variance.c +439 -500
  96. data/ext/carray_kernels_scan.c +1097 -488
  97. data/ext/carray_kernels_search.c +3787 -2176
  98. data/ext/carray_kernels_sort.c +1200 -920
  99. data/ext/carray_kernels_triop.c +479 -7
  100. data/ext/carray_key_windows.c +216 -0
  101. data/ext/carray_lazy.c +967 -153
  102. data/ext/carray_loop.c +81 -65
  103. data/ext/carray_mask.c +910 -324
  104. data/ext/carray_math_kernel.h +1 -0
  105. data/ext/carray_median_percentile.c +299 -100
  106. data/ext/carray_memory_view.c +872 -758
  107. data/ext/carray_operator.c +1171 -364
  108. data/ext/carray_order.c +505 -133
  109. data/ext/carray_partition.c +112 -65
  110. data/ext/carray_random.c +327 -239
  111. data/ext/carray_round.c +273 -0
  112. data/ext/carray_scatter.c +346 -78
  113. data/ext/carray_segment.c +257 -0
  114. data/ext/carray_slab.c +249 -86
  115. data/ext/carray_sort.c +224 -227
  116. data/ext/carray_sort_kernel.c +8 -1
  117. data/ext/carray_struct.c +118 -39
  118. data/ext/carray_test.c +193 -69
  119. data/ext/carray_time_text.c +1182 -0
  120. data/ext/carray_undef.c +4 -0
  121. data/ext/carray_utils.c +579 -113
  122. data/ext/extconf.rb +27 -2
  123. data/ext/mk_call_cfunc.rb +19 -4
  124. data/ext/mk_pow5_table.rb +35 -0
  125. data/ext/mkkernel.rb +1202 -1014
  126. data/ext/ruby_carray.c +17 -5
  127. data/ext/version.h +4 -4
  128. data/ext/version.rb +4 -2
  129. data/lib/carray/attribute.rb +160 -17
  130. data/lib/carray/autoload_carray.rb +23 -27
  131. data/lib/carray/autoload_method_extension.rb +20 -5
  132. data/lib/carray/axis_group.rb +360 -63
  133. data/lib/carray/basics.rb +162 -28
  134. data/lib/carray/bincount_nd.rb +18 -2
  135. data/lib/carray/block_iterator.rb +231 -58
  136. data/lib/carray/boolean_reduce.rb +34 -42
  137. data/lib/carray/categorical.rb +242 -52
  138. data/lib/carray/categorical_iterator.rb +437 -827
  139. data/lib/carray/complex.rb +41 -34
  140. data/lib/carray/conditional.rb +150 -14
  141. data/lib/carray/const_string.rb +59 -4
  142. data/lib/carray/construct.rb +15 -11
  143. data/lib/carray/data_type_extension.rb +1 -0
  144. data/lib/carray/distance_limit.rb +77 -0
  145. data/lib/carray/fixlen_string.rb +7 -1
  146. data/lib/carray/frame/column_verbs.rb +70 -0
  147. data/lib/carray/frame/concat.rb +157 -6
  148. data/lib/carray/frame/convert.rb +82 -7
  149. data/lib/carray/frame/csv_parser.rb +688 -87
  150. data/lib/carray/frame/describe.rb +80 -0
  151. data/lib/carray/frame/frame.rb +369 -45
  152. data/lib/carray/frame/group.rb +631 -90
  153. data/lib/carray/frame/io.rb +506 -79
  154. data/lib/carray/frame/join.rb +411 -62
  155. data/lib/carray/frame/records.rb +116 -19
  156. data/lib/carray/frame/reshape.rb +455 -0
  157. data/lib/carray/frame/sort.rb +30 -18
  158. data/lib/carray/frame/verbs.rb +868 -61
  159. data/lib/carray/frame/windows.rb +117 -0
  160. data/lib/carray/frame.rb +4 -0
  161. data/lib/carray/fuse_source.rb +118 -2
  162. data/lib/carray/fusion.rb +257 -42
  163. data/lib/carray/histogram.rb +6 -1
  164. data/lib/carray/inspect.rb +54 -13
  165. data/lib/carray/iterator.rb +99 -9
  166. data/lib/carray/key_windows.rb +620 -0
  167. data/lib/carray/lazy.rb +216 -193
  168. data/lib/carray/mask_gap_fill.rb +112 -92
  169. data/lib/carray/math.rb +32 -19
  170. data/lib/carray/meld_reduce.rb +52 -21
  171. data/lib/carray/methods/align_addr.rb +8 -4
  172. data/lib/carray/methods/bin.rb +26 -18
  173. data/lib/carray/methods/bincount.rb +18 -2
  174. data/lib/carray/methods/bit_string.rb +15 -4
  175. data/lib/carray/methods/choose.rb +16 -3
  176. data/lib/carray/methods/composition.rb +18 -10
  177. data/lib/carray/methods/factorize.rb +2 -2
  178. data/lib/carray/methods/gather_nd.rb +25 -5
  179. data/lib/carray/methods/insert_block.rb +9 -14
  180. data/lib/carray/methods/is_between.rb +59 -0
  181. data/lib/carray/methods/is_in.rb +140 -10
  182. data/lib/carray/methods/join.rb +2 -7
  183. data/lib/carray/methods/lag.rb +49 -0
  184. data/lib/carray/methods/locate_addr.rb +182 -45
  185. data/lib/carray/methods/mode.rb +18 -1
  186. data/lib/carray/methods/nunique.rb +11 -6
  187. data/lib/carray/methods/repeat.rb +1 -20
  188. data/lib/carray/methods/resize.rb +21 -23
  189. data/lib/carray/methods/snap.rb +34 -12
  190. data/lib/carray/methods/unique.rb +11 -2
  191. data/lib/carray/methods/value_counts.rb +4 -11
  192. data/lib/carray/record_order.rb +208 -0
  193. data/lib/carray/rng.rb +3 -0
  194. data/lib/carray/runtime.rb +65 -17
  195. data/lib/carray/segment_iterator.rb +1221 -0
  196. data/lib/carray/serialize.rb +214 -30
  197. data/lib/carray/slab_iterator.rb +101 -27
  198. data/lib/carray/stack.rb +10 -4
  199. data/lib/carray/string.rb +105 -5
  200. data/lib/carray/string_operation_extension.rb +12 -4
  201. data/lib/carray/struct.rb +137 -58
  202. data/lib/carray/struct_builder.rb +124 -17
  203. data/lib/carray/time.rb +1222 -186
  204. data/lib/carray/window_iterator.rb +242 -81
  205. data/lib/carray.rb +9 -2
  206. data/yard-stubs/ca_obj_array.rb +4 -4
  207. data/yard-stubs/ca_obj_bitarray.rb +7 -0
  208. data/yard-stubs/ca_obj_bitfield.rb +23 -12
  209. data/yard-stubs/ca_obj_fake.rb +1 -1
  210. data/yard-stubs/ca_obj_field.rb +5 -1
  211. data/yard-stubs/ca_obj_grid.rb +21 -10
  212. data/yard-stubs/ca_obj_refer.rb +5 -4
  213. data/yard-stubs/ca_obj_roll.rb +2 -3
  214. data/yard-stubs/ca_obj_shift.rb +5 -1
  215. data/yard-stubs/ca_obj_stride.rb +10 -7
  216. data/yard-stubs/ca_obj_tile.rb +1 -1
  217. data/yard-stubs/ca_obj_transpose.rb +1 -1
  218. data/yard-stubs/ca_obj_window.rb +9 -5
  219. data/yard-stubs/carray_access.rb +11 -5
  220. data/yard-stubs/carray_attribute.rb +0 -5
  221. data/yard-stubs/carray_broadcast.rb +1 -1
  222. data/yard-stubs/carray_cast.rb +88 -43
  223. data/yard-stubs/carray_conversion.rb +15 -2
  224. data/yard-stubs/carray_copy.rb +12 -5
  225. data/yard-stubs/carray_core.rb +3 -3
  226. data/yard-stubs/carray_count.rb +9 -0
  227. data/yard-stubs/carray_element.rb +10 -4
  228. data/yard-stubs/carray_generate.rb +21 -1
  229. data/yard-stubs/carray_lazy.rb +5 -1
  230. data/yard-stubs/carray_loop.rb +4 -1
  231. data/yard-stubs/carray_mask.rb +60 -12
  232. data/yard-stubs/carray_math.rb +52 -14
  233. data/yard-stubs/carray_median_percentile.rb +15 -8
  234. data/yard-stubs/carray_memory_view.rb +40 -23
  235. data/yard-stubs/carray_order.rb +61 -29
  236. data/yard-stubs/carray_random.rb +13 -4
  237. data/yard-stubs/carray_scatter.rb +21 -9
  238. data/yard-stubs/carray_segment.rb +72 -0
  239. data/yard-stubs/carray_slab.rb +10 -2
  240. data/yard-stubs/carray_sort.rb +49 -8
  241. data/yard-stubs/carray_test.rb +15 -3
  242. data/yard-stubs/carray_utils.rb +0 -26
  243. metadata +19 -5
  244. data/ext/ca_for_each_element.h +0 -239
  245. data/ext/carray_kernels_map.c +0 -3467
  246. data/lib/carray/arrow_tensor.rb +0 -401
  247. data/lib/carray/table.rb +0 -108
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 728236f069adb2a801da715596ac5ab87d8cf7c460e70de8667d3afa23e9b19f
4
- data.tar.gz: fdf25919377fe2d90919712ecf8c50a0ed183c15a57ec925cefedc4a7066fb90
3
+ metadata.gz: d2edeb545754cf31d330c667913471c1a0035c97de72dabad7e7b2afb4fe272b
4
+ data.tar.gz: 8b34390fcabbb04c5e1f0926ae103052345196112ec3a6a16f244fb310df5583
5
5
  SHA512:
6
- metadata.gz: 26f8ae296774c82b5bba4f9521cf2b53ec0b1804115c0a4a2f39e29d67419932487a4ff892cd115ab3eb34242c942711504c05945b5e95d44653e546e7c70d66
7
- data.tar.gz: e8109043b73d2f71d395ee0cc5711e395f6964ba0cef7c2aea2d35759dadedca5aa649ec3ebe14de66b6034a788213fb0c0fa1a1ef2499eef03d8b0b021d4bc4
6
+ metadata.gz: 0f7430ff0556faf7b609673fb8cf9ef08279e226192995ea58a5dd203e5285733582c5cff0405fc753c39cad7056acd9194f55ba26ce9eb1d1a27cf1de8e37f0
7
+ data.tar.gz: 48d35829402ba2949e865712d8aa89dd9d4228f0ca4abf62719d3b2d32280541d1c6b7b01dba3e2a68927a89e258e0d6b474a20fc6177415154e1ab57f2b380d
data/CHANGELOG.md CHANGED
@@ -34,6 +34,574 @@ 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
+
301
+ ## 3.0.3
302
+
303
+ - New: `CAFrame.from_csv` reads messy tables: `types: :infer` (numbers,
304
+ booleans, year-first dates and times), `types: { default: ... }`,
305
+ `missing:` tokens, `on_error:` (`:mask`, `:warn`, `:raise`), `columns:` to
306
+ read only some columns, and `header:` / `data:` / `column_names:` by line.
307
+ `CAFrame#cast` takes the same map; `parse_to_time(name, :infer)` finds a
308
+ column's date format; `describe` and `split_column` are new; `to_csv`
309
+ takes `encoding:` and `missing:`.
310
+
311
+ - New: `CAFrame` reshapes and resamples: `pivot` / `pivot_grid` / `melt`,
312
+ `stack_rows(by:)` / `unstack_rows`, `stack_columns` / `unstack_column`,
313
+ `CAFrame.stack` / `unstack` (frames as layers), and `resample(name, unit)`
314
+ for time bins. The stacked forms are views. `protect` makes a frame
315
+ read-only.
316
+
317
+ - New: `CAFrame` group reductions and `aggregate` reduce N-D columns along
318
+ the rows (a column `(N, L)` gives `(groups, L)`), take `min_count:` and
319
+ `fill_value:`, and pass a reduction its arguments
320
+ (`"p90" => ["temp", :percentile, 90.0]`).
321
+
322
+ - New: `value.segments(offsets:)` / `segments(lengths:)` iterate over
323
+ consecutive runs of cells, with `CArray.segment_offsets` /
324
+ `segment_index` to convert between lengths, boundaries and segment
325
+ numbers. The scans, `map`, `median` and `percentile` of
326
+ `group_by_category` take `axis:`, and a window's `median`, `percentile`
327
+ and `quantile` answer under the default `bounds: :skip`.
328
+
329
+ - New: `bitfield(range, type)` reads a field as a signed or wider integer;
330
+ `set_attrs(hash)`; `order(kind:)`; `tolerance: "10 minutes"` for time keys
331
+ in `locate_nearest_addr` and `CAFrame#join_asof`. A `CARecord` answers
332
+ `unique`, `value_counts`, `mode`, `is_in`, the set operations,
333
+ `categorize`, `count(v)` and `locate_addr`.
334
+
335
+ - New: for whoever registers a `CArray.expression_evaluator` (carray-jit):
336
+ mixed data types, integer powers, comparisons, `then_else`, `shift`, and
337
+ reductions, scans and sorts of an expression now reach the evaluator. An
338
+ evaluator that does not know a node declines, and CArray computes the
339
+ expression as before.
340
+
341
+ - New: for C extensions: `ca_iter_ensure`, `ca_sync_detach`,
342
+ `ca_attach_n` / `ca_allocate_n`, `ca_iter_state_init_l2_paired`,
343
+ `ca_stride_setup(NULL, ...)` and `ca_check_uninitialized` let an
344
+ extension clean up when its code raises.
345
+
346
+ - Change: `CAFrame` names its columns "columns": `variable_names` is now
347
+ `column_names`, `variables` is `columns` and `nvar` is `ncol`. The old
348
+ names are gone.
349
+
350
+ - Change: `sort_index`, `rank_index`, `partition_index`, `partition` and
351
+ `partition_copy` without `axis:` work on the whole array, as `sort` does;
352
+ they worked along axis 0. On an N-D array pass `axis: 0` to keep the old
353
+ result.
354
+
355
+ - Change: errors a caller can cause no longer raise `RuntimeError`: a bad
356
+ shape, step, axis, option or data type raises `ArgumentError`,
357
+ `TypeError`, `RangeError` or `CArray::DataTypeError`, and every index out
358
+ of range raises `IndexError` (`take_along_axis`, `axis2addr` and
359
+ `addr2index` raised others). `CArray::DataTypeError` is now a
360
+ `TypeError`. A write to a read-only array still raises `RuntimeError`.
361
+ Messages name the method you called and the value you gave. Update a
362
+ `rescue` that matched the old class or wording.
363
+
364
+ - Change: arguments that were truncated or ignored now raise: an axis,
365
+ `min_count:`, `kth` or `n` that is not an Integer; a misspelt keyword; a
366
+ keyword a method does not take (`min_count:` to `all` / `any` of an
367
+ iterator, as to the core); a Symbol column name in `cast` and `types:`;
368
+ `windows` given anything but Ranges (an exclusive range now leaves out
369
+ its end); `CA_INT32(0, 2)`; a fixlen array without `bytes:`. A negative
370
+ axis counts from the end everywhere. The indexer's method form
371
+ (`a[:eq, 0]`) calls public methods only.
372
+
373
+ - Change: a Hash passed as a positional argument is an argument, as in
374
+ Ruby 3, not keywords: `a.sum({axis: 0})` raises (write `a.sum(axis: 0)`
375
+ or `a.sum(**opts)`). An object array of Hashes can now be searched and
376
+ counted.
377
+
378
+ - Change: values that cannot be held raise instead of being bent: storing
379
+ `nil` into a numeric or boolean array, an Integer operand the array's type
380
+ cannot hold (`RangeError`; the comparisons answer by value instead), and a
381
+ String that is not a decimal number (`"010"` is now 10, and `to_type` gives
382
+ `UNDEF`). `CAFrame#cast` to an integer makes `2.5` `UNDEF` instead of 2.
383
+ Store `Float::NAN` or `UNDEF` for a missing value.
384
+
385
+ - Change: reductions with too few values: `variance` / `stddev` of fewer
386
+ than two values is `UNDEF` (pass `fill_value: 0.0` for the old answer),
387
+ and `minmax` of nothing is `[UNDEF, UNDEF]`. `fill_value:` is stored into
388
+ the result's type with or without `axis:`; `fill_value: UNDEF`,
389
+ `strip_mask(UNDEF)` and `unmask(UNDEF)` leave the cells masked.
390
+
391
+ - Change: arrays of mixed types meet in a type that holds both: signed with
392
+ unsigned integers (`uint8` with `int8` is `int16`, `uint64` with `int64` is
393
+ `:object`) and 32-bit or wider integers with `float32` (in `float64`) when
394
+ joined or matched. `CArray.result_type` lets a scalar take the arrays'
395
+ type, as an operator does (`result_type(float32_array, 0.1)` is
396
+ `:float32`). Arithmetic is unchanged.
397
+
398
+ - Change: integer and float edge cases no longer depend on the machine or
399
+ the argument order: a shift count means what it does to `Integer#<<`,
400
+ signed `rcp` / `rcp_mul` round down as `/` does, `to_type` to an integer
401
+ makes NaN `UNDEF`, `maximum` / `minimum` of two zeros are `0.0` / `-0.0`,
402
+ and `clip` raises when `min` exceeds `max` (a one-sided fill clamps the
403
+ other side).
404
+
405
+ - Change: `CAFrame#join` matches as SQL joins do: a key on 2 left and 3
406
+ right rows gives 6 rows, and a masked key matches nothing and stays as an
407
+ unmatched row. When the other frame's key is unique, `:left` gives the
408
+ same rows as before.
409
+
410
+ - Change: `CAFrame.from_csv`'s reading block takes the reader as its
411
+ parameter and its `body` verb is `data`
412
+ (`from_csv(path) { |r| r.skip 2; r.header; r.data }`). Text columns come
413
+ back as `CAString`. Contents that cannot be read raise
414
+ `CAFrame::UnreadableColumn` or `CAFrame::AmbiguousTimeFormat`, which are
415
+ not `ArgumentError`.
416
+
417
+ - Change: reading time from text is stricter: `parse_to_time` without a
418
+ format reads year-first text only (pass a format, or `:mixed` for the old
419
+ guess) in the finest unit the text shows; `CArray.time` and strptime
420
+ formats refuse trailing text and a time of day they cannot read; a date
421
+ the column's unit cannot hold raises `RangeError`. Before, these cells
422
+ were guessed, floored or masked.
423
+
424
+ - Change: `CAFrame#to_csv` writes a boolean as `1` / `0` and a float32 as
425
+ its shortest decimal, refuses a record column, and raises naming the row
426
+ and column of a cell it cannot encode. `extract` masks a cell its pattern
427
+ does not match, where it gave `""`.
428
+
429
+ - Change: `CAFrame`: a frozen frame refuses `[]=`, `set_index`, `cast` and
430
+ the other in-place verbs; `at` on a numeric index takes numbers only; the
431
+ index of a `group_by` result keeps the key's type (a `CATime` key gives a
432
+ `CATime` index); group `sum` / `mean` / `min` / `max` include every column
433
+ whose type has the reduction (times and strings among them).
434
+
435
+ - Change: `CAStruct` / `CARecord`: records are ordered only by the members
436
+ named in `CArray.struct(order_by:)`; without it sorting, `min` / `max` and
437
+ comparison raise. An element's `[]` takes a String or a position (a
438
+ Symbol raises), a member named like a method (`hash`, `size`) gets no
439
+ accessor, a nested member reads as a view (`dup` it for a copy), boolean
440
+ and 1-bit members read as `true` / `false`, and `UNDEF` cannot be stored
441
+ in a member. Records of another struct are refused.
442
+
443
+ - Change: a `CARecord` exported through MemoryView uses Ruby's own format
444
+ (`ruby/memory_view.h`) instead of PEP 3118 `T{...}`; the member names are
445
+ `CARecord#memory_view_field_names`. A union is no longer exported.
446
+
447
+ - Change: a time array compares with, searches for and stores a `String` or
448
+ `Date` as well as a `Time`, at the precision the value carries: a value
449
+ off the array's grid (09:00 against a day array) raises, where a `Time`
450
+ was floored. `union` of two units gives the finer unit. `inspect` shows
451
+ the tick and each cell as `to_s` does.
452
+
453
+ - Change: `==` on a Face (a time, string or categorical array) compares the
454
+ values it holds, and only with a Face of its own class: time arrays of
455
+ different units holding the same instants are `==`, and a `CAString` is
456
+ no longer `==` to an object array of the same strings (compare
457
+ `to_type(:object)` for that).
458
+
459
+ - Change: Faces (`CATime`, `CATimedelta`, `CACategorical`, string arrays):
460
+ `.lazy` returns the Face and computes eagerly; storing one into a
461
+ non-object plain array raises (convert with `to_type(:object)` or
462
+ `ticks`); `CArray.save`, `dump` and `Marshal.dump` refuse one, and a
463
+ `CAWrap` (save `.parent` or `.copy`); `CArray.stack([face])` returns the
464
+ Face, and mixing Faces raises.
465
+
466
+ - Change: for whoever writes a Face: the hooks are renamed
467
+ `storage_to_element` / `element_to_storage`, and a stored value goes
468
+ through `element_to_storage` once (it went through twice). A Face written
469
+ in Ruby on `CAObject` over a numeric storage refuses arithmetic, math and
470
+ reductions unless it passes `numeric: true`.
471
+
472
+ - Change: views: a view of a frozen array is read-only rather than frozen
473
+ (`RuntimeError`, `frozen?` false), so `sort`, selections and lazy
474
+ expressions work on a frozen array. `then_else` and `sort` on a lazy
475
+ expression return a read-only lazy view (call `copy` for a snapshot), and
476
+ `then_else` branches broadcast as operands do. `dup` of a `CAWrap` is a
477
+ plain `CArray`. Attributes survive `copy` and `to_type`.
478
+
479
+ - Change: a `bitarray` view has no mask and refuses a masked array (use
480
+ `value.bitarray`); `pack_bits` raises on masked cells (pack the mask with
481
+ `validity_bits`). `bitfield` refuses a complex array.
482
+
483
+ - Change: on an object array, `min`, `max`, `cummin`, `pmin` and the rest
484
+ compare with `<=>`, as `sort` does; a pair that cannot be ordered raises
485
+ `ArgumentError`. `median`, `percentile` and `quantile` answer in the
486
+ elements' own arithmetic (`CA_OBJECT([1, 2]).median` is `3/2`; convert
487
+ with `to_type(:float64)` for a Float). `&`, `|` and `^` with a boolean
488
+ array read its cells as `true` / `false`, eager and lazy.
489
+
490
+ - Change: smaller behaviour changes: `locate_nearest_addr` (and `join_asof`,
491
+ `snap_to`) with `direction:` matches beyond the reference's ends (limit it
492
+ with `tolerance:`); `map_slab` carries the mask of the block's result; a
493
+ masked cell of a one-axis boolean selector selects nothing; `shift`,
494
+ `roll`, `tile` and `window` on a zero-length axis return an empty view;
495
+ boolean sums in `axis_group` and categorical scans are uint64, as in the
496
+ core; `group_by_category` raises `TypeError` for a non-categorical.
497
+
498
+ - Change: an operand that exports MemoryView and defines `to_ca` (an Arrow
499
+ array, with a bridge) is taken through `to_ca`, so Arrow nulls arrive as
500
+ masked cells and time columns as `CATime`.
501
+
502
+ - Change: for C extensions: `CArray::VERSION_CODE` is
503
+ `major*10000 + minor*100 + teeny` (`30003`); the `CA_FOR_EACH_ELEMENT`
504
+ macros, `CA_WITH_BUFFER` and `CA_CHECK_BOUND` are removed (use
505
+ `ca_call_cslab_N_r`, `ca_call_cfunc_N_r` or `rb_ca_call_with_buffer`);
506
+ the `_INOUT` and `_PAIR` fiber macros raise on a shape mismatch; kernels
507
+ are built with `-fwrapv`. Rebuild the extension.
508
+
509
+ - Change: faster, with the same results: `from_csv` with `types:` (two to
510
+ five times), text to float (eight times), `CAConstString#to_string`,
511
+ reductions over gathered, `shift` and `window` views, a repeated
512
+ `CArray.fuse` block, and selecting from a lazy expression.
513
+
514
+ - Fix: wrong answers that came without an error. An in-place operation
515
+ reading an argument that shares its memory read cells it had already
516
+ written (`a[1..5].add!(a[0..4])` gave a running sum; `scatter_*!`,
517
+ `inherit_mask` and `mask=` too); `refer` to a wider type on a transposed
518
+ or stepped parent read neighbouring values; views of a stack or meld,
519
+ and a slice of a lazy expression, returned other cells; a Float operand
520
+ of an integer array was truncated (`count(1.5)` found `1`); `mask=` with
521
+ another shape copied cells by count; a masked index read cell 0 in
522
+ `gather_nd`; `stddev` of NaN data was 0.0.
523
+
524
+ - Fix: wrong answers that came without an error, time and strings: time
525
+ keys of different units matched or not depending on the side in `is_in`,
526
+ `join` and `align`; `locate_nearest_addr` picked a wrong row for a NaN,
527
+ an infinite or a nanosecond key; `unmask(time)`, `resize(fill_value:)`
528
+ and `insert_block` read a `Time` as a count; `CAConstString` comparisons
529
+ compared buffer positions; a `CAString` compared against a time,
530
+ categorical or const string compared their encodings.
531
+
532
+ - Fix: writes that were lost now reach the array: through a grid, selection
533
+ or `select_axis` over a reshaped transpose, through a stack or meld of
534
+ views, into a nested struct member, into the mask copy of a stack or meld,
535
+ and the masked cells of `c[] = c.flip(0)`.
536
+
537
+ - Fix: crashes and reads outside an array: a garbage collection during an
538
+ operation on a converted or computed array (`CAObject`, lazy, object
539
+ data); a slab kept after `each_slab`; a `CARecord` after `Marshal.load`;
540
+ shapes and indices whose arithmetic overflows; `refer(:object)` and
541
+ `bitfield` on object data; `scatter_*!` on complex; `MIN / -1` on Linux
542
+ x86; struct members outside the record; fixlen stores of another width;
543
+ reductions in several Ractors.
544
+
545
+ - Fix: an operation that raises part way (a block, a conversion, a
546
+ division by zero) leaves its arrays usable and frees its memory. Before,
547
+ an array could stay attached, and after 32 such errors every lazy
548
+ expression failed with "all 32 slots in use".
549
+
550
+ - Fix: iterator reductions answer as the same reduction on an array: every
551
+ one takes `min_count:` and `fill_value:` (`blocks(n).percentile(p,
552
+ min_count: k)` read them as a second percentile), a group's counts apply
553
+ `min_count:` to the right cells, a group's `wmean` no longer takes
554
+ `fill_value:` as a weight, a window of only NaN gives NaN, and object
555
+ weights in `segments` stay exact.
556
+
557
+ - Fix: `CAFrame` round trips through CSV and records: quotes, separators of
558
+ several characters or spaces, lines of spaces, a duplicated header name,
559
+ complex `Infinity` / `NaN`, months and years, hour 24, a one-column file
560
+ with a blank name; nested arrays, `Complex` and `Rational` in
561
+ `from_records`. `fill`, `to_table` and `filter(keep_masked:)` work with
562
+ N-D and categorical columns; `meld` and `concatenate` take empty frames;
563
+ `group_by` takes a categorical key and treats NaN in a composite key as
564
+ one value.
565
+
566
+ - Fix: Faces stay Faces: the reductions of `windows` and `blocks`,
567
+ `partition_copy`, `then_else`, `clip`, `mask_eq` and `meld` return the
568
+ Face, and a Face's own state survives `min(axis:)`, `cummax` and
569
+ `partition_copy`. `axis_group` and categorical reductions take boolean,
570
+ complex, object and Face values; a time array's `fill_value:` is a time
571
+ on every path. `CAFrame#fill(:linear)` interpolates any Face that defines
572
+ `linear_fetch`. A categorical refuses `clip` and `minmax` as it refuses
573
+ `min`.
574
+
575
+ - Fix: types kept through operations: complex arrays work with `unique`,
576
+ `is_in` and the rest of that family; `meld` reductions answer as on a
577
+ copy; fixlen strings of different widths match; `atan2`, `hypot` and
578
+ others keep float32 and integer types; a record member declared with
579
+ `endian:` reads, sorts, saves and loads correctly.
580
+
581
+ - Fix: NaN and masked cells are treated the same everywhere: NaN is last in
582
+ object sorts and `categorize`, loses `min` / `max`, and is found by
583
+ `CAFrame#at(Float::NAN)`; `min_index` never points at a masked cell or a
584
+ NaN; `min_count:` and `fill_value:` are honoured where they were ignored;
585
+ a lazy expression's mask follows its operands; a selection or `shift`
586
+ follows later mask changes; `invert_mask` works on a selection.
587
+
588
+ - Fix: MemoryView: a `CAFixlenString` exports as bytes and a frozen fixlen
589
+ array can be exported; `CATime`, `CACategorical` and `CAConstString` are
590
+ refused by `memory_view_available?` with the reason, instead of answering
591
+ `true` and failing.
592
+
593
+ - Fix: with carray-jit: two expressions that differ only in which operand an
594
+ operation reads no longer share a kernel, and a store whose destination
595
+ overlaps an operand is computed by CArray.
596
+
597
+ - Fix: for C extensions: a `CA_KERNEL_WRITE` walk over a view that holds a
598
+ cell more than once keeps the cells the kernel wrote; a walk left with
599
+ `break` writes back its slab; writes through a `CAGrid`, `CAWindow` or
600
+ `CAShift` over a view reach the array; the sweep engine and paired walks
601
+ read an argument sharing the output's memory as it was; a view class
602
+ that is not registered with `ca_iter_register_source_kind` is still
603
+ accepted. Rebuild the extension.
604
+
37
605
  ## 3.0.2
38
606
 
39
607
  - New: `CArray::AddressBasis`, for a C extension whose code addresses cells
data/README.md CHANGED
@@ -4,18 +4,17 @@ Ruby/CArray is an extension library for the multi-dimensional array class. It pr
4
4
 
5
5
  ## Status
6
6
 
7
- 3.0.x still moves: behavior can change between releases — see [CHANGELOG.md](CHANGELOG.md). 3.1 is the first release meant to be depended on. Until then, treat it as a place to try things out.
7
+ 3.0.x still moves: behavior can change between releases. 3.1 is the first release meant to be depended on. Until then, treat it as a place to try things out.
8
8
 
9
9
  ## Features
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
14
- * Kernel-style iteration: run a Ruby block over each sub-array spanning the axes you choose
15
- * Attach domain meaning (time, angle, quantity with units…) without changing storage — a Face
13
+ * [MemoryView protocol](guides/users/15_memory_view.md) on both sides: share buffers with other numerical libraries without copying
16
14
  * Define your own array class in pure Ruby while keeping the full CArray interface
17
- * Pack multiple values into one element as a record type
18
- * Comes with a DataFrame (`CAFrame`) whose columns are plain CArrays, so masks and views keep working on them
15
+ * Kernel-style iteration: run a Ruby block over each sub-array spanning the axes you choose
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`](guides/dataframe/README.md)) whose columns are plain CArrays, so masks and views keep working on them
19
18
 
20
19
  Each of these is shown, briefly and with a runnable example, in [A tour of the features](docs/FeatureTour.md).
21
20
 
@@ -120,6 +119,7 @@ b.strip_mask(Float::NAN).sum(axis: 0)
120
119
  * [Views](guides/users/06_views.md) — referring to data without copying
121
120
  * [Reduction and statistics](guides/users/04_reduction_and_statistics.md) — summaries, whole or per axis
122
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
123
123
 
124
124
  ## Contributing
125
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.2"
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"