carray 3.0.5 → 3.0.6
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 +233 -0
- data/README.md +1 -1
- data/carray.gemspec +3 -2
- data/ext/ca_axis_dispatch.c +6 -0
- data/ext/ca_axis_group.c +1 -1
- data/ext/ca_categorical_iterator.c +7 -7
- data/ext/ca_kernel_iterator.c +116 -231
- data/ext/ca_kernel_iterator.h +410 -254
- data/ext/ca_obj_bincmp.c +9 -1
- data/ext/ca_obj_binop.c +10 -1
- data/ext/ca_obj_bitfield.c +2 -0
- data/ext/ca_obj_byte_swap.c +2 -0
- data/ext/ca_obj_face.c +2 -0
- data/ext/ca_obj_fake.c +3 -1
- data/ext/ca_obj_grid.c +167 -12
- data/ext/ca_obj_meld.c +69 -113
- data/ext/ca_obj_moncmp.c +9 -1
- data/ext/ca_obj_monop.c +40 -2
- data/ext/ca_obj_object.c +54 -20
- data/ext/ca_obj_reduce.c +15 -1
- data/ext/ca_obj_refer.c +65 -20
- data/ext/ca_obj_remap.c +69 -10
- data/ext/ca_obj_roll.c +1 -0
- data/ext/ca_obj_select.c +4 -1
- data/ext/ca_obj_select_axis.c +1 -0
- data/ext/ca_obj_shift.c +1 -0
- data/ext/ca_obj_stack.c +310 -111
- data/ext/ca_obj_stride.c +131 -45
- data/ext/ca_obj_string.c +18 -2
- data/ext/ca_obj_tile.c +1 -0
- data/ext/ca_obj_triop.c +9 -1
- data/ext/ca_obj_window.c +1 -0
- data/ext/ca_op_ipower.c +8 -8
- data/ext/caframe_csv_reader.c +1 -1
- data/ext/carray.h +2 -1
- data/ext/carray_access.c +27 -64
- data/ext/carray_address_basis.c +134 -0
- data/ext/carray_attribute.c +8 -0
- data/ext/carray_broadcast.c +3 -4
- data/ext/carray_build_flags.h +1 -1
- data/ext/carray_cast.c +8 -11
- data/ext/carray_conversion.c +9 -5
- data/ext/carray_core.c +811 -72
- data/ext/carray_element.c +13 -9
- data/ext/carray_histogram.c +25 -3
- data/ext/carray_internal.h +147 -12
- data/ext/carray_kernels_bincmp.c +2007 -3
- data/ext/carray_kernels_binop.c +25365 -5199
- data/ext/carray_kernels_init.c +8 -8
- data/ext/carray_kernels_monop.c +10696 -3678
- data/ext/carray_kernels_reduce_aggregate.c +4429 -702
- data/ext/carray_kernels_reduce_boolean.c +1533 -15
- data/ext/carray_kernels_reduce_cumulative.c +1808 -248
- data/ext/carray_kernels_reduce_extreme.c +4508 -511
- data/ext/carray_kernels_reduce_variance.c +2284 -152
- data/ext/carray_kernels_scan.c +240 -240
- data/ext/carray_kernels_search.c +4211 -264
- data/ext/carray_kernels_sort.c +367 -450
- data/ext/carray_lazy.c +47 -0
- data/ext/carray_loop.c +1 -1
- data/ext/carray_mask.c +130 -139
- data/ext/carray_median_percentile.c +4 -4
- data/ext/carray_memory_view.c +13 -7
- data/ext/carray_operator.c +147 -44
- data/ext/carray_order.c +3 -2
- data/ext/carray_random.c +4 -1
- data/ext/carray_slab.c +97 -21
- data/ext/carray_sort.c +1 -1
- data/ext/carray_test.c +74 -19
- data/ext/carray_time_text.c +2 -2
- data/ext/extconf.rb +11 -0
- data/ext/mkkernel.rb +346 -94
- data/ext/ruby_carray.c +4 -1
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +25 -1
- data/lib/carray/autoload_carray.rb +3 -3
- data/lib/carray/autoload_method_extension.rb +5 -3
- data/lib/carray/axis_group.rb +13 -7
- data/lib/carray/basics.rb +1 -1
- data/lib/carray/block_iterator.rb +17 -3
- data/lib/carray/categorical.rb +6 -8
- data/lib/carray/categorical_iterator.rb +2 -2
- data/lib/carray/complex.rb +2 -2
- data/lib/carray/conditional.rb +3 -2
- data/lib/carray/frame/column_verbs.rb +45 -14
- data/lib/carray/frame/convert.rb +19 -0
- data/lib/carray/frame/csv_parser.rb +32 -32
- data/lib/carray/frame/describe.rb +4 -2
- data/lib/carray/frame/frame.rb +399 -78
- data/lib/carray/frame/group.rb +679 -53
- data/lib/carray/frame/io.rb +209 -71
- data/lib/carray/frame/join.rb +146 -37
- data/lib/carray/frame/records.rb +3 -3
- data/lib/carray/frame/reshape.rb +89 -11
- data/lib/carray/frame/sort.rb +57 -9
- data/lib/carray/frame/verbs.rb +384 -49
- data/lib/carray/frame/windows.rb +44 -6
- data/lib/carray/inspect.rb +7 -2
- data/lib/carray/iterator.rb +32 -0
- data/lib/carray/lazy.rb +17 -8
- data/lib/carray/mask_gap_fill.rb +37 -17
- data/lib/carray/meld_reduce.rb +1 -1
- data/lib/carray/methods/choose.rb +3 -2
- data/lib/carray/methods/meshgrid.rb +3 -1
- data/lib/carray/runtime.rb +47 -8
- data/lib/carray/segment_iterator.rb +23 -8
- data/lib/carray/serialize.rb +34 -17
- data/lib/carray/stack.rb +18 -6
- data/lib/carray/time.rb +5 -0
- data/lib/carray/window_iterator.rb +16 -4
- data/yard-stubs/ca_obj_array.rb +26 -1
- data/yard-stubs/carray_cast.rb +8 -5
- data/yard-stubs/carray_conversion.rb +8 -2
- data/yard-stubs/carray_mask.rb +20 -1
- data/yard-stubs/carray_math.rb +31 -16
- data/yard-stubs/carray_memory_view.rb +7 -0
- data/yard-stubs/carray_test.rb +7 -4
- metadata +18 -4
data/ext/carray_lazy.c
CHANGED
|
@@ -1084,6 +1084,53 @@ ca_lazy_settle_scalar (VALUE operand, int was_scalar)
|
|
|
1084
1084
|
return operand;
|
|
1085
1085
|
}
|
|
1086
1086
|
|
|
1087
|
+
typedef struct {
|
|
1088
|
+
ca_lazy_eval_fn eval;
|
|
1089
|
+
void *node;
|
|
1090
|
+
const ca_lazy_req_t *req;
|
|
1091
|
+
void *data;
|
|
1092
|
+
int dir;
|
|
1093
|
+
} ca_lazy_eval_args_t;
|
|
1094
|
+
|
|
1095
|
+
static VALUE
|
|
1096
|
+
ca_lazy_eval_body (VALUE varg)
|
|
1097
|
+
{
|
|
1098
|
+
ca_lazy_eval_args_t *a = (ca_lazy_eval_args_t *) varg;
|
|
1099
|
+
a->eval(a->node, a->req, a->data, a->dir);
|
|
1100
|
+
/* A cell computed as an expression over a node being evaluated (x + 1
|
|
1101
|
+
for a cell holding x) stays lazy, and comparing or computing it later
|
|
1102
|
+
evaluates the node again without end: refuse it here, while the node
|
|
1103
|
+
is still recorded. */
|
|
1104
|
+
if ( a->dir == CA_XFER_GET && ca_is_object_type((CArray *) a->node) ) {
|
|
1105
|
+
ca_refuse_cells_reaching_evaluation(a->req->n, (const VALUE *) a->data);
|
|
1106
|
+
}
|
|
1107
|
+
return Qnil;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
void
|
|
1111
|
+
ca_lazy_eval_recorded (void *node, int n, CArray **ops,
|
|
1112
|
+
int nchain, CArray **chain, ca_lazy_eval_fn eval,
|
|
1113
|
+
const ca_lazy_req_t *req, void *data, int dir)
|
|
1114
|
+
{
|
|
1115
|
+
CArray **rec;
|
|
1116
|
+
ca_lazy_eval_args_t a;
|
|
1117
|
+
int i, m = 0, object = ca_is_object_type((CArray *) node);
|
|
1118
|
+
for ( i = 0; i < n; i++ ) {
|
|
1119
|
+
if ( ops[i] && ca_is_object_type(ops[i]) ) object = 1;
|
|
1120
|
+
}
|
|
1121
|
+
if ( ! object ) {
|
|
1122
|
+
eval(node, req, data, dir);
|
|
1123
|
+
return;
|
|
1124
|
+
}
|
|
1125
|
+
rec = ALLOCA_N(CArray *, nchain + 1);
|
|
1126
|
+
rec[m++] = (CArray *) node;
|
|
1127
|
+
for ( i = 0; i < nchain; i++ ) {
|
|
1128
|
+
rec[m++] = chain[i];
|
|
1129
|
+
}
|
|
1130
|
+
a.eval = eval; a.node = node; a.req = req; a.data = data; a.dir = dir;
|
|
1131
|
+
ca_computing_run_nodes(m, rec, ca_lazy_eval_body, (VALUE) &a);
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1087
1134
|
void
|
|
1088
1135
|
ca_lazy_req_pull (void *operand, const ca_lazy_req_t *req, void *buf, int dir)
|
|
1089
1136
|
{
|
data/ext/carray_loop.c
CHANGED
|
@@ -247,7 +247,7 @@ ca_map_bang_run (VALUE self, VALUE (*body)(VALUE), int mode)
|
|
|
247
247
|
c.self = self;
|
|
248
248
|
c.ridx = rb_ary_new2(c.ca->ndim);
|
|
249
249
|
c.mode = mode;
|
|
250
|
-
|
|
250
|
+
ca_attach_window_yielding(self, 1, &c.ca, "w", body, (VALUE) &c);
|
|
251
251
|
return self;
|
|
252
252
|
}
|
|
253
253
|
|
data/ext/carray_mask.c
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
#include "carray.h"
|
|
14
14
|
#include "carray_internal.h" /* ca_lazy_arena_* */
|
|
15
15
|
#include "ca_obj_face.h" /* CA_FACE_LIFT_IF_FACE for the mask-lift path */
|
|
16
|
+
#include <ruby/ractor.h>
|
|
16
17
|
|
|
17
18
|
/* ============================================================================
|
|
18
19
|
* Word-bulk mask substrate helpers.
|
|
@@ -301,7 +302,13 @@ ca_has_mask (void *ap)
|
|
|
301
302
|
if ( ca->mask ) { /* mask array already created */
|
|
302
303
|
return 1;
|
|
303
304
|
}
|
|
304
|
-
else if (
|
|
305
|
+
else if ( ca_test_flag(ca, CA_FLAG_VALUE_ARRAY) ) {
|
|
306
|
+
/* Only this array's own mark, not ca_is_value_array, which walks to
|
|
307
|
+
the root and would make every level of a view pay again for the
|
|
308
|
+
levels above it. A view below a value array still answers 0: it
|
|
309
|
+
asks its parent, and the question reaches the marked array. No
|
|
310
|
+
level in between has a mask, since ca_create_mask refuses one for
|
|
311
|
+
anything below a value array. */
|
|
305
312
|
return 0; /* array itself is returned by CArray#value */
|
|
306
313
|
}
|
|
307
314
|
else if ( ca_is_entity(ca) ) { /* entity array */
|
|
@@ -316,6 +323,11 @@ ca_has_mask (void *ap)
|
|
|
316
323
|
}
|
|
317
324
|
return 0;
|
|
318
325
|
}
|
|
326
|
+
/* The one level that answers without asking its parent: a value
|
|
327
|
+
array above it has to be looked for here. */
|
|
328
|
+
if ( ca_is_value_array(ca) ) {
|
|
329
|
+
return 0;
|
|
330
|
+
}
|
|
319
331
|
if ( rb_obj_respond_to(co->self, rb_intern("mask_created?"), Qtrue) ) {
|
|
320
332
|
return RTEST(rb_funcall(co->self, rb_intern("mask_created?"), 0));
|
|
321
333
|
}
|
|
@@ -412,6 +424,45 @@ ca_view_func_create_mask (void *ap)
|
|
|
412
424
|
CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
|
|
413
425
|
}
|
|
414
426
|
|
|
427
|
+
/* The sync slot of a view whose mask came from ca_view_func_create_mask
|
|
428
|
+
calls this after syncing its parent. The view's mask is a refer over
|
|
429
|
+
the parent's mask, and when the parent's mask is itself a view, both
|
|
430
|
+
hold a buffer while the window is open; the refer writes past the
|
|
431
|
+
parent's buffer to the root. Syncing the parent then writes its
|
|
432
|
+
buffer, from before the view's mask was written, back over the root,
|
|
433
|
+
so the view's mask is synced once more. */
|
|
434
|
+
|
|
435
|
+
/* The sync slot of a view that maps its cells one to one onto its parent's
|
|
436
|
+
(a fake, a cast, a byte swap, a Face) calls this before syncing its
|
|
437
|
+
parent. The view's mask may have been written past the parent's mask
|
|
438
|
+
buffer, straight to the root (by a view over it), so the parent's
|
|
439
|
+
buffer can still hold the bits from before. The parent's own sync
|
|
440
|
+
decides from that buffer which cells it sends back, so the view's bits
|
|
441
|
+
are copied into it first. */
|
|
442
|
+
|
|
443
|
+
void
|
|
444
|
+
ca_view_pass_mask_to_parent (void *ap)
|
|
445
|
+
{
|
|
446
|
+
CAView *ca = (CAView *) ap;
|
|
447
|
+
if ( ca->mask != NULL && ca->mask->ptr != NULL
|
|
448
|
+
&& ca->parent->mask != NULL && ca->parent->mask->ptr != NULL
|
|
449
|
+
&& ca->mask->ptr != ca->parent->mask->ptr
|
|
450
|
+
&& ca->elements == ca->parent->elements ) {
|
|
451
|
+
memmove(ca->parent->mask->ptr, ca->mask->ptr, (size_t) ca->elements);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
void
|
|
456
|
+
ca_view_sync_mask_after_parent (void *ap)
|
|
457
|
+
{
|
|
458
|
+
CAView *ca = (CAView *) ap;
|
|
459
|
+
if ( ca->mask != NULL && ca->mask->ptr != NULL
|
|
460
|
+
&& ca->parent->mask != NULL && ca->parent->mask->ptr != NULL
|
|
461
|
+
&& ca_is_view(ca->parent->mask) ) {
|
|
462
|
+
ca_sync(ca->mask);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
415
466
|
/* create mask array if array has mask but has not mask array */
|
|
416
467
|
|
|
417
468
|
void
|
|
@@ -441,20 +492,27 @@ ca_mask_standin_new (CArray *parent)
|
|
|
441
492
|
return z;
|
|
442
493
|
}
|
|
443
494
|
|
|
444
|
-
/* A value array or a mask array
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
495
|
+
/* A stack or meld refuses a value array or a mask array as a part: such an
|
|
496
|
+
array can have no mask, and a part of a stack or meld is an array like
|
|
497
|
+
any other, which can. */
|
|
498
|
+
void
|
|
499
|
+
ca_multi_parent_check_part (CArray *part, const char *name)
|
|
448
500
|
{
|
|
449
|
-
|
|
501
|
+
if ( ca_is_value_array(part) ) {
|
|
502
|
+
rb_raise(rb_eArgError,
|
|
503
|
+
"%s: a value array can have no mask and can not be a part", name);
|
|
504
|
+
}
|
|
505
|
+
if ( ca_is_mask_array(part) ) {
|
|
506
|
+
rb_raise(rb_eArgError,
|
|
507
|
+
"%s: a mask array can have no mask and can not be a part", name);
|
|
508
|
+
}
|
|
450
509
|
}
|
|
451
510
|
|
|
452
511
|
CArray *
|
|
453
512
|
ca_mask_standin_current (CArray *mask_view, CArray *reading, CArray *parent,
|
|
454
513
|
CArray *standin)
|
|
455
514
|
{
|
|
456
|
-
if ( standin == NULL || reading != standin
|
|
457
|
-
|| ca_mask_standin_parent_unmaskable(parent) ) {
|
|
515
|
+
if ( standin == NULL || reading != standin ) {
|
|
458
516
|
return reading;
|
|
459
517
|
}
|
|
460
518
|
/* Not inside an attach window whose buffer is out: that buffer and the
|
|
@@ -490,23 +548,21 @@ ca_mask_standin_settle (CArray *parent, CArray *standin)
|
|
|
490
548
|
if ( i == n ) {
|
|
491
549
|
return;
|
|
492
550
|
}
|
|
493
|
-
if ( ca_mask_standin_parent_unmaskable(parent) ) {
|
|
494
|
-
MEMZERO(z, boolean8_t, n);
|
|
495
|
-
rb_raise(rb_eTypeError, "can not create mask array for the %s array",
|
|
496
|
-
ca_is_value_array(parent) ? "value" : "mask");
|
|
497
|
-
}
|
|
498
|
-
ca_create_mask(parent);
|
|
499
551
|
/* The trues are added to the parent's mask, not copied over it: the
|
|
500
|
-
parent may have come to have masked cells of its own meanwhile.
|
|
552
|
+
parent may have come to have masked cells of its own meanwhile. The
|
|
553
|
+
stand-in is cleared before the parent is asked for a mask, so a
|
|
554
|
+
parent that refuses one leaves it all false, as its readers take it
|
|
555
|
+
to be at rest. */
|
|
501
556
|
addrs = ALLOCV_N(ca_size_t, holder, n);
|
|
502
557
|
for ( ; i < n; i++ ) {
|
|
503
558
|
if ( z[i] ) {
|
|
504
559
|
addrs[m++] = i;
|
|
505
560
|
}
|
|
506
561
|
}
|
|
562
|
+
MEMZERO(z, boolean8_t, n);
|
|
563
|
+
ca_create_mask(parent);
|
|
507
564
|
ca_fill_addrs(parent->mask, m, addrs, &one);
|
|
508
565
|
ALLOCV_END(holder);
|
|
509
|
-
MEMZERO(z, boolean8_t, n);
|
|
510
566
|
}
|
|
511
567
|
|
|
512
568
|
CArray *
|
|
@@ -539,114 +595,37 @@ ca_multi_parent_mask_refresh (CArray *mask, CArray **parents,
|
|
|
539
595
|
CAVIEW(mask)->parent = mp->parents[0];
|
|
540
596
|
}
|
|
541
597
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
VALUE (*body)(VALUE);
|
|
550
|
-
VALUE arg;
|
|
551
|
-
} ca_mp_trial_t;
|
|
552
|
-
|
|
553
|
-
static VALUE
|
|
554
|
-
ca_mp_trial_body (VALUE p)
|
|
555
|
-
{
|
|
556
|
-
ca_mp_trial_t *t = (ca_mp_trial_t *) p;
|
|
557
|
-
t->body(t->arg);
|
|
558
|
-
t->finished = 1;
|
|
559
|
-
return Qnil;
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
static void
|
|
563
|
-
ca_mp_trial_free_blanks (ca_mp_trial_t *t)
|
|
564
|
-
{
|
|
565
|
-
int32_t k;
|
|
566
|
-
for ( k = 0; k < t->n; k++ ) {
|
|
567
|
-
ca_free(t->blanks[k]);
|
|
568
|
-
t->blanks[k] = NULL;
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
static VALUE
|
|
573
|
-
ca_mp_trial_restore (VALUE p)
|
|
574
|
-
{
|
|
575
|
-
ca_mp_trial_t *t = (ca_mp_trial_t *) p;
|
|
576
|
-
CAMultiParent *mp = (CAMultiParent *) t->mask;
|
|
577
|
-
int32_t k;
|
|
578
|
-
for ( k = 0; k < t->n; k++ ) {
|
|
579
|
-
mp->parents[k] = t->saved[k];
|
|
580
|
-
}
|
|
581
|
-
CAVIEW(t->mask)->parent = t->saved_parent;
|
|
582
|
-
if ( ! t->finished ) {
|
|
583
|
-
ca_mp_trial_free_blanks(t);
|
|
584
|
-
}
|
|
585
|
-
return Qnil;
|
|
586
|
-
}
|
|
587
|
-
|
|
598
|
+
/* Before a write that puts a true into the mask of a stack or meld (not one
|
|
599
|
+
with its buffer out): each part still reading its stand-in that shares
|
|
600
|
+
its root with another part is given its own mask, and the write goes to
|
|
601
|
+
those parts' masks in their order. Parts that share cells then take the
|
|
602
|
+
write of the last of them, as they do for values; through stand-ins,
|
|
603
|
+
settled afterwards, the trues would be added together. A part that
|
|
604
|
+
shares nothing keeps its stand-in, and gets no mask from falses. */
|
|
588
605
|
void
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
VALUE (*body)(VALUE), VALUE arg)
|
|
606
|
+
ca_multi_parent_mask_adopt (CArray *mask, CArray **parents,
|
|
607
|
+
CArray **standins, int32_t n)
|
|
592
608
|
{
|
|
593
609
|
CAMultiParent *mp = (CAMultiParent *) mask;
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
int32_t k, refused = -1;
|
|
597
|
-
if ( standins == NULL ) {
|
|
610
|
+
int32_t k, j;
|
|
611
|
+
if ( standins == NULL || mask->ptr != NULL ) {
|
|
598
612
|
return;
|
|
599
613
|
}
|
|
600
614
|
for ( k = 0; k < n; k++ ) {
|
|
601
|
-
if ( standins[k]
|
|
602
|
-
|
|
603
|
-
|
|
615
|
+
if ( standins[k] == NULL || mp->parents[k] != standins[k]
|
|
616
|
+
|| ca_test_flag(standins[k], CA_FLAG_READ_ONLY) ) {
|
|
617
|
+
continue;
|
|
604
618
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
return;
|
|
608
|
-
}
|
|
609
|
-
t.mask = mask;
|
|
610
|
-
t.n = n;
|
|
611
|
-
t.finished = 0;
|
|
612
|
-
t.body = body;
|
|
613
|
-
t.arg = arg;
|
|
614
|
-
t.saved_parent = CAVIEW(mask)->parent;
|
|
615
|
-
t.blanks = ALLOCV_N(CArray *, h_blank, n);
|
|
616
|
-
t.saved = ALLOCV_N(CArray *, h_saved, n);
|
|
617
|
-
for ( k = 0; k < n; k++ ) {
|
|
618
|
-
t.blanks[k] = NULL;
|
|
619
|
-
}
|
|
620
|
-
for ( k = 0; k < n; k++ ) {
|
|
621
|
-
CArray *m = mp->parents[k];
|
|
622
|
-
t.saved[k] = m;
|
|
623
|
-
t.blanks[k] = carray_new(CA_BOOLEAN, m->ndim, m->dim, 0, NULL);
|
|
624
|
-
MEMZERO(t.blanks[k]->ptr, boolean8_t, t.blanks[k]->elements);
|
|
625
|
-
}
|
|
626
|
-
for ( k = 0; k < n; k++ ) {
|
|
627
|
-
mp->parents[k] = t.blanks[k];
|
|
628
|
-
}
|
|
629
|
-
CAVIEW(mask)->parent = t.blanks[0];
|
|
630
|
-
rb_ensure(ca_mp_trial_body, (VALUE) &t, ca_mp_trial_restore, (VALUE) &t);
|
|
631
|
-
for ( k = 0; k < n && refused < 0; k++ ) {
|
|
632
|
-
CArray *z = t.blanks[k];
|
|
633
|
-
ca_size_t i;
|
|
634
|
-
if ( standins[k] == NULL || t.saved[k] != standins[k]
|
|
635
|
-
|| ! ca_mask_standin_parent_unmaskable(parents[k]) ) {
|
|
619
|
+
for ( j = 0; j < n && ( j == k || ! ca_shares_root(parents[j], parents[k]) ); j++ ) ;
|
|
620
|
+
if ( j == n ) {
|
|
636
621
|
continue;
|
|
637
622
|
}
|
|
638
|
-
|
|
639
|
-
if (
|
|
640
|
-
|
|
623
|
+
ca_create_mask(parents[k]);
|
|
624
|
+
if ( parents[k]->mask != NULL ) {
|
|
625
|
+
mp->parents[k] = parents[k]->mask;
|
|
641
626
|
}
|
|
642
627
|
}
|
|
643
|
-
|
|
644
|
-
ALLOCV_END(h_blank);
|
|
645
|
-
ALLOCV_END(h_saved);
|
|
646
|
-
if ( refused >= 0 ) {
|
|
647
|
-
rb_raise(rb_eTypeError, "can not create mask array for the %s array",
|
|
648
|
-
ca_is_value_array(parents[refused]) ? "value" : "mask");
|
|
649
|
-
}
|
|
628
|
+
CAVIEW(mask)->parent = mp->parents[0];
|
|
650
629
|
}
|
|
651
630
|
|
|
652
631
|
void
|
|
@@ -654,18 +633,12 @@ ca_multi_parent_mask_settle (CArray *mask, CArray **parents,
|
|
|
654
633
|
CArray **standins, int32_t n)
|
|
655
634
|
{
|
|
656
635
|
CAMultiParent *mp = (CAMultiParent *) mask;
|
|
657
|
-
int32_t k
|
|
636
|
+
int32_t k;
|
|
658
637
|
if ( standins == NULL ) {
|
|
659
638
|
return;
|
|
660
639
|
}
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
for ( pass = 0; pass < 2; pass++ ) {
|
|
664
|
-
for ( k = 0; k < n; k++ ) {
|
|
665
|
-
if ( standins[k] == NULL || mp->parents[k] != standins[k]
|
|
666
|
-
|| ca_mask_standin_parent_unmaskable(parents[k]) != ( pass == 0 ) ) {
|
|
667
|
-
continue;
|
|
668
|
-
}
|
|
640
|
+
for ( k = 0; k < n; k++ ) {
|
|
641
|
+
if ( standins[k] != NULL && mp->parents[k] == standins[k] ) {
|
|
669
642
|
ca_mask_standin_settle(parents[k], standins[k]);
|
|
670
643
|
}
|
|
671
644
|
}
|
|
@@ -797,6 +770,9 @@ typedef struct {
|
|
|
797
770
|
int k; /* entries in list */
|
|
798
771
|
int ns; /* sources */
|
|
799
772
|
ca_size_t elements;
|
|
773
|
+
CArray *dest; /* the destination */
|
|
774
|
+
int overwrite; /* clear the destination's mask first */
|
|
775
|
+
char *modes; /* attach modes, one per entry of list */
|
|
800
776
|
} ca_mask_overlay_t;
|
|
801
777
|
|
|
802
778
|
static VALUE
|
|
@@ -823,6 +799,31 @@ ca_mask_overlay_body (VALUE arg)
|
|
|
823
799
|
return Qnil;
|
|
824
800
|
}
|
|
825
801
|
|
|
802
|
+
/* Clear the destination's mask if asked, and OR the sources into it. */
|
|
803
|
+
static VALUE
|
|
804
|
+
ca_mask_overlay_write (VALUE arg)
|
|
805
|
+
{
|
|
806
|
+
ca_mask_overlay_t *o = (ca_mask_overlay_t *) arg;
|
|
807
|
+
CArray *ca = o->dest;
|
|
808
|
+
int i;
|
|
809
|
+
if ( o->overwrite ) {
|
|
810
|
+
boolean8_t zero = 0;
|
|
811
|
+
ca_fill(ca->mask, &zero);
|
|
812
|
+
}
|
|
813
|
+
o->k = 0;
|
|
814
|
+
o->list[o->k] = ca->mask;
|
|
815
|
+
o->modes[o->k++] = 'w';
|
|
816
|
+
for (i=0; i<o->ns; i++) {
|
|
817
|
+
if ( o->att[i] ) {
|
|
818
|
+
o->list[o->k] = o->att[i];
|
|
819
|
+
o->modes[o->k++] = 'r';
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
o->modes[o->k] = '\0';
|
|
823
|
+
ca_attach_window(o->k, o->list, o->modes, ca_mask_overlay_body, arg);
|
|
824
|
+
return Qnil;
|
|
825
|
+
}
|
|
826
|
+
|
|
826
827
|
/* overwrite: the destination's mask is cleared before the sources are
|
|
827
828
|
OR'd in (and left alone when it has none and no source has a mask). */
|
|
828
829
|
static void
|
|
@@ -907,22 +908,10 @@ ca_copy_mask_overlay_core (CArray *ca, ca_size_t elements, int n,
|
|
|
907
908
|
}
|
|
908
909
|
|
|
909
910
|
ca_create_mask(ca);
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
o.k = 0;
|
|
916
|
-
o.list[o.k] = ca->mask;
|
|
917
|
-
modes[o.k++] = 'w';
|
|
918
|
-
for (i=0; i<o.ns; i++) {
|
|
919
|
-
if ( o.att[i] ) {
|
|
920
|
-
o.list[o.k] = o.att[i];
|
|
921
|
-
modes[o.k++] = 'r';
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
modes[o.k] = '\0';
|
|
925
|
-
ca_attach_window(o.k, o.list, modes, ca_mask_overlay_body, (VALUE) &o);
|
|
911
|
+
o.dest = ca;
|
|
912
|
+
o.overwrite = overwrite;
|
|
913
|
+
o.modes = modes;
|
|
914
|
+
ca_mask_overlay_write((VALUE) &o);
|
|
926
915
|
|
|
927
916
|
for (i=0; i<n; i++) {
|
|
928
917
|
if ( holders[i] ) {
|
|
@@ -1848,7 +1837,9 @@ ca_mask_copy_where (VALUE self, int argc, VALUE *argv)
|
|
|
1848
1837
|
obj = rb_ca_copy(self);
|
|
1849
1838
|
memcpy(all_args, argv, argc * sizeof(VALUE));
|
|
1850
1839
|
all_args[argc] = CA_UNDEF;
|
|
1851
|
-
|
|
1840
|
+
/* a CScalar takes no index; its one-cell view does */
|
|
1841
|
+
rb_funcallv(ca_is_scalar(ca) ? rb_funcall(obj, rb_intern("flatten"), 0) : obj,
|
|
1842
|
+
rb_intern("[]="), argc + 1, all_args);
|
|
1852
1843
|
return obj;
|
|
1853
1844
|
}
|
|
1854
1845
|
|
|
@@ -907,10 +907,10 @@ rb_ca_median_m_body (int argc, VALUE *argv, VALUE self)
|
|
|
907
907
|
if ( n == 0 ) return mp_axis_all_masked(self, axis, keep_axis);
|
|
908
908
|
/* mask / min_count / fill_value require the per-fiber select (each fiber
|
|
909
909
|
has its own n_present); the plain partition path assumes a uniform n.
|
|
910
|
-
Switch
|
|
910
|
+
Switch ca_fast_path(CA_SC_MEDIAN_PARTITION): off, the per-fiber select. */
|
|
911
911
|
VALUE res;
|
|
912
912
|
if ( RTEST(rb_ca_has_mask(self)) || min_count > 0 || !NIL_P(fill_value)
|
|
913
|
-
|| !
|
|
913
|
+
|| ! ca_fast_path(CA_SC_MEDIAN_PARTITION) )
|
|
914
914
|
res = is_obj
|
|
915
915
|
? median_object_axis_masked(self, axis, min_count, fill_value, keep_axis)
|
|
916
916
|
: median_axis_masked(self, axis, min_count, fill_value, keep_axis);
|
|
@@ -1364,9 +1364,9 @@ rb_ca_percentile_kw (int argc, VALUE *argv, VALUE ropt, VALUE self)
|
|
|
1364
1364
|
/* mask / min_count / fill_value require the per-fiber select (each fiber
|
|
1365
1365
|
has its own n_present); the plain partition/sort path assumes a
|
|
1366
1366
|
uniform n. These paths bake keep_axis into the reduced output.
|
|
1367
|
-
Switch
|
|
1367
|
+
Switch ca_fast_path(CA_SC_PERCENTILE_PARTITION): off, the per-fiber select. */
|
|
1368
1368
|
int per_fiber = RTEST(rb_ca_has_mask(self)) || min_count > 0
|
|
1369
|
-
|| !NIL_P(fill_value) || !
|
|
1369
|
+
|| !NIL_P(fill_value) || ! ca_fast_path(CA_SC_PERCENTILE_PARTITION);
|
|
1370
1370
|
if ( !is_obj ) {
|
|
1371
1371
|
result = per_fiber
|
|
1372
1372
|
? pct_axis_masked(self, pers, axis, method, min_count, fill_value, keep_axis)
|
data/ext/carray_memory_view.c
CHANGED
|
@@ -202,7 +202,9 @@ ca_mv_record_member_spec (VALUE info, char *out, size_t outlen,
|
|
|
202
202
|
a member it has no item for (see above), or members that overlap or come
|
|
203
203
|
out of offset order (a union).
|
|
204
204
|
|
|
205
|
-
The result is frozen and cached on the data_class.
|
|
205
|
+
The result is frozen and cached on the data_class. Only the main Ractor
|
|
206
|
+
may set an instance variable on a class, so another Ractor builds the
|
|
207
|
+
format each time until the main one has cached it. It is an ordinary
|
|
206
208
|
String that compaction can move, so a view takes a copy of its bytes
|
|
207
209
|
rather than its pointer (ca_mv_get). */
|
|
208
210
|
static VALUE
|
|
@@ -245,11 +247,11 @@ ca_mv_struct_format_for_data_class (VALUE data_class)
|
|
|
245
247
|
}
|
|
246
248
|
|
|
247
249
|
rb_obj_freeze(buf);
|
|
248
|
-
rb_ivar_set(data_class, iv, buf);
|
|
250
|
+
if (ca_in_main_ractor()) rb_ivar_set(data_class, iv, buf);
|
|
249
251
|
return buf;
|
|
250
252
|
|
|
251
253
|
unsupported:
|
|
252
|
-
rb_ivar_set(data_class, iv, Qfalse);
|
|
254
|
+
if (ca_in_main_ractor()) rb_ivar_set(data_class, iv, Qfalse);
|
|
253
255
|
return Qnil;
|
|
254
256
|
}
|
|
255
257
|
|
|
@@ -900,7 +902,7 @@ ca_mv_release (VALUE obj, rb_memory_view_t *view)
|
|
|
900
902
|
}
|
|
901
903
|
|
|
902
904
|
/* ---------------- importer ----------------
|
|
903
|
-
Two-tier API
|
|
905
|
+
Two-tier API:
|
|
904
906
|
|
|
905
907
|
CArray.from_memory_view(obj) -> CArray (copy, independent buffer)
|
|
906
908
|
CArray.wrap_memory_view(obj) -> CAWrap (zero-copy, shared memory)
|
|
@@ -1621,9 +1623,13 @@ rb_ca_s_memory_view_reject_reason (VALUE klass, VALUE obj)
|
|
|
1621
1623
|
"producer cannot express yet (nested struct, "
|
|
1622
1624
|
"CArray template, :fixlen, or :object)");
|
|
1623
1625
|
}
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1626
|
+
if (ca->data_type == CA_OBJECT) {
|
|
1627
|
+
return rb_str_new_cstr("an object array holds Ruby objects, not bytes "
|
|
1628
|
+
"a consumer can read; convert it with to_type "
|
|
1629
|
+
"first");
|
|
1630
|
+
}
|
|
1631
|
+
return rb_sprintf("data_type %s has no MemoryView format",
|
|
1632
|
+
ca_type_name[ca->data_type]);
|
|
1627
1633
|
}
|
|
1628
1634
|
if (ca_has_mask(ca)) {
|
|
1629
1635
|
return rb_str_new_cstr("array has a mask; use arr.value (mask-ignoring CARefer) "
|