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_element.c
CHANGED
|
@@ -82,8 +82,9 @@ elem_probe_mask (CArray *ca)
|
|
|
82
82
|
|
|
83
83
|
/* Entity-array fast path: compute flat addr from idx[] and access ptr directly.
|
|
84
84
|
Bypasses ca_func[ARRAY].xfer_index function-pointer dispatch.
|
|
85
|
-
Caller must ensure ca_is_entity(ca) and ca->ptr
|
|
86
|
-
|
|
85
|
+
Caller must ensure ca_is_entity(ca) and ca->ptr != NULL: an entity can
|
|
86
|
+
leave ptr NULL at rest (a CASource), and then the dispatched path is
|
|
87
|
+
the way in. */
|
|
87
88
|
static inline ca_size_t
|
|
88
89
|
elem_entity_addr (CArray *ca, ca_size_t *idx)
|
|
89
90
|
{
|
|
@@ -273,7 +274,7 @@ rb_ca_elem_store (VALUE self, VALUE ridx, VALUE obj)
|
|
|
273
274
|
Bypasses rb_ca_store_index/addr -> ca_update_mask + rb_ca_obj2ptr ->
|
|
274
275
|
cast_table dispatch. Falls through to general path for: views,
|
|
275
276
|
existing mask, non-numeric data type, UNDEF, or non-Numeric obj. */
|
|
276
|
-
if ( ca_is_entity(ca) && ! ca->mask && obj != CA_UNDEF ) {
|
|
277
|
+
if ( ca_is_entity(ca) && ca->ptr && ! ca->mask && obj != CA_UNDEF ) {
|
|
277
278
|
int8_t dt = ca->data_type;
|
|
278
279
|
if ( dt == CA_FLOAT64 || dt == CA_FLOAT32 ||
|
|
279
280
|
dt == CA_INT64 || dt == CA_INT32 ||
|
|
@@ -383,7 +384,7 @@ rb_ca_elem_fetch (VALUE self, VALUE ridx)
|
|
|
383
384
|
/* Super-hot path: entity + common numeric data type + no mask.
|
|
384
385
|
Bypass ca_fetch_index dispatch AND rb_ca_ptr2obj_storage cast-table dispatch.
|
|
385
386
|
Covers the bench's float64 / int64 / int32 cases. */
|
|
386
|
-
if ( ca_is_entity(ca) && ! ca->mask ) {
|
|
387
|
+
if ( ca_is_entity(ca) && ca->ptr && ! ca->mask ) {
|
|
387
388
|
ca_size_t addr = elem_entity_addr(ca, idx);
|
|
388
389
|
char *p = ca->ptr + ca->bytes * addr;
|
|
389
390
|
switch ( ca->data_type ) {
|
|
@@ -406,7 +407,7 @@ rb_ca_elem_fetch (VALUE self, VALUE ridx)
|
|
|
406
407
|
TypedData_Get_Struct). Semantics identical to rb_ca_fetch_index. */
|
|
407
408
|
if ( ca->bytes <= 64 ) {
|
|
408
409
|
char v[64];
|
|
409
|
-
if ( ca_is_entity(ca) ) {
|
|
410
|
+
if ( ca_is_entity(ca) && ca->ptr ) {
|
|
410
411
|
ca_size_t addr = elem_entity_addr(ca, idx);
|
|
411
412
|
memcpy(v, ca->ptr + ca->bytes * addr, ca->bytes);
|
|
412
413
|
}
|
|
@@ -439,12 +440,15 @@ rb_ca_elem_fetch (VALUE self, VALUE ridx)
|
|
|
439
440
|
}
|
|
440
441
|
|
|
441
442
|
CA_FACE_STORAGE_TO_ELEMENT_IF_FACE(out, self, ca);
|
|
443
|
+
if ( ca->data_type == CA_BOOLEAN ) {
|
|
444
|
+
out = RTEST(out) && out != INT2FIX(0) ? Qtrue : Qfalse;
|
|
445
|
+
}
|
|
442
446
|
return out;
|
|
443
447
|
}
|
|
444
448
|
else {
|
|
445
449
|
ca_size_t addr = elem_parse_idx_scalar(ca, ridx);
|
|
446
450
|
/* Super-hot flat-addr path: entity + numeric + no mask. */
|
|
447
|
-
if ( ca_is_entity(ca) && ! ca->mask ) {
|
|
451
|
+
if ( ca_is_entity(ca) && ca->ptr && ! ca->mask ) {
|
|
448
452
|
char *p = ca->ptr + ca->bytes * addr;
|
|
449
453
|
switch ( ca->data_type ) {
|
|
450
454
|
case CA_FLOAT64: return rb_float_new(*(double *)p);
|
|
@@ -493,7 +497,7 @@ rb_ca_elem_incr (VALUE self, VALUE ridx1)
|
|
|
493
497
|
|
|
494
498
|
/* Super-hot path: entity + no mask + integer data type.
|
|
495
499
|
Reads p directly, modifies in place — no separate fetch/store dispatch. */
|
|
496
|
-
if ( ca_is_entity(ca) && ! has_mask ) {
|
|
500
|
+
if ( ca_is_entity(ca) && ca->ptr && ! has_mask ) {
|
|
497
501
|
ca_size_t addr;
|
|
498
502
|
if ( TYPE(ridx1) == T_ARRAY ) {
|
|
499
503
|
elem_parse_idx_array(ca, ridx1, idx1);
|
|
@@ -583,7 +587,7 @@ rb_ca_elem_decr (VALUE self, VALUE ridx1)
|
|
|
583
587
|
has_mask = elem_probe_mask(ca);
|
|
584
588
|
|
|
585
589
|
/* Super-hot path: mirror of elem_incr. */
|
|
586
|
-
if ( ca_is_entity(ca) && ! has_mask ) {
|
|
590
|
+
if ( ca_is_entity(ca) && ca->ptr && ! has_mask ) {
|
|
587
591
|
ca_size_t addr;
|
|
588
592
|
if ( TYPE(ridx1) == T_ARRAY ) {
|
|
589
593
|
elem_parse_idx_array(ca, ridx1, idx1);
|
|
@@ -798,7 +802,7 @@ rb_ca_elem_unmask (VALUE self, VALUE ridx)
|
|
|
798
802
|
general path, which compares in Ruby and stores as `self[idx] = v`
|
|
799
803
|
does, so a value that wins but does not fit raises. */
|
|
800
804
|
#define ELEM_MINMAX_BODY(OP) do { \
|
|
801
|
-
if ( ca_is_entity(ca) ) { \
|
|
805
|
+
if ( ca_is_entity(ca) && ca->ptr ) { \
|
|
802
806
|
ca_size_t addr; \
|
|
803
807
|
if ( TYPE(ridx) == T_ARRAY ) { \
|
|
804
808
|
elem_parse_idx_array(ca, ridx, idx); \
|
data/ext/carray_histogram.c
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
#include "carray.h"
|
|
26
26
|
#include "carray_internal.h" /* ca_attach_window */
|
|
27
27
|
#include <math.h>
|
|
28
|
+
#include <float.h>
|
|
28
29
|
|
|
29
30
|
/* Edges are the bin boundaries and must read as such: no masked edge (its
|
|
30
31
|
stored value is no boundary), no NaN, and no edge below the one before
|
|
@@ -88,6 +89,8 @@ typedef struct {
|
|
|
88
89
|
const double *ep;
|
|
89
90
|
ca_size_t n; /* number of bins */
|
|
90
91
|
double lo, hi, inv_dx;
|
|
92
|
+
double window; /* fraction of a bin within which the
|
|
93
|
+
linearised floor is checked */
|
|
91
94
|
int uniform;
|
|
92
95
|
int include_max;
|
|
93
96
|
} histbin_axis_t;
|
|
@@ -115,7 +118,7 @@ histbin_index (const histbin_axis_t *ax, double v)
|
|
|
115
118
|
Interior values (the bulk) skip the data-dependent edge loads, keeping
|
|
116
119
|
the fast path vectorisable. */
|
|
117
120
|
frac = pos - (double) k;
|
|
118
|
-
if ( frac <
|
|
121
|
+
if ( frac < ax->window || frac > 1.0 - ax->window ) {
|
|
119
122
|
while ( k + 1 < ax->n && v >= ax->ep[k + 1] ) k++;
|
|
120
123
|
while ( k > 0 && v < ax->ep[k] ) k--;
|
|
121
124
|
}
|
|
@@ -136,7 +139,7 @@ histbin_axis_setup (histbin_axis_t *ax, const double *ep, ca_size_t ne,
|
|
|
136
139
|
int include_max)
|
|
137
140
|
{
|
|
138
141
|
ca_size_t kk;
|
|
139
|
-
double dx, tol;
|
|
142
|
+
double dx, tol, maxdev;
|
|
140
143
|
|
|
141
144
|
ax->ep = ep;
|
|
142
145
|
ax->n = ne - 1;
|
|
@@ -149,8 +152,27 @@ histbin_axis_setup (histbin_axis_t *ax, const double *ep, ca_size_t ne,
|
|
|
149
152
|
width infinite, and a subnormal width makes the reciprocal infinite.
|
|
150
153
|
Either turns the position into NaN, which has no integer. */
|
|
151
154
|
ax->uniform = isfinite(dx) && dx != 0.0 && isfinite(1.0 / dx);
|
|
155
|
+
maxdev = 0.0;
|
|
152
156
|
for ( kk = 0; ax->uniform && kk <= ax->n; kk++ ) {
|
|
153
|
-
|
|
157
|
+
double dev = fabs(ax->ep[kk] - (ax->lo + (double) kk * dx));
|
|
158
|
+
if ( dev > tol ) { ax->uniform = 0; break; }
|
|
159
|
+
if ( dev > maxdev ) maxdev = dev;
|
|
160
|
+
}
|
|
161
|
+
/* A value can land on the wrong side of the linearised floor by as much
|
|
162
|
+
as an edge strays from the straight line, plus the rounding of the
|
|
163
|
+
position itself: v - lo is rounded at the scale of the edges' magnitude
|
|
164
|
+
(an ulp of lo or hi, which can be most of a bin when the edges are
|
|
165
|
+
close together far from zero), and the product grows with the number
|
|
166
|
+
of bins. Values within that much of a boundary are checked against the
|
|
167
|
+
stored edges. When the window covers a good part of a bin, the binary
|
|
168
|
+
search is cheaper. */
|
|
169
|
+
ax->window = ( ax->uniform )
|
|
170
|
+
? maxdev / fabs(dx)
|
|
171
|
+
+ 4.0 * DBL_EPSILON * (fabs(ax->lo) + fabs(ax->hi)) / fabs(dx)
|
|
172
|
+
+ (double) (ax->n + 2) * 8.0 * DBL_EPSILON + 1e-9
|
|
173
|
+
: 0.0;
|
|
174
|
+
if ( ax->window > 0.25 ) {
|
|
175
|
+
ax->uniform = 0;
|
|
154
176
|
}
|
|
155
177
|
ax->inv_dx = (dx != 0.0) ? 1.0 / dx : 0.0;
|
|
156
178
|
ax->include_max = include_max;
|
data/ext/carray_internal.h
CHANGED
|
@@ -35,6 +35,18 @@
|
|
|
35
35
|
CArray#initialize_dup / #initialize_clone. */
|
|
36
36
|
void ca_keep_chain_flags (CArray *view, CArray *src);
|
|
37
37
|
|
|
38
|
+
/* A reshape / flatten folded onto the root of its source (CA_FLAG_FOLDED,
|
|
39
|
+
ca_obj_refer.c). The source is not on the view's C parent chain, so a
|
|
40
|
+
read-only flag it takes after the view is made would not be seen by
|
|
41
|
+
ca_is_readonly. The view records its source here; ca_is_readonly asks the
|
|
42
|
+
source of a view that carries the flag. The source stays alive while the
|
|
43
|
+
view does (the view's @parent). ca_fold_source answers NULL for a view
|
|
44
|
+
with no record; ca_fold_forget drops the record when the view is freed. */
|
|
45
|
+
#define CA_FLAG_FOLDED 8192
|
|
46
|
+
void ca_fold_note_source (CArray *view, CArray *src);
|
|
47
|
+
CArray *ca_fold_source (CArray *view);
|
|
48
|
+
void ca_fold_forget (CArray *view);
|
|
49
|
+
|
|
38
50
|
/* ---- bulk bit pack / unpack (ca_obj_bitarray.c) --------------------------
|
|
39
51
|
|
|
40
52
|
Drive the CABitarray whole-view xfer_all / xfer_addrs fast paths, which
|
|
@@ -188,9 +200,24 @@ ca_mask_from_bytes (CArray *ca, const boolean8_t *m)
|
|
|
188
200
|
|
|
189
201
|
void ca_attach_all (CArray **list, int32_t n);
|
|
190
202
|
void ca_sync_all (CArray **list, int32_t n);
|
|
203
|
+
void ca_sync_carry_on (CArray *ca, volatile VALUE *error);
|
|
191
204
|
VALUE ca_attach_window (int32_t n, CArray **list, const char *modes,
|
|
192
205
|
VALUE (*body)(VALUE), VALUE arg);
|
|
193
206
|
|
|
207
|
+
/* A window that yields to a block can be left open for good: Ruby does not
|
|
208
|
+
run the ensure of a suspended Fiber that is collected (an Enumerator
|
|
209
|
+
stopped with #next and dropped). ca_window_guard_arm makes a guard that
|
|
210
|
+
runs cleanup(arg) from a finalizer when that happens; the window disarms
|
|
211
|
+
it when it closes normally. arg is heap memory the guard frees, and
|
|
212
|
+
mark marks the VALUEs it holds. ca_attach_window_yielding is
|
|
213
|
+
ca_attach_window with such a guard; owners keeps the arrays alive. */
|
|
214
|
+
VALUE ca_window_guard_arm (void (*cleanup)(void *), void (*mark)(void *),
|
|
215
|
+
void *arg, VALUE *sentinel);
|
|
216
|
+
void ca_window_guard_disarm (VALUE guard, VALUE sentinel);
|
|
217
|
+
VALUE ca_attach_window_yielding (VALUE owners, int32_t n, CArray **list,
|
|
218
|
+
const char *modes, VALUE (*body)(VALUE),
|
|
219
|
+
VALUE arg);
|
|
220
|
+
|
|
194
221
|
/* ---- Filling a result Ruby does not own yet (carray_copy.c) ---------------
|
|
195
222
|
|
|
196
223
|
A C builder that allocates its result with carray_new / ca_template and
|
|
@@ -272,6 +299,8 @@ int ca_shares_root (void *ap, void *aq);
|
|
|
272
299
|
view's shape (carray_mask.c). Installed directly in operation tables. */
|
|
273
300
|
|
|
274
301
|
void ca_view_func_create_mask (void *ap);
|
|
302
|
+
void ca_view_sync_mask_after_parent (void *ap);
|
|
303
|
+
void ca_view_pass_mask_to_parent (void *ap);
|
|
275
304
|
|
|
276
305
|
/* Running count of the present cells of any data type along axis (Qnil:
|
|
277
306
|
the flattened array), read off the mask alone (carray_mask.c). The
|
|
@@ -307,6 +336,21 @@ int ca_lazy_req_is_packed (const ca_lazy_req_t *req, void *view);
|
|
|
307
336
|
void ca_lazy_req_pull (void *operand, const ca_lazy_req_t *req,
|
|
308
337
|
void *buf, int dir);
|
|
309
338
|
boolean8_t *ca_lazy_req_mask (const ca_lazy_req_t *req, int n, CArray **ops);
|
|
339
|
+
|
|
340
|
+
/* Runs eval(node, req, data, dir), the evaluation of a lazy node over the
|
|
341
|
+
cells req names. When the node or one of its operands ops[0..n) is an
|
|
342
|
+
object array, the evaluation calls Ruby on each cell, and a cell holding
|
|
343
|
+
an expression over the node comes back into it: the node, and the nodes
|
|
344
|
+
of its chain in chain[0..nchain), are then recorded as computed over
|
|
345
|
+
(ca_computing_run_nodes), so coming back is refused as cyclic. The
|
|
346
|
+
operands are not recorded: an expression over the same operand that does
|
|
347
|
+
not need the node is no cycle. Otherwise eval runs as it is. */
|
|
348
|
+
typedef void (*ca_lazy_eval_fn) (void *node, const ca_lazy_req_t *req,
|
|
349
|
+
void *data, int dir);
|
|
350
|
+
void ca_lazy_eval_recorded (void *node, int n, CArray **ops,
|
|
351
|
+
int nchain, CArray **chain,
|
|
352
|
+
ca_lazy_eval_fn eval, const ca_lazy_req_t *req,
|
|
353
|
+
void *data, int dir);
|
|
310
354
|
VALUE ca_lazy_settle_scalar (VALUE operand, int was_scalar);
|
|
311
355
|
|
|
312
356
|
/* Non-zero iff the array a view's cells come from -- the parent, or the
|
|
@@ -425,6 +469,27 @@ void ca_check_rank_fits (long ndim, const char *name);
|
|
|
425
469
|
#define CA_FLAG_LENT 2048
|
|
426
470
|
#define CA_FLAG_LENT_VIEWED 4096
|
|
427
471
|
|
|
472
|
+
/* A computation over object arrays. A cell whose value is the array
|
|
473
|
+
itself or a view of it makes the kernel call back into a computation
|
|
474
|
+
over the same cells; entering an array that the same method is already
|
|
475
|
+
computing over, in this thread and fiber, is refused as cyclic, as
|
|
476
|
+
reading such a cell is (ca_test_cyclic_check). ca_computing_run runs
|
|
477
|
+
body(arg) with the object arrays among ops[0..n) recorded
|
|
478
|
+
(rb_exec_recursive, carray_core.c); nothing is written to the arrays. */
|
|
479
|
+
VALUE ca_computing_run (int n, CArray **ops, VALUE (*body)(VALUE), VALUE arg);
|
|
480
|
+
VALUE ca_computing_run_nodes (int n, CArray **ops, VALUE (*body)(VALUE), VALUE arg);
|
|
481
|
+
/* Refuses as cyclic a cell among cells[0..n) that is an array reaching a
|
|
482
|
+
lazy node being evaluated: computing it would come back into the node. */
|
|
483
|
+
void ca_refuse_cells_reaching_evaluation (ca_size_t n, const VALUE *cells);
|
|
484
|
+
|
|
485
|
+
/* Registers a view type whose transfers only move cells between its parents
|
|
486
|
+
and the caller (an index view: CAGrid, CASelect, CAWindow, CAStack, ...),
|
|
487
|
+
calling no Ruby. A transfer through such views down to entities cannot
|
|
488
|
+
come back into an array, and is not recorded (ca_with_cyclic_check). */
|
|
489
|
+
void ca_register_cell_moving_view (int8_t obj_type);
|
|
490
|
+
VALUE ca_iter_ensure_computing (CArray *ca, int32_t n, ca_iter_state *states,
|
|
491
|
+
VALUE (*body)(VALUE), VALUE arg);
|
|
492
|
+
|
|
428
493
|
#define CA_CHECK_DATA_TYPE_GIVEN(data_type) \
|
|
429
494
|
do { \
|
|
430
495
|
int ca_dt_ = (data_type); \
|
|
@@ -696,19 +761,41 @@ CArray *ca_multi_parent_mask (CArray *p, CArray **standin);
|
|
|
696
761
|
void ca_multi_parent_mask_refresh (CArray *mask, CArray **parents,
|
|
697
762
|
CArray **standins, int32_t n);
|
|
698
763
|
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
764
|
+
void ca_multi_parent_check_part (CArray *part, const char *name);
|
|
765
|
+
|
|
766
|
+
/* A write to a stack or meld goes to its parts one after another, and a
|
|
767
|
+
part that converts the value on its way (a writable cast) can refuse it
|
|
768
|
+
after the parts before it were written. ca_multi_parent_value_trial
|
|
769
|
+
gives a stack or meld laid out as `ca` over scratch arrays standing for
|
|
770
|
+
its parts (held by `keep`), to run the write against first, when
|
|
771
|
+
ca_multi_parent_value_needs_trial says such a part is there. */
|
|
772
|
+
int ca_multi_parent_value_needs_trial (CArray *ca);
|
|
773
|
+
CArray *ca_multi_parent_value_trial (CArray *ca, VALUE keep);
|
|
774
|
+
|
|
775
|
+
/* A write through the view `ca` that reaches a stack or meld needing the
|
|
776
|
+
trial, in pieces: ca_multi_parent_value_trial_below gives the stack or
|
|
777
|
+
meld, and ca_multi_parent_value_trial_through runs the write against its
|
|
778
|
+
stand-ins first. */
|
|
779
|
+
CArray *ca_multi_parent_value_trial_below (CArray *ca);
|
|
780
|
+
void ca_multi_parent_value_trial_through (CArray *m, VALUE (*body)(VALUE),
|
|
781
|
+
VALUE arg);
|
|
782
|
+
|
|
783
|
+
#define CA_MULTI_PARENT_VALUE_TRIAL(ap, t, call) \
|
|
784
|
+
do { \
|
|
785
|
+
if ( ca_multi_parent_value_needs_trial((CArray *) (ap)) ) { \
|
|
786
|
+
volatile VALUE keep_ = rb_ary_new(); \
|
|
787
|
+
CArray *t = ca_multi_parent_value_trial((CArray *) (ap), keep_); \
|
|
788
|
+
call; \
|
|
789
|
+
RB_GC_GUARD(keep_); \
|
|
790
|
+
} \
|
|
791
|
+
} while (0)
|
|
792
|
+
int ca_monop_writable_cast_target (CArray *ca, int8_t *target);
|
|
793
|
+
|
|
794
|
+
void ca_multi_parent_mask_adopt (CArray *mask, CArray **parents,
|
|
795
|
+
CArray **standins, int32_t n);
|
|
709
796
|
|
|
710
797
|
/* ca_mask_standin_settle for each part of a multi-parent view's mask
|
|
711
|
-
still reading its stand-in
|
|
798
|
+
still reading its stand-in. */
|
|
712
799
|
void ca_multi_parent_mask_settle (CArray *mask, CArray **parents,
|
|
713
800
|
CArray **standins, int32_t n);
|
|
714
801
|
|
|
@@ -774,7 +861,7 @@ ca_obj_equal (VALUE a, VALUE b)
|
|
|
774
861
|
/* ---- fast paths (carray_core.c) --------------------------------------------
|
|
775
862
|
|
|
776
863
|
A fast path answers what a general path also answers, by a different
|
|
777
|
-
algorithm. Each one tests
|
|
864
|
+
algorithm. Each one tests ca_fast_path(CA_SC_name) alongside its own
|
|
778
865
|
condition, so a development build run with CARRAY_GENERAL_PATH=1 in the
|
|
779
866
|
environment takes the general path everywhere and the test suite
|
|
780
867
|
compares the two. A release build has no switch: the test is the
|
|
@@ -794,13 +881,61 @@ ca_obj_equal (VALUE a, VALUE b)
|
|
|
794
881
|
|
|
795
882
|
---------------------------------------------------------------------------- */
|
|
796
883
|
|
|
884
|
+
/* The number of obj_types carray installs for itself (carray_core.c). */
|
|
885
|
+
extern int ca_obj_num_builtin;
|
|
886
|
+
|
|
887
|
+
/* Each fast path has a name, so that a development build can switch it off
|
|
888
|
+
alone: CARRAY_SHORTCUTS_OFF=stack,stack_outer_k in the environment turns
|
|
889
|
+
off the ones named, CARRAY_GENERAL_PATH=1 all of them. A fast path tests
|
|
890
|
+
ca_fast_path(CA_SC_name) alongside its own condition. The names are in
|
|
891
|
+
ca_shortcut_names (carray_core.c) in this order; the Ruby ones are asked
|
|
892
|
+
through CArray.__fast_paths_enabled__(:name). */
|
|
893
|
+
enum ca_shortcut {
|
|
894
|
+
CA_SC_SHIFT_WHOLE_VIEW,
|
|
895
|
+
CA_SC_STACK,
|
|
896
|
+
CA_SC_STACK_OUTER_K,
|
|
897
|
+
CA_SC_FIBER_FUSED_CONVERSION,
|
|
898
|
+
CA_SC_PER_SLAB_HOIST,
|
|
899
|
+
CA_SC_PROTECT_ONLY_MAY_RAISE,
|
|
900
|
+
CA_SC_STACK_ADDRS_K0,
|
|
901
|
+
CA_SC_STACK_STRIDE_BOX,
|
|
902
|
+
CA_SC_STACK_STRIDE_RELOC,
|
|
903
|
+
CA_SC_STACK_PARENTS_K0,
|
|
904
|
+
CA_SC_STACK_FOLD,
|
|
905
|
+
CA_SC_MELD_STRIDE_BOX,
|
|
906
|
+
CA_SC_MELD_PARENTS_AXIS0,
|
|
907
|
+
CA_SC_MEDIAN_PARTITION,
|
|
908
|
+
CA_SC_PERCENTILE_PARTITION,
|
|
909
|
+
CA_SC_LOOP_INTERCHANGE,
|
|
910
|
+
CA_SC_STACK_LOOP_INTERCHANGE,
|
|
911
|
+
CA_SC_LAZY_STREAMING_REDUCE,
|
|
912
|
+
CA_SC_SHORT_FIBER_REDUCE,
|
|
913
|
+
/* asked from lib/carray */
|
|
914
|
+
CA_SC_MELD_REDUCE,
|
|
915
|
+
CA_SC_SEGMENT_NUNIQUE,
|
|
916
|
+
CA_SC_SEGMENT_SCAN_KERNEL,
|
|
917
|
+
CA_SC_SEGMENT_EDGE_KERNEL,
|
|
918
|
+
CA_SC_SEGMENT_REDUCE_KERNEL,
|
|
919
|
+
CA_SC_SEGMENT_ALL_ANY_KERNEL,
|
|
920
|
+
CA_SC_CATEGORICAL_GROUP_BY_INDEX,
|
|
921
|
+
CA_SC_AXIS_GROUP_COUNT_KERNEL,
|
|
922
|
+
CA_SC_AXIS_GROUP_WHOLE_BLOCK,
|
|
923
|
+
CA_SC_AXIS_GROUP_REDUCE_KERNEL,
|
|
924
|
+
CA_SC_AXIS_GROUP_SCAN_KERNEL,
|
|
925
|
+
CA_SC_WINDOW_FOLD_BY_OFFSET,
|
|
926
|
+
CA_SC_COUNT
|
|
927
|
+
};
|
|
928
|
+
|
|
797
929
|
#ifdef CARRAY_DEV_BUILD
|
|
798
930
|
extern int ca_fast_paths_on;
|
|
799
931
|
extern int ca_iter_transfer_only_on;
|
|
932
|
+
extern unsigned char ca_shortcut_off[CA_SC_COUNT];
|
|
800
933
|
#define ca_fast_paths_enabled() (ca_fast_paths_on)
|
|
934
|
+
#define ca_fast_path(id) (ca_fast_paths_on && ! ca_shortcut_off[id])
|
|
801
935
|
#define ca_iter_by_transfer_only() (ca_iter_transfer_only_on)
|
|
802
936
|
#else
|
|
803
937
|
#define ca_fast_paths_enabled() (1)
|
|
938
|
+
#define ca_fast_path(id) (1)
|
|
804
939
|
#define ca_iter_by_transfer_only() (0)
|
|
805
940
|
#endif
|
|
806
941
|
|