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_order.c
CHANGED
|
@@ -242,7 +242,13 @@ rb_ca_project (int argc, VALUE *argv, VALUE self)
|
|
|
242
242
|
char *lfval, *ufval;
|
|
243
243
|
int self_is_face;
|
|
244
244
|
|
|
245
|
-
|
|
245
|
+
{
|
|
246
|
+
VALUE ropt = Qnil;
|
|
247
|
+
/* project takes no keyword: one given was read as a fill value. */
|
|
248
|
+
rb_scan_args(argc, argv, "12:", (VALUE *)&ridx, (VALUE *) &vlfval,
|
|
249
|
+
(VALUE *) &vufval, &ropt);
|
|
250
|
+
rb_scan_options(ropt, "");
|
|
251
|
+
}
|
|
246
252
|
|
|
247
253
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
248
254
|
self_is_face = ca_is_face(ca);
|
|
@@ -721,13 +727,14 @@ rb_ca_range_method (VALUE self)
|
|
|
721
727
|
|
|
722
728
|
/* ---- nlargest / nsmallest family ------------------------------------- */
|
|
723
729
|
|
|
724
|
-
/* The
|
|
725
|
-
|
|
726
|
-
order
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
730
|
+
/* The answer is the cells first in the order (value, then NaN, then
|
|
731
|
+
masked; the values descending for the largest) with ties broken by
|
|
732
|
+
position, as `order` breaks them. Fewer cells than the fiber are found
|
|
733
|
+
by the buffered walk below. The other routes (the whole fiber, and the
|
|
734
|
+
keys the walk does not read) sort or partition every cell, which picks
|
|
735
|
+
the right values but, among cells that tie with the last one picked,
|
|
736
|
+
any of them; ca_topk_stable replaces the tied candidates by the
|
|
737
|
+
earliest cells that tie and sorts the candidates by (order, position). */
|
|
731
738
|
|
|
732
739
|
typedef struct {
|
|
733
740
|
const char *v; /* the fiber's values, contiguous */
|
|
@@ -892,8 +899,9 @@ ca_topk_stable (VALUE self, VALUE picked, long axis, int desc)
|
|
|
892
899
|
for (k = 0; k < ndim; k++) inv[NUM2INT(perm[k])] = INT2FIX(k);
|
|
893
900
|
}
|
|
894
901
|
/* An entity whose fibers already lie along its last axis is read in
|
|
895
|
-
place; anything else is copied into that layout
|
|
896
|
-
|
|
902
|
+
place; anything else is copied into that layout, as is an entity
|
|
903
|
+
that leaves ptr NULL at rest (a CASource). */
|
|
904
|
+
if ( last && ca_is_entity(cv) && cv->ptr ) {
|
|
897
905
|
vals = key;
|
|
898
906
|
ca_update_mask(cv);
|
|
899
907
|
}
|
|
@@ -936,6 +944,206 @@ ca_topk_has_cells_after_numbers (VALUE self, CArray *ca)
|
|
|
936
944
|
return 0;
|
|
937
945
|
}
|
|
938
946
|
|
|
947
|
+
/* ---- the buffered walk ------------------------------------------------
|
|
948
|
+
Each fiber is read once. The cells that come before the cut (the last
|
|
949
|
+
of the cap cells kept so far, in (order, position)) are collected in a
|
|
950
|
+
buffer of a few times cap; when it fills, a selection keeps the first
|
|
951
|
+
cap and the cut moves up. The work area is the buffer, whatever the
|
|
952
|
+
length of the fiber, and a fiber in order costs one selection per
|
|
953
|
+
bufferful instead of a heap update per cell.
|
|
954
|
+
|
|
955
|
+
The walk is written once as a macro over three others: CLASS(i) (0 a
|
|
956
|
+
value, 1 NaN, 2 masked), AFTER(i, j) (cell i comes after cell j in
|
|
957
|
+
(order, position)) and ENTERS(j) (cell j comes before the cut), and
|
|
958
|
+
instantiated per type so that the comparisons
|
|
959
|
+
are inline. The fixlen type takes the generic comparison. */
|
|
960
|
+
|
|
961
|
+
/* Rearranges b[0..nb) so that b[0..cap) hold the cap cells first in
|
|
962
|
+
(order, position): quickselect with median-of-three pivots; past a
|
|
963
|
+
depth limit the remaining range is sorted (tmp holds nb positions). */
|
|
964
|
+
#define CA_TOPK_SELECT(AFTER) \
|
|
965
|
+
do { \
|
|
966
|
+
lo = 0; hi = nb; \
|
|
967
|
+
depth = 2; \
|
|
968
|
+
for (s = nb; s > 1; s >>= 1) depth += 2; \
|
|
969
|
+
while ( hi - lo > 16 ) { \
|
|
970
|
+
mid = lo + ( hi - lo ) / 2; last = hi - 1; \
|
|
971
|
+
if ( depth-- == 0 ) break; \
|
|
972
|
+
if ( AFTER(b[lo], b[mid]) ) { t = b[lo]; b[lo] = b[mid]; b[mid] = t; } \
|
|
973
|
+
if ( AFTER(b[mid], b[last]) ) { t = b[mid]; b[mid] = b[last]; b[last] = t; } \
|
|
974
|
+
if ( AFTER(b[lo], b[mid]) ) { t = b[lo]; b[lo] = b[mid]; b[mid] = t; } \
|
|
975
|
+
t = b[mid]; b[mid] = b[last]; b[last] = t; \
|
|
976
|
+
for (s = lo, i = lo; i < last; i++) { \
|
|
977
|
+
if ( AFTER(b[last], b[i]) ) { t = b[s]; b[s] = b[i]; b[i] = t; s++; } \
|
|
978
|
+
} \
|
|
979
|
+
t = b[s]; b[s] = b[last]; b[last] = t; \
|
|
980
|
+
if ( s == cap || s + 1 == cap ) { lo = hi; break; } \
|
|
981
|
+
if ( cap < s ) hi = s; \
|
|
982
|
+
else lo = s + 1; \
|
|
983
|
+
} \
|
|
984
|
+
if ( hi > lo ) ca_topk_sort(f, b + lo, tmp, hi - lo); \
|
|
985
|
+
} while (0)
|
|
986
|
+
|
|
987
|
+
#define CA_TOPK_DEFINE_BUF(NAME, T, CLASS, AFTER, ENTERS) \
|
|
988
|
+
static void \
|
|
989
|
+
NAME (const ca_topk_fiber_t *f, ca_size_t len, ca_size_t cap, \
|
|
990
|
+
ca_size_t *b, ca_size_t *tmp, ca_size_t size) \
|
|
991
|
+
{ \
|
|
992
|
+
const T *v_ = (const T *) f->v; \
|
|
993
|
+
ca_size_t j, nb = 0, cut = 0, lo, hi, i, s, t, mid, last; \
|
|
994
|
+
int rc_ = 3, depth; \
|
|
995
|
+
T rv_; \
|
|
996
|
+
(void) v_; \
|
|
997
|
+
memset(&rv_, 0, sizeof(rv_)); \
|
|
998
|
+
for (j = 0; j < len; j++) { \
|
|
999
|
+
if ( rc_ != 3 && ! ( ENTERS(j) ) ) continue; \
|
|
1000
|
+
b[nb++] = j; \
|
|
1001
|
+
if ( nb == size ) { \
|
|
1002
|
+
CA_TOPK_SELECT(AFTER); \
|
|
1003
|
+
nb = cap; \
|
|
1004
|
+
} \
|
|
1005
|
+
else if ( ! ( nb == cap && rc_ == 3 ) ) { /* the first cap cells */ \
|
|
1006
|
+
continue; \
|
|
1007
|
+
} \
|
|
1008
|
+
cut = b[0]; \
|
|
1009
|
+
for (i = 1; i < cap; i++) if ( AFTER(b[i], cut) ) cut = b[i]; \
|
|
1010
|
+
rc_ = CLASS(cut); \
|
|
1011
|
+
if ( rc_ == 0 ) memcpy(&rv_, f->v + cut * f->bytes, sizeof(rv_)); \
|
|
1012
|
+
} \
|
|
1013
|
+
if ( nb > cap ) CA_TOPK_SELECT(AFTER); \
|
|
1014
|
+
ca_topk_sort(f, b, tmp, cap); \
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
/* The typed comparisons. A cell enters when it comes before the cut;
|
|
1018
|
+
one that ties the cut does not, it lies later. */
|
|
1019
|
+
#define CA_TOPK_CLASS_INT(i) ( ( f->m && f->m[i] ) ? 2 : 0 )
|
|
1020
|
+
#define CA_TOPK_CLASS_FLT(i) ( ( f->m && f->m[i] ) ? 2 : ( isnan(v_[i]) ? 1 : 0 ) )
|
|
1021
|
+
#define CA_TOPK_AFTER_V(CLASS, i, j) \
|
|
1022
|
+
( CLASS(i) != CLASS(j) ? CLASS(i) > CLASS(j) \
|
|
1023
|
+
: ( CLASS(i) == 0 && v_[i] != v_[j] ) \
|
|
1024
|
+
? ( f->desc ? v_[i] < v_[j] : v_[i] > v_[j] ) \
|
|
1025
|
+
: (i) > (j) )
|
|
1026
|
+
#define CA_TOPK_AFTER_INT(i, j) CA_TOPK_AFTER_V(CA_TOPK_CLASS_INT, i, j)
|
|
1027
|
+
#define CA_TOPK_AFTER_FLT(i, j) CA_TOPK_AFTER_V(CA_TOPK_CLASS_FLT, i, j)
|
|
1028
|
+
#define CA_TOPK_ENTERS_V(CLASS, j) \
|
|
1029
|
+
( CLASS(j) < rc_ || \
|
|
1030
|
+
( CLASS(j) == 0 && rc_ == 0 && \
|
|
1031
|
+
( f->desc ? v_[j] > rv_ : v_[j] < rv_ ) ) )
|
|
1032
|
+
#define CA_TOPK_ENTERS_INT(j) CA_TOPK_ENTERS_V(CA_TOPK_CLASS_INT, j)
|
|
1033
|
+
#define CA_TOPK_ENTERS_FLT(j) CA_TOPK_ENTERS_V(CA_TOPK_CLASS_FLT, j)
|
|
1034
|
+
|
|
1035
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_u8, uint8_t, CA_TOPK_CLASS_INT, CA_TOPK_AFTER_INT, CA_TOPK_ENTERS_INT)
|
|
1036
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_i8, int8_t, CA_TOPK_CLASS_INT, CA_TOPK_AFTER_INT, CA_TOPK_ENTERS_INT)
|
|
1037
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_i16, int16_t, CA_TOPK_CLASS_INT, CA_TOPK_AFTER_INT, CA_TOPK_ENTERS_INT)
|
|
1038
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_u16, uint16_t, CA_TOPK_CLASS_INT, CA_TOPK_AFTER_INT, CA_TOPK_ENTERS_INT)
|
|
1039
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_i32, int32_t, CA_TOPK_CLASS_INT, CA_TOPK_AFTER_INT, CA_TOPK_ENTERS_INT)
|
|
1040
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_u32, uint32_t, CA_TOPK_CLASS_INT, CA_TOPK_AFTER_INT, CA_TOPK_ENTERS_INT)
|
|
1041
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_i64, int64_t, CA_TOPK_CLASS_INT, CA_TOPK_AFTER_INT, CA_TOPK_ENTERS_INT)
|
|
1042
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_u64, uint64_t, CA_TOPK_CLASS_INT, CA_TOPK_AFTER_INT, CA_TOPK_ENTERS_INT)
|
|
1043
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_f32, float, CA_TOPK_CLASS_FLT, CA_TOPK_AFTER_FLT, CA_TOPK_ENTERS_FLT)
|
|
1044
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_f64, double, CA_TOPK_CLASS_FLT, CA_TOPK_AFTER_FLT, CA_TOPK_ENTERS_FLT)
|
|
1045
|
+
|
|
1046
|
+
/* fixlen: the generic comparison; v_ is unused. */
|
|
1047
|
+
#define CA_TOPK_CLASS_GEN(i) ca_topk_class(f, i)
|
|
1048
|
+
#define CA_TOPK_AFTER_GEN(i, j) ca_topk_after(f, i, j)
|
|
1049
|
+
#define CA_TOPK_ENTERS_GEN(j) ( ca_topk_cmp(f, j, cut) < 0 )
|
|
1050
|
+
|
|
1051
|
+
/* Whether cell i comes after cell j in (order, position). */
|
|
1052
|
+
static int
|
|
1053
|
+
ca_topk_after (const ca_topk_fiber_t *f, ca_size_t i, ca_size_t j)
|
|
1054
|
+
{
|
|
1055
|
+
int r = ca_topk_cmp(f, i, j);
|
|
1056
|
+
return r > 0 || ( r == 0 && i > j );
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_gen, char, CA_TOPK_CLASS_GEN, CA_TOPK_AFTER_GEN, CA_TOPK_ENTERS_GEN)
|
|
1060
|
+
|
|
1061
|
+
#undef CA_TOPK_DEFINE_BUF
|
|
1062
|
+
#undef CA_TOPK_SELECT
|
|
1063
|
+
#undef CA_TOPK_CLASS_INT
|
|
1064
|
+
#undef CA_TOPK_CLASS_FLT
|
|
1065
|
+
#undef CA_TOPK_AFTER_V
|
|
1066
|
+
#undef CA_TOPK_AFTER_INT
|
|
1067
|
+
#undef CA_TOPK_AFTER_FLT
|
|
1068
|
+
#undef CA_TOPK_ENTERS_V
|
|
1069
|
+
#undef CA_TOPK_ENTERS_INT
|
|
1070
|
+
#undef CA_TOPK_ENTERS_FLT
|
|
1071
|
+
#undef CA_TOPK_CLASS_GEN
|
|
1072
|
+
#undef CA_TOPK_AFTER_GEN
|
|
1073
|
+
#undef CA_TOPK_ENTERS_GEN
|
|
1074
|
+
|
|
1075
|
+
/* The first cap cells of one fiber in (order, position), sorted, into
|
|
1076
|
+
b[0..cap). b and tmp hold size positions, cap < size <= len. */
|
|
1077
|
+
static void
|
|
1078
|
+
ca_topk_buf_fiber (const ca_topk_fiber_t *f, ca_size_t len, ca_size_t cap,
|
|
1079
|
+
ca_size_t *b, ca_size_t *tmp, ca_size_t size)
|
|
1080
|
+
{
|
|
1081
|
+
switch ( f->type ) {
|
|
1082
|
+
case CA_BOOLEAN:
|
|
1083
|
+
case CA_UINT8: ca_topk_buf_u8(f, len, cap, b, tmp, size); break;
|
|
1084
|
+
case CA_INT8: ca_topk_buf_i8(f, len, cap, b, tmp, size); break;
|
|
1085
|
+
case CA_INT16: ca_topk_buf_i16(f, len, cap, b, tmp, size); break;
|
|
1086
|
+
case CA_UINT16: ca_topk_buf_u16(f, len, cap, b, tmp, size); break;
|
|
1087
|
+
case CA_INT32: ca_topk_buf_i32(f, len, cap, b, tmp, size); break;
|
|
1088
|
+
case CA_UINT32: ca_topk_buf_u32(f, len, cap, b, tmp, size); break;
|
|
1089
|
+
case CA_INT64: ca_topk_buf_i64(f, len, cap, b, tmp, size); break;
|
|
1090
|
+
case CA_UINT64: ca_topk_buf_u64(f, len, cap, b, tmp, size); break;
|
|
1091
|
+
case CA_FLOAT32: ca_topk_buf_f32(f, len, cap, b, tmp, size); break;
|
|
1092
|
+
case CA_FLOAT64: ca_topk_buf_f64(f, len, cap, b, tmp, size); break;
|
|
1093
|
+
default: ca_topk_buf_gen(f, len, cap, b, tmp, size); break;
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
/* Per-axis top-k positions of `key` (an order key: not object, not
|
|
1098
|
+
complex) by the buffered walk, for cap < the length of the axis. The
|
|
1099
|
+
fibers come in the row-major order of the other axes, so the answer is
|
|
1100
|
+
filled with the axis last and moved into place at the end (cap cells
|
|
1101
|
+
per fiber). */
|
|
1102
|
+
static VALUE
|
|
1103
|
+
ca_topk_buffered_positions (VALUE key, long cap, long axis, int desc)
|
|
1104
|
+
{
|
|
1105
|
+
volatile VALUE holder = 0, out;
|
|
1106
|
+
VALUE perm[CA_RANK_MAX];
|
|
1107
|
+
ca_size_t odim[CA_RANK_MAX];
|
|
1108
|
+
CArray *ck, *co;
|
|
1109
|
+
ca_iter_state st;
|
|
1110
|
+
ca_topk_fiber_t f;
|
|
1111
|
+
ca_size_t *buf, *tmp, n, o = 0, k, len, size;
|
|
1112
|
+
int64_t *op;
|
|
1113
|
+
boolean8_t *m;
|
|
1114
|
+
char *p;
|
|
1115
|
+
int ndim, i, j = 0;
|
|
1116
|
+
|
|
1117
|
+
GetCArray(key, ck);
|
|
1118
|
+
ndim = ck->ndim;
|
|
1119
|
+
for (i = 0; i < ndim; i++) if ( i != axis ) odim[j++] = ck->dim[i];
|
|
1120
|
+
odim[ndim - 1] = cap;
|
|
1121
|
+
len = ck->dim[axis];
|
|
1122
|
+
out = rb_carray_new(CA_INT64, ndim, odim, 0, NULL);
|
|
1123
|
+
GetCArray(out, co);
|
|
1124
|
+
op = (int64_t *) co->ptr;
|
|
1125
|
+
|
|
1126
|
+
f.type = ck->data_type;
|
|
1127
|
+
f.bytes = ck->bytes;
|
|
1128
|
+
f.desc = desc;
|
|
1129
|
+
size = ( len < 4 * cap + 256 ) ? len : 4 * cap + 256;
|
|
1130
|
+
buf = ALLOCV_N(ca_size_t, holder, 2 * size);
|
|
1131
|
+
tmp = buf + size;
|
|
1132
|
+
CA_FOR_EACH_FIBER_MASKED(st, ck, axis, 0, p, n, m) {
|
|
1133
|
+
f.v = p;
|
|
1134
|
+
f.m = m;
|
|
1135
|
+
ca_topk_buf_fiber(&f, n, cap, buf, tmp, size);
|
|
1136
|
+
for (k = 0; k < cap; k++) op[o * cap + k] = (int64_t) buf[k];
|
|
1137
|
+
o++;
|
|
1138
|
+
}
|
|
1139
|
+
ALLOCV_END(holder);
|
|
1140
|
+
if ( axis == ndim - 1 ) return out;
|
|
1141
|
+
for (i = 0; i < ndim; i++) {
|
|
1142
|
+
perm[i] = INT2FIX( i < axis ? i : ( i == axis ? ndim - 1 : i - 1 ) );
|
|
1143
|
+
}
|
|
1144
|
+
return rb_ca_copy(rb_funcallv(out, rb_intern("transpose"), ndim, perm));
|
|
1145
|
+
}
|
|
1146
|
+
|
|
939
1147
|
/* Per-axis top-k positions (cap clamped, axis normalized).
|
|
940
1148
|
* Called by rb_ca_topk_index below. */
|
|
941
1149
|
static VALUE
|
|
@@ -946,6 +1154,18 @@ rb_ca_topk_positions (VALUE self, long cap, long axis_norm, int desc)
|
|
|
946
1154
|
long dim_axis = (long) ca->dim[axis_norm];
|
|
947
1155
|
VALUE raxis_norm = LONG2NUM(axis_norm);
|
|
948
1156
|
|
|
1157
|
+
/* The buffered walk reads any key but an object (its cells compare in
|
|
1158
|
+
Ruby) or a complex one (no order), and keeps cap cells per fiber. */
|
|
1159
|
+
if ( ca->data_type != CA_OBJECT && ! ca_is_complex_type(ca) ) {
|
|
1160
|
+
VALUE key = ca_order_key(self, desc ? "nlargest" : "nsmallest");
|
|
1161
|
+
CArray *ck;
|
|
1162
|
+
GetCArray(key, ck);
|
|
1163
|
+
if ( ck->data_type != CA_OBJECT && ! ca_is_complex_type(ck) &&
|
|
1164
|
+
cap < dim_axis ) {
|
|
1165
|
+
return ca_topk_buffered_positions(key, cap, axis_norm, desc);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
|
|
949
1169
|
/* The largest: reversing the ascending order would put the NaN and the
|
|
950
1170
|
masked cells first, so rank them descending (NaN, then the masked
|
|
951
1171
|
cells, last) when there are any. An object array is ranked by
|
data/ext/carray_random.c
CHANGED
|
@@ -165,7 +165,7 @@ ca_random_bang_fill (VALUE arg)
|
|
|
165
165
|
ca_rng_bind(&c->source);
|
|
166
166
|
switch (ca->data_type) {
|
|
167
167
|
case CA_FLOAT64: {
|
|
168
|
-
double *p = (double *)ca->ptr;
|
|
168
|
+
CA_U(double) *p = (CA_U(double) *)ca->ptr;
|
|
169
169
|
if (is_default) {
|
|
170
170
|
for (i = 0; i < n; i++)
|
|
171
171
|
p[i] = ca_random_real(&c->source);
|
|
@@ -177,7 +177,7 @@ ca_random_bang_fill (VALUE arg)
|
|
|
177
177
|
break;
|
|
178
178
|
}
|
|
179
179
|
case CA_FLOAT32: {
|
|
180
|
-
float *p = (float *)ca->ptr;
|
|
180
|
+
CA_U(float) *p = (CA_U(float) *)ca->ptr;
|
|
181
181
|
if (is_default) {
|
|
182
182
|
for (i = 0; i < n; i++)
|
|
183
183
|
p[i] = (float)ca_random_real(&c->source);
|
|
@@ -189,7 +189,7 @@ ca_random_bang_fill (VALUE arg)
|
|
|
189
189
|
break;
|
|
190
190
|
}
|
|
191
191
|
case CA_CMPLX128: {
|
|
192
|
-
|
|
192
|
+
ca_u_cmplx128_t *p = (ca_u_cmplx128_t *)ca->ptr;
|
|
193
193
|
if (is_default) {
|
|
194
194
|
for (i = 0; i < n; i++)
|
|
195
195
|
p[i] = ca_random_real(&c->source) + ca_random_real(&c->source) * I;
|
|
@@ -202,7 +202,7 @@ ca_random_bang_fill (VALUE arg)
|
|
|
202
202
|
break;
|
|
203
203
|
}
|
|
204
204
|
case CA_CMPLX64: {
|
|
205
|
-
|
|
205
|
+
ca_u_cmplx64_t *p = (ca_u_cmplx64_t *)ca->ptr;
|
|
206
206
|
if (is_default) {
|
|
207
207
|
for (i = 0; i < n; i++)
|
|
208
208
|
p[i] = (float)ca_random_real(&c->source) + (float)ca_random_real(&c->source) * I;
|
|
@@ -242,37 +242,37 @@ ca_random_bang_fill (VALUE arg)
|
|
|
242
242
|
break;
|
|
243
243
|
}
|
|
244
244
|
case CA_INT16: {
|
|
245
|
-
int16_t *p = (int16_t *)ca->ptr;
|
|
245
|
+
CA_U(int16_t) *p = (CA_U(int16_t) *)ca->ptr;
|
|
246
246
|
for (i = 0; i < n; i++)
|
|
247
247
|
p[i] = (int16_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
248
248
|
break;
|
|
249
249
|
}
|
|
250
250
|
case CA_UINT16: {
|
|
251
|
-
uint16_t *p = (uint16_t *)ca->ptr;
|
|
251
|
+
CA_U(uint16_t) *p = (CA_U(uint16_t) *)ca->ptr;
|
|
252
252
|
for (i = 0; i < n; i++)
|
|
253
253
|
p[i] = (uint16_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
254
254
|
break;
|
|
255
255
|
}
|
|
256
256
|
case CA_INT32: {
|
|
257
|
-
int32_t *p = (int32_t *)ca->ptr;
|
|
257
|
+
CA_U(int32_t) *p = (CA_U(int32_t) *)ca->ptr;
|
|
258
258
|
for (i = 0; i < n; i++)
|
|
259
259
|
p[i] = (int32_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
260
260
|
break;
|
|
261
261
|
}
|
|
262
262
|
case CA_UINT32: {
|
|
263
|
-
uint32_t *p = (uint32_t *)ca->ptr;
|
|
263
|
+
CA_U(uint32_t) *p = (CA_U(uint32_t) *)ca->ptr;
|
|
264
264
|
for (i = 0; i < n; i++)
|
|
265
265
|
p[i] = (uint32_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
266
266
|
break;
|
|
267
267
|
}
|
|
268
268
|
case CA_INT64: {
|
|
269
|
-
int64_t *p = (int64_t *)ca->ptr;
|
|
269
|
+
CA_U(int64_t) *p = (CA_U(int64_t) *)ca->ptr;
|
|
270
270
|
for (i = 0; i < n; i++)
|
|
271
271
|
p[i] = (int64_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
272
272
|
break;
|
|
273
273
|
}
|
|
274
274
|
case CA_UINT64: {
|
|
275
|
-
uint64_t *p = (uint64_t *)ca->ptr;
|
|
275
|
+
CA_U(uint64_t) *p = (CA_U(uint64_t) *)ca->ptr;
|
|
276
276
|
for (i = 0; i < n; i++)
|
|
277
277
|
p[i] = (uint64_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
278
278
|
break;
|
|
@@ -483,19 +483,19 @@ ca_randomn_bang_fill (VALUE arg)
|
|
|
483
483
|
if (c->source.kind == CA_RNG_OWN) {
|
|
484
484
|
switch (ca->data_type) {
|
|
485
485
|
case CA_FLOAT64: {
|
|
486
|
-
double *p = (double *)ca->ptr;
|
|
486
|
+
CA_U(double) *p = (CA_U(double) *)ca->ptr;
|
|
487
487
|
for (i = 0; i < n; i++)
|
|
488
488
|
p[i] = ca_random_normal(&c->source);
|
|
489
489
|
break;
|
|
490
490
|
}
|
|
491
491
|
case CA_FLOAT32: {
|
|
492
|
-
float *p = (float *)ca->ptr;
|
|
492
|
+
CA_U(float) *p = (CA_U(float) *)ca->ptr;
|
|
493
493
|
for (i = 0; i < n; i++)
|
|
494
494
|
p[i] = (float) ca_random_normal(&c->source);
|
|
495
495
|
break;
|
|
496
496
|
}
|
|
497
497
|
case CA_CMPLX128: {
|
|
498
|
-
|
|
498
|
+
ca_u_cmplx128_t *p = (ca_u_cmplx128_t *)ca->ptr;
|
|
499
499
|
for (i = 0; i < n; i++) {
|
|
500
500
|
/* Into locals first: C does not say which order a call's
|
|
501
501
|
arguments are evaluated in, and these two advance a state. */
|
|
@@ -506,7 +506,7 @@ ca_randomn_bang_fill (VALUE arg)
|
|
|
506
506
|
break;
|
|
507
507
|
}
|
|
508
508
|
case CA_CMPLX64: {
|
|
509
|
-
|
|
509
|
+
ca_u_cmplx64_t *p = (ca_u_cmplx64_t *)ca->ptr;
|
|
510
510
|
for (i = 0; i < n; i++) {
|
|
511
511
|
double re = ca_random_normal(&c->source);
|
|
512
512
|
double im = ca_random_normal(&c->source);
|
|
@@ -522,10 +522,13 @@ ca_randomn_bang_fill (VALUE arg)
|
|
|
522
522
|
|
|
523
523
|
switch (ca->data_type) {
|
|
524
524
|
case CA_FLOAT64: {
|
|
525
|
-
double *p = (double *)ca->ptr;
|
|
525
|
+
CA_U(double) *p = (CA_U(double) *)ca->ptr;
|
|
526
526
|
ca_size_t pairs = n / 2;
|
|
527
527
|
for (i = 0; i < pairs; i++) {
|
|
528
|
-
|
|
528
|
+
double r1, r2;
|
|
529
|
+
box_muller_pair(&c->source, &r1, &r2);
|
|
530
|
+
p[2*i] = r1;
|
|
531
|
+
p[2*i+1] = r2;
|
|
529
532
|
}
|
|
530
533
|
if (n % 2 == 1) {
|
|
531
534
|
double r1, r2;
|
|
@@ -535,7 +538,7 @@ ca_randomn_bang_fill (VALUE arg)
|
|
|
535
538
|
break;
|
|
536
539
|
}
|
|
537
540
|
case CA_FLOAT32: {
|
|
538
|
-
float *p = (float *)ca->ptr;
|
|
541
|
+
CA_U(float) *p = (CA_U(float) *)ca->ptr;
|
|
539
542
|
ca_size_t pairs = n / 2;
|
|
540
543
|
for (i = 0; i < pairs; i++) {
|
|
541
544
|
double r1, r2;
|
|
@@ -551,7 +554,7 @@ ca_randomn_bang_fill (VALUE arg)
|
|
|
551
554
|
break;
|
|
552
555
|
}
|
|
553
556
|
case CA_CMPLX128: {
|
|
554
|
-
|
|
557
|
+
ca_u_cmplx128_t *p = (ca_u_cmplx128_t *)ca->ptr;
|
|
555
558
|
for (i = 0; i < n; i++) {
|
|
556
559
|
double r1, r2;
|
|
557
560
|
box_muller_pair(&c->source, &r1, &r2);
|
|
@@ -560,7 +563,7 @@ ca_randomn_bang_fill (VALUE arg)
|
|
|
560
563
|
break;
|
|
561
564
|
}
|
|
562
565
|
case CA_CMPLX64: {
|
|
563
|
-
|
|
566
|
+
ca_u_cmplx64_t *p = (ca_u_cmplx64_t *)ca->ptr;
|
|
564
567
|
for (i = 0; i < n; i++) {
|
|
565
568
|
double r1, r2;
|
|
566
569
|
box_muller_pair(&c->source, &r1, &r2);
|
data/ext/carray_scatter.c
CHANGED
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
min / max: real numeric only (complex has no order)
|
|
14
14
|
(boolean / object / fixlen → CADataTypeError; the bang
|
|
15
15
|
cannot widen self, same rationale as fma! / fms!)
|
|
16
|
-
replace:
|
|
16
|
+
replace: any type (assignment, no widening); an object or
|
|
17
|
+
fixlen array is written through the indexer
|
|
17
18
|
scalar any Numeric, true / false, or UNDEF; converted to self's
|
|
18
19
|
type as the indexer's store converts it (a value that does
|
|
19
20
|
not fit raises, as `self[i] = v` does)
|
|
@@ -63,7 +64,7 @@ typedef union {
|
|
|
63
64
|
#define LOOP_SCALAR(T, APPLY) LOOP_SCALAR_V(T, APPLY, SCALAR_REAL(T))
|
|
64
65
|
|
|
65
66
|
#define LOOP_SCALAR_V(T, APPLY, VS) do { \
|
|
66
|
-
T *q = (T *) qbase; \
|
|
67
|
+
CA_U(T) *q = (CA_U(T) *) qbase; \
|
|
67
68
|
T vs = VS; \
|
|
68
69
|
if ( mself ) { \
|
|
69
70
|
for (i = 0; i < n; i++) { \
|
|
@@ -85,8 +86,8 @@ typedef union {
|
|
|
85
86
|
} while (0)
|
|
86
87
|
|
|
87
88
|
#define LOOP_VEC(T, APPLY) do { \
|
|
88
|
-
T *q = (T *) qbase; \
|
|
89
|
-
T *r = (T *) cv->ptr; \
|
|
89
|
+
CA_U(T) *q = (CA_U(T) *) qbase; \
|
|
90
|
+
CA_U(T) *r = (CA_U(T) *) cv->ptr; \
|
|
90
91
|
if ( mself ) { \
|
|
91
92
|
for (i = 0; i < n; i++) { \
|
|
92
93
|
if ( maddrs && maddrs[i] ) continue; \
|
|
@@ -120,7 +121,7 @@ typedef union {
|
|
|
120
121
|
#define LOOP_SCALAR_REPLACE(T) LOOP_SCALAR_REPLACE_V(T, SCALAR_REAL(T))
|
|
121
122
|
|
|
122
123
|
#define LOOP_SCALAR_REPLACE_V(T, VS) do { \
|
|
123
|
-
T *q = (T *) qbase; \
|
|
124
|
+
CA_U(T) *q = (CA_U(T) *) qbase; \
|
|
124
125
|
T vs = VS; \
|
|
125
126
|
for (i = 0; i < n; i++) { \
|
|
126
127
|
if ( maddrs && maddrs[i] ) continue; \
|
|
@@ -136,8 +137,8 @@ typedef union {
|
|
|
136
137
|
} while (0)
|
|
137
138
|
|
|
138
139
|
#define LOOP_VEC_REPLACE(T) do { \
|
|
139
|
-
T *q = (T *) qbase; \
|
|
140
|
-
T *r = (T *) cv->ptr; \
|
|
140
|
+
CA_U(T) *q = (CA_U(T) *) qbase; \
|
|
141
|
+
CA_U(T) *r = (CA_U(T) *) cv->ptr; \
|
|
141
142
|
for (i = 0; i < n; i++) { \
|
|
142
143
|
if ( maddrs && maddrs[i] ) continue; \
|
|
143
144
|
addr = p[i]; \
|
|
@@ -592,6 +593,22 @@ AT_BODY(ca_scatter_replace_body, DISPATCH_NUMERIC_REPLACE())
|
|
|
592
593
|
static VALUE
|
|
593
594
|
rb_ca_scatter_replace_bang (VALUE self, VALUE raddrs, VALUE rvals)
|
|
594
595
|
{
|
|
596
|
+
/* An object or fixlen array takes the assignment through the indexer,
|
|
597
|
+
which reads and writes its cells by their own rules (a VALUE kept
|
|
598
|
+
visible to the GC, a fixlen value fitted to the cell); the kernel
|
|
599
|
+
below is for the numeric and boolean cells. */
|
|
600
|
+
{
|
|
601
|
+
CArray *cs;
|
|
602
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, cs);
|
|
603
|
+
if ( cs->data_type == CA_OBJECT || cs->data_type == CA_FIXLEN ) {
|
|
604
|
+
rb_ca_modify(self);
|
|
605
|
+
if ( RB_TYPE_P(raddrs, T_ARRAY) ) { /* a list of addresses */
|
|
606
|
+
raddrs = rb_ca_wrap_readonly(raddrs, INT2NUM(CA_SIZE));
|
|
607
|
+
}
|
|
608
|
+
rb_funcall(rb_ca_flatten(self), rb_intern("[]="), 2, raddrs, rvals);
|
|
609
|
+
return self;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
595
612
|
/* Pre-scan: if vals is a masked CArray and self isn't yet masked,
|
|
596
613
|
promote self so the kernel can flip target cells to masked (indexer
|
|
597
614
|
`self[addrs] = vals` establishes self.mask lazily the same way). */
|