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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +264 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +1 -6
- data/ext/ca_axis_group.c +27 -27
- data/ext/ca_binop_dispatch.c +1 -29
- data/ext/ca_binop_dispatch.h +0 -1
- data/ext/ca_categorical_iterator.c +205 -134
- data/ext/ca_compare.c +7 -18
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1234 -1994
- data/ext/ca_kernel_iterator.h +391 -437
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +96 -39
- data/ext/ca_obj_bincmp.c +24 -21
- data/ext/ca_obj_binop.c +15 -26
- data/ext/ca_obj_bitarray.c +3 -2
- data/ext/ca_obj_bitfield.c +5 -6
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +5 -6
- data/ext/ca_obj_const_string.c +173 -19
- data/ext/ca_obj_face.c +238 -57
- data/ext/ca_obj_face.h +19 -0
- data/ext/ca_obj_fake.c +15 -29
- data/ext/ca_obj_farray.c +6 -3
- data/ext/ca_obj_field.c +17 -5
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +406 -132
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +67 -57
- data/ext/ca_obj_object.c +157 -51
- data/ext/ca_obj_record.c +12 -7
- data/ext/ca_obj_reduce.c +13 -8
- data/ext/ca_obj_refer.c +25 -27
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +6 -5
- data/ext/ca_obj_select.c +14 -9
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +11 -1
- data/ext/ca_obj_stack.c +179 -34
- data/ext/ca_obj_stride.c +162 -115
- data/ext/ca_obj_string.c +71 -4
- data/ext/ca_obj_tile.c +6 -5
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +5 -3
- data/ext/ca_obj_triop.c +23 -32
- data/ext/ca_obj_window.c +190 -26
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +181 -75
- data/ext/carray_access.c +184 -96
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +89 -6
- data/ext/carray_bincount.c +10 -8
- data/ext/carray_broadcast.c +13 -8
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +108 -0
- data/ext/carray_cast.c +142 -24
- data/ext/carray_cast_func.rb +46 -6
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +16 -7
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +147 -55
- data/ext/carray_count.c +50 -20
- data/ext/carray_element.c +76 -33
- data/ext/carray_factorize.c +118 -64
- data/ext/carray_generate.c +191 -50
- data/ext/carray_histogram.c +62 -17
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +336 -29
- data/ext/carray_kernels_bincmp.c +4453 -0
- data/ext/carray_kernels_binop.c +11368 -0
- data/ext/carray_kernels_init.c +1734 -0
- data/ext/carray_kernels_moncmp.c +2104 -0
- data/ext/carray_kernels_monop.c +18369 -0
- data/ext/carray_kernels_reduce_aggregate.c +23818 -0
- data/ext/carray_kernels_reduce_boolean.c +406 -0
- data/ext/carray_kernels_reduce_cumulative.c +10086 -0
- data/ext/carray_kernels_reduce_extreme.c +17634 -0
- data/ext/carray_kernels_reduce_variance.c +3849 -0
- data/ext/carray_kernels_scan.c +4302 -0
- data/ext/carray_kernels_search.c +33829 -0
- data/ext/carray_kernels_sort.c +10906 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +292 -72
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +124 -47
- data/ext/carray_order.c +384 -76
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +67 -13
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +63 -38
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +91 -28
- data/ext/carray_sort.c +35 -35
- data/ext/carray_struct.c +19 -18
- data/ext/carray_test.c +26 -5
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +246 -45
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +198 -240
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +126 -22
- data/lib/carray/autoload_carray.rb +8 -31
- data/lib/carray/autoload_method_extension.rb +14 -5
- data/lib/carray/axis_group.rb +255 -106
- data/lib/carray/basics.rb +78 -10
- data/lib/carray/bincount_nd.rb +12 -2
- data/lib/carray/block_iterator.rb +126 -23
- data/lib/carray/boolean_reduce.rb +17 -17
- data/lib/carray/categorical.rb +165 -43
- data/lib/carray/categorical_iterator.rb +130 -27
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +14 -5
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +7 -1
- data/lib/carray/frame/column_verbs.rb +70 -0
- data/lib/carray/frame/convert.rb +69 -0
- data/lib/carray/frame/csv_parser.rb +111 -17
- data/lib/carray/frame/describe.rb +3 -2
- data/lib/carray/frame/frame.rb +246 -21
- data/lib/carray/frame/group.rb +510 -95
- data/lib/carray/frame/io.rb +115 -28
- data/lib/carray/frame/join.rb +312 -51
- data/lib/carray/frame/records.rb +83 -7
- data/lib/carray/frame/reshape.rb +42 -35
- data/lib/carray/frame/sort.rb +7 -19
- data/lib/carray/frame/verbs.rb +188 -48
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +11 -4
- data/lib/carray/fusion.rb +40 -16
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +31 -8
- data/lib/carray/iterator.rb +85 -7
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +182 -183
- data/lib/carray/mask_gap_fill.rb +63 -57
- data/lib/carray/meld_reduce.rb +12 -14
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +16 -0
- data/lib/carray/methods/bit_string.rb +1 -1
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +3 -1
- data/lib/carray/methods/gather_nd.rb +14 -5
- data/lib/carray/methods/insert_block.rb +2 -2
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +53 -36
- data/lib/carray/methods/join.rb +1 -6
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +47 -51
- data/lib/carray/methods/mode.rb +1 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/resize.rb +3 -3
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +3 -3
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +53 -8
- data/lib/carray/segment_iterator.rb +313 -82
- data/lib/carray/serialize.rb +24 -10
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +8 -1
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +19 -8
- data/lib/carray/time.rb +726 -104
- data/lib/carray/window_iterator.rb +122 -16
- data/lib/carray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +4 -0
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +2 -1
- data/yard-stubs/ca_obj_roll.rb +2 -2
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_cast.rb +10 -0
- data/yard-stubs/carray_conversion.rb +2 -1
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +26 -2
- data/yard-stubs/carray_math.rb +27 -1
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +29 -18
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +14 -9
- data/yard-stubs/carray_slab.rb +9 -2
- data/yard-stubs/carray_sort.rb +6 -5
- data/yard-stubs/carray_test.rb +5 -3
- metadata +25 -3
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d2edeb545754cf31d330c667913471c1a0035c97de72dabad7e7b2afb4fe272b
|
|
4
|
+
data.tar.gz: 8b34390fcabbb04c5e1f0926ae103052345196112ec3a6a16f244fb310df5583
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
data/ext/ca_axis_descriptor.h
CHANGED
|
@@ -2,13 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
ca_axis_descriptor.h
|
|
4
4
|
|
|
5
|
-
Per-axis descriptor framework
|
|
6
|
-
|
|
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 (
|
|
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
|
-
/* ----
|
|
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
|
|
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
|
-
/* ----
|
|
86
|
+
/* ---- producer interface --------------------------------------------------
|
|
90
87
|
|
|
91
|
-
|
|
92
|
-
and `out_parent_dims` (caller-allocated, sized
|
|
93
|
-
|
|
94
|
-
|
|
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
|
|
98
|
-
flat-index
|
|
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
|
-
/* ----
|
|
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
|
|
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
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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.
|
|
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.) */
|
data/ext/ca_axis_dispatch.c
CHANGED
|
@@ -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
|
-
|
|
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
|
-
/*
|
|
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(); /*
|
|
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
|
|
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
|
-
|
|
395
|
-
|
|
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
|
|
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
|
-
/*
|
|
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
|
|
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
|
|
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
|
-
|
|
1230
|
-
|
|
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, "
|
|
1424
|
+
rb_define_method(rb_cCArray, "__reduce_by_axis_groups__",
|
|
1425
1425
|
rb_ca_axis_group_reduce, 3);
|
|
1426
|
-
rb_define_method(rb_cCArray, "
|
|
1426
|
+
rb_define_method(rb_cCArray, "__scan_by_axis_groups__",
|
|
1427
1427
|
rb_ca_axis_group_scan, 3);
|
|
1428
1428
|
}
|
data/ext/ca_binop_dispatch.c
CHANGED
|
@@ -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
|
|
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
|
-
}
|
data/ext/ca_binop_dispatch.h
CHANGED
|
@@ -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 */
|