carray 3.0.3 → 3.0.4
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 +264 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +1 -6
- data/ext/ca_axis_group.c +27 -27
- data/ext/ca_binop_dispatch.c +1 -29
- data/ext/ca_binop_dispatch.h +0 -1
- data/ext/ca_categorical_iterator.c +205 -134
- data/ext/ca_compare.c +7 -18
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1234 -1994
- data/ext/ca_kernel_iterator.h +391 -437
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +96 -39
- data/ext/ca_obj_bincmp.c +24 -21
- data/ext/ca_obj_binop.c +15 -26
- data/ext/ca_obj_bitarray.c +3 -2
- data/ext/ca_obj_bitfield.c +5 -6
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +5 -6
- data/ext/ca_obj_const_string.c +173 -19
- data/ext/ca_obj_face.c +238 -57
- data/ext/ca_obj_face.h +19 -0
- data/ext/ca_obj_fake.c +15 -29
- data/ext/ca_obj_farray.c +6 -3
- data/ext/ca_obj_field.c +17 -5
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +406 -132
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +67 -57
- data/ext/ca_obj_object.c +157 -51
- data/ext/ca_obj_record.c +12 -7
- data/ext/ca_obj_reduce.c +13 -8
- data/ext/ca_obj_refer.c +25 -27
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +6 -5
- data/ext/ca_obj_select.c +14 -9
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +11 -1
- data/ext/ca_obj_stack.c +179 -34
- data/ext/ca_obj_stride.c +162 -115
- data/ext/ca_obj_string.c +71 -4
- data/ext/ca_obj_tile.c +6 -5
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +5 -3
- data/ext/ca_obj_triop.c +23 -32
- data/ext/ca_obj_window.c +190 -26
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +181 -75
- data/ext/carray_access.c +184 -96
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +89 -6
- data/ext/carray_bincount.c +10 -8
- data/ext/carray_broadcast.c +13 -8
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +108 -0
- data/ext/carray_cast.c +142 -24
- data/ext/carray_cast_func.rb +46 -6
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +16 -7
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +147 -55
- data/ext/carray_count.c +50 -20
- data/ext/carray_element.c +76 -33
- data/ext/carray_factorize.c +118 -64
- data/ext/carray_generate.c +191 -50
- data/ext/carray_histogram.c +62 -17
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +336 -29
- data/ext/carray_kernels_bincmp.c +4453 -0
- data/ext/carray_kernels_binop.c +11368 -0
- data/ext/carray_kernels_init.c +1734 -0
- data/ext/carray_kernels_moncmp.c +2104 -0
- data/ext/carray_kernels_monop.c +18369 -0
- data/ext/carray_kernels_reduce_aggregate.c +23818 -0
- data/ext/carray_kernels_reduce_boolean.c +406 -0
- data/ext/carray_kernels_reduce_cumulative.c +10086 -0
- data/ext/carray_kernels_reduce_extreme.c +17634 -0
- data/ext/carray_kernels_reduce_variance.c +3849 -0
- data/ext/carray_kernels_scan.c +4302 -0
- data/ext/carray_kernels_search.c +33829 -0
- data/ext/carray_kernels_sort.c +10906 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +292 -72
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +124 -47
- data/ext/carray_order.c +384 -76
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +67 -13
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +63 -38
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +91 -28
- data/ext/carray_sort.c +35 -35
- data/ext/carray_struct.c +19 -18
- data/ext/carray_test.c +26 -5
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +246 -45
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +198 -240
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +126 -22
- data/lib/carray/autoload_carray.rb +8 -31
- data/lib/carray/autoload_method_extension.rb +14 -5
- data/lib/carray/axis_group.rb +255 -106
- data/lib/carray/basics.rb +78 -10
- data/lib/carray/bincount_nd.rb +12 -2
- data/lib/carray/block_iterator.rb +126 -23
- data/lib/carray/boolean_reduce.rb +17 -17
- data/lib/carray/categorical.rb +165 -43
- data/lib/carray/categorical_iterator.rb +130 -27
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +14 -5
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +7 -1
- data/lib/carray/frame/column_verbs.rb +70 -0
- data/lib/carray/frame/convert.rb +69 -0
- data/lib/carray/frame/csv_parser.rb +111 -17
- data/lib/carray/frame/describe.rb +3 -2
- data/lib/carray/frame/frame.rb +246 -21
- data/lib/carray/frame/group.rb +510 -95
- data/lib/carray/frame/io.rb +115 -28
- data/lib/carray/frame/join.rb +312 -51
- data/lib/carray/frame/records.rb +83 -7
- data/lib/carray/frame/reshape.rb +42 -35
- data/lib/carray/frame/sort.rb +7 -19
- data/lib/carray/frame/verbs.rb +188 -48
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +11 -4
- data/lib/carray/fusion.rb +40 -16
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +31 -8
- data/lib/carray/iterator.rb +85 -7
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +182 -183
- data/lib/carray/mask_gap_fill.rb +63 -57
- data/lib/carray/meld_reduce.rb +12 -14
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +16 -0
- data/lib/carray/methods/bit_string.rb +1 -1
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +3 -1
- data/lib/carray/methods/gather_nd.rb +14 -5
- data/lib/carray/methods/insert_block.rb +2 -2
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +53 -36
- data/lib/carray/methods/join.rb +1 -6
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +47 -51
- data/lib/carray/methods/mode.rb +1 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/resize.rb +3 -3
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +3 -3
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +53 -8
- data/lib/carray/segment_iterator.rb +313 -82
- data/lib/carray/serialize.rb +24 -10
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +8 -1
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +19 -8
- data/lib/carray/time.rb +726 -104
- data/lib/carray/window_iterator.rb +122 -16
- data/lib/carray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +4 -0
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +2 -1
- data/yard-stubs/ca_obj_roll.rb +2 -2
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_cast.rb +10 -0
- data/yard-stubs/carray_conversion.rb +2 -1
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +26 -2
- data/yard-stubs/carray_math.rb +27 -1
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +29 -18
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +14 -9
- data/yard-stubs/carray_slab.rb +9 -2
- data/yard-stubs/carray_sort.rb +6 -5
- data/yard-stubs/carray_test.rb +5 -3
- metadata +25 -3
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/ext/carray_partition.c
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
#include "ruby.h"
|
|
16
16
|
#include "carray.h"
|
|
17
|
-
#include "carray_internal.h" /*
|
|
17
|
+
#include "carray_internal.h" /* ca_normalize_axis_arg */
|
|
18
18
|
#include "ca_kernel_iterator.h" /* CA_FOR_EACH_FIBER_INOUT */
|
|
19
19
|
#include "ca_obj_face.h" /* CA_FACE_LIFT_IF_FACE */
|
|
20
20
|
#include "ca_sort_kernels.h" /* ca_partition_quick_* / ca_partition_nan_* */
|
|
@@ -155,7 +155,7 @@ rb_ca_partition_copy_c (VALUE self, VALUE vkth, VALUE vaxis)
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
/* Normalize axis. */
|
|
158
|
-
int axis =
|
|
158
|
+
int axis = ca_normalize_axis_arg(vaxis, cat->ndim, NULL);
|
|
159
159
|
|
|
160
160
|
ca_size_t fiber_n = cat->dim[axis];
|
|
161
161
|
ca_size_t kth = partition_kth(fiber_n, vkth);
|
|
@@ -166,14 +166,9 @@ rb_ca_partition_copy_c (VALUE self, VALUE vkth, VALUE vaxis)
|
|
|
166
166
|
* but the cost is the per-pair rb_funcall, not an architectural
|
|
167
167
|
* penalty. */
|
|
168
168
|
if ( cat->data_type == CA_OBJECT ) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if ( !id_partition_index_ki ) {
|
|
173
|
-
id_partition_index_ki = rb_intern("partition_index_ki");
|
|
174
|
-
id_take_along_axis = rb_intern("take_along_axis");
|
|
175
|
-
id_axis_sym = rb_intern("axis");
|
|
176
|
-
}
|
|
169
|
+
ID id_partition_index_ki = rb_intern("partition_index_ki");
|
|
170
|
+
ID id_take_along_axis = rb_intern("take_along_axis");
|
|
171
|
+
ID id_axis_sym = rb_intern("axis");
|
|
177
172
|
VALUE idx = rb_funcall(target, id_partition_index_ki, 2,
|
|
178
173
|
INT2NUM(axis), SIZET2NUM(kth));
|
|
179
174
|
VALUE kw = rb_hash_new();
|
|
@@ -297,8 +292,7 @@ rb_ca_partition_copy_c_mp (VALUE self, VALUE vkth, VALUE vaxis, int masked_last)
|
|
|
297
292
|
/* Check axis and kth here, so a bad one is reported as partition_copy's
|
|
298
293
|
rather than as the partition this delegates to. */
|
|
299
294
|
{
|
|
300
|
-
int axis =
|
|
301
|
-
ca->ndim, NULL);
|
|
295
|
+
int axis = ca_normalize_axis_arg(vaxis, ca->ndim, NULL);
|
|
302
296
|
partition_kth(ca->dim[axis], vkth);
|
|
303
297
|
}
|
|
304
298
|
/* rb_ca_partitioned_view's rb_scan_args "1:" pattern needs call-frame
|
|
@@ -337,26 +331,30 @@ rb_ca_partition_copy_body (int argc, VALUE *argv, VALUE self)
|
|
|
337
331
|
int masked_last = NIL_P(vmasked_position) ? 1
|
|
338
332
|
: ca_symbol_choice(vmasked_position, "masked_position", "first", "last", NULL);
|
|
339
333
|
|
|
340
|
-
/* Face gate, the same policy as the sort family's
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
(CATime) and not the label order of a code (CACategorical). */
|
|
334
|
+
/* Face gate, the same policy as the sort family's. An ORDERABLE Face
|
|
335
|
+
is selected on its storage and put back on the result. A Face that
|
|
336
|
+
orders by itself (ca_face_orders_by_itself) is partitioned by the view,
|
|
337
|
+
which orders by that order (ca_order_key), and its copy is the answer.
|
|
338
|
+
Any other Face raises. */
|
|
346
339
|
volatile VALUE face = Qnil;
|
|
347
340
|
{
|
|
348
341
|
CArray *ca;
|
|
349
342
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
350
343
|
if ( ca_is_face(ca) ) {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
344
|
+
if ( ca_face_orders_by_itself(self) ) {
|
|
345
|
+
VALUE kw = rb_hash_new();
|
|
346
|
+
VALUE pv_argv[2];
|
|
347
|
+
rb_hash_aset(kw, ID2SYM(rb_intern("axis")), vaxis);
|
|
348
|
+
rb_hash_aset(kw, ID2SYM(rb_intern("masked_position")),
|
|
349
|
+
masked_last ? ID2SYM(rb_intern("last")) : ID2SYM(rb_intern("first")));
|
|
350
|
+
pv_argv[0] = vkth;
|
|
351
|
+
pv_argv[1] = kw;
|
|
352
|
+
return rb_ca_copy(rb_funcallv_kw(self, rb_intern("partition"), 2, pv_argv,
|
|
353
|
+
RB_PASS_KEYWORDS));
|
|
357
354
|
}
|
|
355
|
+
ca_face_require_orderable(self, "partition_copy", "order");
|
|
358
356
|
face = self;
|
|
359
|
-
self =
|
|
357
|
+
self = rb_ca_strip_face_value(self);
|
|
360
358
|
}
|
|
361
359
|
}
|
|
362
360
|
|
|
@@ -418,7 +416,8 @@ rb_ca_partitioned_view (int argc, VALUE *argv, VALUE self)
|
|
|
418
416
|
suitable for direct ca_remap_new wrap; the remap gather carries
|
|
419
417
|
target's mask bits through so masked cells stay masked at their
|
|
420
418
|
clustered position (no extra output-mask step needed here). */
|
|
421
|
-
volatile VALUE sigma_addr =
|
|
419
|
+
volatile VALUE sigma_addr =
|
|
420
|
+
rb_ca_partition_addr_ki_mp(target, vaxis, vkth, masked_last);
|
|
422
421
|
{
|
|
423
422
|
VALUE obj = rb_ca_remap_new(target, sigma_addr);
|
|
424
423
|
CA_FACE_LIFT_IF_FACE(obj, self, ca);
|
|
@@ -443,7 +442,9 @@ static VALUE
|
|
|
443
442
|
rb_ca_partition_copy (int argc, VALUE *argv, VALUE self)
|
|
444
443
|
{
|
|
445
444
|
pc_call_t c = { argc, argv, self };
|
|
446
|
-
|
|
445
|
+
VALUE out = ca_answer_as_caller(pc_answer_body, (VALUE) &c);
|
|
446
|
+
rb_ca_inherit_attr(out, self);
|
|
447
|
+
return out;
|
|
447
448
|
}
|
|
448
449
|
|
|
449
450
|
void
|
data/ext/carray_random.c
CHANGED
|
@@ -88,16 +88,18 @@ typedef struct {
|
|
|
88
88
|
long low_long;
|
|
89
89
|
unsigned long limit;
|
|
90
90
|
int axis; /* shuffle!: -1 = all cells */
|
|
91
|
+
CArray *mask; /* shuffle!: self's mask, moved with the values */
|
|
91
92
|
} ca_random_ctx_t;
|
|
92
93
|
|
|
93
94
|
static void
|
|
94
95
|
ca_random_run (ca_random_ctx_t *c, VALUE rng, VALUE (*fill)(VALUE))
|
|
95
96
|
{
|
|
96
|
-
CArray *list[
|
|
97
|
+
CArray *list[3];
|
|
97
98
|
ca_rng_resolve(rng, &c->source);
|
|
98
99
|
list[0] = c->ca;
|
|
99
100
|
list[1] = c->source.state;
|
|
100
|
-
|
|
101
|
+
list[2] = c->mask;
|
|
102
|
+
ca_attach_window(c->mask ? 3 : 2, list, "www", fill, (VALUE) c);
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
/* The state is attached once the window is open. */
|
|
@@ -359,19 +361,55 @@ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
|
|
|
359
361
|
int is_integer_type = (ca->data_type >= CA_INT8
|
|
360
362
|
&& ca->data_type <= CA_UINT64);
|
|
361
363
|
if (is_integer_type) {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
364
|
+
/* The bounds stay Ruby Integers until they are known to fit: the
|
|
365
|
+
last value drawn is high (closed) or high - 1, and every value
|
|
366
|
+
from low to it must be one of the type's. The draw is low plus
|
|
367
|
+
an offset up to last - low, which holds even the whole int64 or
|
|
368
|
+
uint64 range. */
|
|
369
|
+
VALUE last, type_min, type_max;
|
|
370
|
+
if (!RB_INTEGER_TYPE_P(low_val) || !RB_INTEGER_TYPE_P(high_val)) {
|
|
371
|
+
rb_raise(rb_eTypeError,
|
|
372
|
+
"random: an integer array takes Integer bounds "
|
|
373
|
+
"(got %"PRIsVALUE", %"PRIsVALUE")",
|
|
374
|
+
rb_inspect(low_val), rb_inspect(high_val));
|
|
375
|
+
}
|
|
376
|
+
last = high_is_closed ? high_val
|
|
377
|
+
: rb_funcall(high_val, '-', 1, INT2FIX(1));
|
|
378
|
+
if (RTEST(rb_funcall(low_val, '>', 1, last))) {
|
|
366
379
|
rb_raise(rb_eArgError,
|
|
367
380
|
"random: low must be less than high "
|
|
368
|
-
"(got low=%
|
|
369
|
-
|
|
381
|
+
"(got low=%"PRIsVALUE", high=%"PRIsVALUE")",
|
|
382
|
+
low_val, high_val);
|
|
383
|
+
}
|
|
384
|
+
switch (ca->data_type) {
|
|
385
|
+
case CA_INT8: type_min = INT2FIX(INT8_MIN); type_max = INT2FIX(INT8_MAX); break;
|
|
386
|
+
case CA_UINT8: type_min = INT2FIX(0); type_max = INT2FIX(UINT8_MAX); break;
|
|
387
|
+
case CA_INT16: type_min = INT2FIX(INT16_MIN); type_max = INT2FIX(INT16_MAX); break;
|
|
388
|
+
case CA_UINT16: type_min = INT2FIX(0); type_max = INT2FIX(UINT16_MAX); break;
|
|
389
|
+
case CA_INT32: type_min = LL2NUM(INT32_MIN); type_max = LL2NUM(INT32_MAX); break;
|
|
390
|
+
case CA_UINT32: type_min = INT2FIX(0); type_max = ULL2NUM(UINT32_MAX); break;
|
|
391
|
+
case CA_INT64: type_min = LL2NUM(INT64_MIN); type_max = LL2NUM(INT64_MAX); break;
|
|
392
|
+
default: type_min = INT2FIX(0); type_max = ULL2NUM(UINT64_MAX); break;
|
|
393
|
+
}
|
|
394
|
+
if (RTEST(rb_funcall(low_val, '<', 1, type_min)) ||
|
|
395
|
+
RTEST(rb_funcall(last, '>', 1, type_max))) {
|
|
396
|
+
rb_raise(rb_eRangeError,
|
|
397
|
+
"random: the values %"PRIsVALUE"..%"PRIsVALUE" are not all %s "
|
|
398
|
+
"(%"PRIsVALUE"..%"PRIsVALUE")",
|
|
399
|
+
low_val, last, ca_type_name[ca->data_type], type_min, type_max);
|
|
370
400
|
}
|
|
371
|
-
|
|
401
|
+
low_long = RTEST(rb_funcall(low_val, '<', 1, INT2FIX(0)))
|
|
402
|
+
? (long) NUM2LL(low_val) : (long) NUM2ULL(low_val);
|
|
403
|
+
limit = (unsigned long) NUM2ULL(rb_funcall(last, '-', 1, low_val));
|
|
404
|
+
(void) high_long;
|
|
372
405
|
} else {
|
|
373
406
|
low_dbl = NUM2DBL(low_val);
|
|
374
407
|
high_dbl = NUM2DBL(high_val);
|
|
408
|
+
if (!isfinite(low_dbl) || !isfinite(high_dbl)) {
|
|
409
|
+
rb_raise(rb_eArgError,
|
|
410
|
+
"random: the bounds are finite numbers "
|
|
411
|
+
"(got low=%g, high=%g)", low_dbl, high_dbl);
|
|
412
|
+
}
|
|
375
413
|
if (low_dbl >= high_dbl) {
|
|
376
414
|
rb_raise(rb_eArgError,
|
|
377
415
|
"random: low must be less than high "
|
|
@@ -382,7 +420,7 @@ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
|
|
|
382
420
|
}
|
|
383
421
|
|
|
384
422
|
{
|
|
385
|
-
ca_random_ctx_t c;
|
|
423
|
+
ca_random_ctx_t c = { 0 };
|
|
386
424
|
c.ca = ca;
|
|
387
425
|
c.n = ca->elements;
|
|
388
426
|
c.is_default = is_default;
|
|
@@ -392,6 +430,8 @@ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
|
|
|
392
430
|
c.limit = limit;
|
|
393
431
|
ca_random_run(&c, rng, ca_random_bang_fill);
|
|
394
432
|
}
|
|
433
|
+
/* Every cell now holds a value, as after seq! or fill. */
|
|
434
|
+
ca_clear_mask(ca);
|
|
395
435
|
return self;
|
|
396
436
|
}
|
|
397
437
|
|
|
@@ -560,11 +600,13 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
|
560
600
|
}
|
|
561
601
|
|
|
562
602
|
{
|
|
563
|
-
ca_random_ctx_t c;
|
|
603
|
+
ca_random_ctx_t c = { 0 };
|
|
564
604
|
c.ca = ca;
|
|
565
605
|
c.n = ca->elements;
|
|
566
606
|
ca_random_run(&c, rng, ca_randomn_bang_fill);
|
|
567
607
|
}
|
|
608
|
+
/* Every cell now holds a value, as after seq! or fill. */
|
|
609
|
+
ca_clear_mask(ca);
|
|
568
610
|
return self;
|
|
569
611
|
}
|
|
570
612
|
|
|
@@ -600,12 +642,16 @@ ca_shuffle_bang_fill (VALUE arg)
|
|
|
600
642
|
ca_size_t elem_bytes = ca->bytes;
|
|
601
643
|
char *tmp = ALLOCV_N(char, tmp_holder, elem_bytes);
|
|
602
644
|
char *p = ca->ptr;
|
|
645
|
+
char *m = c->mask ? c->mask->ptr : NULL;
|
|
603
646
|
|
|
604
647
|
n = ca->elements;
|
|
605
648
|
for (ca_size_t i = n - 1; i > 0; i--) {
|
|
606
649
|
unsigned long j = ca_random_ulong_limited(&c->source, (unsigned long)i);
|
|
607
650
|
if ((ca_size_t)j != i) {
|
|
608
651
|
swap_chunks(p + i * elem_bytes, p + j * elem_bytes, elem_bytes, tmp);
|
|
652
|
+
if ( m ) {
|
|
653
|
+
char b = m[i]; m[i] = m[j]; m[j] = b;
|
|
654
|
+
}
|
|
609
655
|
}
|
|
610
656
|
}
|
|
611
657
|
ALLOCV_END(tmp_holder);
|
|
@@ -630,12 +676,16 @@ ca_shuffle_bang_fill (VALUE arg)
|
|
|
630
676
|
|
|
631
677
|
for (ca_size_t o = 0; o < outer; o++) {
|
|
632
678
|
char *base = ca->ptr + o * stride;
|
|
679
|
+
char *mbase = c->mask ? c->mask->ptr + o * n * inner : NULL;
|
|
633
680
|
for (ca_size_t i = n - 1; i > 0; i--) {
|
|
634
681
|
unsigned long j = ca_random_ulong_limited(&c->source, (unsigned long)i);
|
|
635
682
|
if ((ca_size_t)j != i) {
|
|
636
683
|
swap_chunks(base + i * chunk_bytes,
|
|
637
684
|
base + j * chunk_bytes,
|
|
638
685
|
chunk_bytes, tmp);
|
|
686
|
+
if ( mbase ) {
|
|
687
|
+
swap_chunks(mbase + i * inner, mbase + j * inner, inner, tmp);
|
|
688
|
+
}
|
|
639
689
|
}
|
|
640
690
|
}
|
|
641
691
|
}
|
|
@@ -650,7 +700,7 @@ rb_ca_shuffle_bang(int argc, VALUE *argv, VALUE self)
|
|
|
650
700
|
CArray *ca;
|
|
651
701
|
VALUE opts = Qnil, v_axis = Qnil;
|
|
652
702
|
int axis = -1;
|
|
653
|
-
ca_random_ctx_t c;
|
|
703
|
+
ca_random_ctx_t c = { 0 };
|
|
654
704
|
|
|
655
705
|
rb_scan_args(argc, argv, "0:", &opts);
|
|
656
706
|
VALUE rng = Qnil;
|
|
@@ -662,7 +712,7 @@ rb_ca_shuffle_bang(int argc, VALUE *argv, VALUE self)
|
|
|
662
712
|
if (ca->elements <= 1) return self;
|
|
663
713
|
|
|
664
714
|
if (!NIL_P(v_axis)) {
|
|
665
|
-
axis =
|
|
715
|
+
axis = ca_normalize_axis_arg(v_axis, ca->ndim, NULL);
|
|
666
716
|
if (ca->dim[axis] <= 1) {
|
|
667
717
|
return self;
|
|
668
718
|
}
|
|
@@ -670,6 +720,10 @@ rb_ca_shuffle_bang(int argc, VALUE *argv, VALUE self)
|
|
|
670
720
|
|
|
671
721
|
c.ca = ca;
|
|
672
722
|
c.axis = axis;
|
|
723
|
+
/* The mask moves with the values: a masked cell stays masked wherever
|
|
724
|
+
it lands. */
|
|
725
|
+
ca_update_mask(ca);
|
|
726
|
+
c.mask = ca->mask;
|
|
673
727
|
ca_random_run(&c, rng, ca_shuffle_bang_fill);
|
|
674
728
|
return self;
|
|
675
729
|
}
|
data/ext/carray_round.c
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/* ---------------------------------------------------------------------------
|
|
2
|
+
|
|
3
|
+
CArray#round(ndigits) and #round!(ndigits): each element rounded as Ruby's
|
|
4
|
+
Float#round(ndigits) and Integer#round(ndigits) round it, half away from
|
|
5
|
+
zero. The argument-free forms are the generated monop kernels; this file
|
|
6
|
+
takes over the method and hands them the calls without an argument.
|
|
7
|
+
|
|
8
|
+
---------------------------------------------------------------------------- */
|
|
9
|
+
|
|
10
|
+
#include <math.h>
|
|
11
|
+
#include <float.h>
|
|
12
|
+
|
|
13
|
+
#include "carray.h"
|
|
14
|
+
#include "carray_internal.h"
|
|
15
|
+
#include "ca_obj_face.h"
|
|
16
|
+
|
|
17
|
+
VALUE rb_ca_round (VALUE self); /* generated: round without digits */
|
|
18
|
+
VALUE rb_ca_round_bang (VALUE self);
|
|
19
|
+
|
|
20
|
+
static ID id_round;
|
|
21
|
+
|
|
22
|
+
/* The rounding of Float#round for ndigits > 0 (numeric.c, round_half_up
|
|
23
|
+
with its check for a product that came out one short). */
|
|
24
|
+
static double
|
|
25
|
+
ca_round_half_up (double x, double s)
|
|
26
|
+
{
|
|
27
|
+
double f, xs = x * s;
|
|
28
|
+
|
|
29
|
+
f = round(xs);
|
|
30
|
+
if ( x > 0 ) {
|
|
31
|
+
if ( (double)((f + 0.5) / s) <= x ) f += 1;
|
|
32
|
+
x = f;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
if ( (double)((f - 0.5) / s) >= x ) f -= 1;
|
|
36
|
+
x = f;
|
|
37
|
+
}
|
|
38
|
+
return x;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* numeric.c: float_round_overflow / float_round_underflow. When the first
|
|
42
|
+
holds, number * 10**ndigits is already an integer and the number is its
|
|
43
|
+
own answer; when the second holds, the answer is 0. */
|
|
44
|
+
static int
|
|
45
|
+
ca_round_overflow (long ndigits, int binexp)
|
|
46
|
+
{
|
|
47
|
+
enum { float_dig = DBL_DIG + 2 };
|
|
48
|
+
return ndigits >= float_dig - (binexp > 0 ? binexp / 4 : binexp / 3 - 1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static int
|
|
52
|
+
ca_round_underflow (long ndigits, int binexp)
|
|
53
|
+
{
|
|
54
|
+
return ndigits < - (binexp > 0 ? binexp / 3 + 1 : binexp / 4);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* An integer |x| rounded to a multiple of 10**k (k >= 1), half away from
|
|
58
|
+
zero, as Integer#round(-k). Returns 0 when the answer does not fit in
|
|
59
|
+
64 bits, and sets *overflow. */
|
|
60
|
+
static uint64_t
|
|
61
|
+
ca_round_uint64 (uint64_t ax, long k, int *overflow)
|
|
62
|
+
{
|
|
63
|
+
uint64_t y = 1, q, rem, r;
|
|
64
|
+
long i;
|
|
65
|
+
|
|
66
|
+
*overflow = 0;
|
|
67
|
+
if ( k > 19 ) { /* 10**20 / 2 exceeds every 64-bit value */
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
for (i = 0; i < k; i++) {
|
|
71
|
+
y *= 10;
|
|
72
|
+
}
|
|
73
|
+
q = ax / y;
|
|
74
|
+
rem = ax % y;
|
|
75
|
+
r = q * y;
|
|
76
|
+
if ( rem >= y - y / 2 ) { /* rem * 2 >= y, without overflow */
|
|
77
|
+
if ( r > UINT64_MAX - y ) {
|
|
78
|
+
*overflow = 1;
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
r += y;
|
|
82
|
+
}
|
|
83
|
+
return r;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* x rounded as Float#round(ndigits) rounds it, for ndigits != 0. NaN and
|
|
87
|
+
the infinities are their own answer (Float#round raises for them when
|
|
88
|
+
ndigits <= 0; an array of floats keeps them as values). */
|
|
89
|
+
static double
|
|
90
|
+
ca_round_double (double x, long ndigits)
|
|
91
|
+
{
|
|
92
|
+
int binexp;
|
|
93
|
+
|
|
94
|
+
if ( x == 0.0 || ! isfinite(x) ) {
|
|
95
|
+
return x;
|
|
96
|
+
}
|
|
97
|
+
if ( ndigits > 0 ) {
|
|
98
|
+
frexp(x, &binexp);
|
|
99
|
+
if ( ca_round_overflow(ndigits, binexp) ) {
|
|
100
|
+
return x;
|
|
101
|
+
}
|
|
102
|
+
if ( ca_round_underflow(ndigits, binexp) ) {
|
|
103
|
+
return 0.0;
|
|
104
|
+
}
|
|
105
|
+
if ( ndigits > 14 ) {
|
|
106
|
+
/* pow(10, ndigits) may not be exact; Ruby rounds through a Rational. */
|
|
107
|
+
return NUM2DBL(rb_funcall(DBL2NUM(x), id_round, 1, LONG2NUM(ndigits)));
|
|
108
|
+
}
|
|
109
|
+
{
|
|
110
|
+
double f = pow(10, (double) ndigits);
|
|
111
|
+
return ca_round_half_up(x, f) / f;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
/* Ruby truncates to an Integer, then rounds the Integer. */
|
|
116
|
+
double t = trunc(x);
|
|
117
|
+
if ( fabs(t) < 18446744073709551616.0 ) { /* 2**64 */
|
|
118
|
+
int overflow;
|
|
119
|
+
uint64_t r = ca_round_uint64((uint64_t) fabs(t), -ndigits, &overflow);
|
|
120
|
+
if ( ! overflow ) {
|
|
121
|
+
return ( t < 0 ) ? -(double) r : (double) r;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return NUM2DBL(rb_funcall(DBL2NUM(x), id_round, 1, LONG2NUM(ndigits)));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
#define ROUND_INT_LOOP(type, lo, hi, is_signed) \
|
|
129
|
+
{ \
|
|
130
|
+
type *p = (type *) ca->ptr; \
|
|
131
|
+
for (i = 0; i < ca->elements; i++) { \
|
|
132
|
+
int neg, overflow; \
|
|
133
|
+
uint64_t ax, r; \
|
|
134
|
+
if ( m && m[i] ) continue; \
|
|
135
|
+
neg = ( is_signed ) && ( (int64_t) p[i] < 0 ); \
|
|
136
|
+
ax = neg ? (uint64_t) 0 - (uint64_t)(int64_t) p[i] : (uint64_t) p[i]; \
|
|
137
|
+
r = ca_round_uint64(ax, -ndigits, &overflow); \
|
|
138
|
+
if ( overflow || ( neg ? r > (uint64_t) 0 - (uint64_t)(int64_t)(lo) \
|
|
139
|
+
: r > (uint64_t)(hi) ) ) { \
|
|
140
|
+
rb_raise(rb_eRangeError, \
|
|
141
|
+
"round: a value rounded to %ld digits does not fit " \
|
|
142
|
+
"data_type %s", ndigits, ca_type_name[ca->data_type]); \
|
|
143
|
+
} \
|
|
144
|
+
p[i] = neg ? (type)((uint64_t) 0 - r) : (type) r; \
|
|
145
|
+
} \
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* Rounds the cells of the entity `ca` in place; masked cells are left. */
|
|
149
|
+
static void
|
|
150
|
+
ca_round_entity (CArray *ca, long ndigits)
|
|
151
|
+
{
|
|
152
|
+
boolean8_t *m = NULL;
|
|
153
|
+
ca_size_t i;
|
|
154
|
+
|
|
155
|
+
if ( ca->mask ) {
|
|
156
|
+
m = (boolean8_t *) ca->mask->ptr;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
switch ( ca->data_type ) {
|
|
160
|
+
case CA_INT8: ROUND_INT_LOOP(int8_t, INT8_MIN, INT8_MAX, 1); break;
|
|
161
|
+
case CA_UINT8: ROUND_INT_LOOP(uint8_t, 0, UINT8_MAX, 0); break;
|
|
162
|
+
case CA_INT16: ROUND_INT_LOOP(int16_t, INT16_MIN, INT16_MAX, 1); break;
|
|
163
|
+
case CA_UINT16: ROUND_INT_LOOP(uint16_t, 0, UINT16_MAX, 0); break;
|
|
164
|
+
case CA_INT32: ROUND_INT_LOOP(int32_t, INT32_MIN, INT32_MAX, 1); break;
|
|
165
|
+
case CA_UINT32: ROUND_INT_LOOP(uint32_t, 0, UINT32_MAX, 0); break;
|
|
166
|
+
case CA_INT64: ROUND_INT_LOOP(int64_t, INT64_MIN, INT64_MAX, 1); break;
|
|
167
|
+
case CA_UINT64: ROUND_INT_LOOP(uint64_t, 0, UINT64_MAX, 0); break;
|
|
168
|
+
case CA_FLOAT32: {
|
|
169
|
+
float32_t *p = (float32_t *) ca->ptr;
|
|
170
|
+
for (i = 0; i < ca->elements; i++) {
|
|
171
|
+
if ( m && m[i] ) continue;
|
|
172
|
+
p[i] = (float32_t) ca_round_double((double) p[i], ndigits);
|
|
173
|
+
}
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
case CA_FLOAT64: {
|
|
177
|
+
float64_t *p = (float64_t *) ca->ptr;
|
|
178
|
+
for (i = 0; i < ca->elements; i++) {
|
|
179
|
+
if ( m && m[i] ) continue;
|
|
180
|
+
p[i] = ca_round_double(p[i], ndigits);
|
|
181
|
+
}
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
case CA_OBJECT: {
|
|
185
|
+
VALUE *p = (VALUE *) ca->ptr;
|
|
186
|
+
volatile VALUE nd = LONG2NUM(ndigits);
|
|
187
|
+
for (i = 0; i < ca->elements; i++) {
|
|
188
|
+
if ( m && m[i] ) continue;
|
|
189
|
+
p[i] = rb_funcall(p[i], id_round, 1, nd);
|
|
190
|
+
}
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
default:
|
|
194
|
+
rb_raise(rb_eCADataTypeError, "round: not defined for data_type %s",
|
|
195
|
+
ca_type_name[ca->data_type]);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* The array to round: a boolean is rounded as its 0/1 int64 values, as
|
|
200
|
+
round without digits does. */
|
|
201
|
+
static VALUE
|
|
202
|
+
ca_round_source (VALUE self, VALUE vdigits, long *ndigits)
|
|
203
|
+
{
|
|
204
|
+
CArray *ca;
|
|
205
|
+
*ndigits = ca_integer_arg(vdigits, "ndigits", "round");
|
|
206
|
+
ca_face_refuse_numeric(self, "round", rb_eCADataTypeError);
|
|
207
|
+
GetCArray(self, ca);
|
|
208
|
+
if ( ca->data_type == CA_BOOLEAN ) {
|
|
209
|
+
self = rb_ca_wrap_readonly(self, INT2NUM(CA_INT64));
|
|
210
|
+
}
|
|
211
|
+
return self;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/* A copy of `src` rounded to `ndigits`. Rounding to 0 digits is what round
|
|
215
|
+
without digits does (except for objects, which are asked with the digits);
|
|
216
|
+
an integer has no digits below 10**0 to round. */
|
|
217
|
+
static VALUE
|
|
218
|
+
ca_round_copy (VALUE src, long ndigits)
|
|
219
|
+
{
|
|
220
|
+
volatile VALUE out;
|
|
221
|
+
CArray *ca, *co;
|
|
222
|
+
GetCArray(src, ca);
|
|
223
|
+
if ( ndigits == 0 && ca->data_type != CA_OBJECT ) {
|
|
224
|
+
return rb_ca_round(src);
|
|
225
|
+
}
|
|
226
|
+
out = rb_ca_copy(src);
|
|
227
|
+
GetCArray(out, co);
|
|
228
|
+
if ( ndigits > 0 && ca_is_integer_type(co) ) {
|
|
229
|
+
return out;
|
|
230
|
+
}
|
|
231
|
+
ca_round_entity(co, ndigits);
|
|
232
|
+
return out;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
static VALUE
|
|
236
|
+
rb_ca_round_digits (int argc, VALUE *argv, VALUE self)
|
|
237
|
+
{
|
|
238
|
+
long ndigits;
|
|
239
|
+
rb_check_arity(argc, 0, 1);
|
|
240
|
+
if ( argc == 0 ) {
|
|
241
|
+
return rb_ca_round(self);
|
|
242
|
+
}
|
|
243
|
+
self = ca_round_source(self, argv[0], &ndigits);
|
|
244
|
+
return ca_round_copy(self, ndigits);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
static VALUE
|
|
248
|
+
rb_ca_round_digits_bang (int argc, VALUE *argv, VALUE self)
|
|
249
|
+
{
|
|
250
|
+
long ndigits;
|
|
251
|
+
volatile VALUE src, out;
|
|
252
|
+
rb_check_arity(argc, 0, 1);
|
|
253
|
+
if ( argc == 0 ) {
|
|
254
|
+
return rb_ca_round_bang(self);
|
|
255
|
+
}
|
|
256
|
+
rb_ca_modify(self);
|
|
257
|
+
src = ca_round_source(self, argv[0], &ndigits);
|
|
258
|
+
if ( src != self ) {
|
|
259
|
+
rb_raise(rb_eCADataTypeError,
|
|
260
|
+
"round!: a boolean array can not hold the rounded int64 values");
|
|
261
|
+
}
|
|
262
|
+
out = ca_round_copy(self, ndigits);
|
|
263
|
+
rb_ca_store_all(self, out);
|
|
264
|
+
return self;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
void
|
|
268
|
+
Init_carray_round (void)
|
|
269
|
+
{
|
|
270
|
+
id_round = rb_intern("round");
|
|
271
|
+
rb_define_method(rb_cCArray, "round", rb_ca_round_digits, -1);
|
|
272
|
+
rb_define_method(rb_cCArray, "round!", rb_ca_round_digits_bang, -1);
|
|
273
|
+
}
|