carray 3.0.1 → 3.0.3
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 +824 -0
- data/README.md +5 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +258 -4
- data/ext/ca_axis_group.c +368 -184
- data/ext/ca_binop_dispatch.c +54 -32
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +90 -41
- data/ext/ca_compare.c +8 -2
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +27 -11
- data/ext/ca_kernel_iterator.c +960 -245
- data/ext/ca_kernel_iterator.h +352 -181
- data/ext/ca_monop_dispatch.c +4 -4
- data/ext/ca_monop_dispatch.h +4 -0
- data/ext/ca_obj_array.c +194 -42
- data/ext/ca_obj_bincmp.c +152 -121
- data/ext/ca_obj_binop.c +107 -210
- data/ext/ca_obj_bitarray.c +37 -24
- data/ext/ca_obj_bitfield.c +95 -62
- data/ext/ca_obj_block.c +5 -4
- data/ext/ca_obj_byte_swap.c +40 -40
- data/ext/ca_obj_const_string.c +180 -50
- data/ext/ca_obj_face.c +428 -62
- data/ext/ca_obj_face.h +107 -47
- data/ext/ca_obj_fake.c +21 -50
- data/ext/ca_obj_farray.c +1 -0
- data/ext/ca_obj_field.c +16 -3
- data/ext/ca_obj_fixlen_string.c +39 -26
- data/ext/ca_obj_grid.c +181 -124
- data/ext/ca_obj_meld.c +235 -55
- data/ext/ca_obj_moncmp.c +61 -61
- data/ext/ca_obj_monop.c +125 -107
- data/ext/ca_obj_object.c +551 -233
- data/ext/ca_obj_record.c +51 -16
- data/ext/ca_obj_reduce.c +5 -8
- data/ext/ca_obj_refer.c +117 -33
- data/ext/ca_obj_remap.c +57 -17
- data/ext/ca_obj_repeat.c +21 -5
- data/ext/ca_obj_roll.c +115 -11
- data/ext/ca_obj_select.c +88 -75
- data/ext/ca_obj_select_axis.c +58 -60
- data/ext/ca_obj_shift.c +22 -102
- data/ext/ca_obj_stack.c +223 -123
- data/ext/ca_obj_stride.c +267 -35
- data/ext/ca_obj_string.c +25 -22
- data/ext/ca_obj_tile.c +32 -16
- data/ext/ca_obj_time.c +23 -25
- data/ext/ca_obj_timedelta.c +21 -23
- data/ext/ca_obj_transpose.c +12 -3
- data/ext/ca_obj_triop.c +110 -117
- data/ext/ca_obj_window.c +157 -29
- data/ext/ca_op_ipower.c +25 -13
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_rng_normal.h +42 -0
- data/ext/ca_rng_xoshiro256pp.h +105 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +385 -198
- data/ext/ca_sweep_engine.h +31 -23
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +463 -0
- data/ext/carray.h +90 -28
- data/ext/carray_access.c +487 -231
- data/ext/carray_address_basis.c +731 -0
- data/ext/carray_attribute.c +45 -3
- data/ext/carray_bincount.c +32 -2
- data/ext/carray_broadcast.c +49 -17
- data/ext/carray_call_cfunc.c +667 -511
- data/ext/carray_cast.c +1556 -247
- data/ext/carray_cast_func.rb +34 -21
- data/ext/carray_conversion.c +197 -73
- data/ext/carray_copy.c +84 -38
- data/ext/carray_core.c +591 -119
- data/ext/carray_count.c +148 -96
- data/ext/carray_element.c +18 -27
- data/ext/carray_factorize.c +604 -291
- data/ext/carray_generate.c +76 -40
- data/ext/carray_histogram.c +152 -94
- data/ext/carray_hold.c +2 -1
- data/ext/carray_index_classifier.c +63 -96
- data/ext/carray_internal.h +400 -1
- data/ext/carray_lazy.c +834 -79
- data/ext/carray_loop.c +88 -66
- data/ext/carray_mask.c +705 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +263 -63
- data/ext/carray_memory_view.c +254 -248
- data/ext/carray_operator.c +1093 -363
- data/ext/carray_order.c +133 -69
- data/ext/carray_partition.c +102 -56
- data/ext/carray_random.c +582 -204
- data/ext/carray_scatter.c +308 -65
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +183 -70
- data/ext/carray_sort.c +235 -240
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +99 -21
- data/ext/carray_test.c +167 -64
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_utils.c +363 -98
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +103 -118
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1349 -851
- data/ext/ruby_carray.c +17 -2
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +39 -0
- data/lib/carray/autoload_carray.rb +24 -3
- data/lib/carray/autoload_method_extension.rb +18 -0
- data/lib/carray/axis_group.rb +245 -20
- data/lib/carray/basics.rb +95 -25
- data/lib/carray/bincount_nd.rb +6 -0
- data/lib/carray/block_iterator.rb +200 -54
- data/lib/carray/boolean_reduce.rb +21 -29
- data/lib/carray/categorical.rb +244 -59
- data/lib/carray/categorical_iterator.rb +391 -757
- data/lib/carray/complex.rb +36 -29
- data/lib/carray/conditional.rb +94 -7
- data/lib/carray/const_string.rb +177 -27
- data/lib/carray/construct.rb +40 -0
- data/lib/carray/data_type_extension.rb +3 -0
- data/lib/carray/data_type_limits.rb +91 -0
- data/lib/carray/fixlen_string.rb +1 -1
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +13 -7
- data/lib/carray/frame/csv_parser.rb +590 -76
- data/lib/carray/frame/describe.rb +79 -0
- data/lib/carray/frame/frame.rb +205 -35
- data/lib/carray/frame/group.rb +199 -40
- data/lib/carray/frame/io.rb +452 -60
- data/lib/carray/frame/join.rb +134 -46
- data/lib/carray/frame/records.rb +54 -19
- data/lib/carray/frame/reshape.rb +448 -0
- data/lib/carray/frame/sort.rb +26 -2
- data/lib/carray/frame/verbs.rb +726 -56
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +111 -2
- data/lib/carray/fusion.rb +229 -38
- data/lib/carray/inspect.rb +71 -20
- data/lib/carray/iterator.rb +157 -2
- data/lib/carray/lazy.rb +54 -67
- data/lib/carray/mask_gap_fill.rb +66 -50
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +40 -7
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bincount.rb +2 -2
- data/lib/carray/methods/bit_string.rb +14 -3
- data/lib/carray/methods/composition.rb +16 -10
- data/lib/carray/methods/discovery_along.rb +74 -0
- data/lib/carray/methods/factorize.rb +50 -0
- data/lib/carray/methods/gather_nd.rb +13 -2
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_in.rb +130 -6
- data/lib/carray/methods/join.rb +1 -1
- data/lib/carray/methods/locate_addr.rb +235 -21
- data/lib/carray/methods/mask_duplicates.rb +35 -1
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +22 -1
- data/lib/carray/methods/repeat.rb +91 -0
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +52 -3
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +86 -0
- data/lib/carray/runtime.rb +14 -11
- data/lib/carray/segment_iterator.rb +990 -0
- data/lib/carray/serialize.rb +197 -27
- data/lib/carray/slab_iterator.rb +109 -40
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string_operation_extension.rb +9 -4
- data/lib/carray/struct.rb +142 -51
- data/lib/carray/struct_builder.rb +110 -14
- data/lib/carray/table.rb +2 -2
- data/lib/carray/time.rb +535 -105
- data/lib/carray/window_iterator.rb +259 -82
- data/lib/carray.rb +4 -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_block.rb +2 -7
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +1 -1
- data/yard-stubs/ca_obj_refer.rb +3 -3
- data/yard-stubs/ca_obj_roll.rb +0 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +11 -4
- data/yard-stubs/carray_access.rb +6 -5
- data/yard-stubs/carray_broadcast.rb +2 -2
- data/yard-stubs/carray_cast.rb +78 -43
- data/yard-stubs/carray_conversion.rb +13 -1
- data/yard-stubs/carray_copy.rb +8 -3
- data/yard-stubs/carray_core.rb +3 -83
- data/yard-stubs/carray_count.rb +16 -2
- data/yard-stubs/carray_lazy.rb +210 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +34 -10
- data/yard-stubs/carray_math.rb +1499 -4
- data/yard-stubs/carray_median_percentile.rb +26 -8
- data/yard-stubs/carray_order.rb +43 -82
- data/yard-stubs/carray_scatter.rb +10 -3
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +11 -8
- data/yard-stubs/carray_sort.rb +50 -8
- data/yard-stubs/carray_test.rb +10 -0
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -19
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_build_flags.h +0 -3
- data/ext/carray_config.h +0 -28
- data/ext/carray_kernels_bincmp.c +0 -4446
- data/ext/carray_kernels_binop.c +0 -11001
- data/ext/carray_kernels_init.c +0 -1131
- data/ext/carray_kernels_map.c +0 -3467
- data/ext/carray_kernels_moncmp.c +0 -2097
- data/ext/carray_kernels_monop.c +0 -18313
- data/ext/carray_kernels_reduce_aggregate.c +0 -25837
- data/ext/carray_kernels_reduce_boolean.c +0 -330
- data/ext/carray_kernels_reduce_cumulative.c +0 -14593
- data/ext/carray_kernels_reduce_extreme.c +0 -16948
- data/ext/carray_kernels_reduce_variance.c +0 -3910
- data/ext/carray_kernels_scan.c +0 -3693
- data/ext/carray_kernels_search.c +0 -32138
- data/ext/carray_kernels_sort.c +0 -10626
- data/ext/carray_kernels_triop.c +0 -1392
data/README.md
CHANGED
|
@@ -4,17 +4,16 @@ Ruby/CArray is an extension library for the multi-dimensional array class. It pr
|
|
|
4
4
|
|
|
5
5
|
## Status
|
|
6
6
|
|
|
7
|
-
3.0.x still moves: behavior can change between releases
|
|
7
|
+
3.0.x still moves: behavior can change between releases. 3.1 is the first release meant to be depended on. Until then, treat it as a place to try things out.
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
11
|
* Every array carries a per-element mask for missing values, respected by reductions and statistics
|
|
12
12
|
* Views compose without copying — a write through the outermost view reaches the source data
|
|
13
13
|
* MemoryView protocol on both sides: share buffers with other numerical libraries without copying
|
|
14
|
-
* Kernel-style iteration: run a Ruby block over each sub-array spanning the axes you choose
|
|
15
|
-
* Attach domain meaning (time, angle, quantity with units…) without changing storage — a Face
|
|
16
14
|
* Define your own array class in pure Ruby while keeping the full CArray interface
|
|
17
|
-
*
|
|
15
|
+
* Kernel-style iteration: run a Ruby block over each sub-array spanning the axes you choose
|
|
16
|
+
* Faces: array types for time, strings and categories, with methods of their own on top of everything CArray does
|
|
18
17
|
* Comes with a DataFrame (`CAFrame`) whose columns are plain CArrays, so masks and views keep working on them
|
|
19
18
|
|
|
20
19
|
Each of these is shown, briefly and with a runnable example, in [A tour of the features](docs/FeatureTour.md).
|
|
@@ -129,9 +128,9 @@ Bug reports and feature requests are welcome — please open an issue.
|
|
|
129
128
|
|
|
130
129
|
## Credits
|
|
131
130
|
|
|
132
|
-
|
|
131
|
+
CArray is created and maintained by himotoyoshi.
|
|
133
132
|
|
|
134
|
-
|
|
133
|
+
Versions up to 2.0 were written by the author. For version 3.0, the author provided the design, and most of the implementation was rewritten with AI coding tools; it has been verified primarily through the test suite and practical use.
|
|
135
134
|
|
|
136
135
|
## License
|
|
137
136
|
|
data/carray.gemspec
CHANGED
data/ext/ca_axis_dispatch.c
CHANGED
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
#include "carray.h"
|
|
43
43
|
#include "ca_iter_substrate.h"
|
|
44
44
|
#include "ca_composite_dispatch.h"
|
|
45
|
+
#include "carray_internal.h" /* ca_parent_lends_no_memory */
|
|
45
46
|
|
|
46
47
|
#include <string.h>
|
|
47
48
|
|
|
@@ -339,13 +340,27 @@ ca_axis_dispatch_scatter_cb (ca_size_t off, int oob, ca_size_t n, void *vctx)
|
|
|
339
340
|
/* Callback context for fill_value (broadcast a single value). parent is set
|
|
340
341
|
when the value goes through the parent's own fill_stride instead of a
|
|
341
342
|
buffer this side has attached. */
|
|
343
|
+
/* Same size as the window ca_fill_stride_via_addrs collects into. */
|
|
344
|
+
#define CA_AXIS_FILL_ADDR_WINDOW 1024
|
|
345
|
+
|
|
342
346
|
typedef struct {
|
|
343
347
|
const void *val;
|
|
344
348
|
ca_size_t bytes;
|
|
345
349
|
char *parent_ptr;
|
|
346
350
|
CArray *parent;
|
|
351
|
+
ca_size_t window[CA_AXIS_FILL_ADDR_WINDOW];
|
|
352
|
+
ca_size_t nw;
|
|
347
353
|
} ca_axis_fill_ctx_t;
|
|
348
354
|
|
|
355
|
+
static void
|
|
356
|
+
ca_axis_dispatch_fill_flush (ca_axis_fill_ctx_t *c)
|
|
357
|
+
{
|
|
358
|
+
if ( c->nw ) {
|
|
359
|
+
ca_fill_addrs(c->parent, c->nw, c->window, (void *) c->val);
|
|
360
|
+
c->nw = 0;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
349
364
|
static void
|
|
350
365
|
ca_axis_dispatch_fill_value_cb (ca_size_t off, int oob, ca_size_t n, void *vctx)
|
|
351
366
|
{
|
|
@@ -354,17 +369,125 @@ ca_axis_dispatch_fill_value_cb (ca_size_t off, int oob, ca_size_t n, void *vctx)
|
|
|
354
369
|
if ( c->parent ) {
|
|
355
370
|
/* One slab is one contiguous run of parent cells, which is a region the
|
|
356
371
|
parent can fill for itself -- no borrowed buffer, so nothing outside
|
|
357
|
-
the run is read or written.
|
|
372
|
+
the run is read or written. A run of one cell is not worth a call of
|
|
373
|
+
its own, though: when the innermost selected axis picks individual
|
|
374
|
+
indices every run is one cell, and the same cell count that costs the
|
|
375
|
+
parent eight calls on an outer axis cost it one per cell here. Collect
|
|
376
|
+
those and hand them over as a list. The value is the same for every
|
|
377
|
+
cell and the walk visits each cell once, so batching cannot change
|
|
378
|
+
which cells are written. */
|
|
358
379
|
ca_size_t count = n / c->bytes;
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
380
|
+
if ( count == 1 ) {
|
|
381
|
+
c->window[c->nw++] = off / c->bytes;
|
|
382
|
+
if ( c->nw == CA_AXIS_FILL_ADDR_WINDOW ) {
|
|
383
|
+
ca_axis_dispatch_fill_flush(c);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
ca_size_t step = 1;
|
|
388
|
+
ca_fill_stride(c->parent, off / c->bytes, 1, &count, &step,
|
|
389
|
+
(void *) c->val);
|
|
390
|
+
}
|
|
362
391
|
}
|
|
363
392
|
else {
|
|
364
393
|
ca_axis_dispatch_fill_slab(c->parent_ptr + off, c->val, c->bytes, n);
|
|
365
394
|
}
|
|
366
395
|
}
|
|
367
396
|
|
|
397
|
+
/* Rows whose innermost axis is a step-1 SHIFT axis. View cell i of the row
|
|
398
|
+
reads parent cell start + i, so the cells with 0 <= start + i < size0 form
|
|
399
|
+
one run and go to cb together. The cells before and after it are out of
|
|
400
|
+
range: under FILL / MASK every one of them is (cb gets each side as one
|
|
401
|
+
oob slab), under the other policies each maps to a cell of its own. */
|
|
402
|
+
static void
|
|
403
|
+
ca_axis_dispatch_shift_cell (const ca_axis_desc_t *ax, ca_size_t pstride,
|
|
404
|
+
ca_size_t row_off, ca_size_t i, ca_size_t bytes,
|
|
405
|
+
ca_slab_cb_t cb, void *ctx)
|
|
406
|
+
{
|
|
407
|
+
ca_size_t pi = ca_bounds_normalize_index(ax->policy, ax->size0,
|
|
408
|
+
ax->start + i);
|
|
409
|
+
if ( pi < 0 || pi >= ax->size0 ) {
|
|
410
|
+
cb(row_off, 1, bytes, ctx);
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
cb(row_off + pi * pstride, 0, bytes, ctx);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
static void
|
|
418
|
+
ca_axis_dispatch_for_each_shift_row (ca_axis_desc_t *laxes,
|
|
419
|
+
const ca_size_t *pstrides,
|
|
420
|
+
int8_t lndim,
|
|
421
|
+
ca_size_t bytes,
|
|
422
|
+
ca_size_t total_elements,
|
|
423
|
+
ca_slab_cb_t cb,
|
|
424
|
+
void *ctx)
|
|
425
|
+
{
|
|
426
|
+
int8_t inner = lndim - 1;
|
|
427
|
+
const ca_axis_desc_t *ax = &laxes[inner];
|
|
428
|
+
ca_size_t pstride = pstrides[inner];
|
|
429
|
+
ca_size_t count = ax->count;
|
|
430
|
+
int coalesce = ( ax->policy == CA_BOUNDS_FILL
|
|
431
|
+
|| ax->policy == CA_BOUNDS_MASK );
|
|
432
|
+
ca_op_prefix_axis_t prefix[CA_RANK_MAX];
|
|
433
|
+
ca_size_t idx[CA_RANK_MAX];
|
|
434
|
+
ca_size_t lo, hi, n_rows, r, i;
|
|
435
|
+
int8_t k;
|
|
436
|
+
|
|
437
|
+
/* In-range view cells: lo <= i < hi. */
|
|
438
|
+
lo = -ax->start;
|
|
439
|
+
if ( lo < 0 ) lo = 0;
|
|
440
|
+
if ( lo > count ) lo = count;
|
|
441
|
+
hi = ax->size0 - ax->start;
|
|
442
|
+
if ( hi > count ) hi = count;
|
|
443
|
+
if ( hi < lo ) hi = lo;
|
|
444
|
+
|
|
445
|
+
ca_axis_dispatch_classify_prefix(laxes, pstrides, inner, prefix);
|
|
446
|
+
for ( k = 0; k < inner; k++ ) idx[k] = 0;
|
|
447
|
+
|
|
448
|
+
n_rows = total_elements / count;
|
|
449
|
+
for ( r = 0; r < n_rows; r++ ) {
|
|
450
|
+
int oob;
|
|
451
|
+
ca_size_t row_off = ca_axis_dispatch_prefix_offset(prefix, idx, inner,
|
|
452
|
+
&oob);
|
|
453
|
+
if ( oob ) {
|
|
454
|
+
cb(row_off, 1, count * bytes, ctx);
|
|
455
|
+
}
|
|
456
|
+
else {
|
|
457
|
+
if ( lo > 0 ) {
|
|
458
|
+
if ( coalesce ) {
|
|
459
|
+
cb(row_off, 1, lo * bytes, ctx);
|
|
460
|
+
}
|
|
461
|
+
else {
|
|
462
|
+
for ( i = 0; i < lo; i++ ) {
|
|
463
|
+
ca_axis_dispatch_shift_cell(ax, pstride, row_off, i, bytes,
|
|
464
|
+
cb, ctx);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
if ( hi > lo ) {
|
|
469
|
+
cb(row_off + (ax->start + lo) * pstride, 0, (hi - lo) * bytes, ctx);
|
|
470
|
+
}
|
|
471
|
+
if ( hi < count ) {
|
|
472
|
+
if ( coalesce ) {
|
|
473
|
+
cb(row_off, 1, (count - hi) * bytes, ctx);
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
for ( i = hi; i < count; i++ ) {
|
|
477
|
+
ca_axis_dispatch_shift_cell(ax, pstride, row_off, i, bytes,
|
|
478
|
+
cb, ctx);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
for ( k = inner - 1; k >= 0; k-- ) {
|
|
485
|
+
if ( ++idx[k] < prefix[k].count ) break;
|
|
486
|
+
idx[k] = 0;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
368
491
|
/* Generic per-slab driver. Walks the (post-merge / post-layout)
|
|
369
492
|
prefix axes row-major and invokes `cb` once per slab iteration.
|
|
370
493
|
The all-slab case degenerates to a single `cb` invocation with
|
|
@@ -409,6 +532,17 @@ ca_axis_dispatch_for_each_slab (CArray *parent,
|
|
|
409
532
|
return;
|
|
410
533
|
}
|
|
411
534
|
|
|
535
|
+
/* Innermost SHIFT axis with step 1: the in-range part of each row is one
|
|
536
|
+
contiguous run of parent cells, so it goes to cb as one slab instead of
|
|
537
|
+
one cell at a time. */
|
|
538
|
+
if ( slab_start == lndim
|
|
539
|
+
&& laxes[lndim - 1].kind == CA_AXIS_KIND_SHIFT
|
|
540
|
+
&& laxes[lndim - 1].step == 1 ) {
|
|
541
|
+
ca_axis_dispatch_for_each_shift_row(laxes, pstrides, lndim, bytes,
|
|
542
|
+
total_elements, cb, ctx);
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
|
|
412
546
|
/* Pre-classify prefix axes once. Inner loop becomes branchless
|
|
413
547
|
modulo a per-axis kind tag whose value is constant across
|
|
414
548
|
iters. */
|
|
@@ -895,6 +1029,7 @@ ca_axis_dispatch_fill_value_via_parent (CArray *parent,
|
|
|
895
1029
|
ca_axis_dispatch_for_each_slab(parent, parent_axis_dims, axes, ndim,
|
|
896
1030
|
bytes, total_elements,
|
|
897
1031
|
ca_axis_dispatch_fill_value_cb, &ctx);
|
|
1032
|
+
ca_axis_dispatch_fill_flush(&ctx);
|
|
898
1033
|
}
|
|
899
1034
|
|
|
900
1035
|
/* ==========================================================================
|
|
@@ -922,3 +1057,122 @@ ca_axis_dispatch_outer_has_shift (const ca_axis_desc_t *descs,
|
|
|
922
1057
|
}
|
|
923
1058
|
return 0;
|
|
924
1059
|
}
|
|
1060
|
+
|
|
1061
|
+
/* ==========================================================================
|
|
1062
|
+
Transfers of a descriptor view (CAGrid, CASelect, CASelectAxis, CAWindow)
|
|
1063
|
+
whose parent holds no ptr.
|
|
1064
|
+
|
|
1065
|
+
The engine above walks parent->ptr. A cold parent is handled by what it
|
|
1066
|
+
is:
|
|
1067
|
+
|
|
1068
|
+
- one ca_attach_is_alias accepts already has the memory: borrow it;
|
|
1069
|
+
- one with no memory to lend (ca_parent_lends_no_memory) is asked for
|
|
1070
|
+
the selected cells only, through the view's own xfer_stride over the
|
|
1071
|
+
whole view -- producing every cell of the parent to serve a selection
|
|
1072
|
+
would make the cost follow the parent's size;
|
|
1073
|
+
- anything else is gathered into a parent-shaped scratch that stands in
|
|
1074
|
+
for parent->ptr, and pushed back for PUT.
|
|
1075
|
+
========================================================================== */
|
|
1076
|
+
|
|
1077
|
+
/* The whole view as one region request to its own xfer_stride slot. */
|
|
1078
|
+
static void
|
|
1079
|
+
ca_axis_view_xfer_region (CArray *ca, void *data, int dir)
|
|
1080
|
+
{
|
|
1081
|
+
ca_size_t starts[CA_RANK_MAX], strides[CA_RANK_MAX], s;
|
|
1082
|
+
int8_t k;
|
|
1083
|
+
|
|
1084
|
+
/* The slot is called directly, past ca_xfer_stride's empty-region check. */
|
|
1085
|
+
if ( ca->elements == 0 ) return;
|
|
1086
|
+
|
|
1087
|
+
s = ca->bytes;
|
|
1088
|
+
for ( k = ca->ndim - 1; k >= 0; k-- ) {
|
|
1089
|
+
starts[k] = 0;
|
|
1090
|
+
strides[k] = s;
|
|
1091
|
+
s *= ca->dim[k];
|
|
1092
|
+
}
|
|
1093
|
+
ca_func[ca->obj_type].xfer_stride(ca, starts, ca->dim, strides, data, dir);
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
void
|
|
1097
|
+
ca_axis_view_xfer_all (void *ap, ca_axis_view_fast_t fast, int region_ok,
|
|
1098
|
+
void *data, int dir)
|
|
1099
|
+
{
|
|
1100
|
+
CArray *ca = (CArray *) ap;
|
|
1101
|
+
CArray *parent = ((CAView *) ca)->parent;
|
|
1102
|
+
|
|
1103
|
+
if ( parent->ptr ) {
|
|
1104
|
+
fast(ca, (char *) data, dir);
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
if ( ca_attach_is_alias(parent) ) {
|
|
1109
|
+
ca_attach(parent); /* window: an alias attach, cannot raise */
|
|
1110
|
+
fast(ca, (char *) data, dir);
|
|
1111
|
+
ca_detach(parent);
|
|
1112
|
+
return;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
if ( region_ok && ca_parent_lends_no_memory(parent) ) {
|
|
1116
|
+
ca_axis_view_xfer_region(ca, data, dir);
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
{
|
|
1121
|
+
volatile VALUE holder;
|
|
1122
|
+
ca_size_t plen = parent->elements * parent->bytes;
|
|
1123
|
+
char *parent_scratch = ALLOCV_N(char, holder, plen);
|
|
1124
|
+
ca_xfer_all(parent, parent_scratch, CA_XFER_GET);
|
|
1125
|
+
parent->ptr = parent_scratch;
|
|
1126
|
+
fast(ca, (char *) data, dir);
|
|
1127
|
+
/* Put parent->ptr back before the PUT: the PUT can raise (a lazy
|
|
1128
|
+
backing's sync failing), and the scratch is gone once this frame
|
|
1129
|
+
is. */
|
|
1130
|
+
parent->ptr = NULL;
|
|
1131
|
+
if ( dir == CA_XFER_PUT ) {
|
|
1132
|
+
ca_xfer_all(parent, parent_scratch, CA_XFER_PUT);
|
|
1133
|
+
}
|
|
1134
|
+
ALLOCV_END(holder);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
/* The attach of a view that owns its buffer and fills it through its own
|
|
1139
|
+
transfers (a descriptor view whose parent has no memory to lend, CARemap,
|
|
1140
|
+
CAStack, CAMeld). The buffer is published only once filled -- a view
|
|
1141
|
+
with a live ptr makes the per-cell dispatchers bypass the transfer slots,
|
|
1142
|
+
and for CA_OBJECT the garbage cells of an unfilled buffer would be marked
|
|
1143
|
+
-- and a raise while filling frees it. The fill goes through ca_xfer_all,
|
|
1144
|
+
which holds the object cells against a collection while the transfers
|
|
1145
|
+
call Ruby. */
|
|
1146
|
+
|
|
1147
|
+
static VALUE
|
|
1148
|
+
ca_axis_view_fill_owned (VALUE arg)
|
|
1149
|
+
{
|
|
1150
|
+
void **args = (void **) arg;
|
|
1151
|
+
ca_xfer_all((CArray *) args[0], args[1], CA_XFER_GET);
|
|
1152
|
+
return Qnil;
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
void
|
|
1156
|
+
ca_axis_view_attach_owned (void *ap)
|
|
1157
|
+
{
|
|
1158
|
+
CArray *ca = (CArray *) ap;
|
|
1159
|
+
char *buf = xmalloc(ca_length(ca) > 0 ? ca_length(ca) : 1);
|
|
1160
|
+
void *args[2];
|
|
1161
|
+
int tag = 0;
|
|
1162
|
+
|
|
1163
|
+
args[0] = ca;
|
|
1164
|
+
args[1] = buf;
|
|
1165
|
+
rb_protect(ca_axis_view_fill_owned, (VALUE) args, &tag);
|
|
1166
|
+
if ( tag ) {
|
|
1167
|
+
xfree(buf);
|
|
1168
|
+
rb_jump_tag(tag);
|
|
1169
|
+
}
|
|
1170
|
+
ca->ptr = buf;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
void
|
|
1174
|
+
ca_axis_view_sync_owned (void *ap)
|
|
1175
|
+
{
|
|
1176
|
+
CArray *ca = (CArray *) ap;
|
|
1177
|
+
ca_func[ca->obj_type].xfer_all(ca, ca->ptr, CA_XFER_PUT);
|
|
1178
|
+
}
|