carray 3.0.3 → 3.0.5
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 +469 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_array_pool.c +25 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +14 -26
- 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 +231 -153
- data/ext/ca_compare.c +9 -20
- data/ext/ca_composite_dispatch.c +9 -9
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1240 -2000
- data/ext/ca_kernel_iterator.h +502 -519
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +152 -45
- data/ext/ca_obj_bincmp.c +25 -21
- data/ext/ca_obj_binop.c +16 -26
- data/ext/ca_obj_bitarray.c +8 -3
- data/ext/ca_obj_bitfield.c +63 -49
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +7 -7
- data/ext/ca_obj_const_string.c +188 -22
- data/ext/ca_obj_face.c +280 -58
- 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 +30 -8
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +455 -134
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +113 -67
- data/ext/ca_obj_object.c +210 -52
- data/ext/ca_obj_record.c +15 -7
- data/ext/ca_obj_reduce.c +17 -8
- data/ext/ca_obj_refer.c +42 -35
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +31 -10
- data/ext/ca_obj_select.c +48 -14
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +41 -7
- data/ext/ca_obj_stack.c +180 -34
- data/ext/ca_obj_stride.c +190 -134
- data/ext/ca_obj_string.c +80 -4
- data/ext/ca_obj_tile.c +32 -11
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +13 -7
- data/ext/ca_obj_triop.c +26 -32
- data/ext/ca_obj_window.c +267 -74
- data/ext/ca_op_ipower.c +4 -4
- data/ext/ca_sort_kernels.h +6 -3
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +214 -75
- data/ext/carray_access.c +200 -99
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +113 -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 +375 -96
- data/ext/carray_cast_func.rb +90 -20
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +18 -9
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +150 -55
- data/ext/carray_count.c +56 -20
- data/ext/carray_element.c +81 -33
- data/ext/carray_factorize.c +138 -84
- data/ext/carray_generate.c +199 -52
- data/ext/carray_histogram.c +63 -18
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +348 -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 +10897 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +220 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +337 -94
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +129 -52
- data/ext/carray_order.c +604 -77
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +85 -31
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +87 -45
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +123 -37
- data/ext/carray_sort.c +259 -51
- data/ext/carray_sort_kernel.c +5 -7
- data/ext/carray_struct.c +54 -61
- data/ext/carray_test.c +26 -5
- data/ext/carray_time_text.c +4 -2
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +309 -66
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +403 -350
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +139 -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 +105 -17
- 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 +195 -59
- data/lib/carray/categorical_iterator.rb +132 -29
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +24 -5
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +9 -1
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +48 -3
- data/lib/carray/frame/column_verbs.rb +71 -0
- data/lib/carray/frame/concat.rb +17 -3
- 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 +252 -28
- data/lib/carray/frame/group.rb +603 -101
- data/lib/carray/frame/io.rb +117 -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 +42 -6
- 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 +217 -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 +61 -37
- 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 +323 -88
- data/lib/carray/serialize.rb +45 -14
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/stack.rb +15 -12
- data/lib/carray/string.rb +113 -5
- data/lib/carray/string_operation_extension.rb +21 -6
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +24 -11
- data/lib/carray/time.rb +819 -158
- 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_transpose.rb +5 -4
- data/yard-stubs/ca_obj_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +3 -6
- data/yard-stubs/carray_cast.rb +12 -0
- data/yard-stubs/carray_conversion.rb +7 -2
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +17 -10
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +32 -3
- data/yard-stubs/carray_math.rb +41 -5
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +129 -22
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +17 -10
- 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: ccd30e8ea5b53c3a2654a86a0ab7473b3073f7feffa7db7be0e5c9aef5bc17c8
|
|
4
|
+
data.tar.gz: ffcd91fe93ca10b4b12dbff035ffc25533699472b364482a59bf2aa635296032
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 53c08f4ccf6a4c25219cef4e8f27e7de9740dc8c69ee493ff8e3631c87499cd15ed121d5f7707bd1017f77e0309dc1be2628fa3611b9b3c979e0e075008842d6
|
|
7
|
+
data.tar.gz: 2200b047a456603d6274d9dfaf8f93c011ce1cc1eb457c454fa7f9cdc9c75ea4b96c9bbe1dab0b37710f8b872ac5e8b630db5c0dacae12a9012b1b34d4c7f1ec
|
data/CHANGELOG.md
CHANGED
|
@@ -34,6 +34,475 @@ 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.5
|
|
38
|
+
|
|
39
|
+
- New: `GroupedFrame#aggregate` takes a block instead of a spec. The block
|
|
40
|
+
is given the grouping once and returns a Hash of output name => a
|
|
41
|
+
CArray with one value per group, built from `g["col"]` iterators and
|
|
42
|
+
CArray arithmetic (`g["temp"].max - g["temp"].min`). `grp[array]`
|
|
43
|
+
groups any CArray with one entry per row, such as a value computed
|
|
44
|
+
from columns or a column with cells masked.
|
|
45
|
+
|
|
46
|
+
- New: a `CAFrame` grouped reduction takes a Hash of column name => value
|
|
47
|
+
as `fill_value:`, filling only the named columns. A single
|
|
48
|
+
`fill_value:` still goes to every column and has to suit each.
|
|
49
|
+
|
|
50
|
+
- New: `CArray.meld` brings pieces of different data types to a common
|
|
51
|
+
one, as `CArray.stack` does, and takes `data_type:`. `CAFrame.meld` and
|
|
52
|
+
a frame splice still refuse a column whose pieces differ in data type;
|
|
53
|
+
cast the column first, or use `concatenate`.
|
|
54
|
+
|
|
55
|
+
- New: `scatter_replace!` takes an object or fixed-length array, as
|
|
56
|
+
`put_nd` and `put_along_axis` do. The accumulating members
|
|
57
|
+
(`scatter_add!` and the others) still take numeric arrays only.
|
|
58
|
+
|
|
59
|
+
- New: `CAConstString#count` and `CACategorical#count` with no argument
|
|
60
|
+
count the cells that are not masked, as `CArray#count` does.
|
|
61
|
+
|
|
62
|
+
- New: `CAFixlenString` answers `minmax`, `cummax` and `cummin`, as
|
|
63
|
+
`CAString` does.
|
|
64
|
+
|
|
65
|
+
- New (C extensions): `carray.h` defines `ca_u_<type>` cell types and
|
|
66
|
+
`CA_U(type)`, of the same size and value as the plain types but with no
|
|
67
|
+
alignment requirement, for reading cells that need not be aligned (a
|
|
68
|
+
refer with a byte offset, a struct member, a wrapped buffer). The slab
|
|
69
|
+
macros in `ca_kernel_iterator.h` use them for their pointers.
|
|
70
|
+
|
|
71
|
+
- Change: `CACategorical#sort_addr` is renamed `group_addr`, the order of
|
|
72
|
+
the cells by category. `sort_addr` on a categorical now raises, as
|
|
73
|
+
`sort_index` does, since a categorical has no order of values.
|
|
74
|
+
|
|
75
|
+
- Change: a Face's `parent` (of a `CATime`, `CARecord`, ...) is a
|
|
76
|
+
read-only view of its storage. Write the storage of a time through
|
|
77
|
+
`CATime#ticks`.
|
|
78
|
+
|
|
79
|
+
- Change: an operator that cannot bring two data types together raises
|
|
80
|
+
`CArray::DataTypeError` instead of `TypeError`. `DataTypeError` is a
|
|
81
|
+
`TypeError`, so `rescue TypeError` still catches it.
|
|
82
|
+
|
|
83
|
+
- Change: a float cell with no integer of the target type -- an infinity,
|
|
84
|
+
or a value out of the type's range -- is now treated the way NaN
|
|
85
|
+
already was. `to_type` (`int32`, `as_int64`, ...) masks it to `UNDEF`;
|
|
86
|
+
storing it into an integer array raises `RangeError`
|
|
87
|
+
(`FloatDomainError` for an infinity). Before, it became whatever the
|
|
88
|
+
machine's C conversion gave, which differed between x86 and ARM.
|
|
89
|
+
`clip_int64` and the other `clip_<type>` methods saturate a float
|
|
90
|
+
source to the type's limits on every machine; integer `linspace` raises
|
|
91
|
+
`RangeError` for a span the type cannot hold.
|
|
92
|
+
|
|
93
|
+
- Change: a Ruby Array operand of a numeric or boolean array is read as
|
|
94
|
+
its cells: `a.eq([1, 5, 3])` compares cell by cell (it compared every
|
|
95
|
+
cell with the whole Array), and `a + [1, 2, 3]` adds (it raised).
|
|
96
|
+
Nested Arrays give the axes. An object array still takes an Array as
|
|
97
|
+
one value.
|
|
98
|
+
|
|
99
|
+
- Change: `window`'s `bounds:` is a policy named by a Symbol or String,
|
|
100
|
+
matched whole; an Integer and an abbreviation raise. A `fill_value:`
|
|
101
|
+
given with a policy that does not use it (`:nearest`, `:strict`, ...)
|
|
102
|
+
raises instead of being dropped.
|
|
103
|
+
|
|
104
|
+
- Change: a length, count, offset or shift given to a view
|
|
105
|
+
(`sliding_windows`, `block_view`, `tile`, `roll`, `shift`, `field`,
|
|
106
|
+
`diagonal`) must be an Integer; a Float raises `TypeError` instead of
|
|
107
|
+
being truncated. `transpose` reads its axes as the other axis arguments
|
|
108
|
+
are read: negative from the end, an Integer only.
|
|
109
|
+
|
|
110
|
+
- Change: `drop_axis` on an array whose every axis has size 1 keeps one
|
|
111
|
+
axis of size 1, and `reshape` with no axes raises.
|
|
112
|
+
|
|
113
|
+
- Change: in an index of one key per axis, an index array of more than
|
|
114
|
+
one axis on one axis raises `ArgumentError`; it was read flat. Pass
|
|
115
|
+
`idx.flatten` for the old reading.
|
|
116
|
+
|
|
117
|
+
- Change: `elem_fetch`, `elem_store` and the other `elem_*` methods read
|
|
118
|
+
an index as `[]` reads a key: a Float with no fraction is an index, a
|
|
119
|
+
Float with a fraction raises `IndexError`.
|
|
120
|
+
|
|
121
|
+
- Change: two string arrays of different kinds (`CAString`,
|
|
122
|
+
`CAFixlenString`, `CAConstString`) or of different widths compare by
|
|
123
|
+
their strings. A String query longer than a fixed-width cell matches
|
|
124
|
+
no cell in `eq`, `count`, `search`, `bsearch` and `is_in`; it was cut
|
|
125
|
+
to the cell's width.
|
|
126
|
+
|
|
127
|
+
- Change: `str_index` and `rindex` give `UNDEF` for a cell that does not
|
|
128
|
+
hold the substring; they raised for the whole array.
|
|
129
|
+
|
|
130
|
+
- Change: `bsearch` and `bsearch_addr` answer the first of several equal
|
|
131
|
+
cells.
|
|
132
|
+
|
|
133
|
+
- Change: `search` and `search_addr` raise `ArgumentError` for a negative
|
|
134
|
+
or NaN `eps`, which acted as an exact match.
|
|
135
|
+
|
|
136
|
+
- Change: `inherit_mask` and `inherit_mask_replace` raise `ArgumentError`
|
|
137
|
+
for a source whose number of cells differs from the receiver's (a
|
|
138
|
+
scalar source still applies to every cell).
|
|
139
|
+
|
|
140
|
+
- Change: a reduction's `fill_value:` that its result cannot hold raises
|
|
141
|
+
even when no cell needs it, and `fill` on an empty array checks its
|
|
142
|
+
value as an assignment does.
|
|
143
|
+
|
|
144
|
+
- Change: rounding a `:M` or `:Y` `CATime` to a calendar bucket
|
|
145
|
+
(`round(unit: :Y)`, `"3 months"`) measures the distance by the instant,
|
|
146
|
+
so it agrees with the same dates on `:D`.
|
|
147
|
+
|
|
148
|
+
- Change: a `CATime` reduction (`mean`, `median`, ...) sends a tie to the
|
|
149
|
+
later tick on both sides of 1970; before 1970 it went to the earlier
|
|
150
|
+
one.
|
|
151
|
+
|
|
152
|
+
- Change: a duration String added to or subtracted from a `CATime` is
|
|
153
|
+
one step of its own resolution, so `"15 minutes"` on a `"10 minutes"`
|
|
154
|
+
grid raises, as the same duration as a `CATimedelta` does. It was read
|
|
155
|
+
as fifteen one-minute steps and cut to the grid.
|
|
156
|
+
|
|
157
|
+
- Change: of `-0.0` and `0.0`, `pmax` gives `0.0` and `pmin` gives
|
|
158
|
+
`-0.0`, in either order and on every platform, as `maximum` and
|
|
159
|
+
`minimum` do. Which zero `min` and `max` answer is not specified.
|
|
160
|
+
|
|
161
|
+
- Change: a one-sided `clip` passes a NaN cell through, as a two-sided
|
|
162
|
+
`clip` does.
|
|
163
|
+
|
|
164
|
+
- Change: a categorical's `fill_value:` (of `shift`, `window`, `project`)
|
|
165
|
+
is a label; a `CAConstString` takes only `UNDEF` as a fill value.
|
|
166
|
+
|
|
167
|
+
- Change: a lazy operator with a Face operand (a categorical, a time, a
|
|
168
|
+
string array) answers as the eager operator does; it read the Face's
|
|
169
|
+
storage. `CAConstString#eq` with another array compares cell by cell.
|
|
170
|
+
|
|
171
|
+
- Change: a boolean member of a record (or `field(offset, :boolean)` of a
|
|
172
|
+
fixed-length array) raises `RangeError` when read as a byte that is not
|
|
173
|
+
0 or 1, instead of answering differently in each method.
|
|
174
|
+
|
|
175
|
+
- Change: unmasking a cell of a `CAString` that holds no String gives an
|
|
176
|
+
empty String.
|
|
177
|
+
|
|
178
|
+
- Change: `swap_bytes` keeps the attributes, as `refer` and `bitfield`
|
|
179
|
+
do. An array with no cells has no say in the attributes a `meld`,
|
|
180
|
+
`stack` or `concatenate` keeps.
|
|
181
|
+
|
|
182
|
+
- Change: `dim_view` keeps a Face, as `transpose` does.
|
|
183
|
+
|
|
184
|
+
- Change: `CArray.string(n)` without a block, and `CArray.string("ab")`,
|
|
185
|
+
raise; `fixlen_string` and `to_fixlen_string` raise for `bytes:` below 1.
|
|
186
|
+
`project` raises for a keyword argument, `paste` into a frozen array
|
|
187
|
+
raises `FrozenError`, and `CArray.result_type` refuses a MemoryView
|
|
188
|
+
operand whose format carray cannot read, as the operators do.
|
|
189
|
+
|
|
190
|
+
- Change: `CArray.sort_addr` with numeric keys is two to three times as fast, and
|
|
191
|
+
`nlargest` / `nsmallest` read each fiber once with a work area of a
|
|
192
|
+
few times n.
|
|
193
|
+
|
|
194
|
+
- Fix: x86-64 Linux. Inputs that reached an integer division by zero
|
|
195
|
+
inside the library stopped the process with SIGFPE there (on ARM they
|
|
196
|
+
were refused later or gave a wrong answer): a sum over a view with a
|
|
197
|
+
zero-length axis, `wsum` / `wmean` with 1-D weights over a zero-length
|
|
198
|
+
axis, a view of a stack of empty arrays, `window` with a step of 0, and
|
|
199
|
+
`wrap_readonly(String, CA_FIXLEN)`. Each now answers or raises
|
|
200
|
+
`ArgumentError`. The extension builds with GCC 14 without warnings.
|
|
201
|
+
|
|
202
|
+
- Fix: big-endian hosts. `bitfield` read 0 and lost writes, a struct's
|
|
203
|
+
bit members overwrote each other, and an element-wise operation applied
|
|
204
|
+
in place could give a wrong cell.
|
|
205
|
+
|
|
206
|
+
- Fix: `save` and `dump` with `endian: :little` or `:big` wrote the other
|
|
207
|
+
byte order. `load` reads the marker, so files written so far still load
|
|
208
|
+
correctly.
|
|
209
|
+
|
|
210
|
+
- Fix: running out of memory inside a kernel left a view attached, lost
|
|
211
|
+
the keywords of the call (`a.sum(axis: 1)` returned the total), or
|
|
212
|
+
leaked the array being built.
|
|
213
|
+
|
|
214
|
+
- Fix: an array with 16 axes (the maximum) given to `bitarray`, `field`,
|
|
215
|
+
a narrowing `refer` or a `:_` index wrote past an internal array.
|
|
216
|
+
|
|
217
|
+
- Fix: a lazy chain whose step narrows the cells (`a.lazy.abs` of a
|
|
218
|
+
complex array) overran the heap; `seq` on an empty object array wrote
|
|
219
|
+
past its end.
|
|
220
|
+
|
|
221
|
+
- Fix: a CAObject's copy and sync hooks: a view the hook kept of the
|
|
222
|
+
array it was lent, or the lent array's mask, pointed at freed memory
|
|
223
|
+
after the hook returned.
|
|
224
|
+
|
|
225
|
+
- Fix: `CArray.fuse` crashed when several Ractors ran a fuse block for the
|
|
226
|
+
first time at once.
|
|
227
|
+
|
|
228
|
+
- Fix: a grouped `variancep` / `stddevp` matches `CArray#variancep` to the
|
|
229
|
+
last bit.
|
|
230
|
+
|
|
231
|
+
- Fix: `count` with an array of values honours `keep_axis:`.
|
|
232
|
+
|
|
233
|
+
- Fix: `CARecord.wrap` of a record array wraps its storage, not the
|
|
234
|
+
record array.
|
|
235
|
+
|
|
236
|
+
- Fix: an unnamed struct's `order_by` survives `save` / `load` and
|
|
237
|
+
Marshal.
|
|
238
|
+
|
|
239
|
+
- Fix: `CAFrame.from_csv` and `cast(name => :time)` read a leap second
|
|
240
|
+
(`23:59:60`) as `CArray.time` does, into the next minute.
|
|
241
|
+
|
|
242
|
+
## 3.0.4
|
|
243
|
+
|
|
244
|
+
- New: `CAFrame#verify(rules)` judges every row against named rules (each
|
|
245
|
+
a callable that returns a boolean CArray) and returns the verdicts as a
|
|
246
|
+
frame, one column per rule; a row whose rule read a masked value is
|
|
247
|
+
`UNDEF`, so `count(false)` counts the rows that break it.
|
|
248
|
+
|
|
249
|
+
- New: `CAFrame#join` takes `how: :semi` and `:anti` (the left rows that
|
|
250
|
+
have, or have no, match), several key columns (`on: ["station",
|
|
251
|
+
"date"]`), and the index as a key by the row axis name.
|
|
252
|
+
`CAFrame#join_asof` takes the index too, and `by:` columns that must
|
|
253
|
+
match exactly before the nearest key is taken.
|
|
254
|
+
|
|
255
|
+
- New: a `CAFrame` grouping has more verbs. The short form of `prod`,
|
|
256
|
+
`accumulate`, `median`, `variance`, `stddev`, `variancep`, `stddevp`,
|
|
257
|
+
`first`, `last`, `nunique`, `count`, `all` and `any`, beside `sum` /
|
|
258
|
+
`mean` / `min` / `max`; `filter` (keep the groups a block chooses);
|
|
259
|
+
`lag`, `order`, `cumsum` and the other running values, and
|
|
260
|
+
`fill(name, :ffill)` / `:bfill`, all kept on the frame's rows; and
|
|
261
|
+
`to_frame`. The reductions take column names (`grp.mean("temp")` is a
|
|
262
|
+
CArray) and `keep_rows: true`, which gives each row its own group's
|
|
263
|
+
result.
|
|
264
|
+
|
|
265
|
+
- New: `CAFrame#resample` takes `by:`, columns whose groups are binned
|
|
266
|
+
apart: `df.resample("time", "1 day", by: "station").max("temp")`.
|
|
267
|
+
|
|
268
|
+
- New: `CArray#windows(on:, before:, after:)` bounds each window by a
|
|
269
|
+
width of a key (a time, a duration or a number) instead of a count of
|
|
270
|
+
cells, with `by:`, `exclude:`, `interval:` and `at:` (windows placed at
|
|
271
|
+
given points, which may overlap). The key need not be sorted, and the
|
|
272
|
+
value may have several columns (shape `(N, ...)`). `CAFrame#windows(on:
|
|
273
|
+
"time", ...)` does the same for a frame's columns.
|
|
274
|
+
|
|
275
|
+
- New: `CArray#lag(n = 1, axis:)` is the value `n` steps earlier along an
|
|
276
|
+
axis, `UNDEF` where there is none, so `x - x.lag` starts with `UNDEF`.
|
|
277
|
+
|
|
278
|
+
- New: the slab, block, segment, categorical and axis-group iterators
|
|
279
|
+
have `lag`, `order` (each cell's rank within its piece) and
|
|
280
|
+
`strip_mask(method: :ffill / :bfill)`; each of them works within one
|
|
281
|
+
piece and never takes a value from another. Every iterator has `first`,
|
|
282
|
+
`last` and `nunique`.
|
|
283
|
+
|
|
284
|
+
- New: `CArray#is_between(lo, hi, exclude:)` (or a Range) is true where a
|
|
285
|
+
value lies between two bounds; `exclude: :lower`, `:upper` or `:both`
|
|
286
|
+
leaves bounds out, and `nil` or an open end leaves a side unbounded.
|
|
287
|
+
|
|
288
|
+
- New: `CArray#round(ndigits)` rounds each element to `ndigits` decimal
|
|
289
|
+
places (negative for tens, hundreds, ...), as `Float#round` and
|
|
290
|
+
`Integer#round` do.
|
|
291
|
+
|
|
292
|
+
- New: `CArray#to_frame(*names, axis: -1)` shows an array as a CAFrame
|
|
293
|
+
whose columns are views of it, one per position along `axis`.
|
|
294
|
+
|
|
295
|
+
- New: `CACategorical#contrast(base:, full:)` gives one int8 column per
|
|
296
|
+
category (1 in the cell's category, the base left out unless `full:
|
|
297
|
+
true`), and `CAFrame#contrast_columns(name, ...)` puts those columns in
|
|
298
|
+
the frame in place of the categorical.
|
|
299
|
+
|
|
300
|
+
- New: `CAFrame#is_duplicate(*names, except:)` is true for the rows that
|
|
301
|
+
repeat an earlier row in the named columns; `except: :last` or `:none`
|
|
302
|
+
chooses which occurrence stays unmarked.
|
|
303
|
+
|
|
304
|
+
- New: `CAFrame#append(name, col, before:, after:)` puts the column next
|
|
305
|
+
to another one.
|
|
306
|
+
|
|
307
|
+
- New: a `CAFrame` carries attributes of the frame as a whole (`attr`,
|
|
308
|
+
`set_attr`, `attrs`, ..., and `CAFrame.new(..., attrs:)`), separate from
|
|
309
|
+
each column's. A row selection or a change of columns keeps them; a
|
|
310
|
+
summary, a join or a reshape does not.
|
|
311
|
+
|
|
312
|
+
- New: `CAFrame#to_csv(attrs: [:units, ...])` writes one line per
|
|
313
|
+
attribute key below the names, and `CAFrame.from_csv(attrs: [...])`
|
|
314
|
+
reads them back as column attributes; in a reading block,
|
|
315
|
+
`r.header(:units)` does the same for a line anywhere in the header.
|
|
316
|
+
|
|
317
|
+
- New: `CAFrame.from_csv` `columns:` takes a Hash that selects and names
|
|
318
|
+
columns, and the names `c0`, `c1`, ... of a file without a header;
|
|
319
|
+
`cast` and `from_csv` `types:` take `:categorical`. `CAFrame.new` takes
|
|
320
|
+
`types:` and `on_error:`, as `from_records` does.
|
|
321
|
+
|
|
322
|
+
- New: `CArray#delete_attr(key)` removes an attribute and returns its
|
|
323
|
+
value.
|
|
324
|
+
|
|
325
|
+
- New: `CATime#end_of(unit:, origin:)` (the last tick of each time's
|
|
326
|
+
bucket), `days_in_month`, `quarter`, and the ISO 8601 week `iso_week`
|
|
327
|
+
with its year `iso_year`.
|
|
328
|
+
|
|
329
|
+
- New: a time or duration array takes a single value in `+` and `-`
|
|
330
|
+
(`t + "3 days"`, `t - t.min`, `t - Time.utc(2024, 1, 1)`), and a month
|
|
331
|
+
or year duration moves a time on a day or finer grid as `Date#>>` does
|
|
332
|
+
(`2024-01-31 + 1 month` is `2024-02-29`). A bare number is still
|
|
333
|
+
refused.
|
|
334
|
+
|
|
335
|
+
- New: a time array compares with a value off its grid (`days.eq(
|
|
336
|
+
"2024-01-03T05:00")`, `<`, `search_nearest`, `is_in`, ...) in the finer
|
|
337
|
+
unit the two share, where it raised `ArgumentError`. An assignment
|
|
338
|
+
still raises.
|
|
339
|
+
|
|
340
|
+
- New: `CATime#pmax` / `pmin` (and `maximum` / `minimum` / `fmax` /
|
|
341
|
+
`fmin`) give the later / earlier time cell by cell.
|
|
342
|
+
|
|
343
|
+
- New: CArray can be used in a Ractor other than the main one, `fuse`
|
|
344
|
+
included, and a frozen array is shared between Ractors without
|
|
345
|
+
copying. See `docs/topics/Ractor.md`.
|
|
346
|
+
|
|
347
|
+
- New: C extensions: `CA_FOR_EACH_WHOLE` and `CA_FOR_EACH_WHOLE_MASKED`
|
|
348
|
+
hand a kernel the whole array as one contiguous run.
|
|
349
|
+
|
|
350
|
+
- Change: `CArray#rank` is removed; use `#ndim`.
|
|
351
|
+
|
|
352
|
+
- Change: `CArray::TableMethods` (`column_names=`, `column`, `row`, `rows`
|
|
353
|
+
and `select` on a 2-D array) is removed; use `a.to_frame("x", "y")`,
|
|
354
|
+
then `df["x"]` for a column or `df.to_records[i]` for a row.
|
|
355
|
+
|
|
356
|
+
- Change: `CArray.load_arrow_tensor`, `CArray#save_arrow_tensor` and
|
|
357
|
+
`CArray::ArrowTensor`, the experimental Arrow tensor IPC reader and
|
|
358
|
+
writer, are removed.
|
|
359
|
+
|
|
360
|
+
- Change: methods whose names start and end with `__` that were public
|
|
361
|
+
internals are now private, renamed or removed. Call the public method
|
|
362
|
+
they served instead.
|
|
363
|
+
|
|
364
|
+
- Change: CAFrame takes column names as Strings only. A Symbol name
|
|
365
|
+
(`df.drop(:a)`, `join(on: :a)`, `CAFrame.new(axis_name: :row)`) raises
|
|
366
|
+
`TypeError`; write `"a"`. Record keys given to `from_records` may still
|
|
367
|
+
be Symbols, and `df[:x]` stays the predicate syntax.
|
|
368
|
+
|
|
369
|
+
- Change: a masked cell of an integer index array keeps its place:
|
|
370
|
+
`x[i]`, the grid forms and `CAFrame` row selection `df[i]` give a
|
|
371
|
+
result shaped like `i`, `UNDEF` where `i` is masked, where they dropped
|
|
372
|
+
those positions. To drop them as before, index by
|
|
373
|
+
`i[i.is_not_masked]`.
|
|
374
|
+
|
|
375
|
+
- Change: an index beside a CArray key is read as it is without one: a
|
|
376
|
+
range ending before its start reads backwards (`a[i, -1..1]`), and an
|
|
377
|
+
Integer key drops its axis (`a[i, 1]` has the shape of `i`; add `:_`
|
|
378
|
+
or use `1..1` to keep it).
|
|
379
|
+
|
|
380
|
+
- Change: an index with a Float that has a fraction (`a[1.5..3]`, a step
|
|
381
|
+
of `0.5`) raises `IndexError`; it was cut to an integer. Convert with
|
|
382
|
+
`to_i` or `round` first. A Float that holds an integer, such as a count
|
|
383
|
+
from `sum`, is still that position.
|
|
384
|
+
|
|
385
|
+
- Change: an index step says the direction, as in Ruby: a step pointing
|
|
386
|
+
away from the end reads nothing (`a[(0..4).step(-1)]` read `a[0]`).
|
|
387
|
+
|
|
388
|
+
- Change: a boolean selector of more than one axis must have the array's
|
|
389
|
+
shape; it picked cells by flat position. Flatten both sides to keep the
|
|
390
|
+
old reading.
|
|
391
|
+
|
|
392
|
+
- Change: storing an integer a cell cannot hold raises `RangeError`
|
|
393
|
+
(`CA_INT8([300])`, `a[0] = 300`, `fill`, `scatter_add!`, a record
|
|
394
|
+
member); it wrapped (`300` into int8 was `44`). Storing or reading a
|
|
395
|
+
NaN into an integer cell (`ints[] = floats`, `as_type`, `fake`) raises
|
|
396
|
+
`FloatDomainError`. To keep C's conversion, use `to_type`, which is
|
|
397
|
+
unchanged.
|
|
398
|
+
|
|
399
|
+
- Change: `CArray.time` reads an Integer as a count of ticks of `unit:`
|
|
400
|
+
(`CArray.time(CA_INT64([0, 10]), unit: :m)` is 00:00 and 00:10); it
|
|
401
|
+
read Unix seconds. To read Unix seconds onto another unit, write
|
|
402
|
+
`CArray.time(secs).to_unit(:m)`.
|
|
403
|
+
|
|
404
|
+
- Change: `CArray.time` without `unit:`, and `CAFrame#parse_to_time` with
|
|
405
|
+
a format or `:mixed`, read the values in the finest unit they show
|
|
406
|
+
(dates alone `:D`, fractions of a second `:ms` / `:us` / `:ns`); it was
|
|
407
|
+
always `:s`. Pass `unit: :s` to keep the old unit.
|
|
408
|
+
|
|
409
|
+
- Change: adding a duration that is coarser than a time's unit and not a
|
|
410
|
+
whole number of its ticks (`"1 day"` on a `"7 hours"` time) raises, and
|
|
411
|
+
so does `CArray#time(origin:)` between two ticks of `unit:`; both were
|
|
412
|
+
cut to the grid. Convert the time to a unit both share first.
|
|
413
|
+
|
|
414
|
+
- Change: `order(descending: true)` puts NaN last and keeps tied cells in
|
|
415
|
+
their original order (`[5, 3, 5, 1, 5]` gives `[0, 3, 1, 4, 2]`, was
|
|
416
|
+
`[2, 3, 1, 4, 0]`); with `method: :dense` the largest value is 0 and
|
|
417
|
+
the ranks have no gaps. Code that used `(n - 1) - order` for the
|
|
418
|
+
descending rank needs that formula written out. `nlargest` no longer
|
|
419
|
+
returns NaN or masked cells first, and `nsmallest` / `nlargest` and
|
|
420
|
+
their `_index` forms break ties by position.
|
|
421
|
+
|
|
422
|
+
- Change: a CAFrame column built from Ruby values is typed by them:
|
|
423
|
+
Integers `int64`, numbers `float64`, Strings a text column (`CAString`),
|
|
424
|
+
arrays of one shape an N-D column, anything else `:object`; it was
|
|
425
|
+
`:object`. This holds for `CAFrame.new("x" => [...])`, `df["x"] = [...]`,
|
|
426
|
+
a group's `table` block and a Proc in `aggregate`. Wrap the values in
|
|
427
|
+
`CA_OBJECT(...)` to keep an object column. A returned array is read
|
|
428
|
+
from the N-D column as `col[i, nil]`.
|
|
429
|
+
|
|
430
|
+
- Change: `CAFrame#melt` names each row's source in a text column
|
|
431
|
+
(`CAString`); it was an object column.
|
|
432
|
+
|
|
433
|
+
- Change: `CAFrame#group_by` on several keys gives a result with no
|
|
434
|
+
index: each key is a column, before the reduced columns. Read the keys
|
|
435
|
+
with `result["station"]` and so on, where the index held tuples.
|
|
436
|
+
|
|
437
|
+
- Change: `CAFrame#data_types`, `describe` and `p df` name a Face column
|
|
438
|
+
by its class (`CATime[D]`, `CAString`) where they gave its storage
|
|
439
|
+
`data_type` (`:fixlen` for most). Read the storage through the Face's
|
|
440
|
+
accessor (`ticks`, `codes`, ...).
|
|
441
|
+
|
|
442
|
+
- Change: a CAFrame verb that takes a list of columns refuses a name
|
|
443
|
+
given twice (`select("a", "a")`, `group_by("a", "a")`) with
|
|
444
|
+
`ArgumentError`. `df["a", "a"]` still gives the column twice.
|
|
445
|
+
|
|
446
|
+
- Change: a CAFrame group or window reduction over a column whose type
|
|
447
|
+
lacks it raises `CArray::DataTypeError`; it raised `ArgumentError`.
|
|
448
|
+
|
|
449
|
+
- Change: a `CAString` holds only Strings: storing `nil`, a number or an
|
|
450
|
+
Array into it raises (use `UNDEF` to mask a cell). A selection among
|
|
451
|
+
Strings (`then_else`, `choose`, `select`, `conditional`) and a
|
|
452
|
+
`CAString`'s String operators give a `CAString`, where they gave an
|
|
453
|
+
object array.
|
|
454
|
+
|
|
455
|
+
- Change: attributes follow conversions, views and copies but not
|
|
456
|
+
reductions: `categorize`, `cast`, `parse_to_time`, `dup`, Marshal and a
|
|
457
|
+
Face's views keep them, and `first` / `last` of a grouping no longer
|
|
458
|
+
carry them. A joined or concatenated array shows the keys every piece
|
|
459
|
+
shows with the same value. An attribute value is stored frozen; change
|
|
460
|
+
it by setting it again.
|
|
461
|
+
|
|
462
|
+
- Change: an error names the method you called, and the common refusals
|
|
463
|
+
open with it ("+: shape mismatch between operands ...", "fill: can not
|
|
464
|
+
modify read-only array"). The exception classes are unchanged; code
|
|
465
|
+
that matches a message needs the new text.
|
|
466
|
+
|
|
467
|
+
- Change: `clip` refuses `UNDEF` or a masked cell as a bound with
|
|
468
|
+
`ArgumentError`. To mask the cells out of range, pass `UNDEF` as the
|
|
469
|
+
fill (`clip(0, 10, UNDEF)`).
|
|
470
|
+
|
|
471
|
+
- Change: `is_in`, `intersection`, `difference` and `union` refuse a
|
|
472
|
+
Range; pass an Array (`(1..3).to_a`), or use `is_between` for an
|
|
473
|
+
interval.
|
|
474
|
+
|
|
475
|
+
- Change: `median`, `percentile` and `quantile` along the only axis of a
|
|
476
|
+
1-D array give a bare value, as `sum` does. `nunique(axis:)` naming
|
|
477
|
+
every axis gives an Integer; pass `keep_axis: true` to keep an array.
|
|
478
|
+
|
|
479
|
+
- Change: `valid_index?` and `valid_addr?` count a negative index from
|
|
480
|
+
the end, as `[]` does. `elem_fetch` on an empty array raises
|
|
481
|
+
`IndexError`; it returned `nil`.
|
|
482
|
+
|
|
483
|
+
- Change: `seq` / `seq!` on an integer array take a Float or Rational
|
|
484
|
+
start or step as `init_val + step*i` cut toward zero
|
|
485
|
+
(`int32.seq(0.5, 0.5)` is `[0, 1, 1, 2]`, was `[0, 0, 1, 1]`), and
|
|
486
|
+
raise `RangeError` for a start or Integer step the type cannot hold.
|
|
487
|
+
|
|
488
|
+
- Change: `random!` on an integer array raises for bounds the type
|
|
489
|
+
cannot hold or a Float bound, and clears the mask. `bin`, `bincount`,
|
|
490
|
+
`bincount_nd` and the histograms raise for a non-Integer count and for
|
|
491
|
+
edges that decrease.
|
|
492
|
+
|
|
493
|
+
- Change: MemoryView: `wrap_memory_view` refuses a boolean buffer (any
|
|
494
|
+
byte other than 0 or 1 cannot be told apart; use `from_memory_view`,
|
|
495
|
+
which reads it as true), and a wrap with a read-only `mask:` is
|
|
496
|
+
read-only. `CArray.memory_view_reject_reason` returns `nil` for an
|
|
497
|
+
object that is not a CArray.
|
|
498
|
+
|
|
499
|
+
- Change: C extensions: fifteen kernel iterator shorthand macros
|
|
500
|
+
(`CA_SLAB_REDUCE_F64`, `CA_SLAB_REDUCE_T_PLUS`,
|
|
501
|
+
`CA_L2_FOR_EACH_UNMASKED` and others) are removed; write the macro they
|
|
502
|
+
stood for (`CA_SLAB_REDUCE_T` with `double`, ...).
|
|
503
|
+
`ca_iter_state_next_slab_strided` is removed, and
|
|
504
|
+
`ca_iter_state_init_l2` takes `CA_SLAB_AXES` only.
|
|
505
|
+
|
|
37
506
|
## 3.0.3
|
|
38
507
|
|
|
39
508
|
- 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_array_pool.c
CHANGED
|
@@ -43,18 +43,42 @@
|
|
|
43
43
|
---------------------------------------------------------------------------- */
|
|
44
44
|
|
|
45
45
|
#include "carray.h"
|
|
46
|
+
#include "carray_internal.h"
|
|
46
47
|
#include <string.h>
|
|
47
48
|
|
|
48
49
|
/* Allocate struct + pool in one shot, then run pool_init.
|
|
49
50
|
*
|
|
50
51
|
* Called by per-class C `*_new` constructors. */
|
|
52
|
+
typedef struct {
|
|
53
|
+
CArray *ca;
|
|
54
|
+
int8_t obj_type;
|
|
55
|
+
int8_t ndim;
|
|
56
|
+
} ca_array_alloc_arg;
|
|
57
|
+
|
|
58
|
+
static VALUE
|
|
59
|
+
ca_array_alloc_pool (VALUE varg)
|
|
60
|
+
{
|
|
61
|
+
ca_array_alloc_arg *a = (ca_array_alloc_arg *) varg;
|
|
62
|
+
ca_array_pool_alloc(a->ca, a->obj_type, a->ndim);
|
|
63
|
+
return Qnil;
|
|
64
|
+
}
|
|
65
|
+
|
|
51
66
|
void *
|
|
52
67
|
ca_array_alloc (int8_t obj_type, int8_t ndim)
|
|
53
68
|
{
|
|
54
69
|
ca_operation_function_t *func = &ca_func[obj_type];
|
|
55
70
|
CArray *ca = xmalloc(func->struct_size);
|
|
71
|
+
ca_array_alloc_arg a;
|
|
56
72
|
memset(ca, 0, func->struct_size);
|
|
57
|
-
|
|
73
|
+
/* The type is set now so that a constructor whose setup raises can hand
|
|
74
|
+
the struct to ca_free, which dispatches on it. The setup sets it
|
|
75
|
+
again. */
|
|
76
|
+
ca->obj_type = obj_type;
|
|
77
|
+
/* The pool is a second allocation; when it fails, the struct goes too. */
|
|
78
|
+
a.ca = ca;
|
|
79
|
+
a.obj_type = obj_type;
|
|
80
|
+
a.ndim = ndim;
|
|
81
|
+
ca_fill_or_xfree(ca, ca_array_alloc_pool, (VALUE) &a);
|
|
58
82
|
return ca;
|
|
59
83
|
}
|
|
60
84
|
|
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.) */
|