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
data/ext/ruby_carray.c
CHANGED
|
@@ -38,6 +38,7 @@ void Init_carray_attribute ();
|
|
|
38
38
|
void Init_carray_loop ();
|
|
39
39
|
void Init_carray_mask ();
|
|
40
40
|
void Init_carray_hold ();
|
|
41
|
+
void Init_carray_key_windows ();
|
|
41
42
|
void Init_carray_mask_fast_paths (); /* patches generated bit-op tables;
|
|
42
43
|
must run AFTER Init_ca_op_ipower */
|
|
43
44
|
void Init_carray_access ();
|
|
@@ -60,6 +61,7 @@ void Init_carray_median_percentile (); /* median / percentile / quantile */
|
|
|
60
61
|
void Init_carray_sort (); /* sort / sort_copy / sort_addr / axis2addr */
|
|
61
62
|
void Init_carray_count ();
|
|
62
63
|
void Init_carray_kernels (); /* mkkernel-generated: reductions + maps */
|
|
64
|
+
void Init_carray_round ();
|
|
63
65
|
void Init_carray_utils ();
|
|
64
66
|
void Init_carray_generate ();
|
|
65
67
|
void Init_carray_copy ();
|
|
@@ -183,13 +185,13 @@ Init_carray_ext (void)
|
|
|
183
185
|
/* The flags this build's arithmetic was compiled with. Anything that
|
|
184
186
|
computes what these kernels compute, somewhere other than in them, has
|
|
185
187
|
to be built the same way to arrive at the same answer. */
|
|
186
|
-
rb_define_const(rb_cCArray, "BUILD_FLAGS", rb_str_new2(CA_BUILD_FLAGS));
|
|
187
|
-
rb_define_const(rb_cCArray, "VERSION", rb_str_new2(CA_VERSION));
|
|
188
|
+
rb_define_const(rb_cCArray, "BUILD_FLAGS", rb_obj_freeze(rb_str_new2(CA_BUILD_FLAGS)));
|
|
189
|
+
rb_define_const(rb_cCArray, "VERSION", rb_obj_freeze(rb_str_new2(CA_VERSION)));
|
|
188
190
|
rb_define_const(rb_cCArray, "VERSION_CODE", INT2NUM(CA_VERSION_CODE));
|
|
189
191
|
rb_define_const(rb_cCArray, "VERSION_MAJOR", INT2NUM(CA_VERSION_MAJOR));
|
|
190
192
|
rb_define_const(rb_cCArray, "VERSION_MINOR", INT2NUM(CA_VERSION_MINOR));
|
|
191
193
|
rb_define_const(rb_cCArray, "VERSION_TEENY", INT2NUM(CA_VERSION_TEENY));
|
|
192
|
-
rb_define_const(rb_cCArray, "VERSION_DATE", rb_str_new2(CA_VERSION_DATE));
|
|
194
|
+
rb_define_const(rb_cCArray, "VERSION_DATE", rb_obj_freeze(rb_str_new2(CA_VERSION_DATE)));
|
|
193
195
|
|
|
194
196
|
/* -- system -- */
|
|
195
197
|
rb_define_const(rb_cObject, "CA_RANK_MAX", INT2NUM(CA_RANK_MAX));
|
|
@@ -199,8 +201,10 @@ Init_carray_ext (void)
|
|
|
199
201
|
absence. C code only ever compares against it; the value is never
|
|
200
202
|
read and must never be passed in from Ruby. The constant exists to
|
|
201
203
|
anchor the object against the GC. */
|
|
202
|
-
CA_UNSPECIFIED = rb_funcall(rb_cObject, rb_intern("new"), 0);
|
|
204
|
+
CA_UNSPECIFIED = rb_obj_freeze(rb_funcall(rb_cObject, rb_intern("new"), 0));
|
|
203
205
|
rb_define_const(rb_cCArray, "UNSPECIFIED", CA_UNSPECIFIED);
|
|
206
|
+
/* Compared by identity in C, so it must not move. */
|
|
207
|
+
rb_gc_register_mark_object(CA_UNSPECIFIED);
|
|
204
208
|
|
|
205
209
|
#ifdef HAVE_COMPLEX_H
|
|
206
210
|
/* @private */
|
|
@@ -284,6 +288,7 @@ Init_carray_ext (void)
|
|
|
284
288
|
Init_carray_undef();
|
|
285
289
|
Init_carray_mask();
|
|
286
290
|
Init_carray_hold();
|
|
291
|
+
Init_carray_key_windows();
|
|
287
292
|
Init_carray_loop();
|
|
288
293
|
Init_carray_access();
|
|
289
294
|
Init_carray_index_classifier();
|
|
@@ -308,6 +313,7 @@ Init_carray_ext (void)
|
|
|
308
313
|
Init_carray_sort(); /* sort / sort_copy / sort_addr / axis2addr */
|
|
309
314
|
Init_carray_count();
|
|
310
315
|
Init_carray_kernels(); /* mkkernel-generated: reductions + maps */
|
|
316
|
+
Init_carray_round(); /* round(ndigits); after the generated round */
|
|
311
317
|
|
|
312
318
|
Init_carray_utils();
|
|
313
319
|
|
data/ext/version.h
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#define CA_VERSION "3.0.
|
|
2
|
-
#define CA_VERSION_CODE
|
|
1
|
+
#define CA_VERSION "3.0.5"
|
|
2
|
+
#define CA_VERSION_CODE 30005
|
|
3
3
|
#define CA_VERSION_MAJOR 3
|
|
4
4
|
#define CA_VERSION_MINOR 0
|
|
5
|
-
#define CA_VERSION_TEENY
|
|
6
|
-
#define CA_VERSION_DATE "2026/10/
|
|
5
|
+
#define CA_VERSION_TEENY 5
|
|
6
|
+
#define CA_VERSION_DATE "2026/10/20"
|
data/lib/carray/attribute.rb
CHANGED
|
@@ -31,11 +31,40 @@
|
|
|
31
31
|
# The walk stops at a lazy operation view (CAMonOp / CABinOp /
|
|
32
32
|
# CATriOp / CAMonCmp / CABinCmp): its cells are computed, not the
|
|
33
33
|
# parent's cells, so the parent's attributes do not describe them.
|
|
34
|
-
# `a.lazy` itself (CALazyMarker) is a view of `a` and walks through
|
|
34
|
+
# `a.lazy` itself (CALazyMarker) is a view of `a` and walks through,
|
|
35
|
+
# and so does a lazy type conversion (the cast lane `promote_list`
|
|
36
|
+
# and `wrap_readonly` build), for the reason `to_type` carries them,
|
|
37
|
+
# and `swap_bytes`: like `refer`, `bitarray` and `bitfield`, a view
|
|
38
|
+
# that reads the same cells another way carries them.
|
|
39
|
+
# A view of a Face shows the attributes of the Face it was taken
|
|
40
|
+
# from (the walk goes to that Face, which the view's own parent
|
|
41
|
+
# chain skips).
|
|
42
|
+
# A view of several arrays (CAStack / CAMeld, so `stack`, `meld` and
|
|
43
|
+
# `montage`) shows, below its own @attr, the keys every one of its
|
|
44
|
+
# arrays shows with the same value; a key they disagree on, or one
|
|
45
|
+
# some of them lack, is not shown. An array with no cells is left out
|
|
46
|
+
# of that count, unless all of them are empty.
|
|
35
47
|
#
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
#
|
|
48
|
+
# Stored values are frozen copies, nested Arrays and Hashes included, so
|
|
49
|
+
# an attribute changes only through set_attr / set_attrs: a value read
|
|
50
|
+
# back cannot be changed in place, and a copy that shares it with its
|
|
51
|
+
# source cannot change the source. A frozen array takes no new
|
|
52
|
+
# attribute.
|
|
53
|
+
#
|
|
54
|
+
# A mask array (`a.mask`) holds no attributes: set_attr / set_attrs raise.
|
|
55
|
+
#
|
|
56
|
+
# Copies: `dup` and `clone` give the new array its own Hash of the
|
|
57
|
+
# receiver's own attributes. `copy` and `to_type` give the new array the attributes the
|
|
58
|
+
# source shows, as its own Hash; `concatenate`, `mosaic` and `tabulate`
|
|
59
|
+
# give it the keys every piece shows with the same value, as the views
|
|
60
|
+
# do. A conversion to another type or representation (`to_type`,
|
|
61
|
+
# `categorize`, a CAFrame `cast` / `parse_to_time` / `to_time`) carries
|
|
62
|
+
# them. Arithmetic and reductions do not -- the result is a different
|
|
63
|
+
# quantity -- including those that pick a value (`first`, `last`, `min`,
|
|
64
|
+
# `max`, `unique`) and the element-wise ones that keep the unit (`abs`,
|
|
65
|
+
# `round`, `clip`): an attribute does not say which operations leave it
|
|
66
|
+
# true, so none carries it. Set it on the result again. A CAFrame index built from a key column's values
|
|
67
|
+
# (group and pivot) shows the key column's attributes.
|
|
39
68
|
|
|
40
69
|
class CArray
|
|
41
70
|
|
|
@@ -63,9 +92,15 @@ class CArray
|
|
|
63
92
|
# store.
|
|
64
93
|
# @param key [Symbol, String] attribute key.
|
|
65
94
|
# @param value [Object] JSON-compatible value.
|
|
66
|
-
#
|
|
95
|
+
# The value is stored as a frozen copy (nested Arrays and Hashes
|
|
96
|
+
# too).
|
|
97
|
+
# @return [Object] the stored value.
|
|
67
98
|
# @raise [TypeError] when `key` or `value` is not accepted.
|
|
99
|
+
# @raise [ArgumentError] when `value` nests more than 32 levels.
|
|
100
|
+
# @raise [FrozenError] when `self` is frozen.
|
|
101
|
+
# @raise [TypeError] when `self` is a mask array.
|
|
68
102
|
def set_attr (key, value)
|
|
103
|
+
attr_check_writable
|
|
69
104
|
attr_validate_value(value)
|
|
70
105
|
(@attr ||= {})[attr_normalize_key(key)] = attr_coerce_value(value)
|
|
71
106
|
end
|
|
@@ -79,7 +114,11 @@ class CArray
|
|
|
79
114
|
# @param hash [Hash{Symbol, String => Object}] attributes to set.
|
|
80
115
|
# @return [CArray] self.
|
|
81
116
|
# @raise [TypeError] when a key or a value is not accepted.
|
|
117
|
+
# @raise [ArgumentError] when a value nests more than 32 levels.
|
|
118
|
+
# @raise [FrozenError] when `self` is frozen.
|
|
119
|
+
# @raise [TypeError] when `self` is a mask array.
|
|
82
120
|
def set_attrs (hash)
|
|
121
|
+
attr_check_writable
|
|
83
122
|
unless hash.is_a?(Hash)
|
|
84
123
|
raise TypeError, "set_attrs takes a Hash (got #{hash.class})"
|
|
85
124
|
end
|
|
@@ -94,8 +133,23 @@ class CArray
|
|
|
94
133
|
self
|
|
95
134
|
end
|
|
96
135
|
|
|
136
|
+
# @overload delete_attr(key)
|
|
137
|
+
# Removes attribute `key` from `self` (not from any parent) and
|
|
138
|
+
# returns its value, or `nil` when `self` has no such key. A key a
|
|
139
|
+
# view shows from its parent stays visible after this, as `set_attr`
|
|
140
|
+
# writes to `self` only.
|
|
141
|
+
# @param key [Symbol, String] attribute key.
|
|
142
|
+
# @return [Object, nil] the removed value.
|
|
143
|
+
# @raise [FrozenError] when `self` is frozen.
|
|
144
|
+
def delete_attr (key)
|
|
145
|
+
k = attr_normalize_key(key)
|
|
146
|
+
return nil unless instance_variable_defined?(:@attr) && @attr
|
|
147
|
+
attr_check_not_frozen
|
|
148
|
+
@attr.delete(k)
|
|
149
|
+
end
|
|
150
|
+
|
|
97
151
|
# @overload attrs
|
|
98
|
-
# Returns a frozen
|
|
152
|
+
# Returns a frozen Hash of all attributes visible on
|
|
99
153
|
# `self`, merged along the parent chain (deeper writes shadow
|
|
100
154
|
# shallower ones on a per-key basis).
|
|
101
155
|
# @return [Hash{String => Object}]
|
|
@@ -135,32 +189,93 @@ class CArray
|
|
|
135
189
|
private
|
|
136
190
|
|
|
137
191
|
# Yield each non-nil @attr Hash along the parent chain (self first).
|
|
138
|
-
#
|
|
139
|
-
# real CArray view chains rarely exceed a handful of levels.
|
|
140
|
-
MAX_CHAIN_DEPTH = 64
|
|
141
|
-
private_constant :MAX_CHAIN_DEPTH
|
|
142
|
-
|
|
192
|
+
# The chain has no fixed bound; an array seen twice ends the walk.
|
|
143
193
|
def attr_each_chain
|
|
144
194
|
ca = self
|
|
145
|
-
|
|
195
|
+
seen = nil
|
|
196
|
+
loop do
|
|
146
197
|
if ca.instance_variable_defined?(:@attr)
|
|
147
198
|
h = ca.instance_variable_get(:@attr)
|
|
148
199
|
yield(h) if h
|
|
149
200
|
end
|
|
150
201
|
return nil if attr_computing_view?(ca)
|
|
151
|
-
|
|
152
|
-
|
|
202
|
+
if ca.is_a?(CAStack) || ca.is_a?(CAMeld)
|
|
203
|
+
shared = CArray.__send__(:attrs_shared_by, ca.parents)
|
|
204
|
+
yield(shared) unless shared.empty?
|
|
205
|
+
return nil
|
|
206
|
+
end
|
|
207
|
+
parent = ca.is_a?(CArray) ? ca.__send__(:attribute_parent) : nil
|
|
208
|
+
return nil if parent.nil?
|
|
209
|
+
seen ||= {}.compare_by_identity
|
|
210
|
+
return nil if seen.key?(parent)
|
|
211
|
+
seen[ca] = true
|
|
153
212
|
ca = parent
|
|
154
213
|
end
|
|
155
|
-
nil
|
|
156
214
|
end
|
|
157
215
|
|
|
216
|
+
def attr_check_not_frozen
|
|
217
|
+
raise FrozenError.new("can't modify frozen #{self.class}: attributes", receiver: self) if frozen?
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def attr_check_writable
|
|
221
|
+
attr_check_not_frozen
|
|
222
|
+
raise TypeError, "a mask array holds no attributes" if mask_array?
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# Give `out`, a new array holding self's values in another type or
|
|
226
|
+
# representation, the attributes self shows; returns `out`. A view of
|
|
227
|
+
# self that already shows them is left alone.
|
|
228
|
+
def carry_attrs (out)
|
|
229
|
+
return out if out.equal?(self)
|
|
230
|
+
shown = attrs
|
|
231
|
+
out.set_attrs(shown) unless shown.empty? || out.attrs == shown
|
|
232
|
+
out
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# Remove what `out`, a new array a reduction made, holds of self's
|
|
236
|
+
# attributes; returns `out`.
|
|
237
|
+
def drop_carried_attrs (out)
|
|
238
|
+
out.remove_instance_variable(:@attr) if out.instance_variable_defined?(:@attr)
|
|
239
|
+
out
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# The attributes every array in `list` shows with the same value.
|
|
243
|
+
# An array with no cells holds no values for the attributes to describe,
|
|
244
|
+
# so it has no say (unless every one is empty), as CAFrame leaves a frame
|
|
245
|
+
# with no rows out of a meld.
|
|
246
|
+
def self.attrs_shared_by (list)
|
|
247
|
+
with_cells = list.reject { |a| a.elements == 0 }
|
|
248
|
+
list = with_cells unless with_cells.empty?
|
|
249
|
+
first, *rest = list.map(&:attrs)
|
|
250
|
+
return {} if first.nil?
|
|
251
|
+
first.select { |k, v| rest.all? { |h| h.key?(k) && h[k] == v } }
|
|
252
|
+
end
|
|
253
|
+
private_class_method :attrs_shared_by
|
|
254
|
+
|
|
158
255
|
def attr_computing_view? (ca)
|
|
159
|
-
ca.is_a?(CAMonOp)
|
|
256
|
+
if ca.is_a?(CAMonOp)
|
|
257
|
+
op = ca.__op_id__
|
|
258
|
+
return op < CAMonOp::CAST_BASE && op != CAMonOp::OP_BYTE_SWAP
|
|
259
|
+
end
|
|
260
|
+
ca.is_a?(CABinOp) || ca.is_a?(CATriOp) ||
|
|
160
261
|
ca.is_a?(CAMonCmp) || ca.is_a?(CABinCmp)
|
|
161
262
|
end
|
|
162
263
|
|
|
163
264
|
def attr_normalize_key (key)
|
|
265
|
+
CArray.__send__(:attr_normalize_key, key)
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def attr_validate_value (v)
|
|
269
|
+
CArray.__send__(:attr_validate_value, v)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def attr_coerce_value (v)
|
|
273
|
+
CArray.__send__(:attr_coerce_value, v)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# The key and value rules, as class methods so that CAFrame's attributes
|
|
277
|
+
# follow the same ones.
|
|
278
|
+
def self.attr_normalize_key (key)
|
|
164
279
|
case key
|
|
165
280
|
when String then key
|
|
166
281
|
when Symbol then key.to_s
|
|
@@ -169,7 +284,7 @@ class CArray
|
|
|
169
284
|
end
|
|
170
285
|
end
|
|
171
286
|
|
|
172
|
-
def attr_validate_value (v, depth = 0)
|
|
287
|
+
def self.attr_validate_value (v, depth = 0)
|
|
173
288
|
raise ArgumentError, "attribute value nests too deep" if depth > 32
|
|
174
289
|
case v
|
|
175
290
|
when String, Integer, Float, true, false, nil, Symbol
|
|
@@ -189,17 +304,19 @@ class CArray
|
|
|
189
304
|
end
|
|
190
305
|
end
|
|
191
306
|
|
|
192
|
-
def attr_coerce_value (v)
|
|
307
|
+
def self.attr_coerce_value (v)
|
|
193
308
|
case v
|
|
194
|
-
when Symbol then v.to_s
|
|
195
|
-
when
|
|
309
|
+
when Symbol then v.to_s.freeze
|
|
310
|
+
when String then v.frozen? ? v : v.dup.freeze
|
|
311
|
+
when Array then v.map { |e| attr_coerce_value(e) }.freeze
|
|
196
312
|
when Hash
|
|
197
313
|
v.each_with_object({}) do |(k, vv), h|
|
|
198
|
-
h[k.is_a?(Symbol) ? k.to_s : k] = attr_coerce_value(vv)
|
|
199
|
-
end
|
|
314
|
+
h[(k.is_a?(Symbol) ? k.to_s : k.dup).freeze] = attr_coerce_value(vv)
|
|
315
|
+
end.freeze
|
|
200
316
|
else
|
|
201
317
|
v
|
|
202
318
|
end
|
|
203
319
|
end
|
|
320
|
+
private_class_method :attr_normalize_key, :attr_validate_value, :attr_coerce_value
|
|
204
321
|
|
|
205
322
|
end
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# after autoload_method_extension is installed. Split by intent:
|
|
7
7
|
#
|
|
8
8
|
# (1) Top-level feature files under carray/ — constant class + entry
|
|
9
|
-
# methods (Serializer,
|
|
9
|
+
# methods (Serializer, iterators, aggregation
|
|
10
10
|
# accumulators, categorical / axis-group).
|
|
11
11
|
# (2) Single-feature method files under carray/methods/ — each first
|
|
12
12
|
# call requires its file, whose definitions overwrite the stubs
|
|
@@ -20,21 +20,6 @@
|
|
|
20
20
|
# (1) Top-level feature files
|
|
21
21
|
# ============================================================================
|
|
22
22
|
|
|
23
|
-
# ---- Inspection (#inspect / #source_code) ----------------------------------
|
|
24
|
-
#
|
|
25
|
-
# CArray::Inspector (:nodoc:) and #inspect / #source_code live in carray/inspect.rb.
|
|
26
|
-
# #inspect is an implicit method (p / pp / irb / error interpolation), so the
|
|
27
|
-
# stub loads the file the first time any CArray is displayed. Nothing in the
|
|
28
|
-
# eager core references it at load time; #desc is private (code-internal) and
|
|
29
|
-
# Inspector is internal, so only the two public methods need stubs.
|
|
30
|
-
|
|
31
|
-
class CArray
|
|
32
|
-
inspect_rb = "carray/inspect"
|
|
33
|
-
autoload_method "inspect", inspect_rb
|
|
34
|
-
autoload_method "inspect_full", inspect_rb
|
|
35
|
-
autoload_method "source_code", inspect_rb
|
|
36
|
-
end
|
|
37
|
-
|
|
38
23
|
# ---- Serializer / Marshal / dump / load ------------------------------------
|
|
39
24
|
|
|
40
25
|
class CArray
|
|
@@ -64,21 +49,6 @@ class CARecord
|
|
|
64
49
|
autoload_method "marshal_dump", "carray/serialize"
|
|
65
50
|
end
|
|
66
51
|
|
|
67
|
-
# ---- Arrow tensor IPC (interop) --------------------------------------------
|
|
68
|
-
|
|
69
|
-
class CArray
|
|
70
|
-
arrow_tensor_rb = "carray/arrow_tensor"
|
|
71
|
-
autoload :ArrowTensor, arrow_tensor_rb
|
|
72
|
-
autoload_method "self.load_arrow_tensor", arrow_tensor_rb
|
|
73
|
-
autoload_method "save_arrow_tensor", arrow_tensor_rb
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# ---- Table (row-major dispatch helper) -------------------------------------
|
|
77
|
-
|
|
78
|
-
class CArray
|
|
79
|
-
autoload :TableMethods, "carray/table"
|
|
80
|
-
end
|
|
81
|
-
|
|
82
52
|
# ---- Fusion (reading a lazy expression as a plan) --------------------------
|
|
83
53
|
#
|
|
84
54
|
# Nothing in the core asks for a plan -- CArray can always walk the view --
|
|
@@ -101,6 +71,7 @@ end
|
|
|
101
71
|
|
|
102
72
|
autoload :CASlabIterator, "carray/slab_iterator"
|
|
103
73
|
autoload :CAWindowIterator, "carray/window_iterator"
|
|
74
|
+
autoload :CAKeyWindowIterator, "carray/key_windows"
|
|
104
75
|
autoload :CABlockIterator, "carray/block_iterator"
|
|
105
76
|
|
|
106
77
|
class CArray
|
|
@@ -174,6 +145,10 @@ autoload :CAUnion, "carray/struct"
|
|
|
174
145
|
autoload :CAFrame, "carray/frame"
|
|
175
146
|
autoload :GroupedFrame, "carray/frame"
|
|
176
147
|
|
|
148
|
+
class CArray
|
|
149
|
+
autoload_method "to_frame", "carray/frame"
|
|
150
|
+
end
|
|
151
|
+
|
|
177
152
|
class CArray
|
|
178
153
|
struct_rb = "carray/struct"
|
|
179
154
|
autoload_method "self.struct", struct_rb
|
|
@@ -231,10 +206,12 @@ class CArray
|
|
|
231
206
|
autoload_method "intersection", "carray/methods/is_in"
|
|
232
207
|
autoload_method "difference", "carray/methods/is_in"
|
|
233
208
|
autoload_method "union", "carray/methods/is_in"
|
|
209
|
+
autoload_method "is_between", "carray/methods/is_between"
|
|
234
210
|
autoload_method "self.align_addr", "carray/methods/align_addr"
|
|
235
211
|
autoload_method "self.align_nearest_addr", "carray/methods/align_addr"
|
|
236
212
|
autoload_method "value_counts", "carray/methods/value_counts"
|
|
237
213
|
autoload_method "nunique", "carray/methods/nunique"
|
|
214
|
+
autoload_method "lag", "carray/methods/lag"
|
|
238
215
|
autoload_method "is_mode", "carray/methods/mode"
|
|
239
216
|
autoload_method "mode", "carray/methods/mode"
|
|
240
217
|
autoload_method "snap", "carray/methods/snap"
|
|
@@ -32,8 +32,18 @@ module AutoloadMethodExtension
|
|
|
32
32
|
private
|
|
33
33
|
|
|
34
34
|
def autoload_define (target, name, library, original_spec)
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
library = Ractor.make_shareable(library.to_s.dup)
|
|
36
|
+
original_spec = Ractor.make_shareable(original_spec.to_s.dup)
|
|
37
|
+
# Shareable, so the stub answers in any Ractor. Only the main Ractor
|
|
38
|
+
# loads the library: Ractors that require at the same time can deadlock
|
|
39
|
+
# (Ruby 3.4), so another Ractor is told what to load there instead.
|
|
40
|
+
target.define_method(name, &Ractor.make_shareable(proc do |*args, **kwargs, &block|
|
|
41
|
+
unless Ractor.current == Ractor.main
|
|
42
|
+
raise Ractor::IsolationError,
|
|
43
|
+
"'#{original_spec}' is loaded on first use from '#{library}'; " \
|
|
44
|
+
"require it in the main Ractor before other Ractors use it"
|
|
45
|
+
end
|
|
46
|
+
stub_location = target.instance_method(name).source_location
|
|
37
47
|
begin
|
|
38
48
|
require library
|
|
39
49
|
rescue LoadError
|
|
@@ -45,14 +55,13 @@ module AutoloadMethodExtension
|
|
|
45
55
|
# forwarding would land straight back here and keep doing so until the
|
|
46
56
|
# stack gave out -- naming neither the method nor the library. Say
|
|
47
57
|
# which, once.
|
|
48
|
-
if target.instance_method(name) ==
|
|
58
|
+
if target.instance_method(name).source_location == stub_location
|
|
49
59
|
raise NoMethodError,
|
|
50
60
|
"'#{original_spec}' is registered for autoload from " \
|
|
51
61
|
"'#{library}', but that library defines no such method"
|
|
52
62
|
end
|
|
53
63
|
send(name, *args, **kwargs, &block)
|
|
54
|
-
end
|
|
55
|
-
stub = target.instance_method(name)
|
|
64
|
+
end))
|
|
56
65
|
# The library replaces the stub with a plain `def`, which `ruby -w`
|
|
57
66
|
# reports as a redefinition. Replacing is what the stub is for, so mark
|
|
58
67
|
# it as aliased: Ruby does not warn when the old definition has an alias.
|