carray 3.0.6 → 3.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +110 -0
- data/README.md +24 -3
- data/carray.gemspec +1 -1
- data/ext/ca_axis_group.c +6 -6
- data/ext/ca_binop_dispatch.c +8 -0
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +7 -7
- data/ext/ca_kernel_iterator.h +6 -4
- data/ext/ca_obj_array.c +4 -4
- data/ext/ca_obj_bincmp.c +19 -3
- data/ext/ca_obj_binop.c +36 -11
- data/ext/ca_obj_bitarray.c +2 -4
- data/ext/ca_obj_bitfield.c +86 -4
- data/ext/ca_obj_byte_swap.c +2 -4
- data/ext/ca_obj_const_string.c +422 -257
- data/ext/ca_obj_face.c +71 -33
- data/ext/ca_obj_fake.c +112 -13
- data/ext/ca_obj_farray.c +7 -1
- data/ext/ca_obj_fixlen_string.c +51 -17
- data/ext/ca_obj_grid.c +12 -7
- data/ext/ca_obj_meld.c +5 -5
- data/ext/ca_obj_monop.c +65 -39
- data/ext/ca_obj_object.c +9 -9
- data/ext/ca_obj_reduce.c +2 -4
- data/ext/ca_obj_refer.c +104 -10
- data/ext/ca_obj_repeat.c +1 -1
- data/ext/ca_obj_roll.c +2 -4
- data/ext/ca_obj_select.c +8 -6
- data/ext/ca_obj_select_axis.c +8 -6
- data/ext/ca_obj_stack.c +5 -5
- data/ext/ca_obj_stride.c +46 -8
- data/ext/ca_obj_string.c +2 -2
- data/ext/ca_obj_tile.c +2 -4
- data/ext/ca_obj_triop.c +15 -12
- data/ext/ca_obj_window.c +22 -15
- data/ext/ca_op_ipower.c +63 -15
- data/ext/ca_op_powi.h +6 -29
- data/ext/ca_sort_kernels.h +3 -0
- data/ext/ca_sweep_engine.c +90 -23
- data/ext/ca_sweep_engine.h +5 -6
- data/ext/caframe_csv_reader.c +1 -1
- data/ext/carray.h +3 -1
- data/ext/carray_access.c +98 -39
- data/ext/carray_address_basis.c +98 -24
- data/ext/carray_broadcast.c +2 -2
- data/ext/carray_call_cfunc.c +5 -8
- data/ext/carray_cast.c +311 -37
- data/ext/carray_cast_func.rb +37 -5
- data/ext/carray_conversion.c +56 -2
- data/ext/carray_copy.c +24 -0
- data/ext/carray_core.c +69 -6
- data/ext/carray_count.c +28 -9
- data/ext/carray_element.c +9 -3
- data/ext/carray_factorize.c +11 -11
- data/ext/carray_histogram.c +2 -2
- data/ext/carray_index_classifier.c +7 -5
- data/ext/carray_internal.h +94 -0
- data/ext/carray_kernels_binop.c +55 -55
- data/ext/carray_kernels_init.c +14 -14
- data/ext/carray_kernels_monop.c +90 -140
- data/ext/carray_lazy.c +16 -1
- data/ext/carray_loop.c +9 -2
- data/ext/carray_mask.c +118 -11
- data/ext/carray_median_percentile.c +13 -8
- data/ext/carray_memory_view.c +41 -22
- data/ext/carray_operator.c +72 -11
- data/ext/carray_order.c +52 -9
- data/ext/carray_partition.c +1 -1
- data/ext/carray_random.c +1 -1
- data/ext/carray_round.c +24 -1
- data/ext/carray_scatter.c +4 -0
- data/ext/carray_segment.c +1 -1
- data/ext/carray_slab.c +13 -4
- data/ext/carray_sort.c +6 -3
- data/ext/carray_sort_kernel.c +24 -0
- data/ext/carray_struct.c +21 -6
- data/ext/carray_test.c +85 -39
- data/ext/carray_time_text.c +6 -0
- data/ext/carray_utils.c +124 -54
- data/ext/mk_call_cfunc.rb +6 -11
- data/ext/mkkernel.rb +37 -27
- data/ext/version.h +4 -4
- data/lib/carray/axis_group.rb +9 -6
- data/lib/carray/basics.rb +26 -8
- data/lib/carray/bincount_nd.rb +8 -2
- data/lib/carray/block_iterator.rb +48 -21
- data/lib/carray/categorical.rb +21 -8
- data/lib/carray/categorical_iterator.rb +2 -1
- data/lib/carray/conditional.rb +52 -4
- data/lib/carray/const_string.rb +74 -0
- data/lib/carray/construct.rb +2 -2
- data/lib/carray/core_extensions.rb +19 -68
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/fixlen_string.rb +83 -1
- data/lib/carray/frame/column_verbs.rb +61 -6
- data/lib/carray/frame/concat.rb +50 -6
- data/lib/carray/frame/csv_parser.rb +13 -4
- data/lib/carray/frame/frame.rb +38 -6
- data/lib/carray/frame/group.rb +67 -40
- data/lib/carray/frame/io.rb +10 -5
- data/lib/carray/frame/join.rb +20 -6
- data/lib/carray/frame/records.rb +6 -4
- data/lib/carray/frame/reshape.rb +25 -5
- data/lib/carray/frame/verbs.rb +78 -25
- data/lib/carray/frame/windows.rb +30 -6
- data/lib/carray/fuse_source.rb +4 -2
- data/lib/carray/iterator.rb +8 -0
- data/lib/carray/key_windows.rb +10 -4
- data/lib/carray/lazy.rb +12 -17
- data/lib/carray/methods/bin.rb +3 -0
- data/lib/carray/methods/composition.rb +1 -1
- data/lib/carray/methods/factorize.rb +2 -0
- data/lib/carray/methods/gather_nd.rb +4 -1
- data/lib/carray/methods/is_in.rb +23 -3
- data/lib/carray/methods/locate_addr.rb +63 -12
- data/lib/carray/methods/repeat.rb +11 -1
- data/lib/carray/record_order.rb +35 -6
- data/lib/carray/runtime.rb +10 -0
- data/lib/carray/segment_iterator.rb +19 -16
- data/lib/carray/serialize.rb +22 -0
- data/lib/carray/slab_iterator.rb +1 -1
- data/lib/carray/stack.rb +3 -3
- data/lib/carray/string.rb +6 -6
- data/lib/carray/string_operation_extension.rb +25 -4
- data/lib/carray/struct_builder.rb +4 -1
- data/lib/carray/time.rb +190 -46
- data/lib/carray/window_iterator.rb +48 -12
- data/yard-stubs/ca_obj_bitfield.rb +4 -1
- data/yard-stubs/ca_obj_refer.rb +3 -0
- data/yard-stubs/ca_obj_window.rb +2 -1
- data/yard-stubs/carray_access.rb +4 -2
- data/yard-stubs/carray_cast.rb +6 -0
- data/yard-stubs/carray_count.rb +6 -3
- data/yard-stubs/carray_math.rb +5 -0
- data/yard-stubs/carray_order.rb +6 -0
- data/yard-stubs/carray_scatter.rb +2 -1
- data/yard-stubs/carray_test.rb +18 -5
- metadata +2 -2
data/ext/ca_obj_stack.c
CHANGED
|
@@ -854,8 +854,8 @@ ca_stack_func_allocate (void *ap)
|
|
|
854
854
|
{
|
|
855
855
|
CAStack *ca = (CAStack *) ap;
|
|
856
856
|
ca_stack_mask_refresh(ca);
|
|
857
|
-
|
|
858
|
-
|
|
857
|
+
ca->ptr = ca_alloc_cells_then_attach((CArray *) ca, ca->n_parents,
|
|
858
|
+
ca->parents);
|
|
859
859
|
}
|
|
860
860
|
|
|
861
861
|
static VALUE
|
|
@@ -1408,7 +1408,7 @@ rb_ca_stack_new_with_axis (VALUE parents_ary, int8_t k_axis)
|
|
|
1408
1408
|
}
|
|
1409
1409
|
parents = ALLOCV_N(CArray *, holder, n);
|
|
1410
1410
|
for ( i = 0; i < n; i++ ) {
|
|
1411
|
-
VALUE p = rb_ary_entry(parents_ary, i);
|
|
1411
|
+
volatile VALUE p = rb_ary_entry(parents_ary, i);
|
|
1412
1412
|
rb_check_carray_object(p);
|
|
1413
1413
|
TypedData_Get_Struct(p, CArray, &carray_data_type, parents[i]);
|
|
1414
1414
|
ca_multi_parent_check_part(parents[i], "stack");
|
|
@@ -1485,7 +1485,7 @@ rb_ca_stack_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1485
1485
|
/* Resolve k_axis against the first parent's ndim (= insertion position
|
|
1486
1486
|
range [0, parent_ndim], i.e. half-open [0, parent_ndim + 1)). */
|
|
1487
1487
|
CArray *ref;
|
|
1488
|
-
VALUE first = rb_ary_entry(list, 0);
|
|
1488
|
+
volatile VALUE first = rb_ary_entry(list, 0);
|
|
1489
1489
|
rb_check_carray_object(first);
|
|
1490
1490
|
TypedData_Get_Struct(first, CArray, &carray_data_type, ref);
|
|
1491
1491
|
k_axis = (int8_t) ca_normalize_axis_arg(
|
|
@@ -1495,7 +1495,7 @@ rb_ca_stack_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1495
1495
|
ca_check_uninitialized(ca);
|
|
1496
1496
|
parents = ALLOCV_N(CArray *, holder, n);
|
|
1497
1497
|
for ( i = 0; i < n; i++ ) {
|
|
1498
|
-
VALUE p = rb_ary_entry(list, i);
|
|
1498
|
+
volatile VALUE p = rb_ary_entry(list, i);
|
|
1499
1499
|
rb_check_carray_object(p);
|
|
1500
1500
|
TypedData_Get_Struct(p, CArray, &carray_data_type, parents[i]);
|
|
1501
1501
|
ca_multi_parent_check_part(parents[i], "stack");
|
data/ext/ca_obj_stride.c
CHANGED
|
@@ -1145,7 +1145,10 @@ static int ca_layout_is_contiguous (int8_t ndim, const ca_size_t *dim,
|
|
|
1145
1145
|
Entities hold their own buffer. A CAStride-family root is one the fold
|
|
1146
1146
|
declined to walk through (a reshape over a transpose); its own attach
|
|
1147
1147
|
folds onward from itself, so the answer is the one for the root it folds
|
|
1148
|
-
to
|
|
1148
|
+
to -- unless two of its cells share memory (sliding windows). Its buffer
|
|
1149
|
+
then holds several copies of a cell, and sending the buffer back would
|
|
1150
|
+
let a stale copy overwrite one a view wrote, so it has nothing to lend
|
|
1151
|
+
either. What is left is the
|
|
1149
1152
|
boundary views that compute or fetch their contents -- CAObject, the lazy
|
|
1150
1153
|
per-element transforms, whatever a companion gem installed. All of them
|
|
1151
1154
|
answer a region request: through their xfer_stride slot, or, when a type
|
|
@@ -1153,6 +1156,39 @@ static int ca_layout_is_contiguous (int8_t ndim, const ca_size_t *dim,
|
|
|
1153
1156
|
addresses to xfer_addrs. Attaching one instead would produce all of it
|
|
1154
1157
|
and write all of it back, so a cell nobody touched would go through the
|
|
1155
1158
|
view's conversion both ways. */
|
|
1159
|
+
/* May two cells of this layout land on the same bytes? With the axes in
|
|
1160
|
+
order of stride, none can when each stride clears everything the smaller
|
|
1161
|
+
ones reach. The test is sufficient, not exact: a layout that interleaves
|
|
1162
|
+
its axes answers yes and takes the longer way. */
|
|
1163
|
+
static int
|
|
1164
|
+
ca_layout_cells_may_overlap (int8_t ndim, const ca_size_t *dim,
|
|
1165
|
+
const ca_size_t *strides, ca_size_t bytes)
|
|
1166
|
+
{
|
|
1167
|
+
ca_size_t s[CA_RANK_MAX], d[CA_RANK_MAX];
|
|
1168
|
+
ca_size_t reach = bytes;
|
|
1169
|
+
int n = 0;
|
|
1170
|
+
int8_t k;
|
|
1171
|
+
int i, j;
|
|
1172
|
+
|
|
1173
|
+
for (k = 0; k < ndim; k++) {
|
|
1174
|
+
if ( dim[k] > 1 ) {
|
|
1175
|
+
ca_size_t a = strides[k] < 0 ? -strides[k] : strides[k];
|
|
1176
|
+
for (i = n; i > 0 && s[i-1] > a; i--) {
|
|
1177
|
+
s[i] = s[i-1];
|
|
1178
|
+
d[i] = d[i-1];
|
|
1179
|
+
}
|
|
1180
|
+
s[i] = a;
|
|
1181
|
+
d[i] = dim[k];
|
|
1182
|
+
n++;
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
for (j = 0; j < n; j++) {
|
|
1186
|
+
if ( s[j] < reach ) return 1;
|
|
1187
|
+
reach += s[j] * (d[j] - 1);
|
|
1188
|
+
}
|
|
1189
|
+
return 0;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1156
1192
|
int
|
|
1157
1193
|
ca_root_lends_no_memory (void *ap)
|
|
1158
1194
|
{
|
|
@@ -1168,7 +1204,8 @@ ca_root_lends_no_memory (void *ap)
|
|
|
1168
1204
|
ca_size_t cs[CA_RANK_MAX];
|
|
1169
1205
|
ca_size_t base;
|
|
1170
1206
|
ca_stride_compose_to_root((CAStride *) root, &below, cs, &base);
|
|
1171
|
-
return ca_root_lends_no_memory(below)
|
|
1207
|
+
return ca_root_lends_no_memory(below)
|
|
1208
|
+
|| ca_layout_cells_may_overlap(root->ndim, root->dim, cs, root->bytes);
|
|
1172
1209
|
}
|
|
1173
1210
|
return 1;
|
|
1174
1211
|
}
|
|
@@ -1176,7 +1213,7 @@ ca_root_lends_no_memory (void *ap)
|
|
|
1176
1213
|
/* The same question for the parent of a view that is not itself in the
|
|
1177
1214
|
CAStride family (CAGrid, ...): whether the array its cells come from --
|
|
1178
1215
|
the parent, or the root a CAStride parent folds to -- has no memory to
|
|
1179
|
-
lend. Like ca_root_lends_no_memory it asks only what those arrays are,
|
|
1216
|
+
lend, or the parent has cells that share memory. Like ca_root_lends_no_memory it asks only what those arrays are,
|
|
1180
1217
|
so the lifecycle slots can rely on getting the same answer from attach
|
|
1181
1218
|
to detach. */
|
|
1182
1219
|
int
|
|
@@ -1189,7 +1226,8 @@ ca_parent_lends_no_memory (void *ap)
|
|
|
1189
1226
|
ca_size_t cs[CA_RANK_MAX];
|
|
1190
1227
|
ca_size_t base;
|
|
1191
1228
|
ca_stride_compose_to_root((CAStride *) parent, &root, cs, &base);
|
|
1192
|
-
return ca_root_lends_no_memory(root)
|
|
1229
|
+
return ca_root_lends_no_memory(root)
|
|
1230
|
+
|| ca_layout_cells_may_overlap(parent->ndim, parent->dim, cs, parent->bytes);
|
|
1193
1231
|
}
|
|
1194
1232
|
return ca_root_lends_no_memory(parent);
|
|
1195
1233
|
}
|
|
@@ -1238,11 +1276,11 @@ ca_stride_func_allocate (void *ap)
|
|
|
1238
1276
|
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
1239
1277
|
return;
|
|
1240
1278
|
}
|
|
1241
|
-
ca_attach(root);
|
|
1242
1279
|
if (ca_layout_is_contiguous(ca->ndim, ca->dim, composed_strides, ca->bytes)) {
|
|
1280
|
+
ca_attach(root);
|
|
1243
1281
|
ca->ptr = root->ptr + composed_base;
|
|
1244
1282
|
} else {
|
|
1245
|
-
ca->ptr =
|
|
1283
|
+
ca->ptr = ca_alloc_cells_then_attach((CArray *) ca, 1, &root);
|
|
1246
1284
|
}
|
|
1247
1285
|
}
|
|
1248
1286
|
|
|
@@ -1277,11 +1315,11 @@ ca_stride_func_attach (void *ap)
|
|
|
1277
1315
|
ca->ptr = buf;
|
|
1278
1316
|
return;
|
|
1279
1317
|
}
|
|
1280
|
-
ca_attach(root);
|
|
1281
1318
|
if (ca_layout_is_contiguous(ca->ndim, ca->dim, composed_strides, ca->bytes)) {
|
|
1319
|
+
ca_attach(root);
|
|
1282
1320
|
ca->ptr = root->ptr + composed_base;
|
|
1283
1321
|
} else {
|
|
1284
|
-
ca->ptr =
|
|
1322
|
+
ca->ptr = ca_alloc_cells_then_attach((CArray *) ca, 1, &root);
|
|
1285
1323
|
ca_stride_xfer_with_layout(ca, 0, root->ptr + composed_base, composed_strides);
|
|
1286
1324
|
}
|
|
1287
1325
|
}
|
data/ext/ca_obj_string.c
CHANGED
|
@@ -212,8 +212,8 @@ ca_string_refuse_cell (VALUE v, const char *where)
|
|
|
212
212
|
"UNDEF masks a cell)", where);
|
|
213
213
|
}
|
|
214
214
|
rb_raise(rb_eTypeError,
|
|
215
|
-
"%s is of class %
|
|
216
|
-
"UNDEF masks a cell)", where,
|
|
215
|
+
"%s is of class %"PRIsVALUE", not a String (a CAString holds Strings; "
|
|
216
|
+
"UNDEF masks a cell)", where, rb_obj_class(v));
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
/* Every cell of `parent` that is not masked is a String. Under a masked
|
data/ext/ca_obj_tile.c
CHANGED
|
@@ -422,16 +422,14 @@ static void
|
|
|
422
422
|
ca_tile_func_allocate (void *ap)
|
|
423
423
|
{
|
|
424
424
|
CATile *ca = (CATile *) ap;
|
|
425
|
-
|
|
426
|
-
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
425
|
+
ca->ptr = ca_alloc_cells_then_attach((CArray *) ca, 1, &ca->parent);
|
|
427
426
|
}
|
|
428
427
|
|
|
429
428
|
static void
|
|
430
429
|
ca_tile_func_attach (void *ap)
|
|
431
430
|
{
|
|
432
431
|
CATile *ca = (CATile *) ap;
|
|
433
|
-
|
|
434
|
-
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
432
|
+
ca->ptr = ca_alloc_cells_then_attach((CArray *) ca, 1, &ca->parent);
|
|
435
433
|
ca_tile_attach_into(ca, ca->ptr);
|
|
436
434
|
}
|
|
437
435
|
|
data/ext/ca_obj_triop.c
CHANGED
|
@@ -139,8 +139,8 @@ ca_triop_setup (CATriOp *ca, CArray *op1, CArray *op2, CArray *op3,
|
|
|
139
139
|
ca->op2 = op2;
|
|
140
140
|
ca->op3 = op3;
|
|
141
141
|
ca->op_id = op_id;
|
|
142
|
-
ca->op2_is_scalar = ( op2->elements == 1
|
|
143
|
-
ca->op3_is_scalar = ( op3->elements == 1
|
|
142
|
+
ca->op2_is_scalar = ( op2->elements == 1 ) ? 1 : 0;
|
|
143
|
+
ca->op3_is_scalar = ( op3->elements == 1 ) ? 1 : 0;
|
|
144
144
|
ca->operands[0] = op1;
|
|
145
145
|
ca->operands[1] = op2;
|
|
146
146
|
ca->operands[2] = op3;
|
|
@@ -503,8 +503,9 @@ insert_cast (VALUE cary, int8_t target_dt, CArray **ca_out)
|
|
|
503
503
|
data_type differs from the common data_type, then resolves
|
|
504
504
|
same-ndim size-1 broadcast pairwise against op1 (the walk anchor).
|
|
505
505
|
|
|
506
|
-
Broadcast:
|
|
507
|
-
|
|
506
|
+
Broadcast: the three are aligned pairwise via ca_broadcast_pair
|
|
507
|
+
(op1 / op2 again last, as two of them can meet at a shape smaller than
|
|
508
|
+
the third's). After alignment, op2 / op3 must each have either the
|
|
508
509
|
same elements as op1 or be a 1-element CScalar (walked with
|
|
509
510
|
element_step = 0 by the kernel). If op1 itself is a 1-element
|
|
510
511
|
CScalar and any of op2 / op3 is an array, op1 is lifted via
|
|
@@ -535,17 +536,16 @@ rb_ca_triop_build (VALUE cary1, VALUE cary2, VALUE cary3, uint16_t op_id)
|
|
|
535
536
|
/* Scalar operands (clip's Numeric bounds, a CScalar) are wrapped and
|
|
536
537
|
promoted pairwise in the order the eager triop uses. */
|
|
537
538
|
else if ( ! rb_obj_is_carray(r1) || ! rb_obj_is_carray(r2) || ! rb_obj_is_carray(r3) ||
|
|
538
|
-
rb_obj_is_cscalar(r2) || rb_obj_is_cscalar(r3) ) {
|
|
539
|
+
rb_obj_is_cscalar(r1) || rb_obj_is_cscalar(r2) || rb_obj_is_cscalar(r3) ) {
|
|
539
540
|
if ( ! rb_obj_is_carray(r1) ) {
|
|
540
541
|
rb_raise(rb_eArgError,
|
|
541
542
|
"CATriOp: the first operand must be a CArray");
|
|
542
543
|
}
|
|
544
|
+
int r1_scalar = rb_obj_is_cscalar(r1);
|
|
543
545
|
int r2_scalar = ! rb_obj_is_carray(r2) || rb_obj_is_cscalar(r2);
|
|
544
546
|
int r3_scalar = ! rb_obj_is_carray(r3) || rb_obj_is_cscalar(r3);
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
rb_ca_cast_self_or_other(&r2, &r3);
|
|
548
|
-
rb_ca_cast_self_or_other(&r1, &r2);
|
|
547
|
+
rb_ca_cast_three(&r1, &r2, &r3);
|
|
548
|
+
r1 = ca_lazy_settle_scalar(r1, r1_scalar);
|
|
549
549
|
r2 = ca_lazy_settle_scalar(r2, r2_scalar);
|
|
550
550
|
r3 = ca_lazy_settle_scalar(r3, r3_scalar);
|
|
551
551
|
}
|
|
@@ -609,12 +609,15 @@ rb_ca_triop_build (VALUE cary1, VALUE cary2, VALUE cary3, uint16_t op_id)
|
|
|
609
609
|
}
|
|
610
610
|
}
|
|
611
611
|
|
|
612
|
-
/* Now
|
|
612
|
+
/* Now bring the three to one shape for size-1 broadcast. Every pair is
|
|
613
|
+
aligned, and the first again after the others: op1 and op2 may meet
|
|
614
|
+
at a shape smaller than op3's ([1,4] [1,4] [3,4]). */
|
|
613
615
|
ca_broadcast_pair(&r1, &r2);
|
|
614
|
-
TypedData_Get_Struct(r1, CArray, &carray_data_type, op1);
|
|
615
|
-
TypedData_Get_Struct(r2, CArray, &carray_data_type, op2);
|
|
616
616
|
ca_broadcast_pair(&r1, &r3);
|
|
617
|
+
ca_broadcast_pair(&r2, &r3);
|
|
618
|
+
ca_broadcast_pair(&r1, &r2);
|
|
617
619
|
TypedData_Get_Struct(r1, CArray, &carray_data_type, op1);
|
|
620
|
+
TypedData_Get_Struct(r2, CArray, &carray_data_type, op2);
|
|
618
621
|
TypedData_Get_Struct(r3, CArray, &carray_data_type, op3);
|
|
619
622
|
|
|
620
623
|
/* Step 3: each of op2 / op3 must match op1's element count OR be a
|
data/ext/ca_obj_window.c
CHANGED
|
@@ -275,10 +275,11 @@ static int
|
|
|
275
275
|
ca_window_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
276
276
|
{
|
|
277
277
|
CAWindow *w = (CAWindow *) ap;
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
window
|
|
281
|
-
|
|
278
|
+
/* A mask window never folds. A write folded through to a stand-in would
|
|
279
|
+
bypass the settle in this window's write slots, and answering by what
|
|
280
|
+
the window reads now would change when a write settles: a view attached
|
|
281
|
+
over this window would detach a root it never attached. */
|
|
282
|
+
if ( w->mask_owner ) {
|
|
282
283
|
return 0;
|
|
283
284
|
}
|
|
284
285
|
ca_size_t synth_strides[CA_RANK_MAX];
|
|
@@ -701,7 +702,8 @@ ca_window_setup (CAWindow *ca, CArray *parent,
|
|
|
701
702
|
/* Under "ruby" or "strict" an index outside the parent raises. The
|
|
702
703
|
parent's shape is fixed, so a window that reaches outside it would raise
|
|
703
704
|
on every whole read or write, and a write would have changed the cells
|
|
704
|
-
before the one that raised. It is refused here instead.
|
|
705
|
+
before the one that raised. It is refused here instead. Under
|
|
706
|
+
"nearest" an axis with no cells has no edge to replicate. */
|
|
705
707
|
for (i=0; i<ndim; i++) {
|
|
706
708
|
ca_size_t lo, hi, size = dim[i];
|
|
707
709
|
if ( count[i] == 0 ) {
|
|
@@ -717,6 +719,9 @@ ca_window_setup (CAWindow *ca, CArray *parent,
|
|
|
717
719
|
if ( lo < -size ) ca_index_out_of_range(lo, size, "index");
|
|
718
720
|
if ( hi >= size ) ca_index_out_of_range(hi, size, "index");
|
|
719
721
|
}
|
|
722
|
+
else if ( bounds[i] == CA_BOUNDS_NEAREST && size == 0 ) {
|
|
723
|
+
ca_index_out_of_range(lo, size, "index");
|
|
724
|
+
}
|
|
720
725
|
}
|
|
721
726
|
|
|
722
727
|
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
@@ -1114,12 +1119,12 @@ ca_window_func_allocate (void *ap)
|
|
|
1114
1119
|
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
1115
1120
|
return;
|
|
1116
1121
|
}
|
|
1117
|
-
ca_attach(ca->parent);
|
|
1118
1122
|
if ( ca->embed_alias_eligible ) {
|
|
1123
|
+
ca_attach(ca->parent);
|
|
1119
1124
|
ca->ptr = ca_window_alias_ptr(ca);
|
|
1120
1125
|
return;
|
|
1121
1126
|
}
|
|
1122
|
-
ca->ptr =
|
|
1127
|
+
ca->ptr = ca_alloc_cells_then_attach((CArray *) ca, 1, &ca->parent);
|
|
1123
1128
|
}
|
|
1124
1129
|
|
|
1125
1130
|
/* The engine paths below emit a per-axis descriptor (ca_window_describe_axes)
|
|
@@ -1139,7 +1144,6 @@ ca_window_func_attach (void *ap)
|
|
|
1139
1144
|
ca_axis_view_attach_owned(ca);
|
|
1140
1145
|
return;
|
|
1141
1146
|
}
|
|
1142
|
-
ca_attach(ca->parent);
|
|
1143
1147
|
if ( ca->embed_alias_eligible ) {
|
|
1144
1148
|
/* Alias path: inner axes full + interior, so the embedded region is a
|
|
1145
1149
|
contiguous run of parent storage. Skip malloc/memcpy and point
|
|
@@ -1147,10 +1151,13 @@ ca_window_func_attach (void *ap)
|
|
|
1147
1151
|
CAREFUL: sync and detach must agree with this — sync has nothing to
|
|
1148
1152
|
scatter back (the writes already landed in the parent) and detach must
|
|
1149
1153
|
not xfree a pointer it does not own. */
|
|
1154
|
+
ca_attach(ca->parent);
|
|
1150
1155
|
ca->ptr = ca_window_alias_ptr(ca);
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1156
|
+
return;
|
|
1157
|
+
}
|
|
1158
|
+
ca->ptr = ca_alloc_cells_then_attach((CArray *) ca, 1, &ca->parent);
|
|
1159
|
+
if ( ca->embed_eligible ) {
|
|
1160
|
+
/* Embed path: 1 fill + 1 strided memcpy. */
|
|
1154
1161
|
ca_window_attach_embed(ca, ca->ptr);
|
|
1155
1162
|
} else {
|
|
1156
1163
|
/* Fallback: PERIODIC / REFLECT / NEAREST / RUBY / STRICT go through
|
|
@@ -1158,8 +1165,8 @@ ca_window_func_attach (void *ap)
|
|
|
1158
1165
|
ca_axis_desc_t desc[CA_RANK_MAX];
|
|
1159
1166
|
ca_size_t pdims[CA_RANK_MAX];
|
|
1160
1167
|
ca_window_describe_axes(ca, desc, pdims);
|
|
1161
|
-
|
|
1162
|
-
|
|
1168
|
+
ca_axis_dispatch_gather(ca->parent, pdims, desc, ca->ndim,
|
|
1169
|
+
ca->bytes, ca->elements, ca->fill, ca->ptr);
|
|
1163
1170
|
}
|
|
1164
1171
|
}
|
|
1165
1172
|
|
|
@@ -1700,8 +1707,8 @@ rb_ca_window (int argc, VALUE *argv, VALUE self)
|
|
|
1700
1707
|
}
|
|
1701
1708
|
if ( ! RB_TYPE_P(rbounds, T_STRING) ) {
|
|
1702
1709
|
rb_raise(rb_eTypeError,
|
|
1703
|
-
"window: bounds: must be a Symbol or a String (got %
|
|
1704
|
-
|
|
1710
|
+
"window: bounds: must be a Symbol or a String (got %"PRIsVALUE")",
|
|
1711
|
+
rb_obj_class(rbounds));
|
|
1705
1712
|
}
|
|
1706
1713
|
cbounds = StringValueCStr(rbounds);
|
|
1707
1714
|
if ( ! strcmp(cbounds, "ruby") ) {
|
data/ext/ca_op_ipower.c
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/* ---------------------------------------------------------------------------
|
|
2
2
|
|
|
3
|
-
Float/Complex ** Integer
|
|
4
|
-
|
|
3
|
+
Float/Complex ** Integer: the exponent stays an int64 (no cast of the
|
|
4
|
+
array to a wider type), and each cell is computed exactly as `a ** b`
|
|
5
|
+
computes it when b is an array of that integer: the exponents -2 .. 4
|
|
6
|
+
by at most two multiplications or divisions, the rest by pow / powf /
|
|
7
|
+
cpow.
|
|
5
8
|
|
|
6
9
|
Contents:
|
|
7
10
|
(1) LAZY kernel table `ca_binop_ipower[CA_NTYPE]` — CABinOp dispatch
|
|
@@ -11,14 +14,59 @@
|
|
|
11
14
|
`rb_ca_pow{,_bang}` dispatch between ipower (Float/Complex **
|
|
12
15
|
Integer) and mkkernel-generated `rb_ca_power` (general pow).
|
|
13
16
|
|
|
14
|
-
Both paths share `
|
|
15
|
-
|
|
17
|
+
Both paths share `ca_ipow_<type>` below. The exponent is converted
|
|
18
|
+
the way an int64 cell is converted to the base's type (through double
|
|
19
|
+
for float32 / cmplx64), so the answer is the one the general power
|
|
20
|
+
kernel gives for the same exponent held in an array.
|
|
16
21
|
|
|
17
22
|
---------------------------------------------------------------------------- */
|
|
18
23
|
|
|
19
24
|
#include "carray.h"
|
|
20
25
|
#include "ca_binop_dispatch.h"
|
|
21
|
-
#include
|
|
26
|
+
#include <math.h>
|
|
27
|
+
#include <complex.h>
|
|
28
|
+
|
|
29
|
+
/* The exponents -2 .. 4 take at most two roundings, as in the power
|
|
30
|
+
kernel (MkKernel.pow_short). */
|
|
31
|
+
#define CA_IPOW_SHORT(x, p) do { \
|
|
32
|
+
switch ( p ) { \
|
|
33
|
+
case 2: return (x) * (x); \
|
|
34
|
+
case 3: return (x) * (x) * (x); \
|
|
35
|
+
case 4: return ((x) * (x)) * ((x) * (x)); \
|
|
36
|
+
case 1: return (x); \
|
|
37
|
+
case 0: return 1; \
|
|
38
|
+
case -1: return 1 / (x); \
|
|
39
|
+
case -2: return 1 / ((x) * (x)); \
|
|
40
|
+
} \
|
|
41
|
+
} while (0)
|
|
42
|
+
|
|
43
|
+
static inline float32_t
|
|
44
|
+
ca_ipow_float32_t (float32_t x, int64_t p)
|
|
45
|
+
{
|
|
46
|
+
CA_IPOW_SHORT(x, p);
|
|
47
|
+
return powf(x, (float) (double) p);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static inline float64_t
|
|
51
|
+
ca_ipow_float64_t (float64_t x, int64_t p)
|
|
52
|
+
{
|
|
53
|
+
CA_IPOW_SHORT(x, p);
|
|
54
|
+
return pow(x, (double) p);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static inline cmplx64_t
|
|
58
|
+
ca_ipow_cmplx64_t (cmplx64_t x, int64_t p)
|
|
59
|
+
{
|
|
60
|
+
CA_IPOW_SHORT(x, p);
|
|
61
|
+
return cpow(x, (float) (double) p);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static inline cmplx128_t
|
|
65
|
+
ca_ipow_cmplx128_t (cmplx128_t x, int64_t p)
|
|
66
|
+
{
|
|
67
|
+
CA_IPOW_SHORT(x, p);
|
|
68
|
+
return cpow(x, (double) p);
|
|
69
|
+
}
|
|
22
70
|
|
|
23
71
|
/* Defined in ext/carray_kernels.c (mkkernel-generated general pow /
|
|
24
72
|
cpow binop). Called by rb_ca_pow{,_bang} when the fast path does
|
|
@@ -71,7 +119,7 @@ ca_binop_ipower_##T (ca_size_t n, boolean8_t *m, \
|
|
|
71
119
|
p1 = q1 + k*i1; \
|
|
72
120
|
p2 = q2 + k*i2; \
|
|
73
121
|
p3 = q3 + k*i3; \
|
|
74
|
-
*p3 =
|
|
122
|
+
*p3 = ca_ipow_##T(*p1, *p2); \
|
|
75
123
|
} \
|
|
76
124
|
} \
|
|
77
125
|
} else { \
|
|
@@ -79,7 +127,7 @@ ca_binop_ipower_##T (ca_size_t n, boolean8_t *m, \
|
|
|
79
127
|
p1 = q1 + k*i1; \
|
|
80
128
|
p2 = q2 + k*i2; \
|
|
81
129
|
p3 = q3 + k*i3; \
|
|
82
|
-
*p3 =
|
|
130
|
+
*p3 = ca_ipow_##T(*p1, *p2); \
|
|
83
131
|
} \
|
|
84
132
|
} \
|
|
85
133
|
}
|
|
@@ -115,12 +163,12 @@ ca_ipower_float32_t (ca_size_t n, boolean8_t *m,
|
|
|
115
163
|
ca_u_float32_t *p1 = (ca_u_float32_t *) ptr1, *p2 = (ca_u_float32_t *) ptr2;
|
|
116
164
|
if ( m ) {
|
|
117
165
|
while (n--) {
|
|
118
|
-
if ( ! *m++ ) { *p2 =
|
|
166
|
+
if ( ! *m++ ) { *p2 = ca_ipow_float32_t(*p1, ipow); }
|
|
119
167
|
p1++; p2++;
|
|
120
168
|
}
|
|
121
169
|
}
|
|
122
170
|
else
|
|
123
|
-
while (n--) { (*p2) =
|
|
171
|
+
while (n--) { (*p2) = ca_ipow_float32_t(*p1, ipow); p1++; p2++; }
|
|
124
172
|
}
|
|
125
173
|
|
|
126
174
|
static void
|
|
@@ -130,12 +178,12 @@ ca_ipower_float64_t (ca_size_t n, boolean8_t *m,
|
|
|
130
178
|
ca_u_float64_t *p1 = (ca_u_float64_t *) ptr1, *p2 = (ca_u_float64_t *) ptr2;
|
|
131
179
|
if ( m ) {
|
|
132
180
|
while (n--) {
|
|
133
|
-
if ( ! *m++ ) { *p2 =
|
|
181
|
+
if ( ! *m++ ) { *p2 = ca_ipow_float64_t(*p1, ipow); }
|
|
134
182
|
p1++; p2++;
|
|
135
183
|
}
|
|
136
184
|
}
|
|
137
185
|
else
|
|
138
|
-
while (n--) { (*p2) =
|
|
186
|
+
while (n--) { (*p2) = ca_ipow_float64_t(*p1, ipow); p1++; p2++; }
|
|
139
187
|
}
|
|
140
188
|
|
|
141
189
|
static void
|
|
@@ -145,12 +193,12 @@ ca_ipower_cmplx64_t (ca_size_t n, boolean8_t *m,
|
|
|
145
193
|
ca_u_cmplx64_t *p1 = (ca_u_cmplx64_t *) ptr1, *p2 = (ca_u_cmplx64_t *) ptr2;
|
|
146
194
|
if ( m ) {
|
|
147
195
|
while (n--) {
|
|
148
|
-
if ( ! *m++ ) { *p2 =
|
|
196
|
+
if ( ! *m++ ) { *p2 = ca_ipow_cmplx64_t(*p1, ipow); }
|
|
149
197
|
p1++; p2++;
|
|
150
198
|
}
|
|
151
199
|
}
|
|
152
200
|
else
|
|
153
|
-
while (n--) { (*p2) =
|
|
201
|
+
while (n--) { (*p2) = ca_ipow_cmplx64_t(*p1, ipow); p1++; p2++; }
|
|
154
202
|
}
|
|
155
203
|
|
|
156
204
|
static void
|
|
@@ -160,12 +208,12 @@ ca_ipower_cmplx128_t (ca_size_t n, boolean8_t *m,
|
|
|
160
208
|
ca_u_cmplx128_t *p1 = (ca_u_cmplx128_t *) ptr1, *p2 = (ca_u_cmplx128_t *) ptr2;
|
|
161
209
|
if ( m ) {
|
|
162
210
|
while (n--) {
|
|
163
|
-
if ( ! *m++ ) { *p2 =
|
|
211
|
+
if ( ! *m++ ) { *p2 = ca_ipow_cmplx128_t(*p1, ipow); }
|
|
164
212
|
p1++; p2++;
|
|
165
213
|
}
|
|
166
214
|
}
|
|
167
215
|
else
|
|
168
|
-
while (n--) { (*p2) =
|
|
216
|
+
while (n--) { (*p2) = ca_ipow_cmplx128_t(*p1, ipow); p1++; p2++; }
|
|
169
217
|
}
|
|
170
218
|
|
|
171
219
|
/* The data types the ipower kernels cover; checked before any window
|
data/ext/ca_op_powi.h
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
1
|
/* ---------------------------------------------------------------------------
|
|
2
2
|
|
|
3
|
-
ca_op_powi.h --
|
|
3
|
+
ca_op_powi.h -- `op_powi_<type>`, an integer to an integer power
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
exponentiation (O(log p) vs pow's general path).
|
|
10
|
-
- ext/carray_math.c (hand-written, P.5b.5)
|
|
11
|
-
the `ipower` family (rb_ca_ipower, rb_ca_ipower_bang) uses
|
|
12
|
-
`op_powi_<type>` for the Float**Integer / Complex**Integer
|
|
13
|
-
fast path when invoked via CArray#pow with an Integer rhs.
|
|
14
|
-
|
|
15
|
-
Both files include this header independently; each TU gets its own
|
|
16
|
-
`static inline` copy with no linker conflicts.
|
|
5
|
+
The `power` binop kernel's integer variants (generated from
|
|
6
|
+
ext/mkkernel.rb) call `op_powi_<type>`, binary exponentiation in the
|
|
7
|
+
integer type. A float or complex base goes through pow / cpow
|
|
8
|
+
instead (ext/ca_op_ipower.c for an Integer exponent).
|
|
17
9
|
|
|
18
10
|
--------------------------------------------------------------------------- */
|
|
19
11
|
|
|
@@ -27,7 +19,7 @@
|
|
|
27
19
|
an evaluator that compiles a kernel body calling op_powi_<type>
|
|
28
20
|
(CArray.__kernel_helpers__, written into the build by mkkernel.rb). It
|
|
29
21
|
may use only <stdint.h>, float32_t / float64_t and ca_zerodiv: what such
|
|
30
|
-
an evaluator's C declares.
|
|
22
|
+
an evaluator's C declares. */
|
|
31
23
|
|
|
32
24
|
/* BEGIN kernel helpers */
|
|
33
25
|
|
|
@@ -85,17 +77,6 @@ op_powi_## type (type x, int64_t p) \
|
|
|
85
77
|
return op_powi_mag_## type(x, (uint64_t) p); \
|
|
86
78
|
}
|
|
87
79
|
|
|
88
|
-
#define op_powi_fc(type) \
|
|
89
|
-
op_powi_magnitude(type) \
|
|
90
|
-
static inline type \
|
|
91
|
-
op_powi_## type (type x, int64_t p) \
|
|
92
|
-
{ \
|
|
93
|
-
if ( p < 0 ) { \
|
|
94
|
-
return 1 / op_powi_mag_## type(x, (uint64_t) 0 - (uint64_t) p); \
|
|
95
|
-
} \
|
|
96
|
-
return op_powi_mag_## type(x, (uint64_t) p); \
|
|
97
|
-
}
|
|
98
|
-
|
|
99
80
|
op_powi(int8_t)
|
|
100
81
|
op_powi_u(uint8_t)
|
|
101
82
|
op_powi(int16_t)
|
|
@@ -104,12 +85,8 @@ op_powi(int32_t)
|
|
|
104
85
|
op_powi_u(uint32_t)
|
|
105
86
|
op_powi(int64_t)
|
|
106
87
|
op_powi_u(uint64_t)
|
|
107
|
-
op_powi_fc(float32_t)
|
|
108
|
-
op_powi_fc(float64_t)
|
|
109
88
|
|
|
110
89
|
/* END kernel helpers */
|
|
111
90
|
|
|
112
|
-
op_powi_fc(cmplx64_t)
|
|
113
|
-
op_powi_fc(cmplx128_t)
|
|
114
91
|
|
|
115
92
|
#endif /* CA_OP_POWI_H */
|
data/ext/ca_sort_kernels.h
CHANGED
|
@@ -61,6 +61,9 @@ void ca_sort_merge_f64 (double *a, double *aux, ca_size_t n);
|
|
|
61
61
|
/* P.3: NaN pre-partition for float data types (Hoare 1-pass, returns finite count). */
|
|
62
62
|
ca_size_t ca_partition_nan_f32 (float32_t *a, ca_size_t n);
|
|
63
63
|
ca_size_t ca_partition_nan_f64 (double *a, ca_size_t n);
|
|
64
|
+
/* The same, keeping the order within both regions; scratch holds n values. */
|
|
65
|
+
ca_size_t ca_partition_nan_stable_f32 (float32_t *a, ca_size_t n, float32_t *scratch);
|
|
66
|
+
ca_size_t ca_partition_nan_stable_f64 (double *a, ca_size_t n, double *scratch);
|
|
64
67
|
|
|
65
68
|
/* Pair variant of NaN pre-partition for float argsort kernels. scratch
|
|
66
69
|
holds n pairs; its contents on return are unspecified. */
|