carray 3.0.2 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +304 -0
- data/README.md +3 -4
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +225 -0
- data/ext/ca_axis_group.c +177 -99
- data/ext/ca_binop_dispatch.c +54 -32
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +66 -71
- data/ext/ca_compare.c +8 -2
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +27 -11
- data/ext/ca_kernel_iterator.c +663 -214
- data/ext/ca_kernel_iterator.h +231 -167
- data/ext/ca_monop_dispatch.c +4 -4
- data/ext/ca_monop_dispatch.h +4 -0
- data/ext/ca_obj_array.c +132 -22
- data/ext/ca_obj_bincmp.c +152 -121
- data/ext/ca_obj_binop.c +107 -210
- data/ext/ca_obj_bitarray.c +37 -24
- data/ext/ca_obj_bitfield.c +95 -62
- data/ext/ca_obj_block.c +1 -0
- data/ext/ca_obj_byte_swap.c +40 -40
- data/ext/ca_obj_const_string.c +96 -25
- data/ext/ca_obj_face.c +406 -64
- data/ext/ca_obj_face.h +92 -47
- data/ext/ca_obj_fake.c +21 -50
- data/ext/ca_obj_farray.c +1 -0
- data/ext/ca_obj_field.c +16 -3
- data/ext/ca_obj_fixlen_string.c +21 -21
- data/ext/ca_obj_grid.c +181 -124
- data/ext/ca_obj_meld.c +189 -107
- data/ext/ca_obj_moncmp.c +61 -61
- data/ext/ca_obj_monop.c +125 -107
- data/ext/ca_obj_object.c +543 -233
- data/ext/ca_obj_record.c +51 -16
- data/ext/ca_obj_reduce.c +5 -8
- data/ext/ca_obj_refer.c +117 -33
- data/ext/ca_obj_remap.c +57 -17
- data/ext/ca_obj_repeat.c +21 -5
- data/ext/ca_obj_roll.c +115 -11
- data/ext/ca_obj_select.c +47 -49
- data/ext/ca_obj_select_axis.c +58 -60
- data/ext/ca_obj_shift.c +22 -102
- data/ext/ca_obj_stack.c +223 -118
- data/ext/ca_obj_stride.c +195 -34
- data/ext/ca_obj_string.c +17 -18
- data/ext/ca_obj_tile.c +32 -16
- data/ext/ca_obj_time.c +23 -25
- data/ext/ca_obj_timedelta.c +21 -23
- data/ext/ca_obj_transpose.c +12 -3
- data/ext/ca_obj_triop.c +110 -117
- data/ext/ca_obj_window.c +149 -27
- data/ext/ca_op_ipower.c +24 -11
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +102 -79
- data/ext/ca_sweep_engine.h +7 -20
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +463 -0
- data/ext/carray.h +70 -27
- data/ext/carray_access.c +455 -211
- data/ext/carray_address_basis.c +177 -36
- data/ext/carray_attribute.c +45 -3
- data/ext/carray_bincount.c +32 -2
- data/ext/carray_broadcast.c +46 -14
- data/ext/carray_call_cfunc.c +0 -28
- data/ext/carray_cast.c +1444 -209
- data/ext/carray_cast_func.rb +34 -21
- data/ext/carray_conversion.c +197 -73
- data/ext/carray_copy.c +32 -11
- data/ext/carray_core.c +514 -122
- data/ext/carray_count.c +140 -87
- data/ext/carray_element.c +18 -27
- data/ext/carray_factorize.c +569 -277
- data/ext/carray_generate.c +76 -40
- data/ext/carray_histogram.c +152 -94
- data/ext/carray_hold.c +2 -1
- data/ext/carray_index_classifier.c +63 -96
- data/ext/carray_internal.h +385 -3
- data/ext/carray_lazy.c +834 -79
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +682 -316
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +221 -76
- data/ext/carray_memory_view.c +254 -248
- data/ext/carray_operator.c +1089 -359
- data/ext/carray_order.c +133 -69
- data/ext/carray_partition.c +102 -56
- data/ext/carray_random.c +273 -239
- data/ext/carray_scatter.c +308 -65
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +170 -70
- data/ext/carray_sort.c +215 -218
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +99 -21
- data/ext/carray_test.c +167 -64
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_utils.c +363 -98
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +0 -2
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1076 -846
- data/ext/ruby_carray.c +7 -1
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +39 -0
- data/lib/carray/autoload_carray.rb +19 -0
- data/lib/carray/autoload_method_extension.rb +6 -0
- data/lib/carray/axis_group.rb +174 -26
- data/lib/carray/basics.rb +91 -25
- data/lib/carray/bincount_nd.rb +6 -0
- data/lib/carray/block_iterator.rb +118 -48
- data/lib/carray/boolean_reduce.rb +21 -29
- data/lib/carray/categorical.rb +94 -26
- data/lib/carray/categorical_iterator.rb +333 -826
- data/lib/carray/complex.rb +36 -29
- data/lib/carray/conditional.rb +94 -7
- data/lib/carray/const_string.rb +46 -0
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +13 -7
- data/lib/carray/frame/csv_parser.rb +589 -82
- data/lib/carray/frame/describe.rb +79 -0
- data/lib/carray/frame/frame.rb +124 -25
- data/lib/carray/frame/group.rb +189 -63
- data/lib/carray/frame/io.rb +412 -72
- data/lib/carray/frame/join.rb +134 -46
- data/lib/carray/frame/records.rb +37 -16
- data/lib/carray/frame/reshape.rb +448 -0
- data/lib/carray/frame/sort.rb +26 -2
- data/lib/carray/frame/verbs.rb +715 -48
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +111 -2
- data/lib/carray/fusion.rb +229 -38
- data/lib/carray/inspect.rb +29 -11
- data/lib/carray/iterator.rb +14 -2
- data/lib/carray/lazy.rb +54 -30
- data/lib/carray/mask_gap_fill.rb +66 -52
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +40 -7
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bincount.rb +2 -2
- data/lib/carray/methods/bit_string.rb +14 -3
- data/lib/carray/methods/composition.rb +16 -10
- data/lib/carray/methods/factorize.rb +2 -2
- data/lib/carray/methods/gather_nd.rb +13 -2
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_in.rb +117 -4
- data/lib/carray/methods/join.rb +1 -1
- data/lib/carray/methods/locate_addr.rb +177 -36
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/repeat.rb +1 -20
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +11 -2
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/runtime.rb +14 -11
- data/lib/carray/segment_iterator.rb +990 -0
- data/lib/carray/serialize.rb +197 -27
- data/lib/carray/slab_iterator.rb +51 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string_operation_extension.rb +4 -3
- data/lib/carray/struct.rb +142 -51
- data/lib/carray/struct_builder.rb +110 -14
- data/lib/carray/table.rb +2 -2
- data/lib/carray/time.rb +517 -103
- data/lib/carray/window_iterator.rb +127 -72
- data/lib/carray.rb +2 -2
- data/yard-stubs/ca_obj_array.rb +4 -4
- data/yard-stubs/ca_obj_bitarray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +23 -12
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +1 -1
- data/yard-stubs/ca_obj_refer.rb +3 -3
- data/yard-stubs/ca_obj_roll.rb +0 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +1 -2
- data/yard-stubs/carray_access.rb +5 -4
- data/yard-stubs/carray_broadcast.rb +1 -1
- data/yard-stubs/carray_cast.rb +78 -43
- data/yard-stubs/carray_conversion.rb +13 -1
- data/yard-stubs/carray_copy.rb +8 -3
- data/yard-stubs/carray_core.rb +3 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +34 -10
- data/yard-stubs/carray_math.rb +25 -13
- data/yard-stubs/carray_median_percentile.rb +10 -6
- data/yard-stubs/carray_order.rb +34 -13
- data/yard-stubs/carray_scatter.rb +10 -3
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +2 -1
- data/yard-stubs/carray_sort.rb +43 -3
- data/yard-stubs/carray_test.rb +10 -0
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +11 -19
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_build_flags.h +0 -3
- data/ext/carray_config.h +0 -28
- data/ext/carray_kernels_bincmp.c +0 -4446
- data/ext/carray_kernels_binop.c +0 -11001
- data/ext/carray_kernels_init.c +0 -1131
- data/ext/carray_kernels_map.c +0 -3467
- data/ext/carray_kernels_moncmp.c +0 -2097
- data/ext/carray_kernels_monop.c +0 -18313
- data/ext/carray_kernels_reduce_aggregate.c +0 -26005
- data/ext/carray_kernels_reduce_boolean.c +0 -330
- data/ext/carray_kernels_reduce_cumulative.c +0 -14862
- data/ext/carray_kernels_reduce_extreme.c +0 -17494
- data/ext/carray_kernels_reduce_variance.c +0 -3910
- data/ext/carray_kernels_scan.c +0 -3693
- data/ext/carray_kernels_search.c +0 -32218
- data/ext/carray_kernels_sort.c +0 -10626
- data/ext/carray_kernels_triop.c +0 -1392
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 76ca6c2983cbd1e07acc64daeedc7328bee9239369f56f3af661ed1cc41e0bfb
|
|
4
|
+
data.tar.gz: 1506fa95c68148469451631fb375826e2599a979b4593db8c7508cf16d3c7545
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 66a3078a1bdd6459ab0c7526a588cc81191a4e043a17028b769b87b5d32874a9fd20c2b4828217dfa573457871f476155d005db518da600bbef38baca5551eb8
|
|
7
|
+
data.tar.gz: 23479b0a9b229489ff5ed1afa7fdc0a30150b9d3ba32803b089f1f9e5d7a955cd556c478c7cb5346e516830632a4ba35cb54d186f54a783b589d7cabec9498d5
|
data/CHANGELOG.md
CHANGED
|
@@ -34,6 +34,310 @@ 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.3
|
|
38
|
+
|
|
39
|
+
- New: `CAFrame.from_csv` reads messy tables: `types: :infer` (numbers,
|
|
40
|
+
booleans, year-first dates and times), `types: { default: ... }`,
|
|
41
|
+
`missing:` tokens, `on_error:` (`:mask`, `:warn`, `:raise`), `columns:` to
|
|
42
|
+
read only some columns, and `header:` / `data:` / `column_names:` by line.
|
|
43
|
+
`CAFrame#cast` takes the same map; `parse_to_time(name, :infer)` finds a
|
|
44
|
+
column's date format; `describe` and `split_column` are new; `to_csv`
|
|
45
|
+
takes `encoding:` and `missing:`.
|
|
46
|
+
|
|
47
|
+
- New: `CAFrame` reshapes and resamples: `pivot` / `pivot_grid` / `melt`,
|
|
48
|
+
`stack_rows(by:)` / `unstack_rows`, `stack_columns` / `unstack_column`,
|
|
49
|
+
`CAFrame.stack` / `unstack` (frames as layers), and `resample(name, unit)`
|
|
50
|
+
for time bins. The stacked forms are views. `protect` makes a frame
|
|
51
|
+
read-only.
|
|
52
|
+
|
|
53
|
+
- New: `CAFrame` group reductions and `aggregate` reduce N-D columns along
|
|
54
|
+
the rows (a column `(N, L)` gives `(groups, L)`), take `min_count:` and
|
|
55
|
+
`fill_value:`, and pass a reduction its arguments
|
|
56
|
+
(`"p90" => ["temp", :percentile, 90.0]`).
|
|
57
|
+
|
|
58
|
+
- New: `value.segments(offsets:)` / `segments(lengths:)` iterate over
|
|
59
|
+
consecutive runs of cells, with `CArray.segment_offsets` /
|
|
60
|
+
`segment_index` to convert between lengths, boundaries and segment
|
|
61
|
+
numbers. The scans, `map`, `median` and `percentile` of
|
|
62
|
+
`group_by_category` take `axis:`, and a window's `median`, `percentile`
|
|
63
|
+
and `quantile` answer under the default `bounds: :skip`.
|
|
64
|
+
|
|
65
|
+
- New: `bitfield(range, type)` reads a field as a signed or wider integer;
|
|
66
|
+
`set_attrs(hash)`; `order(kind:)`; `tolerance: "10 minutes"` for time keys
|
|
67
|
+
in `locate_nearest_addr` and `CAFrame#join_asof`. A `CARecord` answers
|
|
68
|
+
`unique`, `value_counts`, `mode`, `is_in`, the set operations,
|
|
69
|
+
`categorize`, `count(v)` and `locate_addr`.
|
|
70
|
+
|
|
71
|
+
- New: for whoever registers a `CArray.expression_evaluator` (carray-jit):
|
|
72
|
+
mixed data types, integer powers, comparisons, `then_else`, `shift`, and
|
|
73
|
+
reductions, scans and sorts of an expression now reach the evaluator. An
|
|
74
|
+
evaluator that does not know a node declines, and CArray computes the
|
|
75
|
+
expression as before.
|
|
76
|
+
|
|
77
|
+
- New: for C extensions: `ca_iter_ensure`, `ca_sync_detach`,
|
|
78
|
+
`ca_attach_n` / `ca_allocate_n`, `ca_iter_state_init_l2_paired`,
|
|
79
|
+
`ca_stride_setup(NULL, ...)` and `ca_check_uninitialized` let an
|
|
80
|
+
extension clean up when its code raises.
|
|
81
|
+
|
|
82
|
+
- Change: `CAFrame` names its columns "columns": `variable_names` is now
|
|
83
|
+
`column_names`, `variables` is `columns` and `nvar` is `ncol`. The old
|
|
84
|
+
names are gone.
|
|
85
|
+
|
|
86
|
+
- Change: `sort_index`, `rank_index`, `partition_index`, `partition` and
|
|
87
|
+
`partition_copy` without `axis:` work on the whole array, as `sort` does;
|
|
88
|
+
they worked along axis 0. On an N-D array pass `axis: 0` to keep the old
|
|
89
|
+
result.
|
|
90
|
+
|
|
91
|
+
- Change: errors a caller can cause no longer raise `RuntimeError`: a bad
|
|
92
|
+
shape, step, axis, option or data type raises `ArgumentError`,
|
|
93
|
+
`TypeError`, `RangeError` or `CArray::DataTypeError`, and every index out
|
|
94
|
+
of range raises `IndexError` (`take_along_axis`, `axis2addr` and
|
|
95
|
+
`addr2index` raised others). `CArray::DataTypeError` is now a
|
|
96
|
+
`TypeError`. A write to a read-only array still raises `RuntimeError`.
|
|
97
|
+
Messages name the method you called and the value you gave. Update a
|
|
98
|
+
`rescue` that matched the old class or wording.
|
|
99
|
+
|
|
100
|
+
- Change: arguments that were truncated or ignored now raise: an axis,
|
|
101
|
+
`min_count:`, `kth` or `n` that is not an Integer; a misspelt keyword; a
|
|
102
|
+
keyword a method does not take (`min_count:` to `all` / `any` of an
|
|
103
|
+
iterator, as to the core); a Symbol column name in `cast` and `types:`;
|
|
104
|
+
`windows` given anything but Ranges (an exclusive range now leaves out
|
|
105
|
+
its end); `CA_INT32(0, 2)`; a fixlen array without `bytes:`. A negative
|
|
106
|
+
axis counts from the end everywhere. The indexer's method form
|
|
107
|
+
(`a[:eq, 0]`) calls public methods only.
|
|
108
|
+
|
|
109
|
+
- Change: a Hash passed as a positional argument is an argument, as in
|
|
110
|
+
Ruby 3, not keywords: `a.sum({axis: 0})` raises (write `a.sum(axis: 0)`
|
|
111
|
+
or `a.sum(**opts)`). An object array of Hashes can now be searched and
|
|
112
|
+
counted.
|
|
113
|
+
|
|
114
|
+
- Change: values that cannot be held raise instead of being bent: storing
|
|
115
|
+
`nil` into a numeric or boolean array, an Integer operand the array's type
|
|
116
|
+
cannot hold (`RangeError`; the comparisons answer by value instead), and a
|
|
117
|
+
String that is not a decimal number (`"010"` is now 10, and `to_type` gives
|
|
118
|
+
`UNDEF`). `CAFrame#cast` to an integer makes `2.5` `UNDEF` instead of 2.
|
|
119
|
+
Store `Float::NAN` or `UNDEF` for a missing value.
|
|
120
|
+
|
|
121
|
+
- Change: reductions with too few values: `variance` / `stddev` of fewer
|
|
122
|
+
than two values is `UNDEF` (pass `fill_value: 0.0` for the old answer),
|
|
123
|
+
and `minmax` of nothing is `[UNDEF, UNDEF]`. `fill_value:` is stored into
|
|
124
|
+
the result's type with or without `axis:`; `fill_value: UNDEF`,
|
|
125
|
+
`strip_mask(UNDEF)` and `unmask(UNDEF)` leave the cells masked.
|
|
126
|
+
|
|
127
|
+
- Change: arrays of mixed types meet in a type that holds both: signed with
|
|
128
|
+
unsigned integers (`uint8` with `int8` is `int16`, `uint64` with `int64` is
|
|
129
|
+
`:object`) and 32-bit or wider integers with `float32` (in `float64`) when
|
|
130
|
+
joined or matched. `CArray.result_type` lets a scalar take the arrays'
|
|
131
|
+
type, as an operator does (`result_type(float32_array, 0.1)` is
|
|
132
|
+
`:float32`). Arithmetic is unchanged.
|
|
133
|
+
|
|
134
|
+
- Change: integer and float edge cases no longer depend on the machine or
|
|
135
|
+
the argument order: a shift count means what it does to `Integer#<<`,
|
|
136
|
+
signed `rcp` / `rcp_mul` round down as `/` does, `to_type` to an integer
|
|
137
|
+
makes NaN `UNDEF`, `maximum` / `minimum` of two zeros are `0.0` / `-0.0`,
|
|
138
|
+
and `clip` raises when `min` exceeds `max` (a one-sided fill clamps the
|
|
139
|
+
other side).
|
|
140
|
+
|
|
141
|
+
- Change: `CAFrame#join` matches as SQL joins do: a key on 2 left and 3
|
|
142
|
+
right rows gives 6 rows, and a masked key matches nothing and stays as an
|
|
143
|
+
unmatched row. When the other frame's key is unique, `:left` gives the
|
|
144
|
+
same rows as before.
|
|
145
|
+
|
|
146
|
+
- Change: `CAFrame.from_csv`'s reading block takes the reader as its
|
|
147
|
+
parameter and its `body` verb is `data`
|
|
148
|
+
(`from_csv(path) { |r| r.skip 2; r.header; r.data }`). Text columns come
|
|
149
|
+
back as `CAString`. Contents that cannot be read raise
|
|
150
|
+
`CAFrame::UnreadableColumn` or `CAFrame::AmbiguousTimeFormat`, which are
|
|
151
|
+
not `ArgumentError`.
|
|
152
|
+
|
|
153
|
+
- Change: reading time from text is stricter: `parse_to_time` without a
|
|
154
|
+
format reads year-first text only (pass a format, or `:mixed` for the old
|
|
155
|
+
guess) in the finest unit the text shows; `CArray.time` and strptime
|
|
156
|
+
formats refuse trailing text and a time of day they cannot read; a date
|
|
157
|
+
the column's unit cannot hold raises `RangeError`. Before, these cells
|
|
158
|
+
were guessed, floored or masked.
|
|
159
|
+
|
|
160
|
+
- Change: `CAFrame#to_csv` writes a boolean as `1` / `0` and a float32 as
|
|
161
|
+
its shortest decimal, refuses a record column, and raises naming the row
|
|
162
|
+
and column of a cell it cannot encode. `extract` masks a cell its pattern
|
|
163
|
+
does not match, where it gave `""`.
|
|
164
|
+
|
|
165
|
+
- Change: `CAFrame`: a frozen frame refuses `[]=`, `set_index`, `cast` and
|
|
166
|
+
the other in-place verbs; `at` on a numeric index takes numbers only; the
|
|
167
|
+
index of a `group_by` result keeps the key's type (a `CATime` key gives a
|
|
168
|
+
`CATime` index); group `sum` / `mean` / `min` / `max` include every column
|
|
169
|
+
whose type has the reduction (times and strings among them).
|
|
170
|
+
|
|
171
|
+
- Change: `CAStruct` / `CARecord`: records are ordered only by the members
|
|
172
|
+
named in `CArray.struct(order_by:)`; without it sorting, `min` / `max` and
|
|
173
|
+
comparison raise. An element's `[]` takes a String or a position (a
|
|
174
|
+
Symbol raises), a member named like a method (`hash`, `size`) gets no
|
|
175
|
+
accessor, a nested member reads as a view (`dup` it for a copy), boolean
|
|
176
|
+
and 1-bit members read as `true` / `false`, and `UNDEF` cannot be stored
|
|
177
|
+
in a member. Records of another struct are refused.
|
|
178
|
+
|
|
179
|
+
- Change: a `CARecord` exported through MemoryView uses Ruby's own format
|
|
180
|
+
(`ruby/memory_view.h`) instead of PEP 3118 `T{...}`; the member names are
|
|
181
|
+
`CARecord#memory_view_field_names`. A union is no longer exported.
|
|
182
|
+
|
|
183
|
+
- Change: a time array compares with, searches for and stores a `String` or
|
|
184
|
+
`Date` as well as a `Time`, at the precision the value carries: a value
|
|
185
|
+
off the array's grid (09:00 against a day array) raises, where a `Time`
|
|
186
|
+
was floored. `union` of two units gives the finer unit. `inspect` shows
|
|
187
|
+
the tick and each cell as `to_s` does.
|
|
188
|
+
|
|
189
|
+
- Change: `==` on a Face (a time, string or categorical array) compares the
|
|
190
|
+
values it holds, and only with a Face of its own class: time arrays of
|
|
191
|
+
different units holding the same instants are `==`, and a `CAString` is
|
|
192
|
+
no longer `==` to an object array of the same strings (compare
|
|
193
|
+
`to_type(:object)` for that).
|
|
194
|
+
|
|
195
|
+
- Change: Faces (`CATime`, `CATimedelta`, `CACategorical`, string arrays):
|
|
196
|
+
`.lazy` returns the Face and computes eagerly; storing one into a
|
|
197
|
+
non-object plain array raises (convert with `to_type(:object)` or
|
|
198
|
+
`ticks`); `CArray.save`, `dump` and `Marshal.dump` refuse one, and a
|
|
199
|
+
`CAWrap` (save `.parent` or `.copy`); `CArray.stack([face])` returns the
|
|
200
|
+
Face, and mixing Faces raises.
|
|
201
|
+
|
|
202
|
+
- Change: for whoever writes a Face: the hooks are renamed
|
|
203
|
+
`storage_to_element` / `element_to_storage`, and a stored value goes
|
|
204
|
+
through `element_to_storage` once (it went through twice). A Face written
|
|
205
|
+
in Ruby on `CAObject` over a numeric storage refuses arithmetic, math and
|
|
206
|
+
reductions unless it passes `numeric: true`.
|
|
207
|
+
|
|
208
|
+
- Change: views: a view of a frozen array is read-only rather than frozen
|
|
209
|
+
(`RuntimeError`, `frozen?` false), so `sort`, selections and lazy
|
|
210
|
+
expressions work on a frozen array. `then_else` and `sort` on a lazy
|
|
211
|
+
expression return a read-only lazy view (call `copy` for a snapshot), and
|
|
212
|
+
`then_else` branches broadcast as operands do. `dup` of a `CAWrap` is a
|
|
213
|
+
plain `CArray`. Attributes survive `copy` and `to_type`.
|
|
214
|
+
|
|
215
|
+
- Change: a `bitarray` view has no mask and refuses a masked array (use
|
|
216
|
+
`value.bitarray`); `pack_bits` raises on masked cells (pack the mask with
|
|
217
|
+
`validity_bits`). `bitfield` refuses a complex array.
|
|
218
|
+
|
|
219
|
+
- Change: on an object array, `min`, `max`, `cummin`, `pmin` and the rest
|
|
220
|
+
compare with `<=>`, as `sort` does; a pair that cannot be ordered raises
|
|
221
|
+
`ArgumentError`. `median`, `percentile` and `quantile` answer in the
|
|
222
|
+
elements' own arithmetic (`CA_OBJECT([1, 2]).median` is `3/2`; convert
|
|
223
|
+
with `to_type(:float64)` for a Float). `&`, `|` and `^` with a boolean
|
|
224
|
+
array read its cells as `true` / `false`, eager and lazy.
|
|
225
|
+
|
|
226
|
+
- Change: smaller behaviour changes: `locate_nearest_addr` (and `join_asof`,
|
|
227
|
+
`snap_to`) with `direction:` matches beyond the reference's ends (limit it
|
|
228
|
+
with `tolerance:`); `map_slab` carries the mask of the block's result; a
|
|
229
|
+
masked cell of a one-axis boolean selector selects nothing; `shift`,
|
|
230
|
+
`roll`, `tile` and `window` on a zero-length axis return an empty view;
|
|
231
|
+
boolean sums in `axis_group` and categorical scans are uint64, as in the
|
|
232
|
+
core; `group_by_category` raises `TypeError` for a non-categorical.
|
|
233
|
+
|
|
234
|
+
- Change: an operand that exports MemoryView and defines `to_ca` (an Arrow
|
|
235
|
+
array, with a bridge) is taken through `to_ca`, so Arrow nulls arrive as
|
|
236
|
+
masked cells and time columns as `CATime`.
|
|
237
|
+
|
|
238
|
+
- Change: for C extensions: `CArray::VERSION_CODE` is
|
|
239
|
+
`major*10000 + minor*100 + teeny` (`30003`); the `CA_FOR_EACH_ELEMENT`
|
|
240
|
+
macros, `CA_WITH_BUFFER` and `CA_CHECK_BOUND` are removed (use
|
|
241
|
+
`ca_call_cslab_N_r`, `ca_call_cfunc_N_r` or `rb_ca_call_with_buffer`);
|
|
242
|
+
the `_INOUT` and `_PAIR` fiber macros raise on a shape mismatch; kernels
|
|
243
|
+
are built with `-fwrapv`. Rebuild the extension.
|
|
244
|
+
|
|
245
|
+
- Change: faster, with the same results: `from_csv` with `types:` (two to
|
|
246
|
+
five times), text to float (eight times), `CAConstString#to_string`,
|
|
247
|
+
reductions over gathered, `shift` and `window` views, a repeated
|
|
248
|
+
`CArray.fuse` block, and selecting from a lazy expression.
|
|
249
|
+
|
|
250
|
+
- Fix: wrong answers that came without an error. An in-place operation
|
|
251
|
+
reading an argument that shares its memory read cells it had already
|
|
252
|
+
written (`a[1..5].add!(a[0..4])` gave a running sum; `scatter_*!`,
|
|
253
|
+
`inherit_mask` and `mask=` too); `refer` to a wider type on a transposed
|
|
254
|
+
or stepped parent read neighbouring values; views of a stack or meld,
|
|
255
|
+
and a slice of a lazy expression, returned other cells; a Float operand
|
|
256
|
+
of an integer array was truncated (`count(1.5)` found `1`); `mask=` with
|
|
257
|
+
another shape copied cells by count; a masked index read cell 0 in
|
|
258
|
+
`gather_nd`; `stddev` of NaN data was 0.0.
|
|
259
|
+
|
|
260
|
+
- Fix: wrong answers that came without an error, time and strings: time
|
|
261
|
+
keys of different units matched or not depending on the side in `is_in`,
|
|
262
|
+
`join` and `align`; `locate_nearest_addr` picked a wrong row for a NaN,
|
|
263
|
+
an infinite or a nanosecond key; `unmask(time)`, `resize(fill_value:)`
|
|
264
|
+
and `insert_block` read a `Time` as a count; `CAConstString` comparisons
|
|
265
|
+
compared buffer positions; a `CAString` compared against a time,
|
|
266
|
+
categorical or const string compared their encodings.
|
|
267
|
+
|
|
268
|
+
- Fix: writes that were lost now reach the array: through a grid, selection
|
|
269
|
+
or `select_axis` over a reshaped transpose, through a stack or meld of
|
|
270
|
+
views, into a nested struct member, into the mask copy of a stack or meld,
|
|
271
|
+
and the masked cells of `c[] = c.flip(0)`.
|
|
272
|
+
|
|
273
|
+
- Fix: crashes and reads outside an array: a garbage collection during an
|
|
274
|
+
operation on a converted or computed array (`CAObject`, lazy, object
|
|
275
|
+
data); a slab kept after `each_slab`; a `CARecord` after `Marshal.load`;
|
|
276
|
+
shapes and indices whose arithmetic overflows; `refer(:object)` and
|
|
277
|
+
`bitfield` on object data; `scatter_*!` on complex; `MIN / -1` on Linux
|
|
278
|
+
x86; struct members outside the record; fixlen stores of another width;
|
|
279
|
+
reductions in several Ractors.
|
|
280
|
+
|
|
281
|
+
- Fix: an operation that raises part way (a block, a conversion, a
|
|
282
|
+
division by zero) leaves its arrays usable and frees its memory. Before,
|
|
283
|
+
an array could stay attached, and after 32 such errors every lazy
|
|
284
|
+
expression failed with "all 32 slots in use".
|
|
285
|
+
|
|
286
|
+
- Fix: iterator reductions answer as the same reduction on an array: every
|
|
287
|
+
one takes `min_count:` and `fill_value:` (`blocks(n).percentile(p,
|
|
288
|
+
min_count: k)` read them as a second percentile), a group's counts apply
|
|
289
|
+
`min_count:` to the right cells, a group's `wmean` no longer takes
|
|
290
|
+
`fill_value:` as a weight, a window of only NaN gives NaN, and object
|
|
291
|
+
weights in `segments` stay exact.
|
|
292
|
+
|
|
293
|
+
- Fix: `CAFrame` round trips through CSV and records: quotes, separators of
|
|
294
|
+
several characters or spaces, lines of spaces, a duplicated header name,
|
|
295
|
+
complex `Infinity` / `NaN`, months and years, hour 24, a one-column file
|
|
296
|
+
with a blank name; nested arrays, `Complex` and `Rational` in
|
|
297
|
+
`from_records`. `fill`, `to_table` and `filter(keep_masked:)` work with
|
|
298
|
+
N-D and categorical columns; `meld` and `concatenate` take empty frames;
|
|
299
|
+
`group_by` takes a categorical key and treats NaN in a composite key as
|
|
300
|
+
one value.
|
|
301
|
+
|
|
302
|
+
- Fix: Faces stay Faces: the reductions of `windows` and `blocks`,
|
|
303
|
+
`partition_copy`, `then_else`, `clip`, `mask_eq` and `meld` return the
|
|
304
|
+
Face, and a Face's own state survives `min(axis:)`, `cummax` and
|
|
305
|
+
`partition_copy`. `axis_group` and categorical reductions take boolean,
|
|
306
|
+
complex, object and Face values; a time array's `fill_value:` is a time
|
|
307
|
+
on every path. `CAFrame#fill(:linear)` interpolates any Face that defines
|
|
308
|
+
`linear_fetch`. A categorical refuses `clip` and `minmax` as it refuses
|
|
309
|
+
`min`.
|
|
310
|
+
|
|
311
|
+
- Fix: types kept through operations: complex arrays work with `unique`,
|
|
312
|
+
`is_in` and the rest of that family; `meld` reductions answer as on a
|
|
313
|
+
copy; fixlen strings of different widths match; `atan2`, `hypot` and
|
|
314
|
+
others keep float32 and integer types; a record member declared with
|
|
315
|
+
`endian:` reads, sorts, saves and loads correctly.
|
|
316
|
+
|
|
317
|
+
- Fix: NaN and masked cells are treated the same everywhere: NaN is last in
|
|
318
|
+
object sorts and `categorize`, loses `min` / `max`, and is found by
|
|
319
|
+
`CAFrame#at(Float::NAN)`; `min_index` never points at a masked cell or a
|
|
320
|
+
NaN; `min_count:` and `fill_value:` are honoured where they were ignored;
|
|
321
|
+
a lazy expression's mask follows its operands; a selection or `shift`
|
|
322
|
+
follows later mask changes; `invert_mask` works on a selection.
|
|
323
|
+
|
|
324
|
+
- Fix: MemoryView: a `CAFixlenString` exports as bytes and a frozen fixlen
|
|
325
|
+
array can be exported; `CATime`, `CACategorical` and `CAConstString` are
|
|
326
|
+
refused by `memory_view_available?` with the reason, instead of answering
|
|
327
|
+
`true` and failing.
|
|
328
|
+
|
|
329
|
+
- Fix: with carray-jit: two expressions that differ only in which operand an
|
|
330
|
+
operation reads no longer share a kernel, and a store whose destination
|
|
331
|
+
overlaps an operand is computed by CArray.
|
|
332
|
+
|
|
333
|
+
- Fix: for C extensions: a `CA_KERNEL_WRITE` walk over a view that holds a
|
|
334
|
+
cell more than once keeps the cells the kernel wrote; a walk left with
|
|
335
|
+
`break` writes back its slab; writes through a `CAGrid`, `CAWindow` or
|
|
336
|
+
`CAShift` over a view reach the array; the sweep engine and paired walks
|
|
337
|
+
read an argument sharing the output's memory as it was; a view class
|
|
338
|
+
that is not registered with `ca_iter_register_source_kind` is still
|
|
339
|
+
accepted. Rebuild the extension.
|
|
340
|
+
|
|
37
341
|
## 3.0.2
|
|
38
342
|
|
|
39
343
|
- New: `CArray::AddressBasis`, for a C extension whose code addresses cells
|
data/README.md
CHANGED
|
@@ -4,17 +4,16 @@ 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
|
|
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
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
|
|
16
14
|
* Define your own array class in pure Ruby while keeping the full CArray interface
|
|
17
|
-
*
|
|
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
|
|
18
17
|
* Comes with a DataFrame (`CAFrame`) 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).
|
data/carray.gemspec
CHANGED
data/ext/ca_axis_dispatch.c
CHANGED
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
#include "carray.h"
|
|
43
43
|
#include "ca_iter_substrate.h"
|
|
44
44
|
#include "ca_composite_dispatch.h"
|
|
45
|
+
#include "carray_internal.h" /* ca_parent_lends_no_memory */
|
|
45
46
|
|
|
46
47
|
#include <string.h>
|
|
47
48
|
|
|
@@ -393,6 +394,100 @@ ca_axis_dispatch_fill_value_cb (ca_size_t off, int oob, ca_size_t n, void *vctx)
|
|
|
393
394
|
}
|
|
394
395
|
}
|
|
395
396
|
|
|
397
|
+
/* Rows whose innermost axis is a step-1 SHIFT axis. View cell i of the row
|
|
398
|
+
reads parent cell start + i, so the cells with 0 <= start + i < size0 form
|
|
399
|
+
one run and go to cb together. The cells before and after it are out of
|
|
400
|
+
range: under FILL / MASK every one of them is (cb gets each side as one
|
|
401
|
+
oob slab), under the other policies each maps to a cell of its own. */
|
|
402
|
+
static void
|
|
403
|
+
ca_axis_dispatch_shift_cell (const ca_axis_desc_t *ax, ca_size_t pstride,
|
|
404
|
+
ca_size_t row_off, ca_size_t i, ca_size_t bytes,
|
|
405
|
+
ca_slab_cb_t cb, void *ctx)
|
|
406
|
+
{
|
|
407
|
+
ca_size_t pi = ca_bounds_normalize_index(ax->policy, ax->size0,
|
|
408
|
+
ax->start + i);
|
|
409
|
+
if ( pi < 0 || pi >= ax->size0 ) {
|
|
410
|
+
cb(row_off, 1, bytes, ctx);
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
cb(row_off + pi * pstride, 0, bytes, ctx);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
static void
|
|
418
|
+
ca_axis_dispatch_for_each_shift_row (ca_axis_desc_t *laxes,
|
|
419
|
+
const ca_size_t *pstrides,
|
|
420
|
+
int8_t lndim,
|
|
421
|
+
ca_size_t bytes,
|
|
422
|
+
ca_size_t total_elements,
|
|
423
|
+
ca_slab_cb_t cb,
|
|
424
|
+
void *ctx)
|
|
425
|
+
{
|
|
426
|
+
int8_t inner = lndim - 1;
|
|
427
|
+
const ca_axis_desc_t *ax = &laxes[inner];
|
|
428
|
+
ca_size_t pstride = pstrides[inner];
|
|
429
|
+
ca_size_t count = ax->count;
|
|
430
|
+
int coalesce = ( ax->policy == CA_BOUNDS_FILL
|
|
431
|
+
|| ax->policy == CA_BOUNDS_MASK );
|
|
432
|
+
ca_op_prefix_axis_t prefix[CA_RANK_MAX];
|
|
433
|
+
ca_size_t idx[CA_RANK_MAX];
|
|
434
|
+
ca_size_t lo, hi, n_rows, r, i;
|
|
435
|
+
int8_t k;
|
|
436
|
+
|
|
437
|
+
/* In-range view cells: lo <= i < hi. */
|
|
438
|
+
lo = -ax->start;
|
|
439
|
+
if ( lo < 0 ) lo = 0;
|
|
440
|
+
if ( lo > count ) lo = count;
|
|
441
|
+
hi = ax->size0 - ax->start;
|
|
442
|
+
if ( hi > count ) hi = count;
|
|
443
|
+
if ( hi < lo ) hi = lo;
|
|
444
|
+
|
|
445
|
+
ca_axis_dispatch_classify_prefix(laxes, pstrides, inner, prefix);
|
|
446
|
+
for ( k = 0; k < inner; k++ ) idx[k] = 0;
|
|
447
|
+
|
|
448
|
+
n_rows = total_elements / count;
|
|
449
|
+
for ( r = 0; r < n_rows; r++ ) {
|
|
450
|
+
int oob;
|
|
451
|
+
ca_size_t row_off = ca_axis_dispatch_prefix_offset(prefix, idx, inner,
|
|
452
|
+
&oob);
|
|
453
|
+
if ( oob ) {
|
|
454
|
+
cb(row_off, 1, count * bytes, ctx);
|
|
455
|
+
}
|
|
456
|
+
else {
|
|
457
|
+
if ( lo > 0 ) {
|
|
458
|
+
if ( coalesce ) {
|
|
459
|
+
cb(row_off, 1, lo * bytes, ctx);
|
|
460
|
+
}
|
|
461
|
+
else {
|
|
462
|
+
for ( i = 0; i < lo; i++ ) {
|
|
463
|
+
ca_axis_dispatch_shift_cell(ax, pstride, row_off, i, bytes,
|
|
464
|
+
cb, ctx);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
if ( hi > lo ) {
|
|
469
|
+
cb(row_off + (ax->start + lo) * pstride, 0, (hi - lo) * bytes, ctx);
|
|
470
|
+
}
|
|
471
|
+
if ( hi < count ) {
|
|
472
|
+
if ( coalesce ) {
|
|
473
|
+
cb(row_off, 1, (count - hi) * bytes, ctx);
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
for ( i = hi; i < count; i++ ) {
|
|
477
|
+
ca_axis_dispatch_shift_cell(ax, pstride, row_off, i, bytes,
|
|
478
|
+
cb, ctx);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
for ( k = inner - 1; k >= 0; k-- ) {
|
|
485
|
+
if ( ++idx[k] < prefix[k].count ) break;
|
|
486
|
+
idx[k] = 0;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
396
491
|
/* Generic per-slab driver. Walks the (post-merge / post-layout)
|
|
397
492
|
prefix axes row-major and invokes `cb` once per slab iteration.
|
|
398
493
|
The all-slab case degenerates to a single `cb` invocation with
|
|
@@ -437,6 +532,17 @@ ca_axis_dispatch_for_each_slab (CArray *parent,
|
|
|
437
532
|
return;
|
|
438
533
|
}
|
|
439
534
|
|
|
535
|
+
/* Innermost SHIFT axis with step 1: the in-range part of each row is one
|
|
536
|
+
contiguous run of parent cells, so it goes to cb as one slab instead of
|
|
537
|
+
one cell at a time. */
|
|
538
|
+
if ( slab_start == lndim
|
|
539
|
+
&& laxes[lndim - 1].kind == CA_AXIS_KIND_SHIFT
|
|
540
|
+
&& laxes[lndim - 1].step == 1 ) {
|
|
541
|
+
ca_axis_dispatch_for_each_shift_row(laxes, pstrides, lndim, bytes,
|
|
542
|
+
total_elements, cb, ctx);
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
|
|
440
546
|
/* Pre-classify prefix axes once. Inner loop becomes branchless
|
|
441
547
|
modulo a per-axis kind tag whose value is constant across
|
|
442
548
|
iters. */
|
|
@@ -951,3 +1057,122 @@ ca_axis_dispatch_outer_has_shift (const ca_axis_desc_t *descs,
|
|
|
951
1057
|
}
|
|
952
1058
|
return 0;
|
|
953
1059
|
}
|
|
1060
|
+
|
|
1061
|
+
/* ==========================================================================
|
|
1062
|
+
Transfers of a descriptor view (CAGrid, CASelect, CASelectAxis, CAWindow)
|
|
1063
|
+
whose parent holds no ptr.
|
|
1064
|
+
|
|
1065
|
+
The engine above walks parent->ptr. A cold parent is handled by what it
|
|
1066
|
+
is:
|
|
1067
|
+
|
|
1068
|
+
- one ca_attach_is_alias accepts already has the memory: borrow it;
|
|
1069
|
+
- one with no memory to lend (ca_parent_lends_no_memory) is asked for
|
|
1070
|
+
the selected cells only, through the view's own xfer_stride over the
|
|
1071
|
+
whole view -- producing every cell of the parent to serve a selection
|
|
1072
|
+
would make the cost follow the parent's size;
|
|
1073
|
+
- anything else is gathered into a parent-shaped scratch that stands in
|
|
1074
|
+
for parent->ptr, and pushed back for PUT.
|
|
1075
|
+
========================================================================== */
|
|
1076
|
+
|
|
1077
|
+
/* The whole view as one region request to its own xfer_stride slot. */
|
|
1078
|
+
static void
|
|
1079
|
+
ca_axis_view_xfer_region (CArray *ca, void *data, int dir)
|
|
1080
|
+
{
|
|
1081
|
+
ca_size_t starts[CA_RANK_MAX], strides[CA_RANK_MAX], s;
|
|
1082
|
+
int8_t k;
|
|
1083
|
+
|
|
1084
|
+
/* The slot is called directly, past ca_xfer_stride's empty-region check. */
|
|
1085
|
+
if ( ca->elements == 0 ) return;
|
|
1086
|
+
|
|
1087
|
+
s = ca->bytes;
|
|
1088
|
+
for ( k = ca->ndim - 1; k >= 0; k-- ) {
|
|
1089
|
+
starts[k] = 0;
|
|
1090
|
+
strides[k] = s;
|
|
1091
|
+
s *= ca->dim[k];
|
|
1092
|
+
}
|
|
1093
|
+
ca_func[ca->obj_type].xfer_stride(ca, starts, ca->dim, strides, data, dir);
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
void
|
|
1097
|
+
ca_axis_view_xfer_all (void *ap, ca_axis_view_fast_t fast, int region_ok,
|
|
1098
|
+
void *data, int dir)
|
|
1099
|
+
{
|
|
1100
|
+
CArray *ca = (CArray *) ap;
|
|
1101
|
+
CArray *parent = ((CAView *) ca)->parent;
|
|
1102
|
+
|
|
1103
|
+
if ( parent->ptr ) {
|
|
1104
|
+
fast(ca, (char *) data, dir);
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
if ( ca_attach_is_alias(parent) ) {
|
|
1109
|
+
ca_attach(parent); /* window: an alias attach, cannot raise */
|
|
1110
|
+
fast(ca, (char *) data, dir);
|
|
1111
|
+
ca_detach(parent);
|
|
1112
|
+
return;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
if ( region_ok && ca_parent_lends_no_memory(parent) ) {
|
|
1116
|
+
ca_axis_view_xfer_region(ca, data, dir);
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
{
|
|
1121
|
+
volatile VALUE holder;
|
|
1122
|
+
ca_size_t plen = parent->elements * parent->bytes;
|
|
1123
|
+
char *parent_scratch = ALLOCV_N(char, holder, plen);
|
|
1124
|
+
ca_xfer_all(parent, parent_scratch, CA_XFER_GET);
|
|
1125
|
+
parent->ptr = parent_scratch;
|
|
1126
|
+
fast(ca, (char *) data, dir);
|
|
1127
|
+
/* Put parent->ptr back before the PUT: the PUT can raise (a lazy
|
|
1128
|
+
backing's sync failing), and the scratch is gone once this frame
|
|
1129
|
+
is. */
|
|
1130
|
+
parent->ptr = NULL;
|
|
1131
|
+
if ( dir == CA_XFER_PUT ) {
|
|
1132
|
+
ca_xfer_all(parent, parent_scratch, CA_XFER_PUT);
|
|
1133
|
+
}
|
|
1134
|
+
ALLOCV_END(holder);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
/* The attach of a view that owns its buffer and fills it through its own
|
|
1139
|
+
transfers (a descriptor view whose parent has no memory to lend, CARemap,
|
|
1140
|
+
CAStack, CAMeld). The buffer is published only once filled -- a view
|
|
1141
|
+
with a live ptr makes the per-cell dispatchers bypass the transfer slots,
|
|
1142
|
+
and for CA_OBJECT the garbage cells of an unfilled buffer would be marked
|
|
1143
|
+
-- and a raise while filling frees it. The fill goes through ca_xfer_all,
|
|
1144
|
+
which holds the object cells against a collection while the transfers
|
|
1145
|
+
call Ruby. */
|
|
1146
|
+
|
|
1147
|
+
static VALUE
|
|
1148
|
+
ca_axis_view_fill_owned (VALUE arg)
|
|
1149
|
+
{
|
|
1150
|
+
void **args = (void **) arg;
|
|
1151
|
+
ca_xfer_all((CArray *) args[0], args[1], CA_XFER_GET);
|
|
1152
|
+
return Qnil;
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
void
|
|
1156
|
+
ca_axis_view_attach_owned (void *ap)
|
|
1157
|
+
{
|
|
1158
|
+
CArray *ca = (CArray *) ap;
|
|
1159
|
+
char *buf = xmalloc(ca_length(ca) > 0 ? ca_length(ca) : 1);
|
|
1160
|
+
void *args[2];
|
|
1161
|
+
int tag = 0;
|
|
1162
|
+
|
|
1163
|
+
args[0] = ca;
|
|
1164
|
+
args[1] = buf;
|
|
1165
|
+
rb_protect(ca_axis_view_fill_owned, (VALUE) args, &tag);
|
|
1166
|
+
if ( tag ) {
|
|
1167
|
+
xfree(buf);
|
|
1168
|
+
rb_jump_tag(tag);
|
|
1169
|
+
}
|
|
1170
|
+
ca->ptr = buf;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
void
|
|
1174
|
+
ca_axis_view_sync_owned (void *ap)
|
|
1175
|
+
{
|
|
1176
|
+
CArray *ca = (CArray *) ap;
|
|
1177
|
+
ca_func[ca->obj_type].xfer_all(ca, ca->ptr, CA_XFER_PUT);
|
|
1178
|
+
}
|