carray 3.0.6 → 3.0.7
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 +110 -0
- data/README.md +24 -3
- data/carray.gemspec +1 -1
- data/ext/ca_axis_group.c +6 -6
- data/ext/ca_binop_dispatch.c +8 -0
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +7 -7
- data/ext/ca_kernel_iterator.h +6 -4
- data/ext/ca_obj_array.c +4 -4
- data/ext/ca_obj_bincmp.c +19 -3
- data/ext/ca_obj_binop.c +36 -11
- data/ext/ca_obj_bitarray.c +2 -4
- data/ext/ca_obj_bitfield.c +86 -4
- data/ext/ca_obj_byte_swap.c +2 -4
- data/ext/ca_obj_const_string.c +422 -257
- data/ext/ca_obj_face.c +71 -33
- data/ext/ca_obj_fake.c +112 -13
- data/ext/ca_obj_farray.c +7 -1
- data/ext/ca_obj_fixlen_string.c +51 -17
- data/ext/ca_obj_grid.c +12 -7
- data/ext/ca_obj_meld.c +5 -5
- data/ext/ca_obj_monop.c +65 -39
- data/ext/ca_obj_object.c +9 -9
- data/ext/ca_obj_reduce.c +2 -4
- data/ext/ca_obj_refer.c +104 -10
- data/ext/ca_obj_repeat.c +1 -1
- data/ext/ca_obj_roll.c +2 -4
- data/ext/ca_obj_select.c +8 -6
- data/ext/ca_obj_select_axis.c +8 -6
- data/ext/ca_obj_stack.c +5 -5
- data/ext/ca_obj_stride.c +46 -8
- data/ext/ca_obj_string.c +2 -2
- data/ext/ca_obj_tile.c +2 -4
- data/ext/ca_obj_triop.c +15 -12
- data/ext/ca_obj_window.c +22 -15
- data/ext/ca_op_ipower.c +63 -15
- data/ext/ca_op_powi.h +6 -29
- data/ext/ca_sort_kernels.h +3 -0
- data/ext/ca_sweep_engine.c +90 -23
- data/ext/ca_sweep_engine.h +5 -6
- data/ext/caframe_csv_reader.c +1 -1
- data/ext/carray.h +3 -1
- data/ext/carray_access.c +98 -39
- data/ext/carray_address_basis.c +98 -24
- data/ext/carray_broadcast.c +2 -2
- data/ext/carray_call_cfunc.c +5 -8
- data/ext/carray_cast.c +311 -37
- data/ext/carray_cast_func.rb +37 -5
- data/ext/carray_conversion.c +56 -2
- data/ext/carray_copy.c +24 -0
- data/ext/carray_core.c +69 -6
- data/ext/carray_count.c +28 -9
- data/ext/carray_element.c +9 -3
- data/ext/carray_factorize.c +11 -11
- data/ext/carray_histogram.c +2 -2
- data/ext/carray_index_classifier.c +7 -5
- data/ext/carray_internal.h +94 -0
- data/ext/carray_kernels_binop.c +55 -55
- data/ext/carray_kernels_init.c +14 -14
- data/ext/carray_kernels_monop.c +90 -140
- data/ext/carray_lazy.c +16 -1
- data/ext/carray_loop.c +9 -2
- data/ext/carray_mask.c +118 -11
- data/ext/carray_median_percentile.c +13 -8
- data/ext/carray_memory_view.c +41 -22
- data/ext/carray_operator.c +72 -11
- data/ext/carray_order.c +52 -9
- data/ext/carray_partition.c +1 -1
- data/ext/carray_random.c +1 -1
- data/ext/carray_round.c +24 -1
- data/ext/carray_scatter.c +4 -0
- data/ext/carray_segment.c +1 -1
- data/ext/carray_slab.c +13 -4
- data/ext/carray_sort.c +6 -3
- data/ext/carray_sort_kernel.c +24 -0
- data/ext/carray_struct.c +21 -6
- data/ext/carray_test.c +85 -39
- data/ext/carray_time_text.c +6 -0
- data/ext/carray_utils.c +124 -54
- data/ext/mk_call_cfunc.rb +6 -11
- data/ext/mkkernel.rb +37 -27
- data/ext/version.h +4 -4
- data/lib/carray/axis_group.rb +9 -6
- data/lib/carray/basics.rb +26 -8
- data/lib/carray/bincount_nd.rb +8 -2
- data/lib/carray/block_iterator.rb +48 -21
- data/lib/carray/categorical.rb +21 -8
- data/lib/carray/categorical_iterator.rb +2 -1
- data/lib/carray/conditional.rb +52 -4
- data/lib/carray/const_string.rb +74 -0
- data/lib/carray/construct.rb +2 -2
- data/lib/carray/core_extensions.rb +19 -68
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/fixlen_string.rb +83 -1
- data/lib/carray/frame/column_verbs.rb +61 -6
- data/lib/carray/frame/concat.rb +50 -6
- data/lib/carray/frame/csv_parser.rb +13 -4
- data/lib/carray/frame/frame.rb +38 -6
- data/lib/carray/frame/group.rb +67 -40
- data/lib/carray/frame/io.rb +10 -5
- data/lib/carray/frame/join.rb +20 -6
- data/lib/carray/frame/records.rb +6 -4
- data/lib/carray/frame/reshape.rb +25 -5
- data/lib/carray/frame/verbs.rb +78 -25
- data/lib/carray/frame/windows.rb +30 -6
- data/lib/carray/fuse_source.rb +4 -2
- data/lib/carray/iterator.rb +8 -0
- data/lib/carray/key_windows.rb +10 -4
- data/lib/carray/lazy.rb +12 -17
- data/lib/carray/methods/bin.rb +3 -0
- data/lib/carray/methods/composition.rb +1 -1
- data/lib/carray/methods/factorize.rb +2 -0
- data/lib/carray/methods/gather_nd.rb +4 -1
- data/lib/carray/methods/is_in.rb +23 -3
- data/lib/carray/methods/locate_addr.rb +63 -12
- data/lib/carray/methods/repeat.rb +11 -1
- data/lib/carray/record_order.rb +35 -6
- data/lib/carray/runtime.rb +10 -0
- data/lib/carray/segment_iterator.rb +19 -16
- data/lib/carray/serialize.rb +22 -0
- data/lib/carray/slab_iterator.rb +1 -1
- data/lib/carray/stack.rb +3 -3
- data/lib/carray/string.rb +6 -6
- data/lib/carray/string_operation_extension.rb +25 -4
- data/lib/carray/struct_builder.rb +4 -1
- data/lib/carray/time.rb +190 -46
- data/lib/carray/window_iterator.rb +48 -12
- data/yard-stubs/ca_obj_bitfield.rb +4 -1
- data/yard-stubs/ca_obj_refer.rb +3 -0
- data/yard-stubs/ca_obj_window.rb +2 -1
- data/yard-stubs/carray_access.rb +4 -2
- data/yard-stubs/carray_cast.rb +6 -0
- data/yard-stubs/carray_count.rb +6 -3
- data/yard-stubs/carray_math.rb +5 -0
- data/yard-stubs/carray_order.rb +6 -0
- data/yard-stubs/carray_scatter.rb +2 -1
- data/yard-stubs/carray_test.rb +18 -5
- metadata +2 -2
data/ext/carray_conversion.c
CHANGED
|
@@ -195,6 +195,23 @@ ca_to_a_universal (VALUE arg)
|
|
|
195
195
|
return Qnil;
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
+
/* An array with no cells still has the nesting of its axes up to the first
|
|
199
|
+
zero-length one: (3, 0) is three empty rows, (2, 0, 4) two empty rows. */
|
|
200
|
+
static VALUE
|
|
201
|
+
ca_to_a_empty_nesting (CArray *ca, int32_t level)
|
|
202
|
+
{
|
|
203
|
+
volatile VALUE ary;
|
|
204
|
+
ca_size_t i;
|
|
205
|
+
|
|
206
|
+
ary = rb_ary_new2(ca->dim[level]);
|
|
207
|
+
if ( level < ca->ndim - 1 ) {
|
|
208
|
+
for (i=0; i<ca->dim[level]; i++) {
|
|
209
|
+
rb_ary_store(ary, i, ca_to_a_empty_nesting(ca, level + 1));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return ary;
|
|
213
|
+
}
|
|
214
|
+
|
|
198
215
|
VALUE
|
|
199
216
|
rb_ca_to_a (VALUE self)
|
|
200
217
|
{
|
|
@@ -203,6 +220,9 @@ rb_ca_to_a (VALUE self)
|
|
|
203
220
|
int data_type, fast_eligible;
|
|
204
221
|
|
|
205
222
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
223
|
+
if ( ca->elements == 0 && ca->ndim > 0 ) {
|
|
224
|
+
return ca_to_a_empty_nesting(ca, 0);
|
|
225
|
+
}
|
|
206
226
|
ary = rb_ca_is_empty(self) ? rb_ary_new() : rb_ary_new2(ca->dim[0]);
|
|
207
227
|
|
|
208
228
|
/* Once attached, ca->ptr is a contig row-major buffer (alias for
|
|
@@ -375,6 +395,28 @@ rb_ca_convert (int argc, VALUE *argv, VALUE self)
|
|
|
375
395
|
return obj;
|
|
376
396
|
}
|
|
377
397
|
|
|
398
|
+
/* The transfer of dump_binary into a String. The String is locked while
|
|
399
|
+
the bytes go in: a view that runs Ruby to make its cells (a CAObject)
|
|
400
|
+
could otherwise resize it under the pointer being written. */
|
|
401
|
+
typedef struct {
|
|
402
|
+
CArray *ca;
|
|
403
|
+
VALUE io;
|
|
404
|
+
} ca_dump_into_string_t;
|
|
405
|
+
|
|
406
|
+
static VALUE
|
|
407
|
+
ca_dump_into_string_body (VALUE arg)
|
|
408
|
+
{
|
|
409
|
+
ca_dump_into_string_t *d = (ca_dump_into_string_t *) arg;
|
|
410
|
+
ca_copy_data(d->ca, RSTRING_PTR(d->io));
|
|
411
|
+
return Qnil;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
static VALUE
|
|
415
|
+
ca_dump_into_string_unlock (VALUE io)
|
|
416
|
+
{
|
|
417
|
+
return rb_str_unlocktmp(io);
|
|
418
|
+
}
|
|
419
|
+
|
|
378
420
|
/* CArray#dump_binary([io]) — write self's raw element bytes to io in
|
|
379
421
|
* row-major order.
|
|
380
422
|
*
|
|
@@ -411,7 +453,17 @@ rb_ca_dump_binary (int argc, VALUE *argv, VALUE self)
|
|
|
411
453
|
if ( ca_length(ca) != RSTRING_LEN(io) ) {
|
|
412
454
|
rb_str_resize(io, ca_length(ca));
|
|
413
455
|
}
|
|
414
|
-
|
|
456
|
+
/* the bytes are written behind Ruby's back: drop the cached code
|
|
457
|
+
range, or the string keeps answering 7-bit for any contents */
|
|
458
|
+
rb_str_modify(io);
|
|
459
|
+
{
|
|
460
|
+
ca_dump_into_string_t d;
|
|
461
|
+
d.ca = ca;
|
|
462
|
+
d.io = io;
|
|
463
|
+
rb_str_locktmp(io);
|
|
464
|
+
rb_ensure(ca_dump_into_string_body, (VALUE) &d,
|
|
465
|
+
ca_dump_into_string_unlock, io);
|
|
466
|
+
}
|
|
415
467
|
break;
|
|
416
468
|
case T_FILE: {
|
|
417
469
|
rb_io_t *iop;
|
|
@@ -487,8 +539,10 @@ rb_ca_load_binary (VALUE self, VALUE io)
|
|
|
487
539
|
"%s: data size mismatch (got %" PRId64 " bytes, expected %" PRId64 ")",
|
|
488
540
|
ca_calling_method_name(), (ca_size_t) RSTRING_LEN(io), (ca_size_t) ca_length(ca));
|
|
489
541
|
}
|
|
542
|
+
/* A copy shares the bytes until either side changes: a view that runs
|
|
543
|
+
Ruby while it stores (a CAObject) cannot then move them. */
|
|
544
|
+
io = rb_str_dup(io);
|
|
490
545
|
if ( ca->data_type == CA_BOOLEAN ) {
|
|
491
|
-
io = rb_str_dup(io);
|
|
492
546
|
rb_str_modify(io);
|
|
493
547
|
ca_boolean_normalize_bytes(RSTRING_PTR(io), ca->elements);
|
|
494
548
|
}
|
data/ext/carray_copy.c
CHANGED
|
@@ -61,6 +61,30 @@ ca_fill_or_detach (int n, CArray **list, VALUE (*fill)(VALUE), VALUE arg)
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
typedef struct {
|
|
65
|
+
CArray **list;
|
|
66
|
+
int32_t n;
|
|
67
|
+
} ca_attach_list_arg;
|
|
68
|
+
|
|
69
|
+
static VALUE
|
|
70
|
+
ca_attach_list_fill (VALUE arg)
|
|
71
|
+
{
|
|
72
|
+
ca_attach_list_arg *a = (ca_attach_list_arg *) arg;
|
|
73
|
+
ca_attach_all(a->list, a->n);
|
|
74
|
+
return Qnil;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
char *
|
|
78
|
+
ca_alloc_cells_then_attach (CArray *ca, int32_t n, CArray **parents)
|
|
79
|
+
{
|
|
80
|
+
char *buf = ca_alloc_cells(ca);
|
|
81
|
+
ca_attach_list_arg a;
|
|
82
|
+
a.list = parents;
|
|
83
|
+
a.n = n;
|
|
84
|
+
ca_fill_or_xfree(buf, ca_attach_list_fill, (VALUE) &a);
|
|
85
|
+
return buf;
|
|
86
|
+
}
|
|
87
|
+
|
|
64
88
|
VALUE
|
|
65
89
|
ca_view_inherit_mask (VALUE view)
|
|
66
90
|
{
|
data/ext/carray_core.c
CHANGED
|
@@ -954,15 +954,29 @@ ca_refuse_cells_reaching_evaluation (ca_size_t n, const VALUE *cells)
|
|
|
954
954
|
}
|
|
955
955
|
}
|
|
956
956
|
|
|
957
|
+
static VALUE
|
|
958
|
+
ca_computing_start (VALUE arg)
|
|
959
|
+
{
|
|
960
|
+
return ca_computing_next((ca_computing_t *) arg);
|
|
961
|
+
}
|
|
962
|
+
|
|
957
963
|
/* Runs body(arg), a computation over ops[0..n), with each object array
|
|
958
964
|
among them recorded as computed over. Raises when one of them is
|
|
959
965
|
already being computed over by the same method: a cell's value, or an
|
|
960
|
-
element's operation, led the computation back into it.
|
|
966
|
+
element's operation, led the computation back into it. A computation
|
|
967
|
+
over object cells calls methods of the cells, so it counts as a walk into
|
|
968
|
+
them (ca_cell_walk_run). */
|
|
961
969
|
VALUE
|
|
962
970
|
ca_computing_run (int n, CArray **ops, VALUE (*body)(VALUE), VALUE arg)
|
|
963
971
|
{
|
|
964
972
|
ca_computing_t c;
|
|
973
|
+
int k;
|
|
965
974
|
c.n = n; c.ops = ops; c.kind = CA_RECURSION_COMPUTE; c.k = 0; c.body = body; c.arg = arg;
|
|
975
|
+
for (k=0; k<n; k++) {
|
|
976
|
+
if ( ops[k] && ca_is_object_type(ops[k]) ) {
|
|
977
|
+
return ca_cell_walk_run(ca_computing_start, (VALUE) &c);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
966
980
|
return ca_computing_next(&c);
|
|
967
981
|
}
|
|
968
982
|
|
|
@@ -985,6 +999,55 @@ ca_recursion_probe (VALUE key, VALUE arg, int recursive)
|
|
|
985
999
|
return recursive ? Qtrue : Qfalse;
|
|
986
1000
|
}
|
|
987
1001
|
|
|
1002
|
+
/* A walk into the cells of an object array (#hash, #==, a nested dump) goes
|
|
1003
|
+
on into any array it finds there. An array holding itself is found by
|
|
1004
|
+
the records above, but a cell can also give a new array each time it is
|
|
1005
|
+
opened (a lazy expression over an array that holds it), and then the walk
|
|
1006
|
+
never meets an array it has seen. So the depth of these walks is
|
|
1007
|
+
limited. It is counted for each fiber, not in the arrays. */
|
|
1008
|
+
|
|
1009
|
+
#define CA_CELL_NESTING_MAX 256
|
|
1010
|
+
|
|
1011
|
+
typedef struct {
|
|
1012
|
+
VALUE thread;
|
|
1013
|
+
VALUE before;
|
|
1014
|
+
} ca_cell_nesting_t;
|
|
1015
|
+
|
|
1016
|
+
static VALUE
|
|
1017
|
+
ca_cell_nesting_leave (VALUE varg)
|
|
1018
|
+
{
|
|
1019
|
+
ca_cell_nesting_t *t = (ca_cell_nesting_t *) varg;
|
|
1020
|
+
rb_thread_local_aset(t->thread, rb_intern("carray_cell_nesting"), t->before);
|
|
1021
|
+
return Qnil;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
VALUE
|
|
1025
|
+
ca_cell_walk_run (VALUE (*body)(VALUE), VALUE arg)
|
|
1026
|
+
{
|
|
1027
|
+
ca_cell_nesting_t t;
|
|
1028
|
+
long depth;
|
|
1029
|
+
|
|
1030
|
+
t.thread = rb_thread_current();
|
|
1031
|
+
if ( OBJ_FROZEN(t.thread) ) { /* it can not hold the count */
|
|
1032
|
+
return body(arg);
|
|
1033
|
+
}
|
|
1034
|
+
t.before = rb_thread_local_aref(t.thread, rb_intern("carray_cell_nesting"));
|
|
1035
|
+
depth = NIL_P(t.before) ? 0 : FIX2LONG(t.before);
|
|
1036
|
+
if ( depth >= CA_CELL_NESTING_MAX ) {
|
|
1037
|
+
rb_raise(rb_eArgError, "%s: object cells nested too deep: more than %d levels",
|
|
1038
|
+
ca_calling_method_name(), CA_CELL_NESTING_MAX);
|
|
1039
|
+
}
|
|
1040
|
+
rb_thread_local_aset(t.thread, rb_intern("carray_cell_nesting"), LONG2FIX(depth + 1));
|
|
1041
|
+
return rb_ensure(body, arg, ca_cell_nesting_leave, (VALUE) &t);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
static VALUE
|
|
1045
|
+
ca_yield_nil (VALUE arg)
|
|
1046
|
+
{
|
|
1047
|
+
(void) arg;
|
|
1048
|
+
return rb_yield(Qnil);
|
|
1049
|
+
}
|
|
1050
|
+
|
|
988
1051
|
static VALUE
|
|
989
1052
|
ca_refuse_reentry_step (VALUE self, VALUE name, int recursive)
|
|
990
1053
|
{
|
|
@@ -993,14 +1056,14 @@ ca_refuse_reentry_step (VALUE self, VALUE name, int recursive)
|
|
|
993
1056
|
rb_raise(rb_eArgError, "%" PRIsVALUE ": cyclic reference is not allowed in CArray",
|
|
994
1057
|
name);
|
|
995
1058
|
}
|
|
996
|
-
return
|
|
1059
|
+
return ca_cell_walk_run(ca_yield_nil, Qnil);
|
|
997
1060
|
}
|
|
998
1061
|
|
|
999
1062
|
/* refuse_reentry(name) { ... } -- runs the block, refusing as cyclic a
|
|
1000
1063
|
second call for the same array from inside it (rb_exec_recursive, by
|
|
1001
|
-
the receiver)
|
|
1002
|
-
|
|
1003
|
-
view, goes through this. */
|
|
1064
|
+
the receiver), and counting it as a walk into cells. Ruby code that
|
|
1065
|
+
walks the cells of an object array and comes back to the array through a
|
|
1066
|
+
cell, such as the nested dump of a view, goes through this. */
|
|
1004
1067
|
static VALUE
|
|
1005
1068
|
rb_ca_refuse_reentry (VALUE self, VALUE name)
|
|
1006
1069
|
{
|
|
@@ -1015,7 +1078,7 @@ ca_test_cyclic_check (void *ap, void *ptr)
|
|
|
1015
1078
|
{
|
|
1016
1079
|
CArray *ca = (CArray *) ap;
|
|
1017
1080
|
if ( ca_is_object_type(ca) ) {
|
|
1018
|
-
VALUE rval = *(VALUE *) ptr;
|
|
1081
|
+
volatile VALUE rval = *(VALUE *) ptr;
|
|
1019
1082
|
if ( rb_obj_is_carray(rval) ) {
|
|
1020
1083
|
CArray *cv;
|
|
1021
1084
|
TypedData_Get_Struct(rval, CArray, &carray_data_type, cv);
|
data/ext/carray_count.c
CHANGED
|
@@ -82,7 +82,7 @@ ca_count_each_body (VALUE arg)
|
|
|
82
82
|
/* Extract vk as a scalar VALUE via flat addr. rb_ca_fetch_addr
|
|
83
83
|
takes a ca_size_t addr (not a Ruby VALUE). */
|
|
84
84
|
VALUE vk = rb_ca_fetch_addr(c->rval, k);
|
|
85
|
-
VALUE sub;
|
|
85
|
+
volatile VALUE sub;
|
|
86
86
|
/* A masked query cell asks nothing: its count is masked. Passing it
|
|
87
87
|
on would ask count(UNDEF), the count of self's masked cells. */
|
|
88
88
|
if ( vk == CA_UNDEF ) {
|
|
@@ -154,7 +154,14 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
|
|
157
|
+
/* true and false count the cells holding 1 and 0 of a numeric array */
|
|
158
|
+
volatile VALUE rval = ca_truth_as_number(src, argv[0]);
|
|
159
|
+
if ( rval != argv[0] ) {
|
|
160
|
+
VALUE *nargv = ALLOCA_N(VALUE, argc);
|
|
161
|
+
MEMCPY(nargv, argv, VALUE, argc);
|
|
162
|
+
nargv[0] = rval;
|
|
163
|
+
argv = nargv;
|
|
164
|
+
}
|
|
158
165
|
|
|
159
166
|
/* count(UNDEF) == count_masked: UNDEF is mask-state vocabulary, not a
|
|
160
167
|
value to compare against. Forward, dropping the UNDEF from argv. */
|
|
@@ -162,6 +169,17 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
162
169
|
return rb_ca_count_masked(argc - 1, argv + 1, self);
|
|
163
170
|
}
|
|
164
171
|
|
|
172
|
+
/* An array that can not hold the value (nil, a String) counts no cell
|
|
173
|
+
for it: the cells that matched, none, are counted the way count(true)
|
|
174
|
+
counts a mask. */
|
|
175
|
+
if ( ca_query_matches_nothing(src, rval) && ! ca_is_complex_type(src) ) {
|
|
176
|
+
VALUE *nargv = ALLOCA_N(VALUE, argc);
|
|
177
|
+
MEMCPY(nargv, argv, VALUE, argc);
|
|
178
|
+
nargv[0] = Qtrue;
|
|
179
|
+
return rb_ca_count(argc, nargv,
|
|
180
|
+
rb_funcall(self, rb_intern("eq"), 1, rval));
|
|
181
|
+
}
|
|
182
|
+
|
|
165
183
|
/* Face gate, mirroring the search / linear family (ext/carray_order.c):
|
|
166
184
|
descend an ORDERABLE Face to its storage so the equality runs on the
|
|
167
185
|
numeric storage, and let the reference reconcile the query into its own
|
|
@@ -284,7 +302,7 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
284
302
|
}
|
|
285
303
|
|
|
286
304
|
/* Allocate output i64 CArray. */
|
|
287
|
-
VALUE vout = rb_funcall(rb_cCArray, rb_intern("new"), 2,
|
|
305
|
+
volatile VALUE vout = rb_funcall(rb_cCArray, rb_intern("new"), 2,
|
|
288
306
|
INT2NUM(CA_INT64),
|
|
289
307
|
rb_ary_new4(out_ndim,
|
|
290
308
|
({ VALUE *tmp = ALLOCA_N(VALUE, out_ndim);
|
|
@@ -348,16 +366,17 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
348
366
|
iv);
|
|
349
367
|
} else {
|
|
350
368
|
rb_raise(rb_eTypeError,
|
|
351
|
-
"count(v) on boolean array: v must be true / false / 1 / 0, got %
|
|
352
|
-
|
|
369
|
+
"count(v) on boolean array: v must be true / false / 1 / 0, got %"PRIsVALUE"",
|
|
370
|
+
rb_obj_class(rval));
|
|
353
371
|
}
|
|
354
372
|
} else {
|
|
355
|
-
/*
|
|
356
|
-
|
|
373
|
+
/* An integer, float or complex array has read true / false as 1 / 0
|
|
374
|
+
above (ca_truth_as_number); an object array stores them as values.
|
|
375
|
+
Any other array that reaches here can not count them. */
|
|
357
376
|
if ( ( rval == Qtrue || rval == Qfalse ) && src->data_type != CA_OBJECT ) {
|
|
358
377
|
rb_raise(rb_eTypeError,
|
|
359
|
-
"count(v) on numeric array: v must be numeric, got %
|
|
360
|
-
|
|
378
|
+
"count(v) on numeric array: v must be numeric, got %"PRIsVALUE"",
|
|
379
|
+
rb_obj_class(rval));
|
|
361
380
|
}
|
|
362
381
|
/* The query is compared in the type it and the array match in, as `eq`
|
|
363
382
|
compares (ca_query_match_type): 1.5 does not match 1, and an Integer
|
data/ext/carray_element.c
CHANGED
|
@@ -38,22 +38,28 @@ elem_index_value (VALUE v)
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
ca_size_t
|
|
42
|
+
ca_index_key_value (VALUE v)
|
|
43
|
+
{
|
|
44
|
+
return elem_index_value(v);
|
|
45
|
+
}
|
|
46
|
+
|
|
41
47
|
/* T_ARRAY index parser. ridx is assumed already known to be T_ARRAY.
|
|
42
48
|
Direct VALUE * access + FIXNUM_P fast path eliminates rb_ary_entry
|
|
43
49
|
bounds check and NUM2SIZE Bignum branching for the common case. */
|
|
44
50
|
static inline void
|
|
45
51
|
elem_parse_idx_array (CArray *ca, VALUE rary, ca_size_t *idx)
|
|
46
52
|
{
|
|
47
|
-
const VALUE *iarr;
|
|
48
53
|
int8_t ndim = ca->ndim;
|
|
49
54
|
int8_t i;
|
|
50
55
|
if ( RARRAY_LEN(rary) != ndim ) {
|
|
51
56
|
rb_raise(rb_eIndexError, "%ld indices given for a carray of ndim %i",
|
|
52
57
|
(long) RARRAY_LEN(rary), (int) ndim);
|
|
53
58
|
}
|
|
54
|
-
iarr = RARRAY_CONST_PTR(rary);
|
|
55
59
|
for (i=0; i<ndim; i++) {
|
|
56
|
-
|
|
60
|
+
/* Read each entry afresh: converting one can run Ruby that changes the
|
|
61
|
+
Array (an entry gone reads as nil, which is refused). */
|
|
62
|
+
ca_size_t k = elem_index_value(rb_ary_entry(rary, i));
|
|
57
63
|
CA_CHECK_INDEX(k, ca->dim[i]);
|
|
58
64
|
idx[i] = k;
|
|
59
65
|
}
|
data/ext/carray_factorize.c
CHANGED
|
@@ -818,7 +818,7 @@ static VALUE
|
|
|
818
818
|
fz_factorize_appearance_body (VALUE arg)
|
|
819
819
|
{
|
|
820
820
|
fz_frame *fr = (fz_frame *) arg;
|
|
821
|
-
VALUE self = fr->self;
|
|
821
|
+
volatile VALUE self = fr->self;
|
|
822
822
|
CArray *ca;
|
|
823
823
|
volatile VALUE face;
|
|
824
824
|
fr->self = self = fz_face_descend(self, &face, "categorize");
|
|
@@ -843,7 +843,7 @@ fz_factorize_appearance_body (VALUE arg)
|
|
|
843
843
|
ca_size_t N = ca->elements;
|
|
844
844
|
|
|
845
845
|
/* uint32 code scratch, same shape as self; narrowed once k is known. */
|
|
846
|
-
VALUE vu32 = rb_carray_new(CA_UINT32, ca->ndim, ca->dim, 0, NULL);
|
|
846
|
+
volatile VALUE vu32 = rb_carray_new(CA_UINT32, ca->ndim, ca->dim, 0, NULL);
|
|
847
847
|
CArray *cu32;
|
|
848
848
|
TypedData_Get_Struct(vu32, CArray, &carray_data_type, cu32);
|
|
849
849
|
|
|
@@ -1028,7 +1028,7 @@ static VALUE
|
|
|
1028
1028
|
fz_mask_duplicates_body (VALUE arg)
|
|
1029
1029
|
{
|
|
1030
1030
|
fz_frame *fr = (fz_frame *) arg;
|
|
1031
|
-
VALUE self = fr->self;
|
|
1031
|
+
volatile VALUE self = fr->self;
|
|
1032
1032
|
VALUE vaxis = fr->a;
|
|
1033
1033
|
CArray *ca;
|
|
1034
1034
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
@@ -1189,7 +1189,7 @@ static VALUE
|
|
|
1189
1189
|
fz_unique_flat_body (VALUE arg)
|
|
1190
1190
|
{
|
|
1191
1191
|
fz_frame *fr = (fz_frame *) arg;
|
|
1192
|
-
VALUE self = fr->self;
|
|
1192
|
+
volatile VALUE self = fr->self;
|
|
1193
1193
|
CArray *ca;
|
|
1194
1194
|
volatile VALUE face;
|
|
1195
1195
|
fr->self = self = fz_face_descend(self, &face, "unique");
|
|
@@ -1429,7 +1429,7 @@ static VALUE
|
|
|
1429
1429
|
fz_is_in_body (VALUE arg)
|
|
1430
1430
|
{
|
|
1431
1431
|
fz_frame *fr = (fz_frame *) arg;
|
|
1432
|
-
VALUE self = fr->self;
|
|
1432
|
+
volatile VALUE self = fr->self;
|
|
1433
1433
|
VALUE rvalues = fr->a;
|
|
1434
1434
|
CArray *ca, *cv;
|
|
1435
1435
|
volatile VALUE face;
|
|
@@ -1592,7 +1592,7 @@ static VALUE
|
|
|
1592
1592
|
fz_locate_addr_body (VALUE arg)
|
|
1593
1593
|
{
|
|
1594
1594
|
fz_frame *fr = (fz_frame *) arg;
|
|
1595
|
-
VALUE self = fr->self;
|
|
1595
|
+
volatile VALUE self = fr->self;
|
|
1596
1596
|
VALUE rref = fr->a;
|
|
1597
1597
|
CArray *ca, *cr;
|
|
1598
1598
|
/* Here the *reference* is the argument (self is the query being placed on
|
|
@@ -1859,7 +1859,7 @@ static VALUE
|
|
|
1859
1859
|
fz_set_relation_body (VALUE arg)
|
|
1860
1860
|
{
|
|
1861
1861
|
fz_frame *fr = (fz_frame *) arg;
|
|
1862
|
-
VALUE self = fr->self;
|
|
1862
|
+
volatile VALUE self = fr->self;
|
|
1863
1863
|
VALUE rother = fr->a;
|
|
1864
1864
|
int keep_when_hit = fr->i;
|
|
1865
1865
|
CArray *ca, *co;
|
|
@@ -2055,7 +2055,7 @@ static VALUE
|
|
|
2055
2055
|
fz_set_union_body (VALUE arg)
|
|
2056
2056
|
{
|
|
2057
2057
|
fz_frame *fr = (fz_frame *) arg;
|
|
2058
|
-
VALUE self = fr->self;
|
|
2058
|
+
volatile VALUE self = fr->self;
|
|
2059
2059
|
VALUE rother = fr->a;
|
|
2060
2060
|
CArray *ca, *co;
|
|
2061
2061
|
volatile VALUE face;
|
|
@@ -2149,7 +2149,7 @@ static VALUE
|
|
|
2149
2149
|
fz_value_counts_flat_body (VALUE arg)
|
|
2150
2150
|
{
|
|
2151
2151
|
fz_frame *fr = (fz_frame *) arg;
|
|
2152
|
-
VALUE self = fr->self;
|
|
2152
|
+
volatile VALUE self = fr->self;
|
|
2153
2153
|
CArray *ca;
|
|
2154
2154
|
volatile VALUE face;
|
|
2155
2155
|
fr->self = self = fz_face_descend(self, &face, "value_counts");
|
|
@@ -2325,7 +2325,7 @@ static VALUE
|
|
|
2325
2325
|
fz_nunique_body (VALUE arg)
|
|
2326
2326
|
{
|
|
2327
2327
|
fz_frame *fr = (fz_frame *) arg;
|
|
2328
|
-
VALUE self = fr->self;
|
|
2328
|
+
volatile VALUE self = fr->self;
|
|
2329
2329
|
VALUE vaxis = fr->a;
|
|
2330
2330
|
VALUE vkeep = fr->b;
|
|
2331
2331
|
CArray *ca;
|
|
@@ -2472,7 +2472,7 @@ static VALUE
|
|
|
2472
2472
|
fz_is_mode_body (VALUE arg)
|
|
2473
2473
|
{
|
|
2474
2474
|
fz_frame *fr = (fz_frame *) arg;
|
|
2475
|
-
VALUE self = fr->self;
|
|
2475
|
+
volatile VALUE self = fr->self;
|
|
2476
2476
|
VALUE vaxis = fr->a;
|
|
2477
2477
|
CArray *ca;
|
|
2478
2478
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
data/ext/carray_histogram.c
CHANGED
|
@@ -437,7 +437,7 @@ rb_ca_histogram_scatter_ki (VALUE self, VALUE rcounts, VALUE redges,
|
|
|
437
437
|
}
|
|
438
438
|
|
|
439
439
|
for ( k = 0; k < M; k++ ) {
|
|
440
|
-
VALUE e = RARRAY_AREF(redges, k);
|
|
440
|
+
volatile VALUE e = RARRAY_AREF(redges, k);
|
|
441
441
|
GetCArray(e, edge_ca[k]);
|
|
442
442
|
histbin_check_edge_mask(edge_ca[k], "histogram");
|
|
443
443
|
}
|
|
@@ -528,7 +528,7 @@ bincount_nd_label_u64 (uint64_t x)
|
|
|
528
528
|
} while (0)
|
|
529
529
|
|
|
530
530
|
static VALUE
|
|
531
|
-
rb_ca_bincount_nd_count_ki (VALUE self, VALUE rcounts, VALUE rweights)
|
|
531
|
+
rb_ca_bincount_nd_count_ki (VALUE self, VALUE rcounts, volatile VALUE rweights)
|
|
532
532
|
{
|
|
533
533
|
CArray *ca, *cc, *cw = NULL;
|
|
534
534
|
long M, nf, k;
|
|
@@ -322,15 +322,15 @@ ca_classifier_check_reserved_symbol (VALUE sym)
|
|
|
322
322
|
{
|
|
323
323
|
const char *name;
|
|
324
324
|
if ( ! SYMBOL_P(sym) ) return;
|
|
325
|
-
name = rb_id2name(SYM2ID(sym));
|
|
325
|
+
name = rb_id2name(SYM2ID(sym)); /* name: its first two bytes are read at once */
|
|
326
326
|
if ( name != NULL
|
|
327
327
|
&& name[0] != '\0' && name[1] == '\0'
|
|
328
328
|
&& ( ( name[0] >= 'a' && name[0] <= 'z' )
|
|
329
329
|
|| ( name[0] >= 'A' && name[0] <= 'Z' ) )
|
|
330
330
|
&& name[0] != '_' /* :_ is iterator marker, handled separately */ ) {
|
|
331
331
|
rb_raise(rb_eIndexError,
|
|
332
|
-
"symbol :%
|
|
333
|
-
|
|
332
|
+
"symbol :%"PRIsVALUE" is reserved",
|
|
333
|
+
rb_sym2str(sym));
|
|
334
334
|
}
|
|
335
335
|
}
|
|
336
336
|
|
|
@@ -1005,7 +1005,7 @@ rb_ca_scan_index_v2 (int ca_ndim, ca_size_t *ca_dim, ca_size_t ca_elements,
|
|
|
1005
1005
|
also fall through here and are raised later by the per-axis
|
|
1006
1006
|
dispatcher's SYMBOL_P branch. */
|
|
1007
1007
|
if ( SYMBOL_P(argv[0]) ) {
|
|
1008
|
-
const char *name = rb_id2name(SYM2ID(argv[0]));
|
|
1008
|
+
const char *name = rb_id2name(SYM2ID(argv[0])); /* name: read at once by strlen */
|
|
1009
1009
|
if ( name != NULL && strlen(name) > 1 ) {
|
|
1010
1010
|
info->type = CA_REG_METHOD_CALL;
|
|
1011
1011
|
info->symbol = argv[0];
|
|
@@ -1069,7 +1069,7 @@ rb_ca_scan_index_v2 (int ca_ndim, ca_size_t *ca_dim, ca_size_t ca_elements,
|
|
|
1069
1069
|
downstream introspection. */
|
|
1070
1070
|
|
|
1071
1071
|
static VALUE
|
|
1072
|
-
rb_ca_s_scan_index_v2 (VALUE self, VALUE rdim, VALUE ridx)
|
|
1072
|
+
rb_ca_s_scan_index_v2 (VALUE self, VALUE rdim, volatile VALUE ridx)
|
|
1073
1073
|
{
|
|
1074
1074
|
CAIndexInfo info;
|
|
1075
1075
|
ca_size_t dim[CA_RANK_MAX];
|
|
@@ -1079,6 +1079,8 @@ rb_ca_s_scan_index_v2 (VALUE self, VALUE rdim, VALUE ridx)
|
|
|
1079
1079
|
|
|
1080
1080
|
Check_Type(rdim, T_ARRAY);
|
|
1081
1081
|
Check_Type(ridx, T_ARRAY);
|
|
1082
|
+
/* Converting an entry can run Ruby that changes the Array: read a copy. */
|
|
1083
|
+
ridx = rb_ary_dup(ridx);
|
|
1082
1084
|
|
|
1083
1085
|
ndim = (int) RARRAY_LEN(rdim);
|
|
1084
1086
|
elements = 1;
|
data/ext/carray_internal.h
CHANGED
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
#ifndef CARRAY_INTERNAL_H
|
|
25
25
|
#define CARRAY_INTERNAL_H
|
|
26
26
|
|
|
27
|
+
#include "ruby/thread_native.h" /* rb_nativethread_lock_t */
|
|
28
|
+
|
|
27
29
|
#include "carray.h"
|
|
28
30
|
#include <math.h> /* isnan, for CA_OBJ_ISNAN */
|
|
29
31
|
|
|
@@ -85,6 +87,7 @@ void ca_lazy_arena_enter (void);
|
|
|
85
87
|
void ca_lazy_arena_exit (void);
|
|
86
88
|
void *ca_lazy_arena_acquire (ca_size_t bytes);
|
|
87
89
|
void *ca_lazy_arena_acquire_object (ca_size_t n_elements);
|
|
90
|
+
void ca_lazy_arena_untag_objects (void *ptr);
|
|
88
91
|
void ca_lazy_arena_release (void *ptr);
|
|
89
92
|
VALUE ca_lazy_arena_protect (VALUE (*body)(VALUE),
|
|
90
93
|
VALUE (*cleanup)(VALUE), VALUE arg);
|
|
@@ -145,6 +148,18 @@ ca_boolean_normalize_bytes (void *ptr, ca_size_t n)
|
|
|
145
148
|
}
|
|
146
149
|
}
|
|
147
150
|
|
|
151
|
+
/* A buffer for n cells of data_type, each bytes long: object cells start
|
|
152
|
+
as nil. */
|
|
153
|
+
static inline char *
|
|
154
|
+
ca_alloc_cells_of (int8_t data_type, ca_size_t elements, ca_size_t bytes)
|
|
155
|
+
{
|
|
156
|
+
char *p = (char *) xmalloc(elements > 0 ? elements * bytes : 1);
|
|
157
|
+
if ( data_type == CA_OBJECT ) {
|
|
158
|
+
ca_object_cells_clear(p, elements);
|
|
159
|
+
}
|
|
160
|
+
return p;
|
|
161
|
+
}
|
|
162
|
+
|
|
148
163
|
static inline char *
|
|
149
164
|
ca_alloc_cells (const CArray *ca)
|
|
150
165
|
{
|
|
@@ -237,6 +252,17 @@ void ca_fill_or_free (CArray *co, VALUE (*fill)(VALUE), VALUE arg);
|
|
|
237
252
|
void ca_fill_or_xfree (void *buf, VALUE (*fill)(VALUE), VALUE arg);
|
|
238
253
|
void ca_fill_or_detach (int n, CArray **list, VALUE (*fill)(VALUE), VALUE arg);
|
|
239
254
|
|
|
255
|
+
/* The buffer of a view's own cells, for an attach or allocate slot that
|
|
256
|
+
attaches parents[0..n-1] and then works in a buffer of its own. The
|
|
257
|
+
buffer is allocated before the parents are attached, and freed if
|
|
258
|
+
attaching them raises: a slot that raises before it publishes ca->ptr
|
|
259
|
+
gives ca_attach no detach slot to call, and a parent left attached keeps
|
|
260
|
+
reading and writing the copy it materialised instead of its root. The
|
|
261
|
+
caller publishes the result as ca->ptr. utils/check_attach_then_alloc.rb
|
|
262
|
+
finds a slot that allocates after attaching. */
|
|
263
|
+
|
|
264
|
+
char *ca_alloc_cells_then_attach (CArray *ca, int32_t n, CArray **parents);
|
|
265
|
+
|
|
240
266
|
/* A view takes its parent's mask by asking the parent whether it has one,
|
|
241
267
|
and a parent that is a CAObject answers in Ruby and can raise. A view's
|
|
242
268
|
setup therefore does not ask: its constructor calls this under
|
|
@@ -360,6 +386,7 @@ VALUE ca_lazy_settle_scalar (VALUE operand, int was_scalar);
|
|
|
360
386
|
of one view all take the same branch. */
|
|
361
387
|
|
|
362
388
|
int ca_parent_lends_no_memory (void *ap);
|
|
389
|
+
void rb_ca_cast_three (volatile VALUE *v1, volatile VALUE *v2, volatile VALUE *v3);
|
|
363
390
|
|
|
364
391
|
/* Transfers of the descriptor views (CAGrid, CASelect, CASelectAxis,
|
|
365
392
|
CAWindow) whose parent holds no ptr (ca_axis_dispatch.c).
|
|
@@ -433,6 +460,13 @@ CAReduce *ca_reduce_new (CArray *carray, ca_size_t count, ca_size_t offset);
|
|
|
433
460
|
void ca_broadcast_to_destination (VALUE dst, volatile VALUE *src);
|
|
434
461
|
VALUE rb_ary_flatten_for_elements (VALUE ary, ca_size_t elements, void *ap);
|
|
435
462
|
|
|
463
|
+
/* carray_access.c */
|
|
464
|
+
void ca_refuse_complex_into_real (CArray *ca, CArray *cv);
|
|
465
|
+
|
|
466
|
+
/* carray_cast.c */
|
|
467
|
+
void ca_cast_block_skip_masked (ca_size_t n, void *ap1, void *ptr1,
|
|
468
|
+
void *ap2, void *ptr2, boolean8_t *m);
|
|
469
|
+
|
|
436
470
|
/* carray_utils.c */
|
|
437
471
|
const char *ca_calling_method_name (void);
|
|
438
472
|
VALUE ca_answer_as_caller (VALUE (*body)(VALUE), VALUE arg);
|
|
@@ -440,13 +474,26 @@ long ca_integer_arg (VALUE v, const char *arg, const char *name);
|
|
|
440
474
|
/* 1 with the position of an index key (an Integer, or a Float with no
|
|
441
475
|
fraction while exact), 2 for an Integer past int64, 0 otherwise. */
|
|
442
476
|
int ca_index_key_position (VALUE v, ca_size_t *out);
|
|
477
|
+
ca_size_t ca_index_key_value (VALUE v);
|
|
443
478
|
void ca_refuse_without_common_type (VALUE self, VALUE other);
|
|
444
479
|
ca_size_t ca_shape_elements (int8_t ndim, const ca_size_t *dim, ca_size_t bytes);
|
|
445
480
|
void ca_check_index_array (VALUE v);
|
|
446
481
|
VALUE ca_order_key (VALUE v, const char *name);
|
|
447
482
|
void ca_check_integer_fits (VALUE v, int8_t data_type);
|
|
448
483
|
VALUE ca_obj2integer_fitting (VALUE v, int8_t data_type);
|
|
484
|
+
/* A Ruby value stored into an integer cell of `dst`: refused when it does
|
|
485
|
+
not fit (ca_obj2integer_fitting), except into the cells of a bit field
|
|
486
|
+
view (ca_bitfield_beneath), which keep it modulo 2 ** bits
|
|
487
|
+
(ca_integer_wrap_bits). */
|
|
488
|
+
VALUE ca_obj2integer_store (CArray *dst, VALUE v, int8_t data_type);
|
|
489
|
+
CArray *ca_bitfield_beneath (CArray *ca);
|
|
490
|
+
VALUE ca_bitfield_wrap_integer (CArray *ca, VALUE v);
|
|
491
|
+
/* v as an Integer modulo 2 ** bits; with sign_extend, in
|
|
492
|
+
-2 ** (bits - 1) ... 2 ** (bits - 1) - 1. A String is read as a
|
|
493
|
+
decimal integer, any other value through Integer() (1.5 is 1). */
|
|
494
|
+
VALUE ca_integer_wrap_bits (VALUE v, int bits, int sign_extend);
|
|
449
495
|
int ca_integer_range_side (VALUE v, int8_t data_type);
|
|
496
|
+
int ca_obj_number_fits_integer (VALUE v, int8_t data_type);
|
|
450
497
|
int ca_bincmp_integer_prepare (volatile VALUE *self, volatile VALUE *other,
|
|
451
498
|
int op_id, int *signed_side);
|
|
452
499
|
int ca_bincmp_answer_when_negative (int op_id, int signed_side);
|
|
@@ -481,6 +528,11 @@ VALUE ca_computing_run_nodes (int n, CArray **ops, VALUE (*body)(VALUE), VALUE a
|
|
|
481
528
|
/* Refuses as cyclic a cell among cells[0..n) that is an array reaching a
|
|
482
529
|
lazy node being evaluated: computing it would come back into the node. */
|
|
483
530
|
void ca_refuse_cells_reaching_evaluation (ca_size_t n, const VALUE *cells);
|
|
531
|
+
/* Runs body(arg), a walk into the cells of an object array, one level deeper
|
|
532
|
+
in this fiber; past the limit it raises ArgumentError. A cell can give a
|
|
533
|
+
new array each time it is opened, which the records above never meet
|
|
534
|
+
twice. */
|
|
535
|
+
VALUE ca_cell_walk_run (VALUE (*body)(VALUE), VALUE arg);
|
|
484
536
|
|
|
485
537
|
/* Registers a view type whose transfers only move cells between its parents
|
|
486
538
|
and the caller (an index view: CAGrid, CASelect, CAWindow, CAStack, ...),
|
|
@@ -845,6 +897,40 @@ ca_query_match_applies (CArray *ref, VALUE query)
|
|
|
845
897
|
return 1;
|
|
846
898
|
}
|
|
847
899
|
|
|
900
|
+
/* A Ruby value an integer, float, complex or boolean array can not hold:
|
|
901
|
+
anything but a Numeric, true, false and UNDEF that does not make an
|
|
902
|
+
array (an Array, a #to_ca, a memory view). nil, a String, a Symbol and
|
|
903
|
+
other objects are foreign. An object or fixlen array and a Face hold or
|
|
904
|
+
read such values, so nothing is foreign to them (ca_cast.c). */
|
|
905
|
+
int ca_value_foreign_to (CArray *ca, VALUE v);
|
|
906
|
+
|
|
907
|
+
/* An operator refuses a foreign value as Float#+ does (TypeError), and an
|
|
908
|
+
ordering refuses it as Float#< does (ArgumentError). `array` is the
|
|
909
|
+
CArray operand (ca_cast.c). */
|
|
910
|
+
void ca_refuse_foreign_operand (VALUE v, VALUE array);
|
|
911
|
+
void ca_refuse_foreign_order (VALUE v, VALUE array);
|
|
912
|
+
|
|
913
|
+
/* true and false as the numbers 1 and 0 for a value query on an integer,
|
|
914
|
+
float or complex array; any other value, or array, is returned as is
|
|
915
|
+
(ca_cast.c). */
|
|
916
|
+
VALUE ca_truth_as_number (CArray *ca, VALUE v);
|
|
917
|
+
|
|
918
|
+
/* eq / ne when no cell can match (carray_operator.c). */
|
|
919
|
+
VALUE ca_bincmp_no_match (VALUE self, int ne);
|
|
920
|
+
|
|
921
|
+
/* A value an array can not hold matches no cell as a value query: eq, ne,
|
|
922
|
+
count and search answer as they do for an Integer outside the array's
|
|
923
|
+
type. nil is such a value for every array but an object one, which
|
|
924
|
+
holds nil and is asked. */
|
|
925
|
+
static inline int
|
|
926
|
+
ca_query_matches_nothing (CArray *ca, VALUE query)
|
|
927
|
+
{
|
|
928
|
+
if ( NIL_P(query) ) {
|
|
929
|
+
return ca->data_type != CA_OBJECT;
|
|
930
|
+
}
|
|
931
|
+
return ca_value_foreign_to(ca, query);
|
|
932
|
+
}
|
|
933
|
+
|
|
848
934
|
/* Equality of two object cells, as the float lanes answer it: Ruby's `==`,
|
|
849
935
|
except that a Float NaN equals nothing, itself included. rb_equal alone
|
|
850
936
|
answers true for the same object, so whether two NaN cells matched would
|
|
@@ -986,4 +1072,12 @@ int ca_index_key_is_scalar (VALUE arg);
|
|
|
986
1072
|
/* Whether this runs in the main Ractor (carray_utils.c). */
|
|
987
1073
|
int ca_in_main_ractor (void);
|
|
988
1074
|
|
|
1075
|
+
/* Take a native lock that guards a table shared by every Ractor, waiting
|
|
1076
|
+
without the GVL (carray_utils.c). A Ractor that waits for the lock while
|
|
1077
|
+
it holds its GVL cannot stop for a GC, so one that holds the lock and
|
|
1078
|
+
allocates (a GC) would wait for it, and it for the lock. The lock is only
|
|
1079
|
+
ever taken outside the wait, so an interrupt that raises there leaves it
|
|
1080
|
+
free. The lock must not be held across a call that can raise. */
|
|
1081
|
+
void ca_native_lock_without_gvl (rb_nativethread_lock_t *lock);
|
|
1082
|
+
|
|
989
1083
|
#endif /* CARRAY_INTERNAL_H */
|