carray 3.0.2 → 3.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +568 -0
- data/README.md +6 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +220 -0
- data/ext/ca_axis_group.c +201 -123
- data/ext/ca_binop_dispatch.c +46 -52
- data/ext/ca_binop_dispatch.h +1 -1
- data/ext/ca_categorical_iterator.c +249 -183
- data/ext/ca_compare.c +7 -12
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +38 -23
- data/ext/ca_kernel_iterator.c +1765 -2076
- data/ext/ca_kernel_iterator.h +584 -566
- data/ext/ca_monop_dispatch.c +86 -63
- data/ext/ca_monop_dispatch.h +5 -0
- data/ext/ca_obj_array.c +223 -56
- data/ext/ca_obj_bincmp.c +172 -138
- data/ext/ca_obj_binop.c +116 -230
- data/ext/ca_obj_bitarray.c +40 -26
- data/ext/ca_obj_bitfield.c +100 -68
- data/ext/ca_obj_block.c +19 -9
- data/ext/ca_obj_byte_swap.c +45 -46
- data/ext/ca_obj_const_string.c +269 -44
- data/ext/ca_obj_face.c +612 -89
- data/ext/ca_obj_face.h +111 -47
- data/ext/ca_obj_fake.c +36 -79
- data/ext/ca_obj_farray.c +7 -3
- data/ext/ca_obj_field.c +33 -8
- data/ext/ca_obj_fixlen_string.c +23 -24
- data/ext/ca_obj_grid.c +541 -210
- data/ext/ca_obj_meld.c +331 -111
- data/ext/ca_obj_moncmp.c +80 -65
- data/ext/ca_obj_monop.c +177 -149
- data/ext/ca_obj_object.c +664 -248
- data/ext/ca_obj_record.c +63 -23
- data/ext/ca_obj_reduce.c +18 -16
- data/ext/ca_obj_refer.c +140 -58
- data/ext/ca_obj_remap.c +85 -24
- data/ext/ca_obj_repeat.c +24 -9
- data/ext/ca_obj_roll.c +121 -16
- data/ext/ca_obj_select.c +61 -58
- data/ext/ca_obj_select_axis.c +73 -107
- data/ext/ca_obj_shift.c +32 -102
- data/ext/ca_obj_stack.c +372 -122
- data/ext/ca_obj_stride.c +348 -140
- data/ext/ca_obj_string.c +88 -22
- data/ext/ca_obj_tile.c +38 -21
- data/ext/ca_obj_time.c +45 -31
- data/ext/ca_obj_timedelta.c +43 -29
- data/ext/ca_obj_transpose.c +17 -6
- data/ext/ca_obj_triop.c +125 -141
- data/ext/ca_obj_window.c +330 -44
- 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 +104 -81
- 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 +542 -0
- data/ext/carray.h +241 -92
- data/ext/carray_access.c +608 -276
- data/ext/carray_address_basis.c +494 -97
- data/ext/carray_attribute.c +129 -4
- data/ext/carray_bincount.c +39 -7
- data/ext/carray_broadcast.c +56 -19
- data/ext/carray_build_flags.h +1 -1
- data/ext/carray_call_cfunc.c +108 -28
- data/ext/carray_cast.c +1576 -223
- data/ext/carray_cast_func.rb +77 -24
- data/ext/carray_class.c +4 -3
- data/ext/carray_conversion.c +208 -75
- data/ext/carray_copy.c +82 -24
- data/ext/carray_core.c +646 -162
- data/ext/carray_count.c +171 -88
- data/ext/carray_element.c +94 -60
- data/ext/carray_factorize.c +670 -324
- data/ext/carray_generate.c +260 -83
- data/ext/carray_histogram.c +209 -106
- data/ext/carray_hold.c +14 -16
- data/ext/carray_index_classifier.c +422 -243
- data/ext/carray_internal.h +692 -3
- data/ext/carray_kernels_bincmp.c +7 -0
- data/ext/carray_kernels_binop.c +487 -120
- data/ext/carray_kernels_init.c +653 -50
- data/ext/carray_kernels_moncmp.c +15 -8
- data/ext/carray_kernels_monop.c +99 -43
- data/ext/carray_kernels_reduce_aggregate.c +3925 -6112
- data/ext/carray_kernels_reduce_boolean.c +112 -36
- data/ext/carray_kernels_reduce_cumulative.c +2127 -6903
- data/ext/carray_kernels_reduce_extreme.c +3032 -2892
- data/ext/carray_kernels_reduce_variance.c +439 -500
- data/ext/carray_kernels_scan.c +1097 -488
- data/ext/carray_kernels_search.c +3787 -2176
- data/ext/carray_kernels_sort.c +1200 -920
- data/ext/carray_kernels_triop.c +479 -7
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +967 -153
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +910 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +299 -100
- data/ext/carray_memory_view.c +872 -758
- data/ext/carray_operator.c +1171 -364
- data/ext/carray_order.c +505 -133
- data/ext/carray_partition.c +112 -65
- data/ext/carray_random.c +327 -239
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +346 -78
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +249 -86
- data/ext/carray_sort.c +224 -227
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +118 -39
- data/ext/carray_test.c +193 -69
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +579 -113
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +19 -4
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1202 -1014
- data/ext/ruby_carray.c +17 -5
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +160 -17
- data/lib/carray/autoload_carray.rb +23 -27
- data/lib/carray/autoload_method_extension.rb +20 -5
- data/lib/carray/axis_group.rb +360 -63
- data/lib/carray/basics.rb +162 -28
- data/lib/carray/bincount_nd.rb +18 -2
- data/lib/carray/block_iterator.rb +231 -58
- data/lib/carray/boolean_reduce.rb +34 -42
- data/lib/carray/categorical.rb +242 -52
- data/lib/carray/categorical_iterator.rb +437 -827
- data/lib/carray/complex.rb +41 -34
- data/lib/carray/conditional.rb +150 -14
- data/lib/carray/const_string.rb +59 -4
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +7 -1
- data/lib/carray/frame/column_verbs.rb +70 -0
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +82 -7
- data/lib/carray/frame/csv_parser.rb +688 -87
- data/lib/carray/frame/describe.rb +80 -0
- data/lib/carray/frame/frame.rb +369 -45
- data/lib/carray/frame/group.rb +631 -90
- data/lib/carray/frame/io.rb +506 -79
- data/lib/carray/frame/join.rb +411 -62
- data/lib/carray/frame/records.rb +116 -19
- data/lib/carray/frame/reshape.rb +455 -0
- data/lib/carray/frame/sort.rb +30 -18
- data/lib/carray/frame/verbs.rb +868 -61
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +4 -0
- data/lib/carray/fuse_source.rb +118 -2
- data/lib/carray/fusion.rb +257 -42
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +54 -13
- data/lib/carray/iterator.rb +99 -9
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +216 -193
- data/lib/carray/mask_gap_fill.rb +112 -92
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +52 -21
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +18 -2
- data/lib/carray/methods/bit_string.rb +15 -4
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +18 -10
- data/lib/carray/methods/factorize.rb +2 -2
- data/lib/carray/methods/gather_nd.rb +25 -5
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +140 -10
- data/lib/carray/methods/join.rb +2 -7
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +182 -45
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +11 -6
- 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/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +65 -17
- data/lib/carray/segment_iterator.rb +1221 -0
- data/lib/carray/serialize.rb +214 -30
- data/lib/carray/slab_iterator.rb +101 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +12 -4
- data/lib/carray/struct.rb +137 -58
- data/lib/carray/struct_builder.rb +124 -17
- data/lib/carray/time.rb +1222 -186
- data/lib/carray/window_iterator.rb +242 -81
- data/lib/carray.rb +9 -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 +5 -1
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +5 -4
- data/yard-stubs/ca_obj_roll.rb +2 -3
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +9 -5
- data/yard-stubs/carray_access.rb +11 -5
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_broadcast.rb +1 -1
- data/yard-stubs/carray_cast.rb +88 -43
- data/yard-stubs/carray_conversion.rb +15 -2
- data/yard-stubs/carray_copy.rb +12 -5
- data/yard-stubs/carray_core.rb +3 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +60 -12
- data/yard-stubs/carray_math.rb +52 -14
- data/yard-stubs/carray_median_percentile.rb +15 -8
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +61 -29
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +21 -9
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +10 -2
- data/yard-stubs/carray_sort.rb +49 -8
- data/yard-stubs/carray_test.rb +15 -3
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -5
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_kernels_map.c +0 -3467
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/ext/ruby_carray.c
CHANGED
|
@@ -38,12 +38,14 @@ 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 ();
|
|
44
45
|
void Init_carray_index_classifier ();
|
|
45
46
|
void Init_carray_element ();
|
|
46
47
|
void Init_carray_scatter (); /* scatter_*! family */
|
|
48
|
+
void Init_carray_segment (); /* segment lengths / offsets / index */
|
|
47
49
|
void Init_ca_axis_group (); /* devel/MEMO_AXIS_GROUP.md — axis-group reduction kernel */
|
|
48
50
|
void Init_ca_group_iter (); /* devel/MEMO_AXIS_GROUP.md — axis-group [] surface */
|
|
49
51
|
void Init_carray_bincount (); /* bincount dedicated kernel */
|
|
@@ -59,6 +61,7 @@ void Init_carray_median_percentile (); /* median / percentile / quantile */
|
|
|
59
61
|
void Init_carray_sort (); /* sort / sort_copy / sort_addr / axis2addr */
|
|
60
62
|
void Init_carray_count ();
|
|
61
63
|
void Init_carray_kernels (); /* mkkernel-generated: reductions + maps */
|
|
64
|
+
void Init_carray_round ();
|
|
62
65
|
void Init_carray_utils ();
|
|
63
66
|
void Init_carray_generate ();
|
|
64
67
|
void Init_carray_copy ();
|
|
@@ -89,6 +92,8 @@ void Init_ca_obj_byte_swap ();
|
|
|
89
92
|
void Init_ca_face (); /* CAFace abstract base; must precede CATime / CATimedelta / CARecord / CAConstString */
|
|
90
93
|
void Init_ca_source (); /* CASource abstract base; concrete sources live in C extensions */
|
|
91
94
|
void Init_ca_obj_time (); /* first numeric Face */
|
|
95
|
+
void Init_carray_time_text ();
|
|
96
|
+
void Init_caframe_csv_reader ();
|
|
92
97
|
void Init_ca_obj_timedelta (); /* CATime sibling */
|
|
93
98
|
void Init_ca_obj_record (); /* composite Face for CAStruct backing */
|
|
94
99
|
void Init_ca_obj_const_string ();/* read-only variable-length string Face */
|
|
@@ -169,7 +174,7 @@ Init_carray_ext (void)
|
|
|
169
174
|
/* -- Exception class -- */
|
|
170
175
|
|
|
171
176
|
rb_eCADataTypeError =
|
|
172
|
-
rb_define_class_under(rb_cCArray, "DataTypeError",
|
|
177
|
+
rb_define_class_under(rb_cCArray, "DataTypeError", rb_eTypeError);
|
|
173
178
|
|
|
174
179
|
/* -- CA module -- namespace for misc utilities related to CArray */
|
|
175
180
|
|
|
@@ -180,13 +185,13 @@ Init_carray_ext (void)
|
|
|
180
185
|
/* The flags this build's arithmetic was compiled with. Anything that
|
|
181
186
|
computes what these kernels compute, somewhere other than in them, has
|
|
182
187
|
to be built the same way to arrive at the same answer. */
|
|
183
|
-
rb_define_const(rb_cCArray, "BUILD_FLAGS", rb_str_new2(CA_BUILD_FLAGS));
|
|
184
|
-
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)));
|
|
185
190
|
rb_define_const(rb_cCArray, "VERSION_CODE", INT2NUM(CA_VERSION_CODE));
|
|
186
191
|
rb_define_const(rb_cCArray, "VERSION_MAJOR", INT2NUM(CA_VERSION_MAJOR));
|
|
187
192
|
rb_define_const(rb_cCArray, "VERSION_MINOR", INT2NUM(CA_VERSION_MINOR));
|
|
188
193
|
rb_define_const(rb_cCArray, "VERSION_TEENY", INT2NUM(CA_VERSION_TEENY));
|
|
189
|
-
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)));
|
|
190
195
|
|
|
191
196
|
/* -- system -- */
|
|
192
197
|
rb_define_const(rb_cObject, "CA_RANK_MAX", INT2NUM(CA_RANK_MAX));
|
|
@@ -196,8 +201,10 @@ Init_carray_ext (void)
|
|
|
196
201
|
absence. C code only ever compares against it; the value is never
|
|
197
202
|
read and must never be passed in from Ruby. The constant exists to
|
|
198
203
|
anchor the object against the GC. */
|
|
199
|
-
CA_UNSPECIFIED = rb_funcall(rb_cObject, rb_intern("new"), 0);
|
|
204
|
+
CA_UNSPECIFIED = rb_obj_freeze(rb_funcall(rb_cObject, rb_intern("new"), 0));
|
|
200
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);
|
|
201
208
|
|
|
202
209
|
#ifdef HAVE_COMPLEX_H
|
|
203
210
|
/* @private */
|
|
@@ -281,11 +288,13 @@ Init_carray_ext (void)
|
|
|
281
288
|
Init_carray_undef();
|
|
282
289
|
Init_carray_mask();
|
|
283
290
|
Init_carray_hold();
|
|
291
|
+
Init_carray_key_windows();
|
|
284
292
|
Init_carray_loop();
|
|
285
293
|
Init_carray_access();
|
|
286
294
|
Init_carray_index_classifier();
|
|
287
295
|
Init_carray_element();
|
|
288
296
|
Init_carray_scatter();
|
|
297
|
+
Init_carray_segment();
|
|
289
298
|
Init_ca_axis_group(); /* devel/MEMO_AXIS_GROUP.md — axis-group reduction kernel */
|
|
290
299
|
Init_carray_bincount();
|
|
291
300
|
Init_carray_factorize();
|
|
@@ -304,6 +313,7 @@ Init_carray_ext (void)
|
|
|
304
313
|
Init_carray_sort(); /* sort / sort_copy / sort_addr / axis2addr */
|
|
305
314
|
Init_carray_count();
|
|
306
315
|
Init_carray_kernels(); /* mkkernel-generated: reductions + maps */
|
|
316
|
+
Init_carray_round(); /* round(ndigits); after the generated round */
|
|
307
317
|
|
|
308
318
|
Init_carray_utils();
|
|
309
319
|
|
|
@@ -343,6 +353,8 @@ Init_carray_ext (void)
|
|
|
343
353
|
(datetime / timedelta / record /
|
|
344
354
|
const_string). */
|
|
345
355
|
Init_ca_obj_time();
|
|
356
|
+
Init_carray_time_text();
|
|
357
|
+
Init_caframe_csv_reader();
|
|
346
358
|
Init_ca_obj_timedelta();
|
|
347
359
|
Init_ca_obj_record();
|
|
348
360
|
Init_ca_obj_const_string();
|
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.4"
|
|
2
|
+
#define CA_VERSION_CODE 30004
|
|
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/
|
|
5
|
+
#define CA_VERSION_TEENY 4
|
|
6
|
+
#define CA_VERSION_DATE "2026/10/19"
|
data/ext/version.rb
CHANGED
|
@@ -21,8 +21,10 @@ def carray_version
|
|
|
21
21
|
|
|
22
22
|
ca_version2 = format("%i.%i.%i",
|
|
23
23
|
ca_version_major, ca_version_minor, ca_version_teeny)
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
# Two decimal digits for each of minor and teeny, so 3.0.10 (30010)
|
|
25
|
+
# comes after 3.0.9 (30009) and before 3.1.0 (30100).
|
|
26
|
+
ca_version_code2 =
|
|
27
|
+
10000 * ca_version_major + 100 * ca_version_minor + ca_version_teeny
|
|
26
28
|
|
|
27
29
|
# Allow pre-release suffix like "3.0.0.dev" / "3.0.0.alpha1" while still
|
|
28
30
|
# validating the numeric MAJOR.MINOR.TEENY prefix.
|
data/lib/carray/attribute.rb
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
# Surface:
|
|
5
5
|
# ca.attr(:unit) # => getter; nil if absent
|
|
6
6
|
# ca.set_attr(:unit, "m/s") # => setter; writes to self's @attr
|
|
7
|
+
# ca.set_attrs(other.attrs) # => sets every key of a Hash at once
|
|
7
8
|
# ca.attrs # => frozen shallow clone of the full Hash
|
|
8
9
|
# ca.has_attr? # => any attribute present?
|
|
9
10
|
# ca.has_attr?(:unit) # => specific key present?
|
|
@@ -27,6 +28,38 @@
|
|
|
27
28
|
# `attrs` returns the effective merged Hash (deeper writes
|
|
28
29
|
# override shallower ones), frozen.
|
|
29
30
|
# Setter side always writes to self's @attr.
|
|
31
|
+
# The walk stops at a lazy operation view (CAMonOp / CABinOp /
|
|
32
|
+
# CATriOp / CAMonCmp / CABinCmp): its cells are computed, not the
|
|
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,
|
|
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
|
+
# A view of a Face shows the attributes of the Face it was taken
|
|
38
|
+
# from (the walk goes to that Face, which the view's own parent
|
|
39
|
+
# chain skips).
|
|
40
|
+
# A view of several arrays (CAStack / CAMeld, so `stack`, `meld` and
|
|
41
|
+
# `montage`) shows, below its own @attr, the keys every one of its
|
|
42
|
+
# arrays shows with the same value; a key they disagree on, or one
|
|
43
|
+
# some of them lack, is not shown.
|
|
44
|
+
#
|
|
45
|
+
# Stored values are frozen copies, nested Arrays and Hashes included, so
|
|
46
|
+
# an attribute changes only through set_attr / set_attrs: a value read
|
|
47
|
+
# back cannot be changed in place, and a copy that shares it with its
|
|
48
|
+
# source cannot change the source. A frozen array takes no new
|
|
49
|
+
# attribute.
|
|
50
|
+
#
|
|
51
|
+
# A mask array (`a.mask`) holds no attributes: set_attr / set_attrs raise.
|
|
52
|
+
#
|
|
53
|
+
# Copies: `dup` and `clone` give the new array its own Hash of the
|
|
54
|
+
# receiver's own attributes. `copy` and `to_type` give the new array the attributes the
|
|
55
|
+
# source shows, as its own Hash; `concatenate`, `mosaic` and `tabulate`
|
|
56
|
+
# give it the keys every piece shows with the same value, as the views
|
|
57
|
+
# do. A conversion to another type or representation (`to_type`,
|
|
58
|
+
# `categorize`, a CAFrame `cast` / `parse_to_time` / `to_time`) carries
|
|
59
|
+
# them. Arithmetic and reductions do not -- the result is a different
|
|
60
|
+
# quantity -- including those that pick a value (`first`, `last`, `min`,
|
|
61
|
+
# `max`, `unique`). A CAFrame index built from a key column's values
|
|
62
|
+
# (group and pivot) shows the key column's attributes.
|
|
30
63
|
|
|
31
64
|
class CArray
|
|
32
65
|
|
|
@@ -54,15 +87,64 @@ class CArray
|
|
|
54
87
|
# store.
|
|
55
88
|
# @param key [Symbol, String] attribute key.
|
|
56
89
|
# @param value [Object] JSON-compatible value.
|
|
57
|
-
#
|
|
90
|
+
# The value is stored as a frozen copy (nested Arrays and Hashes
|
|
91
|
+
# too).
|
|
92
|
+
# @return [Object] the stored value.
|
|
58
93
|
# @raise [TypeError] when `key` or `value` is not accepted.
|
|
94
|
+
# @raise [ArgumentError] when `value` nests more than 32 levels.
|
|
95
|
+
# @raise [FrozenError] when `self` is frozen.
|
|
96
|
+
# @raise [TypeError] when `self` is a mask array.
|
|
59
97
|
def set_attr (key, value)
|
|
98
|
+
attr_check_writable
|
|
60
99
|
attr_validate_value(value)
|
|
61
100
|
(@attr ||= {})[attr_normalize_key(key)] = attr_coerce_value(value)
|
|
62
101
|
end
|
|
63
102
|
|
|
103
|
+
# @overload set_attrs(hash)
|
|
104
|
+
# Sets every key of `hash` on `self`, as {#set_attr} does one key.
|
|
105
|
+
# Keys already on `self` and not in `hash` are kept. Every value is
|
|
106
|
+
# validated before any is written, so a rejected value leaves `self`
|
|
107
|
+
# unchanged. `b.set_attrs(a.attrs)` gives `b` the attributes `a`
|
|
108
|
+
# shows.
|
|
109
|
+
# @param hash [Hash{Symbol, String => Object}] attributes to set.
|
|
110
|
+
# @return [CArray] self.
|
|
111
|
+
# @raise [TypeError] when a key or a value is not accepted.
|
|
112
|
+
# @raise [ArgumentError] when a value nests more than 32 levels.
|
|
113
|
+
# @raise [FrozenError] when `self` is frozen.
|
|
114
|
+
# @raise [TypeError] when `self` is a mask array.
|
|
115
|
+
def set_attrs (hash)
|
|
116
|
+
attr_check_writable
|
|
117
|
+
unless hash.is_a?(Hash)
|
|
118
|
+
raise TypeError, "set_attrs takes a Hash (got #{hash.class})"
|
|
119
|
+
end
|
|
120
|
+
entries = hash.map do |key, value|
|
|
121
|
+
attr_validate_value(value)
|
|
122
|
+
[attr_normalize_key(key), attr_coerce_value(value)]
|
|
123
|
+
end
|
|
124
|
+
unless entries.empty?
|
|
125
|
+
h = (@attr ||= {})
|
|
126
|
+
entries.each { |k, v| h[k] = v }
|
|
127
|
+
end
|
|
128
|
+
self
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# @overload delete_attr(key)
|
|
132
|
+
# Removes attribute `key` from `self` (not from any parent) and
|
|
133
|
+
# returns its value, or `nil` when `self` has no such key. A key a
|
|
134
|
+
# view shows from its parent stays visible after this, as `set_attr`
|
|
135
|
+
# writes to `self` only.
|
|
136
|
+
# @param key [Symbol, String] attribute key.
|
|
137
|
+
# @return [Object, nil] the removed value.
|
|
138
|
+
# @raise [FrozenError] when `self` is frozen.
|
|
139
|
+
def delete_attr (key)
|
|
140
|
+
k = attr_normalize_key(key)
|
|
141
|
+
return nil unless instance_variable_defined?(:@attr) && @attr
|
|
142
|
+
attr_check_not_frozen
|
|
143
|
+
@attr.delete(k)
|
|
144
|
+
end
|
|
145
|
+
|
|
64
146
|
# @overload attrs
|
|
65
|
-
# Returns a frozen
|
|
147
|
+
# Returns a frozen Hash of all attributes visible on
|
|
66
148
|
# `self`, merged along the parent chain (deeper writes shadow
|
|
67
149
|
# shallower ones on a per-key basis).
|
|
68
150
|
# @return [Hash{String => Object}]
|
|
@@ -102,26 +184,85 @@ class CArray
|
|
|
102
184
|
private
|
|
103
185
|
|
|
104
186
|
# Yield each non-nil @attr Hash along the parent chain (self first).
|
|
105
|
-
#
|
|
106
|
-
# real CArray view chains rarely exceed a handful of levels.
|
|
107
|
-
MAX_CHAIN_DEPTH = 64
|
|
108
|
-
private_constant :MAX_CHAIN_DEPTH
|
|
109
|
-
|
|
187
|
+
# The chain has no fixed bound; an array seen twice ends the walk.
|
|
110
188
|
def attr_each_chain
|
|
111
189
|
ca = self
|
|
112
|
-
|
|
190
|
+
seen = nil
|
|
191
|
+
loop do
|
|
113
192
|
if ca.instance_variable_defined?(:@attr)
|
|
114
193
|
h = ca.instance_variable_get(:@attr)
|
|
115
194
|
yield(h) if h
|
|
116
195
|
end
|
|
117
|
-
|
|
118
|
-
|
|
196
|
+
return nil if attr_computing_view?(ca)
|
|
197
|
+
if ca.is_a?(CAStack) || ca.is_a?(CAMeld)
|
|
198
|
+
shared = CArray.__send__(:attrs_shared_by, ca.parents)
|
|
199
|
+
yield(shared) unless shared.empty?
|
|
200
|
+
return nil
|
|
201
|
+
end
|
|
202
|
+
parent = ca.is_a?(CArray) ? ca.__send__(:attribute_parent) : nil
|
|
203
|
+
return nil if parent.nil?
|
|
204
|
+
seen ||= {}.compare_by_identity
|
|
205
|
+
return nil if seen.key?(parent)
|
|
206
|
+
seen[ca] = true
|
|
119
207
|
ca = parent
|
|
120
208
|
end
|
|
121
|
-
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def attr_check_not_frozen
|
|
212
|
+
raise FrozenError.new("can't modify frozen #{self.class}: attributes", receiver: self) if frozen?
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def attr_check_writable
|
|
216
|
+
attr_check_not_frozen
|
|
217
|
+
raise TypeError, "a mask array holds no attributes" if mask_array?
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# Give `out`, a new array holding self's values in another type or
|
|
221
|
+
# representation, the attributes self shows; returns `out`. A view of
|
|
222
|
+
# self that already shows them is left alone.
|
|
223
|
+
def carry_attrs (out)
|
|
224
|
+
return out if out.equal?(self)
|
|
225
|
+
shown = attrs
|
|
226
|
+
out.set_attrs(shown) unless shown.empty? || out.attrs == shown
|
|
227
|
+
out
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Remove what `out`, a new array a reduction made, holds of self's
|
|
231
|
+
# attributes; returns `out`.
|
|
232
|
+
def drop_carried_attrs (out)
|
|
233
|
+
out.remove_instance_variable(:@attr) if out.instance_variable_defined?(:@attr)
|
|
234
|
+
out
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# The attributes every array in `list` shows with the same value.
|
|
238
|
+
def self.attrs_shared_by (list)
|
|
239
|
+
first, *rest = list.map(&:attrs)
|
|
240
|
+
return {} if first.nil?
|
|
241
|
+
first.select { |k, v| rest.all? { |h| h.key?(k) && h[k] == v } }
|
|
242
|
+
end
|
|
243
|
+
private_class_method :attrs_shared_by
|
|
244
|
+
|
|
245
|
+
def attr_computing_view? (ca)
|
|
246
|
+
return ca.__op_id__ < CAMonOp::CAST_BASE if ca.is_a?(CAMonOp)
|
|
247
|
+
ca.is_a?(CABinOp) || ca.is_a?(CATriOp) ||
|
|
248
|
+
ca.is_a?(CAMonCmp) || ca.is_a?(CABinCmp)
|
|
122
249
|
end
|
|
123
250
|
|
|
124
251
|
def attr_normalize_key (key)
|
|
252
|
+
CArray.__send__(:attr_normalize_key, key)
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def attr_validate_value (v)
|
|
256
|
+
CArray.__send__(:attr_validate_value, v)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def attr_coerce_value (v)
|
|
260
|
+
CArray.__send__(:attr_coerce_value, v)
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
# The key and value rules, as class methods so that CAFrame's attributes
|
|
264
|
+
# follow the same ones.
|
|
265
|
+
def self.attr_normalize_key (key)
|
|
125
266
|
case key
|
|
126
267
|
when String then key
|
|
127
268
|
when Symbol then key.to_s
|
|
@@ -130,7 +271,7 @@ class CArray
|
|
|
130
271
|
end
|
|
131
272
|
end
|
|
132
273
|
|
|
133
|
-
def attr_validate_value (v, depth = 0)
|
|
274
|
+
def self.attr_validate_value (v, depth = 0)
|
|
134
275
|
raise ArgumentError, "attribute value nests too deep" if depth > 32
|
|
135
276
|
case v
|
|
136
277
|
when String, Integer, Float, true, false, nil, Symbol
|
|
@@ -150,17 +291,19 @@ class CArray
|
|
|
150
291
|
end
|
|
151
292
|
end
|
|
152
293
|
|
|
153
|
-
def attr_coerce_value (v)
|
|
294
|
+
def self.attr_coerce_value (v)
|
|
154
295
|
case v
|
|
155
|
-
when Symbol then v.to_s
|
|
156
|
-
when
|
|
296
|
+
when Symbol then v.to_s.freeze
|
|
297
|
+
when String then v.frozen? ? v : v.dup.freeze
|
|
298
|
+
when Array then v.map { |e| attr_coerce_value(e) }.freeze
|
|
157
299
|
when Hash
|
|
158
300
|
v.each_with_object({}) do |(k, vv), h|
|
|
159
|
-
h[k.is_a?(Symbol) ? k.to_s : k] = attr_coerce_value(vv)
|
|
160
|
-
end
|
|
301
|
+
h[(k.is_a?(Symbol) ? k.to_s : k.dup).freeze] = attr_coerce_value(vv)
|
|
302
|
+
end.freeze
|
|
161
303
|
else
|
|
162
304
|
v
|
|
163
305
|
end
|
|
164
306
|
end
|
|
307
|
+
private_class_method :attr_normalize_key, :attr_validate_value, :attr_coerce_value
|
|
165
308
|
|
|
166
309
|
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
|
|
@@ -47,19 +32,21 @@ class CArray
|
|
|
47
32
|
autoload_method "marshal_load", serialize_rb
|
|
48
33
|
end
|
|
49
34
|
|
|
50
|
-
#
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
35
|
+
# A view, a wrap and a scalar are marshalled through _dump / self._load,
|
|
36
|
+
# which return a new array: with marshal_dump Marshal records the class and
|
|
37
|
+
# loads into an empty instance of it, which the plain array the payload
|
|
38
|
+
# holds cannot become. A record array keeps marshal_dump, under which it
|
|
39
|
+
# already round-trips with its class.
|
|
40
|
+
[CAView, CAWrap, CScalar].each do |klass|
|
|
41
|
+
klass.class_eval do
|
|
42
|
+
undef_method :marshal_dump
|
|
43
|
+
autoload_method "_dump", "carray/serialize"
|
|
44
|
+
autoload_method "self._load", "carray/serialize"
|
|
45
|
+
end
|
|
57
46
|
end
|
|
58
47
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
class CArray
|
|
62
|
-
autoload :TableMethods, "carray/table"
|
|
48
|
+
class CARecord
|
|
49
|
+
autoload_method "marshal_dump", "carray/serialize"
|
|
63
50
|
end
|
|
64
51
|
|
|
65
52
|
# ---- Fusion (reading a lazy expression as a plan) --------------------------
|
|
@@ -84,6 +71,7 @@ end
|
|
|
84
71
|
|
|
85
72
|
autoload :CASlabIterator, "carray/slab_iterator"
|
|
86
73
|
autoload :CAWindowIterator, "carray/window_iterator"
|
|
74
|
+
autoload :CAKeyWindowIterator, "carray/key_windows"
|
|
87
75
|
autoload :CABlockIterator, "carray/block_iterator"
|
|
88
76
|
|
|
89
77
|
class CArray
|
|
@@ -126,10 +114,12 @@ class CArray
|
|
|
126
114
|
categorical_iterator_rb = "carray/categorical_iterator"
|
|
127
115
|
autoload_method "group_by_category", categorical_iterator_rb
|
|
128
116
|
autoload_method "group_by_run", categorical_iterator_rb
|
|
117
|
+
autoload_method "segments", "carray/segment_iterator"
|
|
129
118
|
end
|
|
130
119
|
|
|
131
120
|
autoload :CACategorical, "carray/categorical"
|
|
132
121
|
autoload :CACategoricalIterator, "carray/categorical_iterator"
|
|
122
|
+
autoload :CASegmentIterator, "carray/segment_iterator"
|
|
133
123
|
autoload :AxisGroup, "carray/axis_group"
|
|
134
124
|
autoload :GroupLabels, "carray/axis_group"
|
|
135
125
|
|
|
@@ -155,6 +145,10 @@ autoload :CAUnion, "carray/struct"
|
|
|
155
145
|
autoload :CAFrame, "carray/frame"
|
|
156
146
|
autoload :GroupedFrame, "carray/frame"
|
|
157
147
|
|
|
148
|
+
class CArray
|
|
149
|
+
autoload_method "to_frame", "carray/frame"
|
|
150
|
+
end
|
|
151
|
+
|
|
158
152
|
class CArray
|
|
159
153
|
struct_rb = "carray/struct"
|
|
160
154
|
autoload_method "self.struct", struct_rb
|
|
@@ -212,10 +206,12 @@ class CArray
|
|
|
212
206
|
autoload_method "intersection", "carray/methods/is_in"
|
|
213
207
|
autoload_method "difference", "carray/methods/is_in"
|
|
214
208
|
autoload_method "union", "carray/methods/is_in"
|
|
209
|
+
autoload_method "is_between", "carray/methods/is_between"
|
|
215
210
|
autoload_method "self.align_addr", "carray/methods/align_addr"
|
|
216
211
|
autoload_method "self.align_nearest_addr", "carray/methods/align_addr"
|
|
217
212
|
autoload_method "value_counts", "carray/methods/value_counts"
|
|
218
213
|
autoload_method "nunique", "carray/methods/nunique"
|
|
214
|
+
autoload_method "lag", "carray/methods/lag"
|
|
219
215
|
autoload_method "is_mode", "carray/methods/mode"
|
|
220
216
|
autoload_method "mode", "carray/methods/mode"
|
|
221
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,13 +55,18 @@ 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
|
|
64
|
+
end))
|
|
65
|
+
# The library replaces the stub with a plain `def`, which `ruby -w`
|
|
66
|
+
# reports as a redefinition. Replacing is what the stub is for, so mark
|
|
67
|
+
# it as aliased: Ruby does not warn when the old definition has an alias.
|
|
68
|
+
tmp = :"__autoload_stub_#{name}__"
|
|
69
|
+
target.send(:alias_method, tmp, name)
|
|
70
|
+
target.send(:remove_method, tmp)
|
|
56
71
|
end
|
|
57
72
|
end
|