carray 3.0.2 → 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 +304 -0
- data/README.md +3 -4
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +225 -0
- data/ext/ca_axis_group.c +177 -99
- data/ext/ca_binop_dispatch.c +54 -32
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +66 -71
- 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 +663 -214
- data/ext/ca_kernel_iterator.h +231 -167
- data/ext/ca_monop_dispatch.c +4 -4
- data/ext/ca_monop_dispatch.h +4 -0
- data/ext/ca_obj_array.c +132 -22
- 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 +1 -0
- data/ext/ca_obj_byte_swap.c +40 -40
- data/ext/ca_obj_const_string.c +96 -25
- data/ext/ca_obj_face.c +406 -64
- data/ext/ca_obj_face.h +92 -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 +21 -21
- data/ext/ca_obj_grid.c +181 -124
- data/ext/ca_obj_meld.c +189 -107
- data/ext/ca_obj_moncmp.c +61 -61
- data/ext/ca_obj_monop.c +125 -107
- data/ext/ca_obj_object.c +543 -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 +47 -49
- data/ext/ca_obj_select_axis.c +58 -60
- data/ext/ca_obj_shift.c +22 -102
- data/ext/ca_obj_stack.c +223 -118
- data/ext/ca_obj_stride.c +195 -34
- data/ext/ca_obj_string.c +17 -18
- 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 +149 -27
- data/ext/ca_op_ipower.c +24 -11
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +102 -79
- data/ext/ca_sweep_engine.h +7 -20
- 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 +70 -27
- data/ext/carray_access.c +455 -211
- data/ext/carray_address_basis.c +177 -36
- data/ext/carray_attribute.c +45 -3
- data/ext/carray_bincount.c +32 -2
- data/ext/carray_broadcast.c +46 -14
- data/ext/carray_call_cfunc.c +0 -28
- data/ext/carray_cast.c +1444 -209
- data/ext/carray_cast_func.rb +34 -21
- data/ext/carray_conversion.c +197 -73
- data/ext/carray_copy.c +32 -11
- data/ext/carray_core.c +514 -122
- data/ext/carray_count.c +140 -87
- data/ext/carray_element.c +18 -27
- data/ext/carray_factorize.c +569 -277
- 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 +385 -3
- data/ext/carray_lazy.c +834 -79
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +682 -316
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +221 -76
- data/ext/carray_memory_view.c +254 -248
- data/ext/carray_operator.c +1089 -359
- data/ext/carray_order.c +133 -69
- data/ext/carray_partition.c +102 -56
- data/ext/carray_random.c +273 -239
- data/ext/carray_scatter.c +308 -65
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +170 -70
- data/ext/carray_sort.c +215 -218
- 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 +0 -2
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1076 -846
- data/ext/ruby_carray.c +7 -1
- 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 +19 -0
- data/lib/carray/autoload_method_extension.rb +6 -0
- data/lib/carray/axis_group.rb +174 -26
- data/lib/carray/basics.rb +91 -25
- data/lib/carray/bincount_nd.rb +6 -0
- data/lib/carray/block_iterator.rb +118 -48
- data/lib/carray/boolean_reduce.rb +21 -29
- data/lib/carray/categorical.rb +94 -26
- data/lib/carray/categorical_iterator.rb +333 -826
- data/lib/carray/complex.rb +36 -29
- data/lib/carray/conditional.rb +94 -7
- data/lib/carray/const_string.rb +46 -0
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +13 -7
- data/lib/carray/frame/csv_parser.rb +589 -82
- data/lib/carray/frame/describe.rb +79 -0
- data/lib/carray/frame/frame.rb +124 -25
- data/lib/carray/frame/group.rb +189 -63
- data/lib/carray/frame/io.rb +412 -72
- data/lib/carray/frame/join.rb +134 -46
- data/lib/carray/frame/records.rb +37 -16
- data/lib/carray/frame/reshape.rb +448 -0
- data/lib/carray/frame/sort.rb +26 -2
- data/lib/carray/frame/verbs.rb +715 -48
- 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 +29 -11
- data/lib/carray/iterator.rb +14 -2
- data/lib/carray/lazy.rb +54 -30
- data/lib/carray/mask_gap_fill.rb +66 -52
- 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/factorize.rb +2 -2
- 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 +117 -4
- data/lib/carray/methods/join.rb +1 -1
- data/lib/carray/methods/locate_addr.rb +177 -36
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/repeat.rb +1 -20
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +11 -2
- data/lib/carray/record_order.rb +208 -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 +51 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string_operation_extension.rb +4 -3
- 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 +517 -103
- data/lib/carray/window_iterator.rb +127 -72
- data/lib/carray.rb +2 -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_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 +1 -2
- data/yard-stubs/carray_access.rb +5 -4
- data/yard-stubs/carray_broadcast.rb +1 -1
- 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 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +34 -10
- data/yard-stubs/carray_math.rb +25 -13
- data/yard-stubs/carray_median_percentile.rb +10 -6
- data/yard-stubs/carray_order.rb +34 -13
- data/yard-stubs/carray_scatter.rb +10 -3
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +2 -1
- data/yard-stubs/carray_sort.rb +43 -3
- data/yard-stubs/carray_test.rb +10 -0
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +11 -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 -26005
- data/ext/carray_kernels_reduce_boolean.c +0 -330
- data/ext/carray_kernels_reduce_cumulative.c +0 -14862
- data/ext/carray_kernels_reduce_extreme.c +0 -17494
- data/ext/carray_kernels_reduce_variance.c +0 -3910
- data/ext/carray_kernels_scan.c +0 -3693
- data/ext/carray_kernels_search.c +0 -32218
- data/ext/carray_kernels_sort.c +0 -10626
- data/ext/carray_kernels_triop.c +0 -1392
data/ext/ca_obj_time.c
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
--------------------------------------------------------------------------- */
|
|
15
15
|
|
|
16
16
|
#include "carray.h"
|
|
17
|
+
#include "carray_internal.h"
|
|
17
18
|
#include "ca_obj_face.h"
|
|
18
19
|
|
|
19
20
|
/* unit enum (base epoch is 1970-01-01) */
|
|
@@ -36,7 +37,7 @@ enum {
|
|
|
36
37
|
typedef struct {
|
|
37
38
|
/* === CAView prefix === */
|
|
38
39
|
int16_t obj_type;
|
|
39
|
-
int8_t data_type; /*
|
|
40
|
+
int8_t data_type; /* surface: CA_FIXLEN (storage is the int64 parent) */
|
|
40
41
|
int8_t ndim;
|
|
41
42
|
int32_t flags; /* CA_FLAG_IS_FACE set */
|
|
42
43
|
ca_size_t bytes; /* fixed to sizeof(int64_t) */
|
|
@@ -182,6 +183,12 @@ ca_time_setup (CATime *ca, CArray *parent, int8_t unit, int64_t count)
|
|
|
182
183
|
"CATime requires int64 storage (parent.data_type != CA_INT64)");
|
|
183
184
|
}
|
|
184
185
|
|
|
186
|
+
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
187
|
+
run them before it allocates. */
|
|
188
|
+
if ( ca == NULL ) {
|
|
189
|
+
return 0;
|
|
190
|
+
}
|
|
191
|
+
|
|
185
192
|
ca->obj_type = CA_OBJ_TIME;
|
|
186
193
|
/* The surface data_type is CA_FIXLEN, not CA_INT64: this routes
|
|
187
194
|
mkkernel dispatch onto the ca_*_not_implement stubs so numeric
|
|
@@ -227,7 +234,9 @@ ca_time_setup (CATime *ca, CArray *parent, int8_t unit, int64_t count)
|
|
|
227
234
|
CATime *
|
|
228
235
|
ca_time_new (CArray *parent, int8_t unit, int64_t count)
|
|
229
236
|
{
|
|
230
|
-
CATime *ca
|
|
237
|
+
CATime *ca;
|
|
238
|
+
ca_time_setup(NULL, parent, unit, count);
|
|
239
|
+
ca = (CATime *) ca_array_alloc(CA_OBJ_TIME, parent->ndim);
|
|
231
240
|
ca_time_setup(ca, parent, unit, count);
|
|
232
241
|
return ca;
|
|
233
242
|
}
|
|
@@ -266,18 +275,6 @@ ca_time_func_allocate (void *ap)
|
|
|
266
275
|
ca->ptr = ca->parent->ptr;
|
|
267
276
|
}
|
|
268
277
|
|
|
269
|
-
static void
|
|
270
|
-
ca_time_func_create_mask (void *ap)
|
|
271
|
-
{
|
|
272
|
-
CATime *ca = (CATime *) ap;
|
|
273
|
-
ca_update_mask(ca->parent);
|
|
274
|
-
if ( ! ca->parent->mask ) {
|
|
275
|
-
ca_create_mask(ca->parent);
|
|
276
|
-
}
|
|
277
|
-
ca->mask = (CArray *) ca_refer_new(ca->parent->mask,
|
|
278
|
-
CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
278
|
ca_operation_function_t ca_time_func = {
|
|
282
279
|
-1, /* CA_OBJ_TIME — filled by ca_install_obj_type */
|
|
283
280
|
CA_VIEW_ARRAY,
|
|
@@ -288,7 +285,7 @@ ca_operation_function_t ca_time_func = {
|
|
|
288
285
|
ca_face_sync,
|
|
289
286
|
ca_face_detach,
|
|
290
287
|
ca_face_fill_data,
|
|
291
|
-
|
|
288
|
+
ca_view_func_create_mask,
|
|
292
289
|
ca_face_xfer_index,
|
|
293
290
|
ca_face_xfer_addrs,
|
|
294
291
|
NULL, /* fold_stride: identity Face is not foldable */
|
|
@@ -422,16 +419,16 @@ rb_ca_time_unit (VALUE self)
|
|
|
422
419
|
return ca_time_resolution(ca->count, ca->unit);
|
|
423
420
|
}
|
|
424
421
|
|
|
425
|
-
/*
|
|
426
|
-
on the fetch hot path. CAREFUL: there must be no Ruby `
|
|
422
|
+
/* storage_to_element implemented in C to avoid per-cell Ruby method dispatch
|
|
423
|
+
on the fetch hot path. CAREFUL: there must be no Ruby `storage_to_element`
|
|
427
424
|
def in lib/carray/time.rb — require order would let a Ruby version
|
|
428
|
-
shadow this C method (the Ruby `
|
|
425
|
+
shadow this C method (the Ruby `element_to_storage` write hook is a
|
|
429
426
|
distinct method and does not collide).
|
|
430
427
|
Since the Face surface is CA_FIXLEN, fetch delivers an 8-byte raw
|
|
431
428
|
String. Decode it as the parent int64 (= storage), then construct
|
|
432
429
|
CATime::Element(epoch, unit). */
|
|
433
430
|
static VALUE
|
|
434
|
-
|
|
431
|
+
rb_ca_time_storage_to_element (VALUE self, VALUE raw)
|
|
435
432
|
{
|
|
436
433
|
CATime *ca;
|
|
437
434
|
CATimeElement *s;
|
|
@@ -443,7 +440,7 @@ rb_ca_time_storage_to_scalar (VALUE self, VALUE raw)
|
|
|
443
440
|
if ( TYPE(raw) == T_STRING ) {
|
|
444
441
|
if ( RSTRING_LEN(raw) != (long) sizeof(int64_t) ) {
|
|
445
442
|
rb_raise(rb_eArgError,
|
|
446
|
-
"CATime#
|
|
443
|
+
"CATime#storage_to_element: expected %lu bytes, got %ld",
|
|
447
444
|
(unsigned long) sizeof(int64_t), RSTRING_LEN(raw));
|
|
448
445
|
}
|
|
449
446
|
memcpy(&epoch, RSTRING_PTR(raw), sizeof(int64_t));
|
|
@@ -476,6 +473,7 @@ rb_ca_time_initialize_copy (VALUE self, VALUE other)
|
|
|
476
473
|
{
|
|
477
474
|
CATime *ca, *cs;
|
|
478
475
|
TypedData_Get_Struct(self, CATime, &catime_data_type, ca);
|
|
476
|
+
ca_check_uninitialized(ca);
|
|
479
477
|
TypedData_Get_Struct(other, CATime, &catime_data_type, cs);
|
|
480
478
|
if ( ca_func[CA_OBJ_TIME].pool_init ) {
|
|
481
479
|
ca_array_pool_alloc(ca, CA_OBJ_TIME, cs->parent->ndim);
|
|
@@ -517,12 +515,12 @@ Init_ca_obj_time (void)
|
|
|
517
515
|
rb_define_singleton_method(rb_cCATime, "__wrap__",
|
|
518
516
|
rb_ca_time_wrap_method, 2);
|
|
519
517
|
rb_define_method(rb_cCATime, "unit", rb_ca_time_unit, 0);
|
|
520
|
-
rb_define_method(rb_cCATime, "
|
|
521
|
-
|
|
522
|
-
/* Registers the C-level fast path so
|
|
518
|
+
rb_define_method(rb_cCATime, "storage_to_element",
|
|
519
|
+
rb_ca_time_storage_to_element, 1);
|
|
520
|
+
/* Registers the C-level fast path so CA_FACE_STORAGE_TO_ELEMENT_IF_FACE can
|
|
523
521
|
skip rb_funcall on the hot path. */
|
|
524
|
-
|
|
525
|
-
|
|
522
|
+
ca_face_register_storage_to_element(CA_OBJ_TIME,
|
|
523
|
+
rb_ca_time_storage_to_element);
|
|
526
524
|
ca_face_register_state_compatible(CA_OBJ_TIME,
|
|
527
525
|
ca_time_state_compatible);
|
|
528
526
|
/* unit is pure metadata (= no per-parent buffer), so the Face wrap can
|
data/ext/ca_obj_timedelta.c
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
--------------------------------------------------------------------------- */
|
|
15
15
|
|
|
16
16
|
#include "carray.h"
|
|
17
|
+
#include "carray_internal.h"
|
|
17
18
|
#include "ca_obj_face.h"
|
|
18
19
|
|
|
19
20
|
/* The unit enum is shared with CATime (= same unit system).
|
|
@@ -26,7 +27,7 @@ extern void ca_time_extract_unit (VALUE unit, int8_t *base, int64_t *count);
|
|
|
26
27
|
typedef struct {
|
|
27
28
|
/* === CAView prefix === */
|
|
28
29
|
int16_t obj_type;
|
|
29
|
-
int8_t data_type; /*
|
|
30
|
+
int8_t data_type; /* surface: CA_FIXLEN (storage is the int64 parent) */
|
|
30
31
|
int8_t ndim;
|
|
31
32
|
int32_t flags; /* CA_FLAG_IS_FACE set */
|
|
32
33
|
ca_size_t bytes; /* fixed to sizeof(int64_t) */
|
|
@@ -161,6 +162,12 @@ ca_timedelta_setup (CATimedelta *ca, CArray *parent, int8_t unit, int64_t count)
|
|
|
161
162
|
"CATimedelta requires int64 storage (parent.data_type != CA_INT64)");
|
|
162
163
|
}
|
|
163
164
|
|
|
165
|
+
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
166
|
+
run them before it allocates. */
|
|
167
|
+
if ( ca == NULL ) {
|
|
168
|
+
return 0;
|
|
169
|
+
}
|
|
170
|
+
|
|
164
171
|
ca->obj_type = CA_OBJ_TIMEDELTA;
|
|
165
172
|
/* NonNumeric surface (the FIXLEN gate), like CATime: the storage is a
|
|
166
173
|
count of `count x unit` ticks, and letting the numeric kernels read it
|
|
@@ -208,7 +215,9 @@ ca_timedelta_setup (CATimedelta *ca, CArray *parent, int8_t unit, int64_t count)
|
|
|
208
215
|
CATimedelta *
|
|
209
216
|
ca_timedelta_new (CArray *parent, int8_t unit, int64_t count)
|
|
210
217
|
{
|
|
211
|
-
CATimedelta *ca
|
|
218
|
+
CATimedelta *ca;
|
|
219
|
+
ca_timedelta_setup(NULL, parent, unit, count);
|
|
220
|
+
ca = (CATimedelta *) ca_array_alloc(CA_OBJ_TIMEDELTA, parent->ndim);
|
|
212
221
|
ca_timedelta_setup(ca, parent, unit, count);
|
|
213
222
|
return ca;
|
|
214
223
|
}
|
|
@@ -246,18 +255,6 @@ ca_timedelta_func_allocate (void *ap)
|
|
|
246
255
|
ca->ptr = ca->parent->ptr;
|
|
247
256
|
}
|
|
248
257
|
|
|
249
|
-
static void
|
|
250
|
-
ca_timedelta_func_create_mask (void *ap)
|
|
251
|
-
{
|
|
252
|
-
CATimedelta *ca = (CATimedelta *) ap;
|
|
253
|
-
ca_update_mask(ca->parent);
|
|
254
|
-
if ( ! ca->parent->mask ) {
|
|
255
|
-
ca_create_mask(ca->parent);
|
|
256
|
-
}
|
|
257
|
-
ca->mask = (CArray *) ca_refer_new(ca->parent->mask,
|
|
258
|
-
CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
258
|
ca_operation_function_t ca_timedelta_func = {
|
|
262
259
|
-1, /* CA_OBJ_TIMEDELTA — filled by ca_install_obj_type */
|
|
263
260
|
CA_VIEW_ARRAY,
|
|
@@ -268,7 +265,7 @@ ca_operation_function_t ca_timedelta_func = {
|
|
|
268
265
|
ca_face_sync,
|
|
269
266
|
ca_face_detach,
|
|
270
267
|
ca_face_fill_data,
|
|
271
|
-
|
|
268
|
+
ca_view_func_create_mask,
|
|
272
269
|
ca_face_xfer_index,
|
|
273
270
|
ca_face_xfer_addrs,
|
|
274
271
|
NULL, /* fold_stride */
|
|
@@ -330,6 +327,7 @@ rb_ca_timedelta_initialize_copy (VALUE self, VALUE other)
|
|
|
330
327
|
{
|
|
331
328
|
CATimedelta *ca, *cs;
|
|
332
329
|
TypedData_Get_Struct(self, CATimedelta, &catimedelta_data_type, ca);
|
|
330
|
+
ca_check_uninitialized(ca);
|
|
333
331
|
TypedData_Get_Struct(other, CATimedelta, &catimedelta_data_type, cs);
|
|
334
332
|
if ( ca_func[CA_OBJ_TIMEDELTA].pool_init ) {
|
|
335
333
|
ca_array_pool_alloc(ca, CA_OBJ_TIMEDELTA, cs->parent->ndim);
|
|
@@ -338,12 +336,12 @@ rb_ca_timedelta_initialize_copy (VALUE self, VALUE other)
|
|
|
338
336
|
return self;
|
|
339
337
|
}
|
|
340
338
|
|
|
341
|
-
/*
|
|
339
|
+
/* storage_to_element implemented in C to avoid per-cell Ruby method dispatch
|
|
342
340
|
on the fetch hot path. Accepts either an Integer (INT64 surface fetch)
|
|
343
341
|
or an 8-byte String (FIXLEN surface fetch); decodes the parent int64
|
|
344
342
|
and constructs CATimedelta::Element(value, unit). */
|
|
345
343
|
static VALUE
|
|
346
|
-
|
|
344
|
+
rb_ca_timedelta_storage_to_element (VALUE self, VALUE raw)
|
|
347
345
|
{
|
|
348
346
|
CATimedelta *ca;
|
|
349
347
|
CATimedeltaElement *s;
|
|
@@ -355,7 +353,7 @@ rb_ca_timedelta_storage_to_scalar (VALUE self, VALUE raw)
|
|
|
355
353
|
if ( TYPE(raw) == T_STRING ) {
|
|
356
354
|
if ( RSTRING_LEN(raw) != (long) sizeof(int64_t) ) {
|
|
357
355
|
rb_raise(rb_eArgError,
|
|
358
|
-
"CATimedelta#
|
|
356
|
+
"CATimedelta#storage_to_element: expected %lu bytes, got %ld",
|
|
359
357
|
(unsigned long) sizeof(int64_t), RSTRING_LEN(raw));
|
|
360
358
|
}
|
|
361
359
|
memcpy(&value, RSTRING_PTR(raw), sizeof(int64_t));
|
|
@@ -408,17 +406,17 @@ Init_ca_obj_timedelta (void)
|
|
|
408
406
|
rb_define_singleton_method(rb_cCATimedelta, "__wrap__",
|
|
409
407
|
rb_ca_timedelta_wrap_method, 2);
|
|
410
408
|
rb_define_method(rb_cCATimedelta, "unit", rb_ca_timedelta_unit, 0);
|
|
411
|
-
rb_define_method(rb_cCATimedelta, "
|
|
412
|
-
|
|
413
|
-
/* Registers the state-compatibility predicate so
|
|
409
|
+
rb_define_method(rb_cCATimedelta, "storage_to_element",
|
|
410
|
+
rb_ca_timedelta_storage_to_element, 1);
|
|
411
|
+
/* Registers the state-compatibility predicate so CA_FACE_STORAGE_TO_ELEMENT_IF_FACE
|
|
414
412
|
can skip rb_funcall on the hot path. */
|
|
415
413
|
ca_face_register_state_compatible(CA_OBJ_TIMEDELTA,
|
|
416
414
|
ca_timedelta_state_compatible);
|
|
417
415
|
/* unit is pure metadata, no per-parent buffer; multi-parent Face lift
|
|
418
416
|
is safe (portable = 1). */
|
|
419
417
|
ca_face_register_state_portable(CA_OBJ_TIMEDELTA, 1);
|
|
420
|
-
|
|
421
|
-
|
|
418
|
+
ca_face_register_storage_to_element(CA_OBJ_TIMEDELTA,
|
|
419
|
+
rb_ca_timedelta_storage_to_element);
|
|
422
420
|
|
|
423
421
|
/* CATimedelta::Element as a C-backed TypedData class. The Ruby-side
|
|
424
422
|
definition in lib/carray/time.rb keeps Comparable + to_seconds /
|
data/ext/ca_obj_transpose.c
CHANGED
|
@@ -37,11 +37,11 @@ ca_trans_setup (CAStride *ca, CArray *parent, ca_size_t *imap)
|
|
|
37
37
|
for (i = 0; i < ndim; i++) {
|
|
38
38
|
idim = imap[i];
|
|
39
39
|
if (idim < 0 || idim >= ndim) {
|
|
40
|
-
rb_raise(
|
|
40
|
+
rb_raise(rb_eArgError,
|
|
41
41
|
"specified %i-th dimension number out of range", i);
|
|
42
42
|
}
|
|
43
43
|
if (map[idim] != -1) {
|
|
44
|
-
rb_raise(
|
|
44
|
+
rb_raise(rb_eArgError,
|
|
45
45
|
"specified %i-th dimension number is duplicated", i);
|
|
46
46
|
}
|
|
47
47
|
map[idim] = i;
|
|
@@ -58,6 +58,12 @@ ca_trans_setup (CAStride *ca, CArray *parent, ca_size_t *imap)
|
|
|
58
58
|
strides[i] = parent_byte_stride[imap[i]];
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
62
|
+
run them before it allocates. */
|
|
63
|
+
if ( ca == NULL ) {
|
|
64
|
+
return 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
61
67
|
ca_stride_setup(ca, CA_OBJ_TRANSPOSE, parent,
|
|
62
68
|
parent->data_type, parent->bytes,
|
|
63
69
|
ndim, newdim, strides, 0);
|
|
@@ -67,7 +73,9 @@ ca_trans_setup (CAStride *ca, CArray *parent, ca_size_t *imap)
|
|
|
67
73
|
CAStride *
|
|
68
74
|
ca_trans_new (CArray *parent, ca_size_t *imap)
|
|
69
75
|
{
|
|
70
|
-
CAStride *ca
|
|
76
|
+
CAStride *ca;
|
|
77
|
+
ca_trans_setup(NULL, parent, imap);
|
|
78
|
+
ca = (CAStride *) ca_array_alloc(CA_OBJ_TRANSPOSE, parent->ndim);
|
|
71
79
|
ca_trans_setup(ca, parent, imap);
|
|
72
80
|
return ca;
|
|
73
81
|
}
|
|
@@ -126,6 +134,7 @@ rb_ca_trans_initialize_copy (VALUE self, VALUE other)
|
|
|
126
134
|
{
|
|
127
135
|
CAStride *ca, *cs;
|
|
128
136
|
TypedData_Get_Struct(self, CAStride, &castride_data_type, ca);
|
|
137
|
+
ca_check_uninitialized(ca);
|
|
129
138
|
TypedData_Get_Struct(other, CAStride, &castride_data_type, cs);
|
|
130
139
|
if ( ca_func[CA_OBJ_TRANSPOSE].pool_init ) {
|
|
131
140
|
ca_array_pool_alloc(ca, CA_OBJ_TRANSPOSE, cs->ndim);
|
data/ext/ca_obj_triop.c
CHANGED
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
op1), src2 == scratch2, src3 == scratch3.
|
|
21
21
|
|
|
22
22
|
Mask handling: none of the currently-defined triops (fma / fms /
|
|
23
|
-
clip) trap on integer zero divisor, so m=NULL always at the
|
|
24
|
-
kernel walk (SIMD fast path). Output mask is
|
|
25
|
-
|
|
23
|
+
clip / select) trap on integer zero divisor, so m=NULL always at the
|
|
24
|
+
kernel walk (SIMD fast path). Output mask is the OR of the operand
|
|
25
|
+
masks, except for select (create_mask time).
|
|
26
26
|
|
|
27
27
|
Cross-ndim promotion: intentional design rejection, mirroring
|
|
28
28
|
CABinOp. Callers must reshape explicitly.
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
#include "carray_internal.h" /* ca_lazy_arena_* */
|
|
34
34
|
#include "ca_triop_dispatch.h"
|
|
35
35
|
#include "ca_monop_dispatch.h" /* CA_MONOP_CAST_BASE */
|
|
36
|
+
#include "carray_math_kernel.h" /* ca_triop_not_implement */
|
|
36
37
|
|
|
37
38
|
extern VALUE ca_broadcast_view (VALUE src, int8_t ndim,
|
|
38
39
|
ca_size_t *target_dim);
|
|
@@ -41,7 +42,6 @@ int8_t CA_OBJ_TRIOP;
|
|
|
41
42
|
VALUE rb_cCATriOp;
|
|
42
43
|
|
|
43
44
|
extern int8_t CA_OBJ_LAZY_MARKER;
|
|
44
|
-
extern VALUE ca_lazy_wrap_scalar (VALUE other, CArray *self_ca);
|
|
45
45
|
|
|
46
46
|
/* ------------------------------------------------------------------- */
|
|
47
47
|
/* CATriOp struct */
|
|
@@ -222,25 +222,6 @@ ca_triop_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
|
222
222
|
ca_triop_func_xfer_stride(ca, starts, counts, strides, data, CA_XFER_GET);
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
-
static void
|
|
226
|
-
ca_triop_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
227
|
-
void *data, int dir)
|
|
228
|
-
{
|
|
229
|
-
CATriOp *ca = (CATriOp *) ap;
|
|
230
|
-
ca_size_t i;
|
|
231
|
-
char *out = (char *) data;
|
|
232
|
-
|
|
233
|
-
if ( dir != CA_XFER_GET ) {
|
|
234
|
-
rb_raise(rb_eRuntimeError, "CATriOp is read-only (xfer_addrs PUT)");
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
for ( i = 0; i < n; i++ ) {
|
|
238
|
-
ca_size_t idx[CA_RANK_MAX];
|
|
239
|
-
ca_addr2index((CArray *)ca, addrs[i], idx);
|
|
240
|
-
ca_triop_func_xfer_index(ca, idx, out + i * ca->bytes, CA_XFER_GET);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
225
|
/* Test / observability counters (mirror CABinOp's counters). */
|
|
245
226
|
ca_size_t ca_triop_scratch_acquire_count = 0;
|
|
246
227
|
ca_size_t ca_triop_materialise_call_count = 0;
|
|
@@ -249,8 +230,7 @@ ca_size_t ca_triop_materialise_call_count = 0;
|
|
|
249
230
|
be broadcast at step=0). Returns the scratch pointer; updates
|
|
250
231
|
*step_out to 0 (scalar) or 1 (same-shape). */
|
|
251
232
|
static void *
|
|
252
|
-
pull_operand (CArray *op, int is_scalar,
|
|
253
|
-
ca_size_t *counts, ca_size_t slab_n, int8_t ndim,
|
|
233
|
+
pull_operand (CArray *op, int is_scalar, const ca_lazy_req_t *req,
|
|
254
234
|
ca_size_t *step_out)
|
|
255
235
|
{
|
|
256
236
|
void *scratch;
|
|
@@ -274,54 +254,40 @@ pull_operand (CArray *op, int is_scalar, ca_size_t *starts,
|
|
|
274
254
|
*step_out = 0;
|
|
275
255
|
}
|
|
276
256
|
else {
|
|
277
|
-
ca_size_t op_strides[CA_RANK_MAX];
|
|
278
|
-
ca_size_t s = bytes;
|
|
279
|
-
for ( k = ndim - 1; k >= 0; k-- ) {
|
|
280
|
-
op_strides[k] = s;
|
|
281
|
-
s *= counts[k];
|
|
282
|
-
}
|
|
283
257
|
scratch = ( op->data_type == CA_OBJECT )
|
|
284
|
-
? ca_lazy_arena_acquire_object(
|
|
285
|
-
: ca_lazy_arena_acquire(
|
|
258
|
+
? ca_lazy_arena_acquire_object(req->n)
|
|
259
|
+
: ca_lazy_arena_acquire(req->n * bytes);
|
|
286
260
|
ca_triop_scratch_acquire_count++;
|
|
287
|
-
|
|
261
|
+
ca_lazy_req_pull(op, req, scratch, CA_XFER_GET);
|
|
288
262
|
*step_out = 1;
|
|
289
263
|
}
|
|
290
264
|
return scratch;
|
|
291
265
|
}
|
|
292
266
|
|
|
267
|
+
/* Evaluate the cells a request names into `data` (packed, n cells). */
|
|
293
268
|
static void
|
|
294
|
-
|
|
295
|
-
ca_size_t *strides, void *data, int dir)
|
|
269
|
+
ca_triop_eval (CATriOp *to, const ca_lazy_req_t *req, void *data)
|
|
296
270
|
{
|
|
297
|
-
|
|
298
|
-
ca_size_t slab_n;
|
|
299
|
-
int8_t k;
|
|
271
|
+
ca_size_t slab_n = req->n;
|
|
300
272
|
void *scratch2, *scratch3;
|
|
301
273
|
ca_size_t op2_step, op3_step;
|
|
302
274
|
|
|
303
|
-
if ( dir != CA_XFER_GET ) {
|
|
304
|
-
rb_raise(rb_eRuntimeError, "CATriOp is read-only (xfer_stride PUT)");
|
|
305
|
-
}
|
|
306
275
|
ca_triop_materialise_call_count++;
|
|
307
276
|
|
|
308
|
-
slab_n = 1;
|
|
309
|
-
for ( k = 0; k < to->ndim; k++ ) slab_n *= counts[k];
|
|
310
|
-
|
|
311
277
|
/* Step 1: pull op1 into the output buffer. */
|
|
312
|
-
|
|
278
|
+
ca_lazy_req_pull(to->parent, req, data, CA_XFER_GET);
|
|
313
279
|
|
|
314
280
|
/* Step 2: pull op2 into an arena scratch. */
|
|
315
|
-
scratch2 = pull_operand(to->op2, to->op2_is_scalar,
|
|
316
|
-
slab_n, to->ndim, &op2_step);
|
|
281
|
+
scratch2 = pull_operand(to->op2, to->op2_is_scalar, req, &op2_step);
|
|
317
282
|
|
|
318
283
|
/* Step 3: pull op3 into another arena scratch. */
|
|
319
|
-
scratch3 = pull_operand(to->op3, to->op3_is_scalar,
|
|
320
|
-
slab_n, to->ndim, &op3_step);
|
|
284
|
+
scratch3 = pull_operand(to->op3, to->op3_is_scalar, req, &op3_step);
|
|
321
285
|
|
|
322
|
-
/* Step 4: apply the kernel. ptr1 == ptr4 (in-place op1)
|
|
323
|
-
|
|
286
|
+
/* Step 4: apply the kernel. ptr1 == ptr4 (in-place op1). No numeric
|
|
287
|
+
triop traps, so m=NULL; object cells call Ruby, and skip the masked
|
|
288
|
+
cells as the eager triop does. */
|
|
324
289
|
{
|
|
290
|
+
boolean8_t *slab_mask = NULL;
|
|
325
291
|
ca_triop_func_t fn = ca_triop_kernel_lookup_vvv(to->op_id, to->data_type);
|
|
326
292
|
if ( fn == NULL ) {
|
|
327
293
|
ca_lazy_arena_release(scratch3);
|
|
@@ -330,17 +296,51 @@ ca_triop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
330
296
|
"CATriOp: kernel not implemented (op_id=%u data_type=%d)",
|
|
331
297
|
(unsigned) to->op_id, (int) to->data_type);
|
|
332
298
|
}
|
|
333
|
-
|
|
299
|
+
if ( to->data_type == CA_OBJECT ) {
|
|
300
|
+
CArray *ops[3];
|
|
301
|
+
ops[0] = to->parent;
|
|
302
|
+
ops[1] = to->op2;
|
|
303
|
+
ops[2] = to->op3;
|
|
304
|
+
slab_mask = ca_lazy_req_mask(req, 3, ops);
|
|
305
|
+
}
|
|
306
|
+
fn(slab_n, slab_mask,
|
|
334
307
|
(char *)data, 1, /* src1 == dst (op1, in-place) */
|
|
335
308
|
(char *)scratch2, op2_step, /* src2 (op2) */
|
|
336
309
|
(char *)scratch3, op3_step, /* src3 (op3) */
|
|
337
310
|
(char *)data, 1); /* dst */
|
|
311
|
+
if ( slab_mask ) ca_lazy_arena_release(slab_mask);
|
|
338
312
|
}
|
|
339
313
|
|
|
340
314
|
ca_lazy_arena_release(scratch3);
|
|
341
315
|
ca_lazy_arena_release(scratch2);
|
|
342
316
|
}
|
|
343
317
|
|
|
318
|
+
static void
|
|
319
|
+
ca_triop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
320
|
+
ca_size_t *strides, void *data, int dir)
|
|
321
|
+
{
|
|
322
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
323
|
+
ca_lazy_req_t req;
|
|
324
|
+
if ( dir != CA_XFER_GET ) {
|
|
325
|
+
rb_raise(rb_eRuntimeError, "CATriOp is read-only (xfer_stride PUT)");
|
|
326
|
+
}
|
|
327
|
+
ca_lazy_req_region(&req, ap, starts, counts, strides);
|
|
328
|
+
ca_triop_eval((CATriOp *) ap, &req, data);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/* An address list is evaluated in one pass, as a region is. */
|
|
332
|
+
static void
|
|
333
|
+
ca_triop_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
334
|
+
void *data, int dir)
|
|
335
|
+
{
|
|
336
|
+
ca_lazy_req_t req;
|
|
337
|
+
if ( dir != CA_XFER_GET ) {
|
|
338
|
+
rb_raise(rb_eRuntimeError, "CATriOp is read-only (xfer_addrs PUT)");
|
|
339
|
+
}
|
|
340
|
+
ca_lazy_req_addrs(&req, n, addrs);
|
|
341
|
+
ca_triop_eval((CATriOp *) ap, &req, data);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
344
|
static void
|
|
345
345
|
ca_triop_func_xfer_all (void *ap, void *data, int dir)
|
|
346
346
|
{
|
|
@@ -419,61 +419,16 @@ ca_triop_func_fill_data (void *ap, void *ptr)
|
|
|
419
419
|
rb_raise(rb_eRuntimeError, "CATriOp is read-only (fill_data)");
|
|
420
420
|
}
|
|
421
421
|
|
|
422
|
-
/* Build out.mask
|
|
423
|
-
|
|
422
|
+
/* Build out.mask on each read (CAMaskOfOperands): the three operands'
|
|
423
|
+
masks ORed, except for select, which is masked where the condition is
|
|
424
|
+
or where the branch it chooses is. */
|
|
424
425
|
static void
|
|
425
426
|
ca_triop_func_create_mask (void *ap)
|
|
426
427
|
{
|
|
427
428
|
CATriOp *to = (CATriOp *) ap;
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
CArray *
|
|
431
|
-
boolean8_t *dst, *m1, *m2, *m3;
|
|
432
|
-
ca_size_t i, n;
|
|
433
|
-
int has1, has2, has3;
|
|
434
|
-
|
|
435
|
-
has1 = ca_has_mask(op1);
|
|
436
|
-
has2 = ca_has_mask(op2);
|
|
437
|
-
has3 = ca_has_mask(op3);
|
|
438
|
-
if ( ! has1 && ! has2 && ! has3 ) return;
|
|
439
|
-
|
|
440
|
-
/* Exactly one masked operand: the answer is that operand's mask, cell
|
|
441
|
-
for cell. Share it rather than allocating a copy per node. */
|
|
442
|
-
if ( has1 + has2 + has3 == 1 ) {
|
|
443
|
-
CArray *src = has1 ? op1 : ( has2 ? op2 : op3 );
|
|
444
|
-
if ( src->elements == to->elements ) {
|
|
445
|
-
to->mask = (CArray *) ca_refer_new(src->mask, CA_BOOLEAN,
|
|
446
|
-
to->ndim, to->dim, 0, 0);
|
|
447
|
-
return;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
to->mask = (CArray *) carray_new(CA_BOOLEAN, to->ndim, to->dim, 0, NULL);
|
|
452
|
-
dst = (boolean8_t *) to->mask->ptr;
|
|
453
|
-
n = to->elements;
|
|
454
|
-
|
|
455
|
-
/* The masks are what is read here; attaching the operand instead
|
|
456
|
-
materialises the whole subexpression under it. */
|
|
457
|
-
if ( has1 ) ca_attach(op1->mask);
|
|
458
|
-
if ( has2 ) ca_attach(op2->mask);
|
|
459
|
-
if ( has3 ) ca_attach(op3->mask);
|
|
460
|
-
|
|
461
|
-
m1 = has1 ? (boolean8_t *) op1->mask->ptr : NULL;
|
|
462
|
-
m2 = has2 ? (boolean8_t *) op2->mask->ptr : NULL;
|
|
463
|
-
m3 = has3 ? (boolean8_t *) op3->mask->ptr : NULL;
|
|
464
|
-
|
|
465
|
-
for ( i = 0; i < n; i++ ) {
|
|
466
|
-
ca_size_t i2 = to->op2_is_scalar ? 0 : i;
|
|
467
|
-
ca_size_t i3 = to->op3_is_scalar ? 0 : i;
|
|
468
|
-
boolean8_t a = m1 ? m1[i] : 0;
|
|
469
|
-
boolean8_t b = m2 ? m2[i2] : 0;
|
|
470
|
-
boolean8_t c = m3 ? m3[i3] : 0;
|
|
471
|
-
dst[i] = (boolean8_t) ( a | b | c );
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
if ( has3 ) ca_detach(op3->mask);
|
|
475
|
-
if ( has2 ) ca_detach(op2->mask);
|
|
476
|
-
if ( has1 ) ca_detach(op1->mask);
|
|
429
|
+
int mode = ( to->op_id == CA_TRIOP_SELECT ) ? CA_LAZY_MASK_SELECT
|
|
430
|
+
: CA_LAZY_MASK_OR;
|
|
431
|
+
to->mask = ca_lazy_operation_mask((CArray *) to, mode);
|
|
477
432
|
}
|
|
478
433
|
|
|
479
434
|
ca_operation_function_t ca_triop_func = {
|
|
@@ -574,21 +529,32 @@ rb_ca_triop_build (VALUE cary1, VALUE cary2, VALUE cary3, uint16_t op_id)
|
|
|
574
529
|
r2 = collapse_marker(cary2);
|
|
575
530
|
r3 = collapse_marker(cary3);
|
|
576
531
|
|
|
577
|
-
/*
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
532
|
+
/* select takes its branches already typed (CArray#then_else makes a
|
|
533
|
+
scalar branch a CScalar of the result type); the condition is boolean
|
|
534
|
+
and takes no part in the promotion. */
|
|
535
|
+
if ( op_id == CA_TRIOP_SELECT ) {
|
|
536
|
+
if ( ! rb_obj_is_carray(r1) || ! rb_obj_is_carray(r2) || ! rb_obj_is_carray(r3) ) {
|
|
537
|
+
rb_raise(rb_eArgError, "CATriOp: select takes three CArrays");
|
|
538
|
+
}
|
|
539
|
+
r2 = ca_lazy_settle_scalar(r2, RTEST(rb_obj_is_cscalar(r2)));
|
|
540
|
+
r3 = ca_lazy_settle_scalar(r3, RTEST(rb_obj_is_cscalar(r3)));
|
|
541
|
+
}
|
|
542
|
+
/* Scalar operands (clip's Numeric bounds, a CScalar) are wrapped and
|
|
543
|
+
promoted pairwise in the order the eager triop uses. */
|
|
544
|
+
else if ( ! rb_obj_is_carray(r1) || ! rb_obj_is_carray(r2) || ! rb_obj_is_carray(r3) ||
|
|
545
|
+
rb_obj_is_cscalar(r2) || rb_obj_is_cscalar(r3) ) {
|
|
546
|
+
if ( ! rb_obj_is_carray(r1) ) {
|
|
586
547
|
rb_raise(rb_eArgError,
|
|
587
|
-
"CATriOp:
|
|
548
|
+
"CATriOp: the first operand must be a CArray");
|
|
588
549
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
550
|
+
int r2_scalar = ! rb_obj_is_carray(r2) || rb_obj_is_cscalar(r2);
|
|
551
|
+
int r3_scalar = ! rb_obj_is_carray(r3) || rb_obj_is_cscalar(r3);
|
|
552
|
+
rb_ca_cast_self_or_other(&r1, &r2);
|
|
553
|
+
rb_ca_cast_self_or_other(&r1, &r3);
|
|
554
|
+
rb_ca_cast_self_or_other(&r2, &r3);
|
|
555
|
+
rb_ca_cast_self_or_other(&r1, &r2);
|
|
556
|
+
r2 = ca_lazy_settle_scalar(r2, r2_scalar);
|
|
557
|
+
r3 = ca_lazy_settle_scalar(r3, r3_scalar);
|
|
592
558
|
}
|
|
593
559
|
|
|
594
560
|
TypedData_Get_Struct(r1, CArray, &carray_data_type, op1);
|
|
@@ -599,6 +565,19 @@ rb_ca_triop_build (VALUE cary1, VALUE cary2, VALUE cary3, uint16_t op_id)
|
|
|
599
565
|
ca_triop_kernel_input_data_types(op_id,
|
|
600
566
|
op1->data_type, op2->data_type, op3->data_type,
|
|
601
567
|
&dt1, &dt2, &dt3);
|
|
568
|
+
|
|
569
|
+
/* All boolean, and no boolean kernel (fma / fms): read the operands as
|
|
570
|
+
their 0/1 storage in int64, as rb_ca_call_triop does. */
|
|
571
|
+
if ( dt1 == CA_BOOLEAN &&
|
|
572
|
+
ca_triop_kernel_lookup_vvv(op_id, CA_BOOLEAN) == ca_triop_not_implement ) {
|
|
573
|
+
dt1 = dt2 = dt3 = CA_INT64;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/* No kernel for that data_type: raise as the eager triop does. */
|
|
577
|
+
if ( ca_triop_kernel_lookup_vvv(op_id, dt1) == ca_triop_not_implement ) {
|
|
578
|
+
rb_raise(rb_eCADataTypeError,
|
|
579
|
+
"invalid data_type for triop (not implemented)");
|
|
580
|
+
}
|
|
602
581
|
r1 = insert_cast(r1, dt1, &op1);
|
|
603
582
|
r2 = insert_cast(r2, dt2, &op2);
|
|
604
583
|
r3 = insert_cast(r3, dt3, &op3);
|
|
@@ -668,6 +647,17 @@ rb_ca_triop_s_build (VALUE klass, VALUE cary1, VALUE cary2, VALUE cary3,
|
|
|
668
647
|
return rb_ca_triop_build(cary1, cary2, cary3, op_id);
|
|
669
648
|
}
|
|
670
649
|
|
|
650
|
+
/* Whether this node's kernel skips the cells its operands mask, rather
|
|
651
|
+
than computing them: a kernel that can raise on a cell or calls Ruby
|
|
652
|
+
for it. CArray::Fusion reads it so a plan carries the same rule. */
|
|
653
|
+
static VALUE
|
|
654
|
+
rb_ca_triop_trapping (VALUE self)
|
|
655
|
+
{
|
|
656
|
+
CArray *ca;
|
|
657
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
658
|
+
return ( ca->data_type == CA_OBJECT ) ? Qtrue : Qfalse;
|
|
659
|
+
}
|
|
660
|
+
|
|
671
661
|
static VALUE
|
|
672
662
|
rb_ca_triop_op_id (VALUE self)
|
|
673
663
|
{
|
|
@@ -731,6 +721,7 @@ rb_ca_triop_initialize_copy (VALUE self, VALUE other)
|
|
|
731
721
|
{
|
|
732
722
|
CATriOp *ca, *cs;
|
|
733
723
|
TypedData_Get_Struct(self, CATriOp, &catriop_data_type, ca);
|
|
724
|
+
ca_check_uninitialized(ca);
|
|
734
725
|
TypedData_Get_Struct(other, CATriOp, &catriop_data_type, cs);
|
|
735
726
|
if ( ca_func[CA_OBJ_TRIOP].pool_init ) {
|
|
736
727
|
ca_array_pool_alloc(ca, CA_OBJ_TRIOP, cs->parent->ndim);
|
|
@@ -758,6 +749,7 @@ Init_ca_obj_triop (void)
|
|
|
758
749
|
rb_define_const(rb_cCATriOp, "OP_FMA", INT2NUM(CA_TRIOP_FMA));
|
|
759
750
|
rb_define_const(rb_cCATriOp, "OP_FMS", INT2NUM(CA_TRIOP_FMS));
|
|
760
751
|
rb_define_const(rb_cCATriOp, "OP_CLIP", INT2NUM(CA_TRIOP_CLIP));
|
|
752
|
+
rb_define_const(rb_cCATriOp, "OP_SELECT", INT2NUM(CA_TRIOP_SELECT));
|
|
761
753
|
|
|
762
754
|
rb_define_alloc_func(rb_cCATriOp, rb_ca_triop_s_allocate);
|
|
763
755
|
rb_define_method(rb_cCATriOp, "initialize_copy",
|
|
@@ -768,6 +760,7 @@ Init_ca_obj_triop (void)
|
|
|
768
760
|
|
|
769
761
|
rb_define_method(rb_cCATriOp, "__op_id__",
|
|
770
762
|
rb_ca_triop_op_id, 0);
|
|
763
|
+
rb_define_method(rb_cCATriOp, "__trapping__", rb_ca_triop_trapping, 0);
|
|
771
764
|
rb_define_method(rb_cCATriOp, "__triop_op2__",
|
|
772
765
|
rb_ca_triop_op2, 0);
|
|
773
766
|
rb_define_method(rb_cCATriOp, "__triop_op3__",
|