carray 3.0.4 → 3.0.6
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 +438 -0
- data/README.md +1 -1
- data/carray.gemspec +3 -2
- data/ext/ca_array_pool.c +25 -1
- data/ext/ca_axis_dispatch.c +19 -20
- data/ext/ca_axis_group.c +1 -1
- data/ext/ca_categorical_iterator.c +34 -27
- data/ext/ca_compare.c +4 -4
- data/ext/ca_composite_dispatch.c +9 -9
- data/ext/ca_kernel_iterator.c +122 -237
- data/ext/ca_kernel_iterator.h +522 -337
- data/ext/ca_obj_array.c +69 -19
- data/ext/ca_obj_bincmp.c +10 -1
- data/ext/ca_obj_binop.c +11 -1
- data/ext/ca_obj_bitarray.c +5 -1
- data/ext/ca_obj_bitfield.c +60 -43
- data/ext/ca_obj_byte_swap.c +4 -1
- data/ext/ca_obj_const_string.c +15 -3
- data/ext/ca_obj_face.c +44 -1
- data/ext/ca_obj_fake.c +3 -1
- data/ext/ca_obj_field.c +13 -3
- data/ext/ca_obj_grid.c +219 -17
- data/ext/ca_obj_meld.c +69 -113
- data/ext/ca_obj_moncmp.c +9 -1
- data/ext/ca_obj_monop.c +86 -12
- data/ext/ca_obj_object.c +118 -32
- data/ext/ca_obj_record.c +3 -0
- data/ext/ca_obj_reduce.c +19 -1
- data/ext/ca_obj_refer.c +80 -26
- data/ext/ca_obj_remap.c +69 -10
- data/ext/ca_obj_roll.c +27 -6
- data/ext/ca_obj_select.c +38 -6
- data/ext/ca_obj_select_axis.c +1 -0
- data/ext/ca_obj_shift.c +32 -7
- data/ext/ca_obj_stack.c +311 -111
- data/ext/ca_obj_stride.c +159 -64
- data/ext/ca_obj_string.c +27 -2
- data/ext/ca_obj_tile.c +28 -7
- data/ext/ca_obj_transpose.c +8 -4
- data/ext/ca_obj_triop.c +12 -1
- data/ext/ca_obj_window.c +80 -50
- data/ext/ca_op_ipower.c +12 -12
- data/ext/ca_sort_kernels.h +6 -3
- data/ext/caframe_csv_reader.c +1 -1
- data/ext/carray.h +35 -1
- data/ext/carray_access.c +43 -67
- data/ext/carray_address_basis.c +134 -0
- data/ext/carray_attribute.c +32 -0
- data/ext/carray_broadcast.c +3 -4
- data/ext/carray_build_flags.h +1 -1
- data/ext/carray_cast.c +251 -93
- data/ext/carray_cast_func.rb +56 -26
- data/ext/carray_conversion.c +11 -7
- data/ext/carray_core.c +814 -72
- data/ext/carray_count.c +6 -0
- data/ext/carray_element.c +22 -13
- data/ext/carray_factorize.c +20 -20
- data/ext/carray_generate.c +8 -2
- data/ext/carray_histogram.c +26 -4
- data/ext/carray_index_classifier.c +4 -4
- data/ext/carray_internal.h +159 -12
- data/ext/carray_kernels_bincmp.c +2174 -170
- data/ext/carray_kernels_binop.c +25653 -5487
- data/ext/carray_kernels_init.c +8 -8
- data/ext/carray_kernels_moncmp.c +96 -96
- data/ext/carray_kernels_monop.c +12253 -5235
- data/ext/carray_kernels_reduce_aggregate.c +6150 -2423
- data/ext/carray_kernels_reduce_boolean.c +1533 -15
- data/ext/carray_kernels_reduce_cumulative.c +2442 -882
- data/ext/carray_kernels_reduce_extreme.c +5658 -1661
- data/ext/carray_kernels_reduce_variance.c +2534 -402
- data/ext/carray_kernels_scan.c +368 -368
- data/ext/carray_kernels_search.c +4551 -604
- data/ext/carray_kernels_sort.c +659 -751
- data/ext/carray_kernels_triop.c +114 -114
- data/ext/carray_key_windows.c +4 -0
- data/ext/carray_lazy.c +47 -0
- data/ext/carray_loop.c +1 -1
- data/ext/carray_mask.c +175 -161
- data/ext/carray_median_percentile.c +4 -4
- data/ext/carray_memory_view.c +15 -9
- data/ext/carray_operator.c +152 -49
- data/ext/carray_order.c +230 -10
- data/ext/carray_random.c +22 -19
- data/ext/carray_scatter.c +24 -7
- data/ext/carray_slab.c +128 -29
- data/ext/carray_sort.c +224 -16
- data/ext/carray_sort_kernel.c +5 -7
- data/ext/carray_struct.c +35 -43
- data/ext/carray_test.c +74 -19
- data/ext/carray_time_text.c +6 -4
- data/ext/carray_utils.c +63 -21
- data/ext/extconf.rb +11 -0
- data/ext/mkkernel.rb +546 -199
- data/ext/ruby_carray.c +4 -1
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +42 -5
- data/lib/carray/autoload_carray.rb +3 -3
- data/lib/carray/autoload_method_extension.rb +5 -3
- data/lib/carray/axis_group.rb +13 -7
- data/lib/carray/basics.rb +28 -8
- data/lib/carray/block_iterator.rb +17 -3
- data/lib/carray/categorical.rb +35 -23
- data/lib/carray/categorical_iterator.rb +8 -8
- data/lib/carray/complex.rb +2 -2
- data/lib/carray/conditional.rb +3 -2
- data/lib/carray/const_string.rb +10 -0
- data/lib/carray/data_type_extension.rb +8 -1
- data/lib/carray/fixlen_string.rb +41 -2
- data/lib/carray/frame/column_verbs.rb +48 -16
- data/lib/carray/frame/concat.rb +17 -3
- data/lib/carray/frame/convert.rb +19 -0
- data/lib/carray/frame/csv_parser.rb +32 -32
- data/lib/carray/frame/describe.rb +4 -2
- data/lib/carray/frame/frame.rb +405 -85
- data/lib/carray/frame/group.rb +777 -64
- data/lib/carray/frame/io.rb +212 -72
- data/lib/carray/frame/join.rb +146 -37
- data/lib/carray/frame/records.rb +3 -3
- data/lib/carray/frame/reshape.rb +89 -11
- data/lib/carray/frame/sort.rb +57 -9
- data/lib/carray/frame/verbs.rb +384 -49
- data/lib/carray/frame/windows.rb +44 -6
- data/lib/carray/fuse_source.rb +31 -2
- data/lib/carray/inspect.rb +7 -2
- data/lib/carray/iterator.rb +32 -0
- data/lib/carray/lazy.rb +52 -8
- data/lib/carray/mask_gap_fill.rb +37 -17
- data/lib/carray/meld_reduce.rb +1 -1
- data/lib/carray/methods/choose.rb +3 -2
- data/lib/carray/methods/is_in.rb +8 -1
- data/lib/carray/methods/meshgrid.rb +3 -1
- data/lib/carray/runtime.rb +47 -8
- data/lib/carray/segment_iterator.rb +35 -16
- data/lib/carray/serialize.rb +53 -19
- data/lib/carray/stack.rb +33 -18
- data/lib/carray/string.rb +8 -0
- data/lib/carray/string_operation_extension.rb +13 -5
- data/lib/carray/struct_builder.rb +5 -3
- data/lib/carray/time.rb +112 -68
- data/lib/carray/window_iterator.rb +16 -4
- data/yard-stubs/ca_obj_array.rb +26 -1
- data/yard-stubs/ca_obj_transpose.rb +5 -4
- data/yard-stubs/carray_attribute.rb +3 -1
- data/yard-stubs/carray_cast.rb +10 -5
- data/yard-stubs/carray_conversion.rb +13 -3
- data/yard-stubs/carray_element.rb +7 -6
- data/yard-stubs/carray_mask.rb +28 -4
- data/yard-stubs/carray_math.rb +45 -20
- data/yard-stubs/carray_memory_view.rb +7 -0
- data/yard-stubs/carray_order.rb +100 -4
- data/yard-stubs/carray_scatter.rb +7 -5
- data/yard-stubs/carray_test.rb +7 -4
- metadata +18 -4
data/ext/carray_count.c
CHANGED
|
@@ -252,8 +252,10 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
252
252
|
int8_t slab_axes[CA_RANK_MAX];
|
|
253
253
|
int8_t naxes;
|
|
254
254
|
VALUE axis_val = Qnil;
|
|
255
|
+
int keep_axis = 0;
|
|
255
256
|
if ( ! NIL_P(opt_hash) ) {
|
|
256
257
|
axis_val = rb_hash_lookup2(opt_hash, ID2SYM(rb_intern("axis")), Qnil);
|
|
258
|
+
keep_axis = RTEST(rb_hash_lookup2(opt_hash, ID2SYM(rb_intern("keep_axis")), Qfalse));
|
|
257
259
|
}
|
|
258
260
|
naxes = rb_ca_parse_reduce_axes_kw(axis_val, src, slab_axes);
|
|
259
261
|
(void) inner_axes; /* axes no longer parsed from inner_axes */
|
|
@@ -270,6 +272,9 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
270
272
|
out_dim[out_ndim++] = src->dim[k];
|
|
271
273
|
base_elements *= src->dim[k];
|
|
272
274
|
}
|
|
275
|
+
else if ( keep_axis ) {
|
|
276
|
+
out_dim[out_ndim++] = 1; /* the reduced axis kept at length 1 */
|
|
277
|
+
}
|
|
273
278
|
}
|
|
274
279
|
/* Full reduction (naxes == ndim): base_elements = 1, no base axes. */
|
|
275
280
|
/* Append v.shape. */
|
|
@@ -377,6 +382,7 @@ rb_ca_count (int argc, VALUE *argv, VALUE self)
|
|
|
377
382
|
self = rb_ca_wrap_readonly(self, INT2NUM(qt));
|
|
378
383
|
}
|
|
379
384
|
}
|
|
385
|
+
self = ca_fixlen_widen_for_query(self, rval);
|
|
380
386
|
/* Pass full argv; count_equal_ki pops argv[0] as value_arg. */
|
|
381
387
|
return rb_ca_count_equal_ki(argc, argv, self);
|
|
382
388
|
}
|
data/ext/carray_element.c
CHANGED
|
@@ -20,17 +20,22 @@
|
|
|
20
20
|
#include "ca_obj_face.h"
|
|
21
21
|
#include "carray_internal.h" /* ca_obj_extremum_replaces */
|
|
22
22
|
|
|
23
|
-
/* An element index is
|
|
24
|
-
|
|
23
|
+
/* An element index is read as `[]` reads a key: an Integer, or a Float
|
|
24
|
+
with no fraction. */
|
|
25
25
|
static inline ca_size_t
|
|
26
26
|
elem_index_value (VALUE v)
|
|
27
27
|
{
|
|
28
|
+
ca_size_t k;
|
|
28
29
|
if ( FIXNUM_P(v) ) return (ca_size_t) FIX2LONG(v);
|
|
29
|
-
|
|
30
|
+
switch ( ca_index_key_position(v, &k) ) {
|
|
31
|
+
case 1:
|
|
32
|
+
return k;
|
|
33
|
+
case 2:
|
|
34
|
+
return CA_LENGTH_MAX; /* past int64: past every axis, refused as out of range */
|
|
35
|
+
default:
|
|
30
36
|
rb_raise(rb_eIndexError, "object '%"PRIsVALUE"' is invalid for an index",
|
|
31
37
|
rb_inspect(v));
|
|
32
38
|
}
|
|
33
|
-
return NUM2SIZE(v);
|
|
34
39
|
}
|
|
35
40
|
|
|
36
41
|
/* T_ARRAY index parser. ridx is assumed already known to be T_ARRAY.
|
|
@@ -77,8 +82,9 @@ elem_probe_mask (CArray *ca)
|
|
|
77
82
|
|
|
78
83
|
/* Entity-array fast path: compute flat addr from idx[] and access ptr directly.
|
|
79
84
|
Bypasses ca_func[ARRAY].xfer_index function-pointer dispatch.
|
|
80
|
-
Caller must ensure ca_is_entity(ca) and ca->ptr
|
|
81
|
-
|
|
85
|
+
Caller must ensure ca_is_entity(ca) and ca->ptr != NULL: an entity can
|
|
86
|
+
leave ptr NULL at rest (a CASource), and then the dispatched path is
|
|
87
|
+
the way in. */
|
|
82
88
|
static inline ca_size_t
|
|
83
89
|
elem_entity_addr (CArray *ca, ca_size_t *idx)
|
|
84
90
|
{
|
|
@@ -268,7 +274,7 @@ rb_ca_elem_store (VALUE self, VALUE ridx, VALUE obj)
|
|
|
268
274
|
Bypasses rb_ca_store_index/addr -> ca_update_mask + rb_ca_obj2ptr ->
|
|
269
275
|
cast_table dispatch. Falls through to general path for: views,
|
|
270
276
|
existing mask, non-numeric data type, UNDEF, or non-Numeric obj. */
|
|
271
|
-
if ( ca_is_entity(ca) && ! ca->mask && obj != CA_UNDEF ) {
|
|
277
|
+
if ( ca_is_entity(ca) && ca->ptr && ! ca->mask && obj != CA_UNDEF ) {
|
|
272
278
|
int8_t dt = ca->data_type;
|
|
273
279
|
if ( dt == CA_FLOAT64 || dt == CA_FLOAT32 ||
|
|
274
280
|
dt == CA_INT64 || dt == CA_INT32 ||
|
|
@@ -378,7 +384,7 @@ rb_ca_elem_fetch (VALUE self, VALUE ridx)
|
|
|
378
384
|
/* Super-hot path: entity + common numeric data type + no mask.
|
|
379
385
|
Bypass ca_fetch_index dispatch AND rb_ca_ptr2obj_storage cast-table dispatch.
|
|
380
386
|
Covers the bench's float64 / int64 / int32 cases. */
|
|
381
|
-
if ( ca_is_entity(ca) && ! ca->mask ) {
|
|
387
|
+
if ( ca_is_entity(ca) && ca->ptr && ! ca->mask ) {
|
|
382
388
|
ca_size_t addr = elem_entity_addr(ca, idx);
|
|
383
389
|
char *p = ca->ptr + ca->bytes * addr;
|
|
384
390
|
switch ( ca->data_type ) {
|
|
@@ -401,7 +407,7 @@ rb_ca_elem_fetch (VALUE self, VALUE ridx)
|
|
|
401
407
|
TypedData_Get_Struct). Semantics identical to rb_ca_fetch_index. */
|
|
402
408
|
if ( ca->bytes <= 64 ) {
|
|
403
409
|
char v[64];
|
|
404
|
-
if ( ca_is_entity(ca) ) {
|
|
410
|
+
if ( ca_is_entity(ca) && ca->ptr ) {
|
|
405
411
|
ca_size_t addr = elem_entity_addr(ca, idx);
|
|
406
412
|
memcpy(v, ca->ptr + ca->bytes * addr, ca->bytes);
|
|
407
413
|
}
|
|
@@ -434,12 +440,15 @@ rb_ca_elem_fetch (VALUE self, VALUE ridx)
|
|
|
434
440
|
}
|
|
435
441
|
|
|
436
442
|
CA_FACE_STORAGE_TO_ELEMENT_IF_FACE(out, self, ca);
|
|
443
|
+
if ( ca->data_type == CA_BOOLEAN ) {
|
|
444
|
+
out = RTEST(out) && out != INT2FIX(0) ? Qtrue : Qfalse;
|
|
445
|
+
}
|
|
437
446
|
return out;
|
|
438
447
|
}
|
|
439
448
|
else {
|
|
440
449
|
ca_size_t addr = elem_parse_idx_scalar(ca, ridx);
|
|
441
450
|
/* Super-hot flat-addr path: entity + numeric + no mask. */
|
|
442
|
-
if ( ca_is_entity(ca) && ! ca->mask ) {
|
|
451
|
+
if ( ca_is_entity(ca) && ca->ptr && ! ca->mask ) {
|
|
443
452
|
char *p = ca->ptr + ca->bytes * addr;
|
|
444
453
|
switch ( ca->data_type ) {
|
|
445
454
|
case CA_FLOAT64: return rb_float_new(*(double *)p);
|
|
@@ -488,7 +497,7 @@ rb_ca_elem_incr (VALUE self, VALUE ridx1)
|
|
|
488
497
|
|
|
489
498
|
/* Super-hot path: entity + no mask + integer data type.
|
|
490
499
|
Reads p directly, modifies in place — no separate fetch/store dispatch. */
|
|
491
|
-
if ( ca_is_entity(ca) && ! has_mask ) {
|
|
500
|
+
if ( ca_is_entity(ca) && ca->ptr && ! has_mask ) {
|
|
492
501
|
ca_size_t addr;
|
|
493
502
|
if ( TYPE(ridx1) == T_ARRAY ) {
|
|
494
503
|
elem_parse_idx_array(ca, ridx1, idx1);
|
|
@@ -578,7 +587,7 @@ rb_ca_elem_decr (VALUE self, VALUE ridx1)
|
|
|
578
587
|
has_mask = elem_probe_mask(ca);
|
|
579
588
|
|
|
580
589
|
/* Super-hot path: mirror of elem_incr. */
|
|
581
|
-
if ( ca_is_entity(ca) && ! has_mask ) {
|
|
590
|
+
if ( ca_is_entity(ca) && ca->ptr && ! has_mask ) {
|
|
582
591
|
ca_size_t addr;
|
|
583
592
|
if ( TYPE(ridx1) == T_ARRAY ) {
|
|
584
593
|
elem_parse_idx_array(ca, ridx1, idx1);
|
|
@@ -793,7 +802,7 @@ rb_ca_elem_unmask (VALUE self, VALUE ridx)
|
|
|
793
802
|
general path, which compares in Ruby and stores as `self[idx] = v`
|
|
794
803
|
does, so a value that wins but does not fit raises. */
|
|
795
804
|
#define ELEM_MINMAX_BODY(OP) do { \
|
|
796
|
-
if ( ca_is_entity(ca) ) { \
|
|
805
|
+
if ( ca_is_entity(ca) && ca->ptr ) { \
|
|
797
806
|
ca_size_t addr; \
|
|
798
807
|
if ( TYPE(ridx) == T_ARRAY ) { \
|
|
799
808
|
elem_parse_idx_array(ca, ridx, idx); \
|
data/ext/carray_factorize.c
CHANGED
|
@@ -865,7 +865,7 @@ fz_factorize_appearance_body (VALUE arg)
|
|
|
865
865
|
element to a 64-bit key; equality within one data type is preserved. */
|
|
866
866
|
#define FZ_LOOP(T, WIDEN) \
|
|
867
867
|
do { \
|
|
868
|
-
const T *ip = (const T *) p_in; \
|
|
868
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_in; \
|
|
869
869
|
uint32_t *op = (uint32_t *) p_out; \
|
|
870
870
|
for ( ca_size_t i = 0; i < n; i++ ) { \
|
|
871
871
|
if ( m && m[i] ) { op[i] = 0xFFFFFFFFu; continue; } \
|
|
@@ -884,7 +884,7 @@ fz_factorize_appearance_body (VALUE arg)
|
|
|
884
884
|
kept as-is), so masked source cells store the sentinel. */
|
|
885
885
|
#define FZ_LOOP_FLOAT(T) \
|
|
886
886
|
do { \
|
|
887
|
-
const T *ip = (const T *) p_in; \
|
|
887
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_in; \
|
|
888
888
|
uint32_t *op = (uint32_t *) p_out; \
|
|
889
889
|
for ( ca_size_t i = 0; i < n; i++ ) { \
|
|
890
890
|
if ( m && m[i] ) { op[i] = 0xFFFFFFFFu; continue; } \
|
|
@@ -1073,7 +1073,7 @@ fz_mask_duplicates_body (VALUE arg)
|
|
|
1073
1073
|
interns first appearances, so is_new == 0 flags a duplicate. */
|
|
1074
1074
|
#define MD_LOOP(T, WIDEN) \
|
|
1075
1075
|
do { \
|
|
1076
|
-
const T *ip = (const T *) p_in; \
|
|
1076
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_in; \
|
|
1077
1077
|
boolean8_t *op = (boolean8_t *) p_out; \
|
|
1078
1078
|
for ( ca_size_t i = 0; i < n; i++ ) { \
|
|
1079
1079
|
if ( m && m[i] ) { op[i] = 0; continue; } \
|
|
@@ -1091,7 +1091,7 @@ fz_mask_duplicates_body (VALUE arg)
|
|
|
1091
1091
|
before the bitwise key. */
|
|
1092
1092
|
#define MD_LOOP_FLOAT(T) \
|
|
1093
1093
|
do { \
|
|
1094
|
-
const T *ip = (const T *) p_in; \
|
|
1094
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_in; \
|
|
1095
1095
|
boolean8_t *op = (boolean8_t *) p_out; \
|
|
1096
1096
|
for ( ca_size_t i = 0; i < n; i++ ) { \
|
|
1097
1097
|
if ( m && m[i] ) { op[i] = 0; continue; } \
|
|
@@ -1225,7 +1225,7 @@ fz_unique_flat_body (VALUE arg)
|
|
|
1225
1225
|
|
|
1226
1226
|
#define UQ_LOOP(T, WIDEN) \
|
|
1227
1227
|
do { \
|
|
1228
|
-
const T *ip = (const T *) p_in; \
|
|
1228
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_in; \
|
|
1229
1229
|
for ( ca_size_t i = 0; i < n; i++ ) { \
|
|
1230
1230
|
if ( m && m[i] ) { continue; } \
|
|
1231
1231
|
uint64_t key = (uint64_t) (WIDEN ip[i]); \
|
|
@@ -1239,7 +1239,7 @@ fz_unique_flat_body (VALUE arg)
|
|
|
1239
1239
|
pushed level is the raw first-seen element. */
|
|
1240
1240
|
#define UQ_LOOP_FLOAT(T) \
|
|
1241
1241
|
do { \
|
|
1242
|
-
const T *ip = (const T *) p_in; \
|
|
1242
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_in; \
|
|
1243
1243
|
for ( ca_size_t i = 0; i < n; i++ ) { \
|
|
1244
1244
|
if ( m && m[i] ) { continue; } \
|
|
1245
1245
|
T v = ip[i]; \
|
|
@@ -1340,7 +1340,7 @@ fz_intern_all (ca_iter_state *st_v, fz_hash *h, CArray *cv, fz_levels *lv)
|
|
|
1340
1340
|
|
|
1341
1341
|
#define FZ_IA(T, WIDEN) \
|
|
1342
1342
|
do { \
|
|
1343
|
-
const T *ip = (const T *) p_v; \
|
|
1343
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_v; \
|
|
1344
1344
|
for ( ca_size_t i = 0; i < nv; i++ ) { \
|
|
1345
1345
|
if ( mv && mv[i] ) { continue; } \
|
|
1346
1346
|
uint64_t key = (uint64_t) (WIDEN ip[i]); \
|
|
@@ -1352,7 +1352,7 @@ fz_intern_all (ca_iter_state *st_v, fz_hash *h, CArray *cv, fz_levels *lv)
|
|
|
1352
1352
|
|
|
1353
1353
|
#define FZ_IA_FLOAT(T) \
|
|
1354
1354
|
do { \
|
|
1355
|
-
const T *ip = (const T *) p_v; \
|
|
1355
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_v; \
|
|
1356
1356
|
for ( ca_size_t i = 0; i < nv; i++ ) { \
|
|
1357
1357
|
if ( mv && mv[i] ) { continue; } \
|
|
1358
1358
|
T v = ip[i]; \
|
|
@@ -1493,7 +1493,7 @@ fz_is_in_body (VALUE arg)
|
|
|
1493
1493
|
|
|
1494
1494
|
#define IN_PROBE(T, WIDEN) \
|
|
1495
1495
|
do { \
|
|
1496
|
-
const T *ip = (const T *) p_in; \
|
|
1496
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_in; \
|
|
1497
1497
|
boolean8_t *op = (boolean8_t *) p_out; \
|
|
1498
1498
|
for ( ca_size_t i = 0; i < n; i++ ) { \
|
|
1499
1499
|
if ( m && m[i] ) { op[i] = 0; continue; } \
|
|
@@ -1504,7 +1504,7 @@ fz_is_in_body (VALUE arg)
|
|
|
1504
1504
|
|
|
1505
1505
|
#define IN_PROBE_FLOAT(T) \
|
|
1506
1506
|
do { \
|
|
1507
|
-
const T *ip = (const T *) p_in; \
|
|
1507
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_in; \
|
|
1508
1508
|
boolean8_t *op = (boolean8_t *) p_out; \
|
|
1509
1509
|
for ( ca_size_t i = 0; i < n; i++ ) { \
|
|
1510
1510
|
if ( m && m[i] ) { op[i] = 0; continue; } \
|
|
@@ -1661,7 +1661,7 @@ fz_locate_addr_body (VALUE arg)
|
|
|
1661
1661
|
|
|
1662
1662
|
#define LOC_BUILD(T, WIDEN) \
|
|
1663
1663
|
do { \
|
|
1664
|
-
const T *ip = (const T *) p_r; \
|
|
1664
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_r; \
|
|
1665
1665
|
for ( ca_size_t i = 0; i < nr; i++ ) { \
|
|
1666
1666
|
if ( mr && mr[i] ) { continue; } \
|
|
1667
1667
|
uint64_t key = (uint64_t) (WIDEN ip[i]); \
|
|
@@ -1674,7 +1674,7 @@ fz_locate_addr_body (VALUE arg)
|
|
|
1674
1674
|
|
|
1675
1675
|
#define LOC_BUILD_FLOAT(T) \
|
|
1676
1676
|
do { \
|
|
1677
|
-
const T *ip = (const T *) p_r; \
|
|
1677
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_r; \
|
|
1678
1678
|
for ( ca_size_t i = 0; i < nr; i++ ) { \
|
|
1679
1679
|
if ( mr && mr[i] ) { continue; } \
|
|
1680
1680
|
T v = ip[i]; \
|
|
@@ -1751,7 +1751,7 @@ fz_locate_addr_body (VALUE arg)
|
|
|
1751
1751
|
|
|
1752
1752
|
#define LOC_PROBE(T, WIDEN) \
|
|
1753
1753
|
do { \
|
|
1754
|
-
const T *ip = (const T *) p_in; \
|
|
1754
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_in; \
|
|
1755
1755
|
const int64_t *ab = (const int64_t *) addr.p; \
|
|
1756
1756
|
for ( ca_size_t i = 0; i < n; i++ ) { \
|
|
1757
1757
|
ca_size_t o = base + i; \
|
|
@@ -1765,7 +1765,7 @@ fz_locate_addr_body (VALUE arg)
|
|
|
1765
1765
|
|
|
1766
1766
|
#define LOC_PROBE_FLOAT(T) \
|
|
1767
1767
|
do { \
|
|
1768
|
-
const T *ip = (const T *) p_in; \
|
|
1768
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_in; \
|
|
1769
1769
|
const int64_t *ab = (const int64_t *) addr.p; \
|
|
1770
1770
|
for ( ca_size_t i = 0; i < n; i++ ) { \
|
|
1771
1771
|
ca_size_t o = base + i; \
|
|
@@ -1929,7 +1929,7 @@ fz_set_relation_body (VALUE arg)
|
|
|
1929
1929
|
|
|
1930
1930
|
#define SR(T, WIDEN) \
|
|
1931
1931
|
do { \
|
|
1932
|
-
const T *ip = (const T *) p; \
|
|
1932
|
+
const CA_U(T) *ip = (const CA_U(T) *) p; \
|
|
1933
1933
|
for ( ca_size_t i = 0; i < n; i++ ) { \
|
|
1934
1934
|
if ( m && m[i] ) { continue; } \
|
|
1935
1935
|
uint64_t key = (uint64_t) (WIDEN ip[i]); \
|
|
@@ -1943,7 +1943,7 @@ fz_set_relation_body (VALUE arg)
|
|
|
1943
1943
|
|
|
1944
1944
|
#define SR_FLOAT(T) \
|
|
1945
1945
|
do { \
|
|
1946
|
-
const T *ip = (const T *) p; \
|
|
1946
|
+
const CA_U(T) *ip = (const CA_U(T) *) p; \
|
|
1947
1947
|
for ( ca_size_t i = 0; i < n; i++ ) { \
|
|
1948
1948
|
if ( m && m[i] ) { continue; } \
|
|
1949
1949
|
T v = ip[i]; \
|
|
@@ -2188,7 +2188,7 @@ fz_value_counts_flat_body (VALUE arg)
|
|
|
2188
2188
|
|
|
2189
2189
|
#define VC_LOOP(T, WIDEN) \
|
|
2190
2190
|
do { \
|
|
2191
|
-
const T *ip = (const T *) p_in; \
|
|
2191
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_in; \
|
|
2192
2192
|
for ( ca_size_t i = 0; i < n; i++ ) { \
|
|
2193
2193
|
if ( m && m[i] ) { continue; } \
|
|
2194
2194
|
uint64_t key = (uint64_t) (WIDEN ip[i]); \
|
|
@@ -2206,7 +2206,7 @@ fz_value_counts_flat_body (VALUE arg)
|
|
|
2206
2206
|
|
|
2207
2207
|
#define VC_LOOP_FLOAT(T) \
|
|
2208
2208
|
do { \
|
|
2209
|
-
const T *ip = (const T *) p_in; \
|
|
2209
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_in; \
|
|
2210
2210
|
for ( ca_size_t i = 0; i < n; i++ ) { \
|
|
2211
2211
|
if ( m && m[i] ) { continue; } \
|
|
2212
2212
|
T v = ip[i]; \
|
|
@@ -2516,7 +2516,7 @@ fz_is_mode_body (VALUE arg)
|
|
|
2516
2516
|
/* Integer: WIDEN gives the key directly. Two passes over the fiber. */
|
|
2517
2517
|
#define IM_BODY(T, WIDEN) \
|
|
2518
2518
|
do { \
|
|
2519
|
-
const T *ip = (const T *) p_in; \
|
|
2519
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_in; \
|
|
2520
2520
|
boolean8_t *op = (boolean8_t *) p_out; \
|
|
2521
2521
|
for ( ca_size_t i = 0; i < n; i++ ) { \
|
|
2522
2522
|
if ( m && m[i] ) { continue; } \
|
|
@@ -2543,7 +2543,7 @@ fz_is_mode_body (VALUE arg)
|
|
|
2543
2543
|
/* Float: NaN collapses to one canonical key; -0.0 / +0.0 share a key. */
|
|
2544
2544
|
#define IM_BODY_FLOAT(T) \
|
|
2545
2545
|
do { \
|
|
2546
|
-
const T *ip = (const T *) p_in; \
|
|
2546
|
+
const CA_U(T) *ip = (const CA_U(T) *) p_in; \
|
|
2547
2547
|
boolean8_t *op = (boolean8_t *) p_out; \
|
|
2548
2548
|
for ( int pass = 0; pass < 2; pass++ ) { \
|
|
2549
2549
|
int64_t mx = 0; \
|
data/ext/carray_generate.c
CHANGED
|
@@ -117,7 +117,7 @@ ca_seq_is_real (VALUE v)
|
|
|
117
117
|
/* Fill the whole array in row-major order with `step*i + offset`. */
|
|
118
118
|
#define proc_seq_bang(type, from, to) \
|
|
119
119
|
{ \
|
|
120
|
-
type *p = (type *)ca->ptr; \
|
|
120
|
+
CA_U(type) *p = (CA_U(type) *)ca->ptr; \
|
|
121
121
|
ca_size_t i; \
|
|
122
122
|
if ( NIL_P(roffset) && NIL_P(rstep) ) { \
|
|
123
123
|
for (i=0; i<ca->elements; i++) { \
|
|
@@ -149,7 +149,7 @@ ca_seq_is_real (VALUE v)
|
|
|
149
149
|
`outer_size` come from the enclosing scope (ca_seq_geometry). */
|
|
150
150
|
#define proc_seq_bang_axis(type, from, to) \
|
|
151
151
|
{ \
|
|
152
|
-
type *p = (type *)ca->ptr; \
|
|
152
|
+
CA_U(type) *p = (CA_U(type) *)ca->ptr; \
|
|
153
153
|
ca_size_t o, k, in; \
|
|
154
154
|
if ( ca_seq_is_real(rstep) || ca_seq_is_real(roffset) ) { \
|
|
155
155
|
double offset = (NIL_P(roffset)) ? 0 : NUM2DBL(roffset); \
|
|
@@ -289,6 +289,9 @@ ca_seq_bang_object_body (VALUE arg)
|
|
|
289
289
|
}
|
|
290
290
|
else if ( ! NIL_P(rmethod) ) { /* a.seq(obj, :method) */
|
|
291
291
|
ID id_method = SYM2ID(rmethod);
|
|
292
|
+
if ( ca->elements == 0 ) { /* no first cell to write */
|
|
293
|
+
return Qnil;
|
|
294
|
+
}
|
|
292
295
|
*p++ = ca_seq_cell(c, rval = roffset);
|
|
293
296
|
for (i=1; i<ca->elements; i++) {
|
|
294
297
|
*p++ = ca_seq_cell(c, rval = rb_funcall(rval, id_method, 0));
|
|
@@ -297,6 +300,9 @@ ca_seq_bang_object_body (VALUE arg)
|
|
|
297
300
|
else { /* a.seq(obj, step) */
|
|
298
301
|
ID id_plus = rb_intern("+");
|
|
299
302
|
rstep = ( NIL_P(rstep) ) ? INT2NUM(1) : rstep;
|
|
303
|
+
if ( ca->elements == 0 ) { /* no first cell to write */
|
|
304
|
+
return Qnil;
|
|
305
|
+
}
|
|
300
306
|
*p++ = ca_seq_cell(c, rval = roffset);
|
|
301
307
|
for (i=1; i<ca->elements; i++) {
|
|
302
308
|
*p++ = ca_seq_cell(c, rval = rb_funcall(rval, id_plus, 1, rstep));
|
data/ext/carray_histogram.c
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
#include "carray.h"
|
|
26
26
|
#include "carray_internal.h" /* ca_attach_window */
|
|
27
27
|
#include <math.h>
|
|
28
|
+
#include <float.h>
|
|
28
29
|
|
|
29
30
|
/* Edges are the bin boundaries and must read as such: no masked edge (its
|
|
30
31
|
stored value is no boundary), no NaN, and no edge below the one before
|
|
@@ -88,6 +89,8 @@ typedef struct {
|
|
|
88
89
|
const double *ep;
|
|
89
90
|
ca_size_t n; /* number of bins */
|
|
90
91
|
double lo, hi, inv_dx;
|
|
92
|
+
double window; /* fraction of a bin within which the
|
|
93
|
+
linearised floor is checked */
|
|
91
94
|
int uniform;
|
|
92
95
|
int include_max;
|
|
93
96
|
} histbin_axis_t;
|
|
@@ -115,7 +118,7 @@ histbin_index (const histbin_axis_t *ax, double v)
|
|
|
115
118
|
Interior values (the bulk) skip the data-dependent edge loads, keeping
|
|
116
119
|
the fast path vectorisable. */
|
|
117
120
|
frac = pos - (double) k;
|
|
118
|
-
if ( frac <
|
|
121
|
+
if ( frac < ax->window || frac > 1.0 - ax->window ) {
|
|
119
122
|
while ( k + 1 < ax->n && v >= ax->ep[k + 1] ) k++;
|
|
120
123
|
while ( k > 0 && v < ax->ep[k] ) k--;
|
|
121
124
|
}
|
|
@@ -136,7 +139,7 @@ histbin_axis_setup (histbin_axis_t *ax, const double *ep, ca_size_t ne,
|
|
|
136
139
|
int include_max)
|
|
137
140
|
{
|
|
138
141
|
ca_size_t kk;
|
|
139
|
-
double dx, tol;
|
|
142
|
+
double dx, tol, maxdev;
|
|
140
143
|
|
|
141
144
|
ax->ep = ep;
|
|
142
145
|
ax->n = ne - 1;
|
|
@@ -149,8 +152,27 @@ histbin_axis_setup (histbin_axis_t *ax, const double *ep, ca_size_t ne,
|
|
|
149
152
|
width infinite, and a subnormal width makes the reciprocal infinite.
|
|
150
153
|
Either turns the position into NaN, which has no integer. */
|
|
151
154
|
ax->uniform = isfinite(dx) && dx != 0.0 && isfinite(1.0 / dx);
|
|
155
|
+
maxdev = 0.0;
|
|
152
156
|
for ( kk = 0; ax->uniform && kk <= ax->n; kk++ ) {
|
|
153
|
-
|
|
157
|
+
double dev = fabs(ax->ep[kk] - (ax->lo + (double) kk * dx));
|
|
158
|
+
if ( dev > tol ) { ax->uniform = 0; break; }
|
|
159
|
+
if ( dev > maxdev ) maxdev = dev;
|
|
160
|
+
}
|
|
161
|
+
/* A value can land on the wrong side of the linearised floor by as much
|
|
162
|
+
as an edge strays from the straight line, plus the rounding of the
|
|
163
|
+
position itself: v - lo is rounded at the scale of the edges' magnitude
|
|
164
|
+
(an ulp of lo or hi, which can be most of a bin when the edges are
|
|
165
|
+
close together far from zero), and the product grows with the number
|
|
166
|
+
of bins. Values within that much of a boundary are checked against the
|
|
167
|
+
stored edges. When the window covers a good part of a bin, the binary
|
|
168
|
+
search is cheaper. */
|
|
169
|
+
ax->window = ( ax->uniform )
|
|
170
|
+
? maxdev / fabs(dx)
|
|
171
|
+
+ 4.0 * DBL_EPSILON * (fabs(ax->lo) + fabs(ax->hi)) / fabs(dx)
|
|
172
|
+
+ (double) (ax->n + 2) * 8.0 * DBL_EPSILON + 1e-9
|
|
173
|
+
: 0.0;
|
|
174
|
+
if ( ax->window > 0.25 ) {
|
|
175
|
+
ax->uniform = 0;
|
|
154
176
|
}
|
|
155
177
|
ax->inv_dx = (dx != 0.0) ? 1.0 / dx : 0.0;
|
|
156
178
|
ax->include_max = include_max;
|
|
@@ -312,7 +334,7 @@ histogram_scatter_walk (VALUE arg)
|
|
|
312
334
|
ca_size_t off = fiber_base;
|
|
313
335
|
int masked = 0;
|
|
314
336
|
for ( kk = 0; kk < (ca_size_t) M; kk++ ) {
|
|
315
|
-
double v = *(const
|
|
337
|
+
double v = *(const ca_u_float64_t *)(p + a * ss + kk * cs);
|
|
316
338
|
if ( (m && m[a * sms + kk * cms]) || isnan(v) ) { masked = 1; break; }
|
|
317
339
|
off += histbin_index(&axes[kk], v) * ext_stride[kk];
|
|
318
340
|
}
|
|
@@ -164,8 +164,8 @@ ca_classifier_key_too_large (VALUE v, const char *where)
|
|
|
164
164
|
Returns 1 with the position in *out, 2 for an Integer past int64 (past
|
|
165
165
|
every axis, which is no longer than int64), and 0 for anything else (a
|
|
166
166
|
Float with a fraction or past 2**53, NaN, Inf, a Rational, a String). */
|
|
167
|
-
|
|
168
|
-
|
|
167
|
+
int
|
|
168
|
+
ca_index_key_position (VALUE v, ca_size_t *out)
|
|
169
169
|
{
|
|
170
170
|
if ( FIXNUM_P(v) ) {
|
|
171
171
|
*out = (ca_size_t) FIX2LONG(v);
|
|
@@ -201,7 +201,7 @@ static ca_size_t
|
|
|
201
201
|
ca_classifier_key_int_where (VALUE v, int axis, const char *where)
|
|
202
202
|
{
|
|
203
203
|
ca_size_t k;
|
|
204
|
-
switch (
|
|
204
|
+
switch ( ca_index_key_position(v, &k) ) {
|
|
205
205
|
case 1:
|
|
206
206
|
return k;
|
|
207
207
|
case 2:
|
|
@@ -232,7 +232,7 @@ static ca_size_t
|
|
|
232
232
|
ca_classifier_key_step (VALUE v, int axis)
|
|
233
233
|
{
|
|
234
234
|
ca_size_t k;
|
|
235
|
-
if (
|
|
235
|
+
if ( ca_index_key_position(v, &k) == 2 ) {
|
|
236
236
|
return rb_big_sign(v) ? (ca_size_t) INT64_MAX : (ca_size_t) INT64_MIN;
|
|
237
237
|
}
|
|
238
238
|
return ca_classifier_key_int(v, axis);
|