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/ca_obj_const_string.c
CHANGED
|
@@ -26,11 +26,13 @@
|
|
|
26
26
|
bytes once in logical order, without offset-sharing dedup.
|
|
27
27
|
|
|
28
28
|
Sibling of ca_obj_record.c (Face + VALUE tail + custom dmark) and
|
|
29
|
-
ca_obj_time.c (int64 Face +
|
|
29
|
+
ca_obj_time.c (int64 Face + storage_to_element fast path).
|
|
30
30
|
|
|
31
31
|
--------------------------------------------------------------------------- */
|
|
32
32
|
|
|
33
33
|
#include "carray.h"
|
|
34
|
+
#include "ruby/util.h"
|
|
35
|
+
#include "carray_internal.h"
|
|
34
36
|
#include "ca_obj_face.h"
|
|
35
37
|
#include <ruby/encoding.h>
|
|
36
38
|
|
|
@@ -121,6 +123,12 @@ ca_const_string_setup (CAConstString *ca, CArray *parent, VALUE buffer, int enco
|
|
|
121
123
|
"(parent.data_type must be CA_FIXLEN with bytes == 16)");
|
|
122
124
|
}
|
|
123
125
|
|
|
126
|
+
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
127
|
+
run them before it allocates. */
|
|
128
|
+
if ( ca == NULL ) {
|
|
129
|
+
return 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
124
132
|
ca->obj_type = CA_OBJ_CONST_STRING;
|
|
125
133
|
/* FIXLEN surface auto-gates mkkernel numeric dispatch. */
|
|
126
134
|
ca->data_type = CA_FIXLEN;
|
|
@@ -142,9 +150,6 @@ ca_const_string_setup (CAConstString *ca, CArray *parent, VALUE buffer, int enco
|
|
|
142
150
|
ca->buffer = buffer;
|
|
143
151
|
ca->encoding_id = encoding_id;
|
|
144
152
|
|
|
145
|
-
if ( ca_has_mask(parent) ) {
|
|
146
|
-
ca_create_mask((CArray *) ca);
|
|
147
|
-
}
|
|
148
153
|
|
|
149
154
|
if ( ca_is_scalar(parent) ) {
|
|
150
155
|
ca_set_flag(ca, CA_FLAG_SCALAR);
|
|
@@ -159,8 +164,11 @@ ca_const_string_setup (CAConstString *ca, CArray *parent, VALUE buffer, int enco
|
|
|
159
164
|
CAConstString *
|
|
160
165
|
ca_const_string_new (CArray *parent, VALUE buffer, int encoding_id)
|
|
161
166
|
{
|
|
162
|
-
CAConstString *ca
|
|
167
|
+
CAConstString *ca;
|
|
168
|
+
ca_const_string_setup(NULL, parent, buffer, encoding_id);
|
|
169
|
+
ca = (CAConstString *) ca_array_alloc(CA_OBJ_CONST_STRING, parent->ndim);
|
|
163
170
|
ca_const_string_setup(ca, parent, buffer, encoding_id);
|
|
171
|
+
ca_fill_or_free((CArray *) ca, ca_view_inherit_mask, (VALUE) ca);
|
|
164
172
|
return ca;
|
|
165
173
|
}
|
|
166
174
|
|
|
@@ -200,18 +208,6 @@ ca_const_string_func_allocate (void *ap)
|
|
|
200
208
|
ca->ptr = ca->parent->ptr;
|
|
201
209
|
}
|
|
202
210
|
|
|
203
|
-
static void
|
|
204
|
-
ca_const_string_func_create_mask (void *ap)
|
|
205
|
-
{
|
|
206
|
-
CAConstString *ca = (CAConstString *) ap;
|
|
207
|
-
ca_update_mask(ca->parent);
|
|
208
|
-
if ( ! ca->parent->mask ) {
|
|
209
|
-
ca_create_mask(ca->parent);
|
|
210
|
-
}
|
|
211
|
-
ca->mask = (CArray *) ca_refer_new(ca->parent->mask,
|
|
212
|
-
CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
211
|
ca_operation_function_t ca_const_string_func = {
|
|
216
212
|
-1, /* CA_OBJ_CONST_STRING — filled by ca_install_obj_type */
|
|
217
213
|
CA_VIEW_ARRAY,
|
|
@@ -222,7 +218,7 @@ ca_operation_function_t ca_const_string_func = {
|
|
|
222
218
|
ca_face_sync,
|
|
223
219
|
ca_face_detach,
|
|
224
220
|
ca_face_fill_data,
|
|
225
|
-
|
|
221
|
+
ca_view_func_create_mask,
|
|
226
222
|
ca_face_xfer_index,
|
|
227
223
|
ca_face_xfer_addrs,
|
|
228
224
|
NULL, /* fold_stride: identity Face is not foldable */
|
|
@@ -255,12 +251,12 @@ ca_const_string_decode (CAConstString *ca, int64_t start, int64_t end)
|
|
|
255
251
|
return rb_str_freeze(s);
|
|
256
252
|
}
|
|
257
253
|
|
|
258
|
-
/*
|
|
254
|
+
/* storage_to_element in C (= skip rb_funcall on the per-cell fetch hot
|
|
259
255
|
path). Since the Face surface is CA_FIXLEN (16 bytes), fetch delivers a
|
|
260
256
|
16-byte raw String = the (start,end) int64 pair. Decode the buffer slice
|
|
261
257
|
→ frozen Ruby String (plain frozen String, no Scalar wrapper). */
|
|
262
258
|
static VALUE
|
|
263
|
-
|
|
259
|
+
rb_ca_const_string_storage_to_element (VALUE self, VALUE raw)
|
|
264
260
|
{
|
|
265
261
|
CAConstString *ca;
|
|
266
262
|
int64_t pair[2];
|
|
@@ -269,7 +265,7 @@ rb_ca_const_string_storage_to_scalar (VALUE self, VALUE raw)
|
|
|
269
265
|
|
|
270
266
|
if ( TYPE(raw) != T_STRING || RSTRING_LEN(raw) != (long) sizeof(pair) ) {
|
|
271
267
|
rb_raise(rb_eArgError,
|
|
272
|
-
"CAConstString#
|
|
268
|
+
"CAConstString#storage_to_element: expected a %lu-byte (start,end) cell",
|
|
273
269
|
(unsigned long) sizeof(pair));
|
|
274
270
|
}
|
|
275
271
|
memcpy(pair, RSTRING_PTR(raw), sizeof(pair));
|
|
@@ -316,8 +312,8 @@ rb_ca_const_string_wrap (VALUE parent_val, VALUE buffer, int encoding_id)
|
|
|
316
312
|
int64_t *pair;
|
|
317
313
|
boolean8_t *m;
|
|
318
314
|
|
|
319
|
-
ca_attach(parent);
|
|
320
315
|
ca_update_mask(parent);
|
|
316
|
+
ca_attach(parent); /* window: detached before its one raise */
|
|
321
317
|
n = parent->elements;
|
|
322
318
|
pair = (int64_t *) parent->ptr;
|
|
323
319
|
m = parent->mask ? (boolean8_t *) parent->mask->ptr : NULL;
|
|
@@ -462,6 +458,54 @@ rb_ca_const_string_buffer (VALUE self)
|
|
|
462
458
|
|
|
463
459
|
/* ------------------------------------------------------------------- */
|
|
464
460
|
|
|
461
|
+
/* to_string: the cells as a CAString over an object array of Strings, in
|
|
462
|
+
one pass over the buffer (shape and mask carried). */
|
|
463
|
+
static VALUE
|
|
464
|
+
rb_ca_const_string_to_string (VALUE self)
|
|
465
|
+
{
|
|
466
|
+
CAConstString *ca;
|
|
467
|
+
volatile VALUE vpairs, out;
|
|
468
|
+
CArray *pe, *co;
|
|
469
|
+
rb_encoding *enc;
|
|
470
|
+
const char *buf;
|
|
471
|
+
const int64_t *pair;
|
|
472
|
+
boolean8_t *m;
|
|
473
|
+
VALUE *cells;
|
|
474
|
+
ca_size_t i;
|
|
475
|
+
|
|
476
|
+
TypedData_Get_Struct(self, CAConstString, &catext_data_type, ca);
|
|
477
|
+
vpairs = rb_ca_parent(self);
|
|
478
|
+
TypedData_Get_Struct(vpairs, CArray, &carray_data_type, pe);
|
|
479
|
+
if ( ! ca_is_entity(pe) ) {
|
|
480
|
+
vpairs = rb_ca_copy(vpairs);
|
|
481
|
+
TypedData_Get_Struct(vpairs, CArray, &carray_data_type, pe);
|
|
482
|
+
}
|
|
483
|
+
enc = rb_enc_from_index(ca->encoding_id);
|
|
484
|
+
out = rb_carray_new(CA_OBJECT, pe->ndim, pe->dim, 0, NULL);
|
|
485
|
+
TypedData_Get_Struct(out, CArray, &carray_data_type, co);
|
|
486
|
+
m = ca_has_mask(pe) ? (boolean8_t *) pe->mask->ptr : NULL;
|
|
487
|
+
if ( m ) {
|
|
488
|
+
ca_create_mask(co);
|
|
489
|
+
memcpy(co->mask->ptr, m, pe->elements);
|
|
490
|
+
}
|
|
491
|
+
buf = RSTRING_PTR(ca->buffer);
|
|
492
|
+
pair = (const int64_t *) pe->ptr;
|
|
493
|
+
cells = (VALUE *) co->ptr;
|
|
494
|
+
for (i = 0; i < pe->elements; i++) {
|
|
495
|
+
if ( m && m[i] ) {
|
|
496
|
+
continue;
|
|
497
|
+
}
|
|
498
|
+
/* out is reachable and marks its cells, so each String is held as it
|
|
499
|
+
is stored */
|
|
500
|
+
cells[i] = rb_enc_str_new(buf + pair[2 * i],
|
|
501
|
+
(long) ( pair[2 * i + 1] - pair[2 * i] ), enc);
|
|
502
|
+
}
|
|
503
|
+
RB_GC_GUARD(vpairs);
|
|
504
|
+
RB_GC_GUARD(self);
|
|
505
|
+
return rb_funcall(rb_const_get(rb_cObject, rb_intern("CAString")),
|
|
506
|
+
rb_intern("wrap"), 1, out);
|
|
507
|
+
}
|
|
508
|
+
|
|
465
509
|
/* copy = compacting deep copy — the only chain-descent point in
|
|
466
510
|
CAConstString. Produces a standalone CAConstString:
|
|
467
511
|
- a fresh contiguous fixlen-16 (start,end) pair entity
|
|
@@ -486,8 +530,8 @@ rb_ca_const_string_copy (VALUE self)
|
|
|
486
530
|
TypedData_Get_Struct(self, CAConstString, &catext_data_type, ca);
|
|
487
531
|
|
|
488
532
|
/* materialize logical-order (start,end) pairs + mask */
|
|
489
|
-
ca_attach((CArray *) ca);
|
|
490
533
|
ca_update_mask((CArray *) ca);
|
|
534
|
+
ca_attach((CArray *) ca); /* window: detached before its one raise */
|
|
491
535
|
|
|
492
536
|
n = ca->elements;
|
|
493
537
|
src_pair = (int64_t *) ca->ptr;
|
|
@@ -537,7 +581,9 @@ rb_ca_const_string_copy (VALUE self)
|
|
|
537
581
|
|
|
538
582
|
ca_detach((CArray *) ca);
|
|
539
583
|
|
|
540
|
-
|
|
584
|
+
vout = rb_ca_const_string_wrap(vout, rb_str_freeze(newbuf), ca->encoding_id);
|
|
585
|
+
rb_ca_inherit_attr(vout, self);
|
|
586
|
+
return vout;
|
|
541
587
|
}
|
|
542
588
|
|
|
543
589
|
/* to_ca descends to the same compacting copy. The result is detached
|
|
@@ -567,12 +613,14 @@ typedef struct {
|
|
|
567
613
|
ca_size_t n;
|
|
568
614
|
} ca_const_string_scan_t;
|
|
569
615
|
|
|
616
|
+
/* Opens the scan's window; ca_const_string_scan_end closes it. What runs
|
|
617
|
+
between them in this file reads bytes and raises only after closing. */
|
|
570
618
|
static void
|
|
571
619
|
ca_const_string_scan_begin (VALUE self, ca_const_string_scan_t *s)
|
|
572
620
|
{
|
|
573
621
|
TypedData_Get_Struct(self, CAConstString, &catext_data_type, s->ca);
|
|
574
|
-
ca_attach((CArray *) s->ca);
|
|
575
622
|
ca_update_mask((CArray *) s->ca);
|
|
623
|
+
ca_attach((CArray *) s->ca); /* window: closed by ca_const_string_scan_end */
|
|
576
624
|
s->off = (int64_t *) s->ca->ptr;
|
|
577
625
|
s->m = s->ca->mask ? (boolean8_t *) s->ca->mask->ptr : NULL;
|
|
578
626
|
s->buf = RSTRING_PTR(s->ca->buffer);
|
|
@@ -586,6 +634,38 @@ ca_const_string_scan_end (ca_const_string_scan_t *s)
|
|
|
586
634
|
ca_detach((CArray *) s->ca);
|
|
587
635
|
}
|
|
588
636
|
|
|
637
|
+
typedef struct {
|
|
638
|
+
VALUE self;
|
|
639
|
+
ca_const_string_scan_t *s;
|
|
640
|
+
} ca_const_string_scan_arg_t;
|
|
641
|
+
|
|
642
|
+
static VALUE
|
|
643
|
+
ca_const_string_scan_begin_body (VALUE arg)
|
|
644
|
+
{
|
|
645
|
+
ca_const_string_scan_arg_t *x = (ca_const_string_scan_arg_t *) arg;
|
|
646
|
+
ca_const_string_scan_begin(x->self, x->s);
|
|
647
|
+
return Qnil;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
/* Begins the scans of two arrays, both or neither: when the second one's
|
|
651
|
+
attach raises, the first is closed before the raise goes on. */
|
|
652
|
+
static void
|
|
653
|
+
ca_const_string_scan_begin_pair (VALUE va, ca_const_string_scan_t *a,
|
|
654
|
+
VALUE vb, ca_const_string_scan_t *b)
|
|
655
|
+
{
|
|
656
|
+
ca_const_string_scan_arg_t x;
|
|
657
|
+
int tag = 0;
|
|
658
|
+
ca_const_string_scan_begin(va, a);
|
|
659
|
+
x.self = vb;
|
|
660
|
+
x.s = b;
|
|
661
|
+
/* protect: ends the first scan, which is not an array */
|
|
662
|
+
rb_protect(ca_const_string_scan_begin_body, (VALUE) &x, &tag);
|
|
663
|
+
if ( tag ) {
|
|
664
|
+
ca_const_string_scan_end(a);
|
|
665
|
+
rb_jump_tag(tag);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
589
669
|
/* Resolve element i to its record bytes; returns 0 if masked.
|
|
590
670
|
Storage is (start,end) int64 pairs: s->off holds 2 int64 per element,
|
|
591
671
|
so element i occupies s->off[2*i] (start) .. s->off[2*i+1] (end).
|
|
@@ -740,8 +820,7 @@ rb_ca_const_string_eq (VALUE self, VALUE other)
|
|
|
740
820
|
int64_t la = 0, lb = 0;
|
|
741
821
|
ca_size_t i;
|
|
742
822
|
|
|
743
|
-
|
|
744
|
-
ca_const_string_scan_begin(other, &b);
|
|
823
|
+
ca_const_string_scan_begin_pair(self, &a, other, &b);
|
|
745
824
|
if ( a.n != b.n ) {
|
|
746
825
|
ca_const_string_scan_end(&a);
|
|
747
826
|
ca_const_string_scan_end(&b);
|
|
@@ -825,13 +904,12 @@ rb_ca_const_string_search (VALUE self, VALUE query)
|
|
|
825
904
|
byte-for-byte faithful to `to_object.sort` with no collation
|
|
826
905
|
loss. */
|
|
827
906
|
|
|
828
|
-
/*
|
|
829
|
-
|
|
830
|
-
static ca_const_string_scan_t *ca_const_string_sort_ctx;
|
|
831
|
-
|
|
907
|
+
/* The scan is passed to the comparator, not held in a static: Ractors
|
|
908
|
+
sort at the same time. */
|
|
832
909
|
static int
|
|
833
|
-
ca_const_string_byte_cmp (const void *a, const void *b)
|
|
910
|
+
ca_const_string_byte_cmp (const void *a, const void *b, void *ctx)
|
|
834
911
|
{
|
|
912
|
+
ca_const_string_scan_t *scan = (ca_const_string_scan_t *) ctx;
|
|
835
913
|
ca_size_t ia = *(const ca_size_t *) a;
|
|
836
914
|
ca_size_t ib = *(const ca_size_t *) b;
|
|
837
915
|
/* sort raises on masked input, so record() always sets these here; the
|
|
@@ -839,13 +917,21 @@ ca_const_string_byte_cmp (const void *a, const void *b)
|
|
|
839
917
|
const char *pa = NULL, *pb = NULL;
|
|
840
918
|
int64_t la = 0, lb = 0;
|
|
841
919
|
int c;
|
|
842
|
-
ca_const_string_record(
|
|
843
|
-
ca_const_string_record(
|
|
920
|
+
ca_const_string_record(scan, ia, &pa, &la);
|
|
921
|
+
ca_const_string_record(scan, ib, &pb, &lb);
|
|
844
922
|
c = memcmp(pa, pb, (size_t) (la < lb ? la : lb));
|
|
845
923
|
if ( c != 0 ) return c;
|
|
846
924
|
return (la > lb) - (la < lb);
|
|
847
925
|
}
|
|
848
926
|
|
|
927
|
+
static int
|
|
928
|
+
ca_const_string_index_cmp (const void *a, const void *b)
|
|
929
|
+
{
|
|
930
|
+
ca_size_t ia = *(const ca_size_t *) a;
|
|
931
|
+
ca_size_t ib = *(const ca_size_t *) b;
|
|
932
|
+
return (ia > ib) - (ia < ib);
|
|
933
|
+
}
|
|
934
|
+
|
|
849
935
|
/* compute the ascending sort permutation; raises on masked input (matches
|
|
850
936
|
base CArray#sort). caller xfree()s the returned index array. */
|
|
851
937
|
static ca_size_t *
|
|
@@ -859,9 +945,19 @@ ca_const_string_sort_perm (ca_const_string_scan_t *s)
|
|
|
859
945
|
}
|
|
860
946
|
idx = ALLOC_N(ca_size_t, s->n);
|
|
861
947
|
for ( i = 0; i < s->n; i++ ) idx[i] = i;
|
|
862
|
-
|
|
863
|
-
qsort
|
|
864
|
-
|
|
948
|
+
ruby_qsort(idx, (size_t) s->n, sizeof(ca_size_t), ca_const_string_byte_cmp, s);
|
|
949
|
+
/* qsort is not stable. Equal strings keep their order, as CArray's own
|
|
950
|
+
sort does, so each run of them is put back in position order. Breaking
|
|
951
|
+
the tie inside the comparator instead doubles the sort on columns with
|
|
952
|
+
many repeats. */
|
|
953
|
+
for ( i = 0; i < s->n; ) {
|
|
954
|
+
ca_size_t j = i + 1;
|
|
955
|
+
while ( j < s->n && ca_const_string_byte_cmp(&idx[i], &idx[j], s) == 0 ) j++;
|
|
956
|
+
if ( j - i > 1 ) {
|
|
957
|
+
qsort(idx + i, (size_t) (j - i), sizeof(ca_size_t), ca_const_string_index_cmp);
|
|
958
|
+
}
|
|
959
|
+
i = j;
|
|
960
|
+
}
|
|
865
961
|
return idx;
|
|
866
962
|
}
|
|
867
963
|
|
|
@@ -936,6 +1032,128 @@ ca_const_string_extremum (VALUE self, int want_max)
|
|
|
936
1032
|
static VALUE rb_ca_const_string_min (VALUE self) { return ca_const_string_extremum(self, 0); }
|
|
937
1033
|
static VALUE rb_ca_const_string_max (VALUE self) { return ca_const_string_extremum(self, 1); }
|
|
938
1034
|
|
|
1035
|
+
/* ------------------------------------------------------------------- */
|
|
1036
|
+
/* Native factorize: categorize's discovery pass, read from the bytes. The
|
|
1037
|
+
storage cells are byte ranges, so the fixlen lane of
|
|
1038
|
+
CArray#__factorize_appearance__ would tell ranges apart, not strings. A
|
|
1039
|
+
String is made per distinct value only, after the scan's window closes. */
|
|
1040
|
+
|
|
1041
|
+
static uint64_t
|
|
1042
|
+
ca_const_string_hash_bytes (const char *p, int64_t len)
|
|
1043
|
+
{
|
|
1044
|
+
uint64_t h = 1469598103934665603ULL; /* FNV-1a */
|
|
1045
|
+
int64_t i;
|
|
1046
|
+
for ( i = 0; i < len; i++ ) {
|
|
1047
|
+
h ^= (unsigned char) p[i];
|
|
1048
|
+
h *= 1099511628211ULL;
|
|
1049
|
+
}
|
|
1050
|
+
return h;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
/* CAConstString#__factorize_appearance__ -> [codes, levels], as the CArray
|
|
1054
|
+
method answers: codes are the narrowest unsigned type holding the k codes
|
|
1055
|
+
and the type-max sentinel, which masked cells store; levels are the k
|
|
1056
|
+
distinct Strings in first-appearance order. */
|
|
1057
|
+
static VALUE
|
|
1058
|
+
rb_ca_const_string_factorize_appearance (VALUE self)
|
|
1059
|
+
{
|
|
1060
|
+
ca_const_string_scan_t s;
|
|
1061
|
+
CAConstString *ca;
|
|
1062
|
+
volatile VALUE vcodes, levels;
|
|
1063
|
+
CArray *co;
|
|
1064
|
+
uint32_t *codes, *slot;
|
|
1065
|
+
int64_t *lev_start, *lev_len;
|
|
1066
|
+
size_t cap = 16, mask_bits;
|
|
1067
|
+
ca_size_t n, i, k = 0;
|
|
1068
|
+
int8_t code_dt;
|
|
1069
|
+
VALUE slot_holder = 0, start_holder = 0, len_holder = 0;
|
|
1070
|
+
|
|
1071
|
+
TypedData_Get_Struct(self, CAConstString, &catext_data_type, ca);
|
|
1072
|
+
n = ca->elements;
|
|
1073
|
+
if ( (uint64_t) n >= 0xFFFFFFFFULL ) {
|
|
1074
|
+
rb_raise(rb_eArgError, "categorize: too many elements for uint32 codes");
|
|
1075
|
+
}
|
|
1076
|
+
while ( cap < (size_t) n * 2 ) {
|
|
1077
|
+
cap <<= 1;
|
|
1078
|
+
}
|
|
1079
|
+
mask_bits = cap - 1;
|
|
1080
|
+
/* Everything the scan writes is allocated before its window opens, and
|
|
1081
|
+
held by the collector: opening the window reads the offsets, which
|
|
1082
|
+
can raise for a parent that answers in Ruby. */
|
|
1083
|
+
vcodes = rb_carray_new(CA_UINT32, ca->ndim, ca->dim, 0, NULL);
|
|
1084
|
+
TypedData_Get_Struct(vcodes, CArray, &carray_data_type, co);
|
|
1085
|
+
codes = (uint32_t *) co->ptr;
|
|
1086
|
+
slot = ALLOCV_N(uint32_t, slot_holder, cap); /* code + 1; 0 is empty */
|
|
1087
|
+
MEMZERO(slot, uint32_t, cap);
|
|
1088
|
+
lev_start = ALLOCV_N(int64_t, start_holder, n > 0 ? n : 1);
|
|
1089
|
+
lev_len = ALLOCV_N(int64_t, len_holder, n > 0 ? n : 1);
|
|
1090
|
+
|
|
1091
|
+
ca_const_string_scan_begin(self, &s);
|
|
1092
|
+
for ( i = 0; i < s.n; i++ ) {
|
|
1093
|
+
const char *p;
|
|
1094
|
+
int64_t len;
|
|
1095
|
+
size_t j;
|
|
1096
|
+
if ( ! ca_const_string_record(&s, i, &p, &len) ) {
|
|
1097
|
+
codes[i] = 0xFFFFFFFFu;
|
|
1098
|
+
continue;
|
|
1099
|
+
}
|
|
1100
|
+
j = (size_t) ca_const_string_hash_bytes(p, len) & mask_bits;
|
|
1101
|
+
for (;;) {
|
|
1102
|
+
uint32_t c = slot[j];
|
|
1103
|
+
if ( c == 0 ) {
|
|
1104
|
+
lev_start[k] = (int64_t) (p - s.buf);
|
|
1105
|
+
lev_len[k] = len;
|
|
1106
|
+
slot[j] = (uint32_t) (k + 1);
|
|
1107
|
+
codes[i] = (uint32_t) k;
|
|
1108
|
+
k++;
|
|
1109
|
+
break;
|
|
1110
|
+
}
|
|
1111
|
+
if ( lev_len[c - 1] == len && memcmp(s.buf + lev_start[c - 1], p, (size_t) len) == 0 ) {
|
|
1112
|
+
codes[i] = c - 1;
|
|
1113
|
+
break;
|
|
1114
|
+
}
|
|
1115
|
+
j = (j + 1) & mask_bits;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
ca_const_string_scan_end(&s);
|
|
1119
|
+
ALLOCV_END(slot_holder);
|
|
1120
|
+
|
|
1121
|
+
/* The buffer is the column's frozen String, alive past the window. */
|
|
1122
|
+
levels = rb_ary_new_capa(k);
|
|
1123
|
+
{
|
|
1124
|
+
const char *buf = RSTRING_PTR(ca->buffer);
|
|
1125
|
+
rb_encoding *enc = rb_enc_from_index(ca->encoding_id);
|
|
1126
|
+
for ( i = 0; i < k; i++ ) {
|
|
1127
|
+
rb_ary_push(levels, rb_enc_str_new(buf + lev_start[i], lev_len[i], enc));
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
ALLOCV_END(start_holder);
|
|
1131
|
+
ALLOCV_END(len_holder);
|
|
1132
|
+
|
|
1133
|
+
if ( k <= 0xFF ) { code_dt = CA_UINT8; }
|
|
1134
|
+
else if ( k <= 0xFFFF ) { code_dt = CA_UINT16; }
|
|
1135
|
+
else { code_dt = CA_UINT32; }
|
|
1136
|
+
if ( code_dt != CA_UINT32 ) {
|
|
1137
|
+
VALUE vnarrow = rb_carray_new(code_dt, ca->ndim, ca->dim, 0, NULL);
|
|
1138
|
+
CArray *cn;
|
|
1139
|
+
TypedData_Get_Struct(vnarrow, CArray, &carray_data_type, cn);
|
|
1140
|
+
if ( code_dt == CA_UINT8 ) {
|
|
1141
|
+
uint8_t *cp = (uint8_t *) cn->ptr;
|
|
1142
|
+
for ( i = 0; i < n; i++ ) {
|
|
1143
|
+
cp[i] = codes[i] == 0xFFFFFFFFu ? (uint8_t) 0xFF : (uint8_t) codes[i];
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
else {
|
|
1147
|
+
uint16_t *cp = (uint16_t *) cn->ptr;
|
|
1148
|
+
for ( i = 0; i < n; i++ ) {
|
|
1149
|
+
cp[i] = codes[i] == 0xFFFFFFFFu ? (uint16_t) 0xFFFF : (uint16_t) codes[i];
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
vcodes = vnarrow;
|
|
1153
|
+
}
|
|
1154
|
+
return rb_ary_new3(2, vcodes, levels);
|
|
1155
|
+
}
|
|
1156
|
+
|
|
939
1157
|
/* ------------------------------------------------------------------- */
|
|
940
1158
|
|
|
941
1159
|
static VALUE
|
|
@@ -950,6 +1168,7 @@ rb_ca_const_string_initialize_copy (VALUE self, VALUE other)
|
|
|
950
1168
|
{
|
|
951
1169
|
CAConstString *ca, *cs;
|
|
952
1170
|
TypedData_Get_Struct(self, CAConstString, &catext_data_type, ca);
|
|
1171
|
+
ca_check_uninitialized(ca);
|
|
953
1172
|
TypedData_Get_Struct(other, CAConstString, &catext_data_type, cs);
|
|
954
1173
|
/* Shallow re-setup: shares the buffer and the offset source, which is the
|
|
955
1174
|
documented `dup` semantics for a view. `copy` is the compacting deep
|
|
@@ -958,6 +1177,7 @@ rb_ca_const_string_initialize_copy (VALUE self, VALUE other)
|
|
|
958
1177
|
ca_array_pool_alloc(ca, CA_OBJ_CONST_STRING, cs->parent->ndim);
|
|
959
1178
|
}
|
|
960
1179
|
ca_const_string_setup(ca, cs->parent, cs->buffer, cs->encoding_id);
|
|
1180
|
+
ca_view_inherit_mask((VALUE) ca);
|
|
961
1181
|
return self;
|
|
962
1182
|
}
|
|
963
1183
|
|
|
@@ -985,11 +1205,12 @@ Init_ca_obj_const_string (void)
|
|
|
985
1205
|
rb_define_singleton_method(rb_cCAConstString, "__build__", rb_ca_const_string_build, 2);
|
|
986
1206
|
rb_define_method(rb_cCAConstString, "encoding", rb_ca_const_string_encoding, 0);
|
|
987
1207
|
rb_define_method(rb_cCAConstString, "buffer", rb_ca_const_string_buffer, 0);
|
|
988
|
-
rb_define_method(rb_cCAConstString, "
|
|
989
|
-
|
|
1208
|
+
rb_define_method(rb_cCAConstString, "storage_to_element",
|
|
1209
|
+
rb_ca_const_string_storage_to_element, 1);
|
|
990
1210
|
|
|
991
1211
|
/* copy = compacting deep copy; to_ca is the same descent point. */
|
|
992
1212
|
rb_define_method(rb_cCAConstString, "copy", rb_ca_const_string_copy, 0);
|
|
1213
|
+
rb_define_method(rb_cCAConstString, "to_string", rb_ca_const_string_to_string, 0);
|
|
993
1214
|
rb_define_method(rb_cCAConstString, "to_ca", rb_ca_const_string_to_ca, -1);
|
|
994
1215
|
|
|
995
1216
|
/* native byte ops (§3.7) */
|
|
@@ -1009,13 +1230,17 @@ Init_ca_obj_const_string (void)
|
|
|
1009
1230
|
/* Native flat sort permutation / min / max (§3.7), byte-memcmp
|
|
1010
1231
|
comparator. The public ordering surface is built on these in
|
|
1011
1232
|
lib/carray/const_string.rb; see the comment above their definitions. */
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1233
|
+
rb_define_private_method(rb_cCAConstString, "sort_addr_by_bytes",
|
|
1234
|
+
rb_ca_const_string_sort_index, 0);
|
|
1235
|
+
rb_define_private_method(rb_cCAConstString, "min_string_by_bytes",
|
|
1236
|
+
rb_ca_const_string_min, 0);
|
|
1237
|
+
rb_define_private_method(rb_cCAConstString, "__factorize_appearance__",
|
|
1238
|
+
rb_ca_const_string_factorize_appearance, 0);
|
|
1239
|
+
rb_define_private_method(rb_cCAConstString, "max_string_by_bytes",
|
|
1240
|
+
rb_ca_const_string_max, 0);
|
|
1016
1241
|
|
|
1017
1242
|
/* Y-pilot: Face-local C-level fast path for per-cell scalar fetch. */
|
|
1018
|
-
|
|
1243
|
+
ca_face_register_storage_to_element(CA_OBJ_CONST_STRING, rb_ca_const_string_storage_to_element);
|
|
1019
1244
|
|
|
1020
1245
|
/* F.S1: CAConstString's `buffer` field is per-parent (= each CAConstString holds its
|
|
1021
1246
|
own frozen byte String; cell offsets index into THIS instance's
|