carray 3.0.0 → 3.0.1
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/.yardopts +2 -1
- data/CHANGELOG.md +325 -3
- data/{NEWS.md → CHANGELOG.v1.md} +1 -1
- data/README.md +32 -32
- data/carray.gemspec +12 -8
- data/ext/ca_axis_group.c +55 -19
- data/ext/ca_binop_dispatch.c +5 -6
- data/ext/ca_binop_dispatch.h +0 -7
- data/ext/ca_categorical_iterator.c +13 -13
- data/ext/ca_for_each_element.h +6 -8
- data/ext/ca_group_iter.c +1 -1
- data/ext/ca_kernel_iterator.c +69 -23
- data/ext/ca_kernel_iterator.h +3 -10
- data/ext/ca_obj_bincmp.c +57 -27
- data/ext/ca_obj_binop.c +86 -30
- data/ext/ca_obj_const_string.c +3 -1
- data/ext/ca_obj_face.c +80 -0
- data/ext/ca_obj_face.h +33 -1
- data/ext/ca_obj_fake.c +11 -0
- data/ext/ca_obj_fixlen_string.c +3 -1
- data/ext/ca_obj_grid.c +11 -3
- data/ext/ca_obj_meld.c +13 -8
- data/ext/ca_obj_moncmp.c +33 -14
- data/ext/ca_obj_monop.c +19 -7
- data/ext/ca_obj_object.c +99 -4
- data/ext/ca_obj_record.c +3 -1
- data/ext/ca_obj_refer.c +30 -6
- data/ext/ca_obj_roll.c +13 -5
- data/ext/ca_obj_select_axis.c +16 -6
- data/ext/ca_obj_shift.c +3 -3
- data/ext/ca_obj_stride.c +106 -23
- data/ext/ca_obj_string.c +3 -1
- data/ext/ca_obj_tile.c +13 -5
- data/ext/ca_obj_time.c +3 -1
- data/ext/ca_obj_timedelta.c +3 -1
- data/ext/ca_obj_transpose.c +1 -1
- data/ext/ca_obj_triop.c +62 -23
- data/ext/ca_obj_window.c +86 -17
- data/ext/ca_op_cmplx64.h +123 -0
- data/ext/ca_op_ipower.c +0 -3
- data/ext/ca_sort_kernels.h +5 -5
- data/ext/ca_sweep_engine.c +78 -35
- data/ext/ca_sweep_engine.h +13 -4
- data/ext/ca_transform_common.c +7 -0
- data/ext/carray.h +127 -130
- data/ext/carray_access.c +56 -34
- data/ext/carray_bincount.c +8 -8
- data/ext/carray_broadcast.c +99 -6
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +1491 -0
- data/ext/carray_call_cfunc.h +153 -0
- data/ext/carray_cast.c +69 -31
- data/ext/carray_conversion.c +22 -22
- data/ext/carray_copy.c +12 -2
- data/ext/carray_core.c +57 -10
- data/ext/carray_count.c +1 -1
- data/ext/carray_element.c +7 -7
- data/ext/carray_factorize.c +28 -28
- data/ext/carray_hold.c +1 -1
- data/ext/carray_index_classifier.c +7 -21
- data/ext/carray_internal.h +19 -3
- data/ext/carray_kernels_bincmp.c +1 -0
- data/ext/carray_kernels_binop.c +320 -298
- data/ext/carray_kernels_init.c +1095 -0
- data/ext/carray_kernels_map.c +1 -0
- data/ext/carray_kernels_moncmp.c +1 -0
- data/ext/carray_kernels_monop.c +412 -411
- data/ext/carray_kernels_reduce_aggregate.c +88 -87
- data/ext/carray_kernels_reduce_boolean.c +1 -0
- data/ext/carray_kernels_reduce_cumulative.c +54 -53
- data/ext/carray_kernels_reduce_extreme.c +51 -50
- data/ext/carray_kernels_reduce_variance.c +1 -0
- data/ext/carray_kernels_scan.c +1 -0
- data/ext/carray_kernels_search.c +93 -92
- data/ext/carray_kernels_sort.c +1 -0
- data/ext/carray_kernels_triop.c +1 -0
- data/ext/carray_lazy.c +175 -5
- data/ext/carray_mask.c +6 -5
- data/ext/carray_median_percentile.c +1 -1
- data/ext/carray_memory_view.c +46 -21
- data/ext/carray_operator.c +46 -49
- data/ext/carray_partition.c +4 -4
- data/ext/carray_random.c +7 -7
- data/ext/carray_scatter.c +1 -1
- data/ext/carray_sort.c +3 -3
- data/ext/carray_sort_kernel.c +10 -10
- data/ext/carray_test.c +1 -1
- data/ext/extconf.rb +18 -0
- data/ext/mk_call_cfunc.rb +243 -52
- data/ext/mkkernel.rb +354 -100
- data/ext/ruby_carray.c +18 -16
- data/ext/version.h +4 -4
- data/lib/carray/autoload_carray.rb +19 -0
- data/lib/carray/autoload_method_extension.rb +2 -1
- data/lib/carray/axis_group.rb +7 -7
- data/lib/carray/basics.rb +59 -59
- data/lib/carray/bincount_nd.rb +12 -12
- data/lib/carray/block_iterator.rb +24 -14
- data/lib/carray/categorical.rb +4 -4
- data/lib/carray/categorical_iterator.rb +98 -76
- data/lib/carray/conditional.rb +14 -14
- data/lib/carray/construct.rb +21 -0
- data/lib/carray/core_extensions.rb +62 -5
- data/lib/carray/data_type_extension.rb +18 -1
- data/lib/carray/frame/concat.rb +3 -3
- data/lib/carray/frame/convert.rb +1 -1
- data/lib/carray/frame/frame.rb +4 -11
- data/lib/carray/frame/io.rb +159 -2
- data/lib/carray/frame/sort.rb +1 -1
- data/lib/carray/frame/verbs.rb +18 -1
- data/lib/carray/fuse_source.rb +123 -0
- data/lib/carray/fusion.rb +218 -0
- data/lib/carray/histogram.rb +16 -16
- data/lib/carray/inspect.rb +1 -7
- data/lib/carray/iterator.rb +4 -3
- data/lib/carray/lazy.rb +125 -73
- data/lib/carray/meld_reduce.rb +2 -2
- data/lib/carray/methods/align_addr.rb +1 -1
- data/lib/carray/methods/composition.rb +1 -1
- data/lib/carray/methods/is_in.rb +12 -12
- data/lib/carray/methods/locate_addr.rb +6 -1
- data/lib/carray/methods/mask_duplicates.rb +1 -1
- data/lib/carray/methods/meshgrid.rb +4 -5
- data/lib/carray/methods/mode.rb +2 -2
- data/lib/carray/methods/nunique.rb +1 -1
- data/lib/carray/methods/snap.rb +7 -2
- data/lib/carray/methods/unique.rb +3 -3
- data/lib/carray/methods/value_counts.rb +2 -2
- data/lib/carray/runtime.rb +0 -19
- data/lib/carray/slab_iterator.rb +20 -7
- data/lib/carray/string_operation_extension.rb +5 -5
- data/lib/carray/time.rb +890 -491
- data/lib/carray/window_iterator.rb +285 -13
- data/lib/carray.rb +5 -5
- data/yard-stubs/ca_obj_array.rb +385 -0
- data/yard-stubs/ca_obj_bitarray.rb +38 -0
- data/yard-stubs/ca_obj_bitfield.rb +43 -0
- data/yard-stubs/ca_obj_block.rb +73 -0
- data/yard-stubs/ca_obj_byte_swap.rb +56 -0
- data/yard-stubs/ca_obj_fake.rb +31 -0
- data/yard-stubs/ca_obj_farray.rb +32 -0
- data/yard-stubs/ca_obj_field.rb +45 -0
- data/yard-stubs/ca_obj_grid.rb +35 -0
- data/yard-stubs/ca_obj_refer.rb +72 -0
- data/yard-stubs/ca_obj_roll.rb +45 -0
- data/yard-stubs/ca_obj_shift.rb +43 -0
- data/yard-stubs/ca_obj_stride.rb +181 -0
- data/yard-stubs/ca_obj_tile.rb +29 -0
- data/yard-stubs/ca_obj_transpose.rb +40 -0
- data/yard-stubs/ca_obj_window.rb +49 -0
- data/yard-stubs/carray_access.rb +131 -0
- data/yard-stubs/carray_attribute.rb +246 -0
- data/yard-stubs/carray_broadcast.rb +37 -0
- data/yard-stubs/carray_cast.rb +489 -0
- data/yard-stubs/carray_class.rb +65 -0
- data/yard-stubs/carray_conversion.rb +76 -0
- data/yard-stubs/carray_copy.rb +79 -0
- data/yard-stubs/carray_core.rb +114 -0
- data/yard-stubs/carray_count.rb +79 -0
- data/yard-stubs/carray_element.rb +108 -0
- data/yard-stubs/carray_generate.rb +66 -0
- data/yard-stubs/carray_lazy.rb +23 -0
- data/yard-stubs/carray_loop.rb +140 -0
- data/yard-stubs/carray_mask.rb +259 -0
- data/yard-stubs/carray_math.rb +132 -0
- data/yard-stubs/carray_mathfunc.rb +45 -0
- data/yard-stubs/carray_median_percentile.rb +89 -0
- data/yard-stubs/carray_memory_view.rb +163 -0
- data/yard-stubs/carray_order.rb +312 -0
- data/yard-stubs/carray_random.rb +89 -0
- data/yard-stubs/carray_scatter.rb +106 -0
- data/yard-stubs/carray_slab.rb +57 -0
- data/yard-stubs/carray_sort.rb +163 -0
- data/yard-stubs/carray_test.rb +85 -0
- data/yard-stubs/carray_undef.rb +64 -0
- data/yard-stubs/carray_utils.rb +97 -0
- data/yard-stubs/ruby_carray.rb +193 -0
- metadata +59 -10
- data/ext/ca_obj_unbound_repeat.c +0 -496
data/ext/ca_sweep_engine.c
CHANGED
|
@@ -179,6 +179,7 @@ ca_sweep_acquire_chunked (ca_sweep_state_t *st)
|
|
|
179
179
|
st->attached[k_op] = 0;
|
|
180
180
|
}
|
|
181
181
|
st->m0 = NULL;
|
|
182
|
+
st->mask_scratch = NULL;
|
|
182
183
|
st->n_kernel = 1;
|
|
183
184
|
st->chunk_off = 0;
|
|
184
185
|
st->chunk_n = 0;
|
|
@@ -206,7 +207,7 @@ ca_sweep_acquire_chunked (ca_sweep_state_t *st)
|
|
|
206
207
|
}
|
|
207
208
|
|
|
208
209
|
/* chunk-size policy: inner = donor's product of dims[1..]; chunk_n_max
|
|
209
|
-
* = compute_n on donor->bytes (=
|
|
210
|
+
* = compute_n on donor->bytes (= type-dependent 32KB target). */
|
|
210
211
|
if (shape_donor) {
|
|
211
212
|
st->inner = ca_chunk_inner_size(shape_donor);
|
|
212
213
|
st->chunk_n_max = ca_chunk_compute_n(st->n_kernel, st->inner,
|
|
@@ -243,8 +244,13 @@ ca_sweep_acquire_chunked (ca_sweep_state_t *st)
|
|
|
243
244
|
}
|
|
244
245
|
}
|
|
245
246
|
|
|
246
|
-
/* iter mask = OR of INPUT operand masks (
|
|
247
|
-
*
|
|
247
|
+
/* iter mask = OR of INPUT operand masks, chunk-sized (chunk_n_max bytes)
|
|
248
|
+
* and re-gathered per chunk in ca_sweep_next_chunk. m0 is indexed by the
|
|
249
|
+
* offset within the chunk, m0[k] for k < chunk_n -- NOT by the flat cell
|
|
250
|
+
* index. Sizing it to n_kernel instead would leave one allocation still
|
|
251
|
+
* scaling with the operand, which is the thing this path exists to avoid:
|
|
252
|
+
* at 1 byte per cell it is an eighth of an f64 operand, but an eighth of
|
|
253
|
+
* unbounded is still unbounded. */
|
|
248
254
|
for (k_op = 0; k_op < st->n_ops; k_op++) {
|
|
249
255
|
if (st->fsync[k_op] == '0' && ca_has_mask(st->cx[k_op])) {
|
|
250
256
|
any_input_mask = 1;
|
|
@@ -258,31 +264,69 @@ ca_sweep_acquire_chunked (ca_sweep_state_t *st)
|
|
|
258
264
|
st->src_label ? st->src_label : "ca_sweep_acquire_chunked");
|
|
259
265
|
}
|
|
260
266
|
if (any_input_mask) {
|
|
261
|
-
st->m0
|
|
262
|
-
|
|
267
|
+
st->m0 = (boolean8_t *) ca_lazy_arena_acquire(st->chunk_n_max);
|
|
268
|
+
st->mask_scratch = (boolean8_t *) ca_lazy_arena_acquire(st->chunk_n_max);
|
|
269
|
+
memset(st->m0, 0, st->chunk_n_max);
|
|
270
|
+
/* The OUTPUT masks have to exist before the walk starts, because each
|
|
271
|
+
* chunk's m0 is flushed into them as the walk passes -- there is no
|
|
272
|
+
* whole m0 left at release time to propagate in one go. */
|
|
263
273
|
for (k_op = 0; k_op < st->n_ops; k_op++) {
|
|
264
274
|
CArray *ca = st->cx[k_op];
|
|
265
|
-
if (st->fsync[k_op] != '
|
|
275
|
+
if (st->fsync[k_op] != '1') continue;
|
|
266
276
|
ca_update_mask(ca);
|
|
267
|
-
if (!ca->mask)
|
|
268
|
-
if (ca_is_scalar(ca)) {
|
|
269
|
-
boolean8_t bit = 0;
|
|
270
|
-
ca_xfer_all(ca->mask, &bit, CA_XFER_GET);
|
|
271
|
-
if (bit) memset(st->m0, 1, st->n_kernel);
|
|
272
|
-
} else {
|
|
273
|
-
boolean8_t *ms = (boolean8_t *) ca_lazy_arena_acquire(st->n_kernel);
|
|
274
|
-
ca_size_t j;
|
|
275
|
-
ca_xfer_all(ca->mask, ms, CA_XFER_GET);
|
|
276
|
-
for (j = 0; j < st->n_kernel; j++) st->m0[j] |= ms[j];
|
|
277
|
-
ca_lazy_arena_release(ms);
|
|
278
|
-
}
|
|
277
|
+
if (!ca->mask) ca_create_mask(ca);
|
|
279
278
|
}
|
|
280
279
|
}
|
|
281
280
|
|
|
282
|
-
/* CAREFUL: m0 -> OUTPUT mask propagation
|
|
283
|
-
*
|
|
284
|
-
*
|
|
285
|
-
*
|
|
281
|
+
/* CAREFUL: m0 -> OUTPUT mask propagation happens per chunk, at the point
|
|
282
|
+
* the chunk is finished (= the top of the next ca_sweep_next_chunk, and
|
|
283
|
+
* once more in release), never at acquire. Author per-cell m_out writes
|
|
284
|
+
* land in m0 during the chunk loop and must be captured after that loop
|
|
285
|
+
* has run, not before it. */
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/* OR one INPUT operand's mask for the current chunk into m0. Gathered via
|
|
289
|
+
* ca_chunked_gather rather than attached, so no operand mask is ever
|
|
290
|
+
* attached -- the same invariant the whole-buffer path keeps with
|
|
291
|
+
* ca_xfer_all. */
|
|
292
|
+
static void
|
|
293
|
+
ca_sweep_gather_chunk_mask (ca_sweep_state_t *st, ca_size_t off, ca_size_t n)
|
|
294
|
+
{
|
|
295
|
+
int k_op;
|
|
296
|
+
ca_size_t j;
|
|
297
|
+
|
|
298
|
+
memset(st->m0, 0, n);
|
|
299
|
+
for (k_op = 0; k_op < st->n_ops; k_op++) {
|
|
300
|
+
CArray *ca = st->cx[k_op];
|
|
301
|
+
if (st->fsync[k_op] != '0') continue;
|
|
302
|
+
ca_update_mask(ca);
|
|
303
|
+
if (!ca->mask) continue;
|
|
304
|
+
if (ca_is_scalar(ca)) {
|
|
305
|
+
/* one cell, broadcast across the chunk */
|
|
306
|
+
boolean8_t bit = 0;
|
|
307
|
+
ca_xfer_all(ca->mask, &bit, CA_XFER_GET);
|
|
308
|
+
if (bit) memset(st->m0, 1, n);
|
|
309
|
+
} else {
|
|
310
|
+
ca_chunked_gather(ca->mask, off, n, st->mask_scratch);
|
|
311
|
+
for (j = 0; j < n; j++) st->m0[j] |= st->mask_scratch[j];
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/* Copy the chunk just finished out to every OUTPUT operand's mask. Runs
|
|
317
|
+
* after the author's loop over that chunk, so m_out writes into m0 are
|
|
318
|
+
* carried through. */
|
|
319
|
+
static void
|
|
320
|
+
ca_sweep_flush_chunk_mask (ca_sweep_state_t *st)
|
|
321
|
+
{
|
|
322
|
+
int k_op;
|
|
323
|
+
if (!st->m0 || st->chunked_state != 1 || st->chunk_n == 0) return;
|
|
324
|
+
for (k_op = 0; k_op < st->n_ops; k_op++) {
|
|
325
|
+
CArray *ca = st->cx[k_op];
|
|
326
|
+
if (st->fsync[k_op] != '1') continue;
|
|
327
|
+
if (!ca->mask) continue;
|
|
328
|
+
memcpy((boolean8_t *) ca->mask->ptr + st->chunk_off, st->m0, st->chunk_n);
|
|
329
|
+
}
|
|
286
330
|
}
|
|
287
331
|
|
|
288
332
|
int
|
|
@@ -296,6 +340,8 @@ ca_sweep_next_chunk (ca_sweep_state_t *st)
|
|
|
296
340
|
st->chunk_off = 0;
|
|
297
341
|
st->chunked_state = 1;
|
|
298
342
|
} else {
|
|
343
|
+
/* the chunk that just finished is the author's last word on its mask */
|
|
344
|
+
ca_sweep_flush_chunk_mask(st);
|
|
299
345
|
/* advance */
|
|
300
346
|
st->chunk_off += st->chunk_n;
|
|
301
347
|
}
|
|
@@ -326,6 +372,8 @@ ca_sweep_next_chunk (ca_sweep_state_t *st)
|
|
|
326
372
|
}
|
|
327
373
|
}
|
|
328
374
|
|
|
375
|
+
if (st->m0) ca_sweep_gather_chunk_mask(st, off, n);
|
|
376
|
+
|
|
329
377
|
return 1;
|
|
330
378
|
}
|
|
331
379
|
|
|
@@ -333,19 +381,10 @@ void
|
|
|
333
381
|
ca_sweep_release_chunked (ca_sweep_state_t *st)
|
|
334
382
|
{
|
|
335
383
|
int k_op;
|
|
336
|
-
/*
|
|
337
|
-
*
|
|
338
|
-
* m_out writes
|
|
339
|
-
|
|
340
|
-
if (st->m0) {
|
|
341
|
-
for (k_op = 0; k_op < st->n_ops; k_op++) {
|
|
342
|
-
CArray *ca = st->cx[k_op];
|
|
343
|
-
if (st->fsync[k_op] != '1') continue;
|
|
344
|
-
ca_update_mask(ca);
|
|
345
|
-
if (!ca->mask) ca_create_mask(ca);
|
|
346
|
-
memcpy(ca->mask->ptr, st->m0, st->n_kernel);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
384
|
+
/* The final chunk has no next_chunk call to flush it, so it is flushed
|
|
385
|
+
* here. For INOUT_MASKED forms this is what captures the author's
|
|
386
|
+
* per-cell m_out writes over that last chunk. */
|
|
387
|
+
ca_sweep_flush_chunk_mask(st);
|
|
349
388
|
/* sync OUTPUTs (reverse order, regardless of whether chunk loop ran) */
|
|
350
389
|
for (k_op = st->n_ops - 1; k_op >= 0; k_op--) {
|
|
351
390
|
if (st->fsync[k_op] == '1') ca_sync(st->cx[k_op]);
|
|
@@ -363,6 +402,10 @@ ca_sweep_release_chunked (ca_sweep_state_t *st)
|
|
|
363
402
|
ca_lazy_arena_release(st->m0);
|
|
364
403
|
st->m0 = NULL;
|
|
365
404
|
}
|
|
405
|
+
if (st->mask_scratch) {
|
|
406
|
+
ca_lazy_arena_release(st->mask_scratch);
|
|
407
|
+
st->mask_scratch = NULL;
|
|
408
|
+
}
|
|
366
409
|
}
|
|
367
410
|
|
|
368
411
|
/* ===== WHOLE_BUFFER function form (rb_ensure-protected) ===== */
|
data/ext/ca_sweep_engine.h
CHANGED
|
@@ -85,6 +85,8 @@ typedef struct ca_sweep_state {
|
|
|
85
85
|
ca_size_t inner; /* product of dims except outermost (= row
|
|
86
86
|
size in elements for outer-axis chunking) */
|
|
87
87
|
int chunked_state; /* 0=pre-init, 1=active, 2=done */
|
|
88
|
+
boolean8_t *mask_scratch; /* chunk-sized staging for the per-chunk
|
|
89
|
+
mask OR; NULL when no INPUT is masked */
|
|
88
90
|
} ca_sweep_state_t;
|
|
89
91
|
|
|
90
92
|
/* Validate fsync length, acquire per-op buffers, compute broadcast shape +
|
|
@@ -134,10 +136,17 @@ void ca_sweep_check_same_shape (CArray *ca_in, CArray *ca_out,
|
|
|
134
136
|
* for the entire walk; ca_chunked_gather rewrites it per chunk.
|
|
135
137
|
*
|
|
136
138
|
* Mask handling (m0):
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
139
|
+
* Chunk-sized (= chunk_n_max bytes), re-gathered per chunk in
|
|
140
|
+
* ca_sweep_next_chunk. Read it at m0[k] for k < chunk_n -- it is
|
|
141
|
+
* indexed within the chunk, NOT by the flat cell index. (This differs
|
|
142
|
+
* from the whole-buffer path, where m0 spans n_kernel.)
|
|
143
|
+
*
|
|
144
|
+
* An author may WRITE m0[k] during the chunk loop (= the INOUT_MASKED
|
|
145
|
+
* forms' m_out). Those writes are flushed into the OUTPUT operands'
|
|
146
|
+
* masks when the chunk finishes -- at the top of the following
|
|
147
|
+
* ca_sweep_next_chunk, and once more in ca_sweep_release_chunked for
|
|
148
|
+
* the last chunk -- so the OUTPUT masks are created up front in
|
|
149
|
+
* acquire_chunked rather than propagated in one go at release.
|
|
141
150
|
*/
|
|
142
151
|
void ca_sweep_acquire_chunked (ca_sweep_state_t *st);
|
|
143
152
|
int ca_sweep_next_chunk (ca_sweep_state_t *st); /* 1 = chunk ready, 0 = done */
|
data/ext/ca_transform_common.c
CHANGED
|
@@ -112,6 +112,13 @@ ca_xfer_stride_transform_fused (CArray *view,
|
|
|
112
112
|
composed_strides, &composed_base);
|
|
113
113
|
if ( !root->ptr ) return 0;
|
|
114
114
|
if ( parent->bytes != root->bytes ) return 0;
|
|
115
|
+
/* Per-axis composition below is only meaningful for a request that walks
|
|
116
|
+
our own axes; a transposed / flat request over the view's addresses
|
|
117
|
+
(legal -- see ca_xfer_stride_request_is_axis_box in carray.h) declines
|
|
118
|
+
to the caller's per-cell path. */
|
|
119
|
+
if ( ! ca_xfer_stride_request_is_axis_box(view, starts, counts, strides) ) {
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
115
122
|
|
|
116
123
|
for ( k = 0; k < ndim; k++ ) {
|
|
117
124
|
if ( view_native[k] == 0 ) return 0;
|