carray 3.0.4 → 3.0.5
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 +205 -0
- data/carray.gemspec +1 -1
- data/ext/ca_array_pool.c +25 -1
- data/ext/ca_axis_dispatch.c +13 -20
- data/ext/ca_categorical_iterator.c +27 -20
- data/ext/ca_compare.c +4 -4
- data/ext/ca_composite_dispatch.c +9 -9
- data/ext/ca_kernel_iterator.c +6 -6
- data/ext/ca_kernel_iterator.h +112 -83
- data/ext/ca_obj_array.c +69 -19
- data/ext/ca_obj_bincmp.c +1 -0
- data/ext/ca_obj_binop.c +1 -0
- data/ext/ca_obj_bitarray.c +5 -1
- data/ext/ca_obj_bitfield.c +58 -43
- data/ext/ca_obj_byte_swap.c +2 -1
- data/ext/ca_obj_const_string.c +15 -3
- data/ext/ca_obj_face.c +42 -1
- data/ext/ca_obj_field.c +13 -3
- data/ext/ca_obj_grid.c +52 -5
- data/ext/ca_obj_monop.c +46 -10
- data/ext/ca_obj_object.c +64 -12
- data/ext/ca_obj_record.c +3 -0
- data/ext/ca_obj_reduce.c +4 -0
- data/ext/ca_obj_refer.c +18 -9
- data/ext/ca_obj_roll.c +26 -6
- data/ext/ca_obj_select.c +34 -5
- data/ext/ca_obj_shift.c +31 -7
- data/ext/ca_obj_stack.c +1 -0
- data/ext/ca_obj_stride.c +28 -19
- data/ext/ca_obj_string.c +11 -2
- data/ext/ca_obj_tile.c +27 -7
- data/ext/ca_obj_transpose.c +8 -4
- data/ext/ca_obj_triop.c +3 -0
- data/ext/ca_obj_window.c +79 -50
- data/ext/ca_op_ipower.c +4 -4
- data/ext/ca_sort_kernels.h +6 -3
- data/ext/carray.h +33 -0
- data/ext/carray_access.c +16 -3
- data/ext/carray_attribute.c +24 -0
- data/ext/carray_cast.c +243 -82
- data/ext/carray_cast_func.rb +56 -26
- data/ext/carray_conversion.c +2 -2
- data/ext/carray_core.c +3 -0
- data/ext/carray_count.c +6 -0
- data/ext/carray_element.c +9 -4
- data/ext/carray_factorize.c +20 -20
- data/ext/carray_generate.c +8 -2
- data/ext/carray_histogram.c +1 -1
- data/ext/carray_index_classifier.c +4 -4
- data/ext/carray_internal.h +12 -0
- data/ext/carray_kernels_bincmp.c +168 -168
- data/ext/carray_kernels_binop.c +900 -900
- data/ext/carray_kernels_init.c +4 -4
- data/ext/carray_kernels_moncmp.c +96 -96
- data/ext/carray_kernels_monop.c +1984 -1984
- data/ext/carray_kernels_reduce_aggregate.c +1733 -1733
- data/ext/carray_kernels_reduce_cumulative.c +642 -642
- data/ext/carray_kernels_reduce_extreme.c +1150 -1150
- data/ext/carray_kernels_reduce_variance.c +258 -258
- data/ext/carray_kernels_scan.c +128 -128
- data/ext/carray_kernels_search.c +340 -340
- data/ext/carray_kernels_sort.c +295 -304
- data/ext/carray_kernels_triop.c +114 -114
- data/ext/carray_key_windows.c +4 -0
- data/ext/carray_mask.c +45 -22
- data/ext/carray_memory_view.c +2 -2
- data/ext/carray_operator.c +5 -5
- data/ext/carray_order.c +227 -8
- data/ext/carray_random.c +18 -18
- data/ext/carray_scatter.c +24 -7
- data/ext/carray_slab.c +32 -9
- 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_time_text.c +4 -2
- data/ext/carray_utils.c +63 -21
- data/ext/mkkernel.rb +210 -115
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +17 -4
- data/lib/carray/basics.rb +27 -7
- data/lib/carray/categorical.rb +30 -16
- data/lib/carray/categorical_iterator.rb +6 -6
- 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 +4 -3
- data/lib/carray/frame/concat.rb +17 -3
- data/lib/carray/frame/frame.rb +6 -7
- data/lib/carray/frame/group.rb +100 -13
- data/lib/carray/frame/io.rb +3 -1
- data/lib/carray/fuse_source.rb +31 -2
- data/lib/carray/lazy.rb +35 -0
- data/lib/carray/methods/is_in.rb +8 -1
- data/lib/carray/segment_iterator.rb +12 -8
- data/lib/carray/serialize.rb +19 -2
- data/lib/carray/stack.rb +15 -12
- 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 +107 -68
- data/yard-stubs/ca_obj_transpose.rb +5 -4
- data/yard-stubs/carray_attribute.rb +3 -1
- data/yard-stubs/carray_cast.rb +2 -0
- data/yard-stubs/carray_conversion.rb +5 -1
- data/yard-stubs/carray_element.rb +7 -6
- data/yard-stubs/carray_mask.rb +8 -3
- data/yard-stubs/carray_math.rb +14 -4
- data/yard-stubs/carray_order.rb +100 -4
- data/yard-stubs/carray_scatter.rb +7 -5
- metadata +1 -1
data/ext/carray_memory_view.c
CHANGED
|
@@ -1410,7 +1410,7 @@ ca_mv_wrap_body (VALUE arg)
|
|
|
1410
1410
|
a->target_class);
|
|
1411
1411
|
rb_ivar_set(wrap, rb_intern("memory_view_source"), a->obj);
|
|
1412
1412
|
rb_ivar_set(wrap, rb_intern("memory_view_holder"), a->data_holder_obj);
|
|
1413
|
-
|
|
1413
|
+
GetCArray(wrap, ca);
|
|
1414
1414
|
if ( v->readonly ) {
|
|
1415
1415
|
ca_set_flag(ca, CA_FLAG_READ_ONLY);
|
|
1416
1416
|
}
|
|
@@ -1527,7 +1527,7 @@ ca_mv_from_body (VALUE arg)
|
|
|
1527
1527
|
|
|
1528
1528
|
result = rb_carray_new(data_type, d->ndim, d->dim,
|
|
1529
1529
|
ca_mv_carray_bytes_for(data_type, v->item_size), NULL);
|
|
1530
|
-
|
|
1530
|
+
GetCArray(result, ca);
|
|
1531
1531
|
|
|
1532
1532
|
if ( d->contiguous ) {
|
|
1533
1533
|
memcpy(ca->ptr, v->data, (size_t) ca_length(ca));
|
data/ext/carray_operator.c
CHANGED
|
@@ -1473,7 +1473,7 @@ rb_ca_call_binop (volatile VALUE self, volatile VALUE other,
|
|
|
1473
1473
|
/* 1-shot ALLOCV path. At most 1 operand needs ALLOCV; the other is
|
|
1474
1474
|
alias-direct. */
|
|
1475
1475
|
volatile VALUE h1 = Qnil, h2 = Qnil;
|
|
1476
|
-
char *p1, *p2;
|
|
1476
|
+
char *p1 = NULL, *p2 = NULL;
|
|
1477
1477
|
int a1 = 0, a2 = 0;
|
|
1478
1478
|
(void) h1; (void) h2;
|
|
1479
1479
|
|
|
@@ -1841,7 +1841,7 @@ rb_ca_call_triop (VALUE self, VALUE other2, VALUE other3,
|
|
|
1841
1841
|
|
|
1842
1842
|
if ( !use_chunked ) {
|
|
1843
1843
|
volatile VALUE h1 = Qnil, h2 = Qnil, h3 = Qnil;
|
|
1844
|
-
char *p1, *p2, *p3;
|
|
1844
|
+
char *p1 = NULL, *p2 = NULL, *p3 = NULL;
|
|
1845
1845
|
int attached1, attached2, attached3;
|
|
1846
1846
|
(void) h1; (void) h2; (void) h3;
|
|
1847
1847
|
|
|
@@ -1984,7 +1984,7 @@ rb_ca_call_triop_bang (VALUE self, VALUE other2, VALUE other3,
|
|
|
1984
1984
|
|
|
1985
1985
|
if ( !use_chunked ) {
|
|
1986
1986
|
volatile VALUE h2 = Qnil, h3 = Qnil;
|
|
1987
|
-
char *p2, *p3;
|
|
1987
|
+
char *p2 = NULL, *p3 = NULL;
|
|
1988
1988
|
int attached2, attached3;
|
|
1989
1989
|
ca_triop_call_t k;
|
|
1990
1990
|
CArray *held[3];
|
|
@@ -2129,7 +2129,7 @@ rb_ca_call_moncmp (VALUE self, ca_moncmp_func_t func[])
|
|
|
2129
2129
|
|
|
2130
2130
|
{
|
|
2131
2131
|
volatile VALUE h1 = Qnil;
|
|
2132
|
-
char *p1;
|
|
2132
|
+
char *p1 = NULL;
|
|
2133
2133
|
int attached1;
|
|
2134
2134
|
(void) h1;
|
|
2135
2135
|
|
|
@@ -2452,7 +2452,7 @@ rb_ca_call_bincmp (volatile VALUE self, volatile VALUE other,
|
|
|
2452
2452
|
|
|
2453
2453
|
if ( !use_chunked ) {
|
|
2454
2454
|
volatile VALUE h1 = Qnil, h2 = Qnil;
|
|
2455
|
-
char *p1, *p2;
|
|
2455
|
+
char *p1 = NULL, *p2 = NULL;
|
|
2456
2456
|
int attached1, attached2;
|
|
2457
2457
|
(void) h1; (void) h2;
|
|
2458
2458
|
|
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 */
|
|
@@ -936,6 +943,206 @@ ca_topk_has_cells_after_numbers (VALUE self, CArray *ca)
|
|
|
936
943
|
return 0;
|
|
937
944
|
}
|
|
938
945
|
|
|
946
|
+
/* ---- the buffered walk ------------------------------------------------
|
|
947
|
+
Each fiber is read once. The cells that come before the cut (the last
|
|
948
|
+
of the cap cells kept so far, in (order, position)) are collected in a
|
|
949
|
+
buffer of a few times cap; when it fills, a selection keeps the first
|
|
950
|
+
cap and the cut moves up. The work area is the buffer, whatever the
|
|
951
|
+
length of the fiber, and a fiber in order costs one selection per
|
|
952
|
+
bufferful instead of a heap update per cell.
|
|
953
|
+
|
|
954
|
+
The walk is written once as a macro over three others: CLASS(i) (0 a
|
|
955
|
+
value, 1 NaN, 2 masked), AFTER(i, j) (cell i comes after cell j in
|
|
956
|
+
(order, position)) and ENTERS(j) (cell j comes before the cut), and
|
|
957
|
+
instantiated per type so that the comparisons
|
|
958
|
+
are inline. The fixlen type takes the generic comparison. */
|
|
959
|
+
|
|
960
|
+
/* Rearranges b[0..nb) so that b[0..cap) hold the cap cells first in
|
|
961
|
+
(order, position): quickselect with median-of-three pivots; past a
|
|
962
|
+
depth limit the remaining range is sorted (tmp holds nb positions). */
|
|
963
|
+
#define CA_TOPK_SELECT(AFTER) \
|
|
964
|
+
do { \
|
|
965
|
+
lo = 0; hi = nb; \
|
|
966
|
+
depth = 2; \
|
|
967
|
+
for (s = nb; s > 1; s >>= 1) depth += 2; \
|
|
968
|
+
while ( hi - lo > 16 ) { \
|
|
969
|
+
mid = lo + ( hi - lo ) / 2; last = hi - 1; \
|
|
970
|
+
if ( depth-- == 0 ) break; \
|
|
971
|
+
if ( AFTER(b[lo], b[mid]) ) { t = b[lo]; b[lo] = b[mid]; b[mid] = t; } \
|
|
972
|
+
if ( AFTER(b[mid], b[last]) ) { t = b[mid]; b[mid] = b[last]; b[last] = t; } \
|
|
973
|
+
if ( AFTER(b[lo], b[mid]) ) { t = b[lo]; b[lo] = b[mid]; b[mid] = t; } \
|
|
974
|
+
t = b[mid]; b[mid] = b[last]; b[last] = t; \
|
|
975
|
+
for (s = lo, i = lo; i < last; i++) { \
|
|
976
|
+
if ( AFTER(b[last], b[i]) ) { t = b[s]; b[s] = b[i]; b[i] = t; s++; } \
|
|
977
|
+
} \
|
|
978
|
+
t = b[s]; b[s] = b[last]; b[last] = t; \
|
|
979
|
+
if ( s == cap || s + 1 == cap ) { lo = hi; break; } \
|
|
980
|
+
if ( cap < s ) hi = s; \
|
|
981
|
+
else lo = s + 1; \
|
|
982
|
+
} \
|
|
983
|
+
if ( hi > lo ) ca_topk_sort(f, b + lo, tmp, hi - lo); \
|
|
984
|
+
} while (0)
|
|
985
|
+
|
|
986
|
+
#define CA_TOPK_DEFINE_BUF(NAME, T, CLASS, AFTER, ENTERS) \
|
|
987
|
+
static void \
|
|
988
|
+
NAME (const ca_topk_fiber_t *f, ca_size_t len, ca_size_t cap, \
|
|
989
|
+
ca_size_t *b, ca_size_t *tmp, ca_size_t size) \
|
|
990
|
+
{ \
|
|
991
|
+
const T *v_ = (const T *) f->v; \
|
|
992
|
+
ca_size_t j, nb = 0, cut = 0, lo, hi, i, s, t, mid, last; \
|
|
993
|
+
int rc_ = 3, depth; \
|
|
994
|
+
T rv_; \
|
|
995
|
+
(void) v_; \
|
|
996
|
+
memset(&rv_, 0, sizeof(rv_)); \
|
|
997
|
+
for (j = 0; j < len; j++) { \
|
|
998
|
+
if ( rc_ != 3 && ! ( ENTERS(j) ) ) continue; \
|
|
999
|
+
b[nb++] = j; \
|
|
1000
|
+
if ( nb == size ) { \
|
|
1001
|
+
CA_TOPK_SELECT(AFTER); \
|
|
1002
|
+
nb = cap; \
|
|
1003
|
+
} \
|
|
1004
|
+
else if ( ! ( nb == cap && rc_ == 3 ) ) { /* the first cap cells */ \
|
|
1005
|
+
continue; \
|
|
1006
|
+
} \
|
|
1007
|
+
cut = b[0]; \
|
|
1008
|
+
for (i = 1; i < cap; i++) if ( AFTER(b[i], cut) ) cut = b[i]; \
|
|
1009
|
+
rc_ = CLASS(cut); \
|
|
1010
|
+
if ( rc_ == 0 ) memcpy(&rv_, f->v + cut * f->bytes, sizeof(rv_)); \
|
|
1011
|
+
} \
|
|
1012
|
+
if ( nb > cap ) CA_TOPK_SELECT(AFTER); \
|
|
1013
|
+
ca_topk_sort(f, b, tmp, cap); \
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
/* The typed comparisons. A cell enters when it comes before the cut;
|
|
1017
|
+
one that ties the cut does not, it lies later. */
|
|
1018
|
+
#define CA_TOPK_CLASS_INT(i) ( ( f->m && f->m[i] ) ? 2 : 0 )
|
|
1019
|
+
#define CA_TOPK_CLASS_FLT(i) ( ( f->m && f->m[i] ) ? 2 : ( isnan(v_[i]) ? 1 : 0 ) )
|
|
1020
|
+
#define CA_TOPK_AFTER_V(CLASS, i, j) \
|
|
1021
|
+
( CLASS(i) != CLASS(j) ? CLASS(i) > CLASS(j) \
|
|
1022
|
+
: ( CLASS(i) == 0 && v_[i] != v_[j] ) \
|
|
1023
|
+
? ( f->desc ? v_[i] < v_[j] : v_[i] > v_[j] ) \
|
|
1024
|
+
: (i) > (j) )
|
|
1025
|
+
#define CA_TOPK_AFTER_INT(i, j) CA_TOPK_AFTER_V(CA_TOPK_CLASS_INT, i, j)
|
|
1026
|
+
#define CA_TOPK_AFTER_FLT(i, j) CA_TOPK_AFTER_V(CA_TOPK_CLASS_FLT, i, j)
|
|
1027
|
+
#define CA_TOPK_ENTERS_V(CLASS, j) \
|
|
1028
|
+
( CLASS(j) < rc_ || \
|
|
1029
|
+
( CLASS(j) == 0 && rc_ == 0 && \
|
|
1030
|
+
( f->desc ? v_[j] > rv_ : v_[j] < rv_ ) ) )
|
|
1031
|
+
#define CA_TOPK_ENTERS_INT(j) CA_TOPK_ENTERS_V(CA_TOPK_CLASS_INT, j)
|
|
1032
|
+
#define CA_TOPK_ENTERS_FLT(j) CA_TOPK_ENTERS_V(CA_TOPK_CLASS_FLT, j)
|
|
1033
|
+
|
|
1034
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_u8, uint8_t, CA_TOPK_CLASS_INT, CA_TOPK_AFTER_INT, CA_TOPK_ENTERS_INT)
|
|
1035
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_i8, int8_t, CA_TOPK_CLASS_INT, CA_TOPK_AFTER_INT, CA_TOPK_ENTERS_INT)
|
|
1036
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_i16, int16_t, CA_TOPK_CLASS_INT, CA_TOPK_AFTER_INT, CA_TOPK_ENTERS_INT)
|
|
1037
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_u16, uint16_t, CA_TOPK_CLASS_INT, CA_TOPK_AFTER_INT, CA_TOPK_ENTERS_INT)
|
|
1038
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_i32, int32_t, CA_TOPK_CLASS_INT, CA_TOPK_AFTER_INT, CA_TOPK_ENTERS_INT)
|
|
1039
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_u32, uint32_t, CA_TOPK_CLASS_INT, CA_TOPK_AFTER_INT, CA_TOPK_ENTERS_INT)
|
|
1040
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_i64, int64_t, CA_TOPK_CLASS_INT, CA_TOPK_AFTER_INT, CA_TOPK_ENTERS_INT)
|
|
1041
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_u64, uint64_t, CA_TOPK_CLASS_INT, CA_TOPK_AFTER_INT, CA_TOPK_ENTERS_INT)
|
|
1042
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_f32, float, CA_TOPK_CLASS_FLT, CA_TOPK_AFTER_FLT, CA_TOPK_ENTERS_FLT)
|
|
1043
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_f64, double, CA_TOPK_CLASS_FLT, CA_TOPK_AFTER_FLT, CA_TOPK_ENTERS_FLT)
|
|
1044
|
+
|
|
1045
|
+
/* fixlen: the generic comparison; v_ is unused. */
|
|
1046
|
+
#define CA_TOPK_CLASS_GEN(i) ca_topk_class(f, i)
|
|
1047
|
+
#define CA_TOPK_AFTER_GEN(i, j) ca_topk_after(f, i, j)
|
|
1048
|
+
#define CA_TOPK_ENTERS_GEN(j) ( ca_topk_cmp(f, j, cut) < 0 )
|
|
1049
|
+
|
|
1050
|
+
/* Whether cell i comes after cell j in (order, position). */
|
|
1051
|
+
static int
|
|
1052
|
+
ca_topk_after (const ca_topk_fiber_t *f, ca_size_t i, ca_size_t j)
|
|
1053
|
+
{
|
|
1054
|
+
int r = ca_topk_cmp(f, i, j);
|
|
1055
|
+
return r > 0 || ( r == 0 && i > j );
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
CA_TOPK_DEFINE_BUF(ca_topk_buf_gen, char, CA_TOPK_CLASS_GEN, CA_TOPK_AFTER_GEN, CA_TOPK_ENTERS_GEN)
|
|
1059
|
+
|
|
1060
|
+
#undef CA_TOPK_DEFINE_BUF
|
|
1061
|
+
#undef CA_TOPK_SELECT
|
|
1062
|
+
#undef CA_TOPK_CLASS_INT
|
|
1063
|
+
#undef CA_TOPK_CLASS_FLT
|
|
1064
|
+
#undef CA_TOPK_AFTER_V
|
|
1065
|
+
#undef CA_TOPK_AFTER_INT
|
|
1066
|
+
#undef CA_TOPK_AFTER_FLT
|
|
1067
|
+
#undef CA_TOPK_ENTERS_V
|
|
1068
|
+
#undef CA_TOPK_ENTERS_INT
|
|
1069
|
+
#undef CA_TOPK_ENTERS_FLT
|
|
1070
|
+
#undef CA_TOPK_CLASS_GEN
|
|
1071
|
+
#undef CA_TOPK_AFTER_GEN
|
|
1072
|
+
#undef CA_TOPK_ENTERS_GEN
|
|
1073
|
+
|
|
1074
|
+
/* The first cap cells of one fiber in (order, position), sorted, into
|
|
1075
|
+
b[0..cap). b and tmp hold size positions, cap < size <= len. */
|
|
1076
|
+
static void
|
|
1077
|
+
ca_topk_buf_fiber (const ca_topk_fiber_t *f, ca_size_t len, ca_size_t cap,
|
|
1078
|
+
ca_size_t *b, ca_size_t *tmp, ca_size_t size)
|
|
1079
|
+
{
|
|
1080
|
+
switch ( f->type ) {
|
|
1081
|
+
case CA_BOOLEAN:
|
|
1082
|
+
case CA_UINT8: ca_topk_buf_u8(f, len, cap, b, tmp, size); break;
|
|
1083
|
+
case CA_INT8: ca_topk_buf_i8(f, len, cap, b, tmp, size); break;
|
|
1084
|
+
case CA_INT16: ca_topk_buf_i16(f, len, cap, b, tmp, size); break;
|
|
1085
|
+
case CA_UINT16: ca_topk_buf_u16(f, len, cap, b, tmp, size); break;
|
|
1086
|
+
case CA_INT32: ca_topk_buf_i32(f, len, cap, b, tmp, size); break;
|
|
1087
|
+
case CA_UINT32: ca_topk_buf_u32(f, len, cap, b, tmp, size); break;
|
|
1088
|
+
case CA_INT64: ca_topk_buf_i64(f, len, cap, b, tmp, size); break;
|
|
1089
|
+
case CA_UINT64: ca_topk_buf_u64(f, len, cap, b, tmp, size); break;
|
|
1090
|
+
case CA_FLOAT32: ca_topk_buf_f32(f, len, cap, b, tmp, size); break;
|
|
1091
|
+
case CA_FLOAT64: ca_topk_buf_f64(f, len, cap, b, tmp, size); break;
|
|
1092
|
+
default: ca_topk_buf_gen(f, len, cap, b, tmp, size); break;
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
/* Per-axis top-k positions of `key` (an order key: not object, not
|
|
1097
|
+
complex) by the buffered walk, for cap < the length of the axis. The
|
|
1098
|
+
fibers come in the row-major order of the other axes, so the answer is
|
|
1099
|
+
filled with the axis last and moved into place at the end (cap cells
|
|
1100
|
+
per fiber). */
|
|
1101
|
+
static VALUE
|
|
1102
|
+
ca_topk_buffered_positions (VALUE key, long cap, long axis, int desc)
|
|
1103
|
+
{
|
|
1104
|
+
volatile VALUE holder = 0, out;
|
|
1105
|
+
VALUE perm[CA_RANK_MAX];
|
|
1106
|
+
ca_size_t odim[CA_RANK_MAX];
|
|
1107
|
+
CArray *ck, *co;
|
|
1108
|
+
ca_iter_state st;
|
|
1109
|
+
ca_topk_fiber_t f;
|
|
1110
|
+
ca_size_t *buf, *tmp, n, o = 0, k, len, size;
|
|
1111
|
+
int64_t *op;
|
|
1112
|
+
boolean8_t *m;
|
|
1113
|
+
char *p;
|
|
1114
|
+
int ndim, i, j = 0;
|
|
1115
|
+
|
|
1116
|
+
GetCArray(key, ck);
|
|
1117
|
+
ndim = ck->ndim;
|
|
1118
|
+
for (i = 0; i < ndim; i++) if ( i != axis ) odim[j++] = ck->dim[i];
|
|
1119
|
+
odim[ndim - 1] = cap;
|
|
1120
|
+
len = ck->dim[axis];
|
|
1121
|
+
out = rb_carray_new(CA_INT64, ndim, odim, 0, NULL);
|
|
1122
|
+
GetCArray(out, co);
|
|
1123
|
+
op = (int64_t *) co->ptr;
|
|
1124
|
+
|
|
1125
|
+
f.type = ck->data_type;
|
|
1126
|
+
f.bytes = ck->bytes;
|
|
1127
|
+
f.desc = desc;
|
|
1128
|
+
size = ( len < 4 * cap + 256 ) ? len : 4 * cap + 256;
|
|
1129
|
+
buf = ALLOCV_N(ca_size_t, holder, 2 * size);
|
|
1130
|
+
tmp = buf + size;
|
|
1131
|
+
CA_FOR_EACH_FIBER_MASKED(st, ck, axis, 0, p, n, m) {
|
|
1132
|
+
f.v = p;
|
|
1133
|
+
f.m = m;
|
|
1134
|
+
ca_topk_buf_fiber(&f, n, cap, buf, tmp, size);
|
|
1135
|
+
for (k = 0; k < cap; k++) op[o * cap + k] = (int64_t) buf[k];
|
|
1136
|
+
o++;
|
|
1137
|
+
}
|
|
1138
|
+
ALLOCV_END(holder);
|
|
1139
|
+
if ( axis == ndim - 1 ) return out;
|
|
1140
|
+
for (i = 0; i < ndim; i++) {
|
|
1141
|
+
perm[i] = INT2FIX( i < axis ? i : ( i == axis ? ndim - 1 : i - 1 ) );
|
|
1142
|
+
}
|
|
1143
|
+
return rb_ca_copy(rb_funcallv(out, rb_intern("transpose"), ndim, perm));
|
|
1144
|
+
}
|
|
1145
|
+
|
|
939
1146
|
/* Per-axis top-k positions (cap clamped, axis normalized).
|
|
940
1147
|
* Called by rb_ca_topk_index below. */
|
|
941
1148
|
static VALUE
|
|
@@ -946,6 +1153,18 @@ rb_ca_topk_positions (VALUE self, long cap, long axis_norm, int desc)
|
|
|
946
1153
|
long dim_axis = (long) ca->dim[axis_norm];
|
|
947
1154
|
VALUE raxis_norm = LONG2NUM(axis_norm);
|
|
948
1155
|
|
|
1156
|
+
/* The buffered walk reads any key but an object (its cells compare in
|
|
1157
|
+
Ruby) or a complex one (no order), and keeps cap cells per fiber. */
|
|
1158
|
+
if ( ca->data_type != CA_OBJECT && ! ca_is_complex_type(ca) ) {
|
|
1159
|
+
VALUE key = ca_order_key(self, desc ? "nlargest" : "nsmallest");
|
|
1160
|
+
CArray *ck;
|
|
1161
|
+
GetCArray(key, ck);
|
|
1162
|
+
if ( ck->data_type != CA_OBJECT && ! ca_is_complex_type(ck) &&
|
|
1163
|
+
cap < dim_axis ) {
|
|
1164
|
+
return ca_topk_buffered_positions(key, cap, axis_norm, desc);
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
|
|
949
1168
|
/* The largest: reversing the ascending order would put the NaN and the
|
|
950
1169
|
masked cells first, so rank them descending (NaN, then the masked
|
|
951
1170
|
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,7 +522,7 @@ 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
|
box_muller_pair(&c->source, &p[2*i], &p[2*i+1]);
|
|
@@ -535,7 +535,7 @@ ca_randomn_bang_fill (VALUE arg)
|
|
|
535
535
|
break;
|
|
536
536
|
}
|
|
537
537
|
case CA_FLOAT32: {
|
|
538
|
-
float *p = (float *)ca->ptr;
|
|
538
|
+
CA_U(float) *p = (CA_U(float) *)ca->ptr;
|
|
539
539
|
ca_size_t pairs = n / 2;
|
|
540
540
|
for (i = 0; i < pairs; i++) {
|
|
541
541
|
double r1, r2;
|
|
@@ -551,7 +551,7 @@ ca_randomn_bang_fill (VALUE arg)
|
|
|
551
551
|
break;
|
|
552
552
|
}
|
|
553
553
|
case CA_CMPLX128: {
|
|
554
|
-
|
|
554
|
+
ca_u_cmplx128_t *p = (ca_u_cmplx128_t *)ca->ptr;
|
|
555
555
|
for (i = 0; i < n; i++) {
|
|
556
556
|
double r1, r2;
|
|
557
557
|
box_muller_pair(&c->source, &r1, &r2);
|
|
@@ -560,7 +560,7 @@ ca_randomn_bang_fill (VALUE arg)
|
|
|
560
560
|
break;
|
|
561
561
|
}
|
|
562
562
|
case CA_CMPLX64: {
|
|
563
|
-
|
|
563
|
+
ca_u_cmplx64_t *p = (ca_u_cmplx64_t *)ca->ptr;
|
|
564
564
|
for (i = 0; i < n; i++) {
|
|
565
565
|
double r1, r2;
|
|
566
566
|
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). */
|
data/ext/carray_slab.c
CHANGED
|
@@ -346,6 +346,26 @@ ca_slab_build_output_view (int8_t data_type, ca_size_t bytes,
|
|
|
346
346
|
return TypedData_Wrap_Struct(rb_cCAWrap, &cawrap_data_type, cw);
|
|
347
347
|
}
|
|
348
348
|
|
|
349
|
+
/* The array the slab views move onto when the walk ends (see
|
|
350
|
+
slab_state_release_views), made with the carrier and held by it. It is
|
|
351
|
+
made here rather than at the end: the end runs in an ensure, after the
|
|
352
|
+
block, and an allocation failing there would leave the walk open and
|
|
353
|
+
the views pointing into freed scratch. */
|
|
354
|
+
static void
|
|
355
|
+
ca_slab_prepare_backing (ca_slab_iter_state_t *st)
|
|
356
|
+
{
|
|
357
|
+
CArray *cw, *backing;
|
|
358
|
+
volatile VALUE bv;
|
|
359
|
+
TypedData_Get_Struct(st->carrier, CArray, &carray_data_type, cw);
|
|
360
|
+
bv = rb_carray_new(cw->data_type, cw->ndim, cw->dim, cw->bytes, NULL);
|
|
361
|
+
TypedData_Get_Struct(bv, CArray, &carray_data_type, backing);
|
|
362
|
+
if ( cw->mask ) {
|
|
363
|
+
ca_create_mask(backing);
|
|
364
|
+
}
|
|
365
|
+
rb_ivar_set(st->carrier, rb_intern("__slab_backing__"), bv);
|
|
366
|
+
RB_GC_GUARD(bv);
|
|
367
|
+
}
|
|
368
|
+
|
|
349
369
|
/* Common setup of the input slab view for all 4 forms. Decides ALIAS
|
|
350
370
|
vs SCRATCH from T1's slab_strides[0] vs src->bytes equality, builds
|
|
351
371
|
the slab_view + (when SCRATCH) carrier in place. The mask travels
|
|
@@ -465,6 +485,10 @@ ca_slab_setup_input_slab_view (ca_slab_iter_state_t *st, CArray *src,
|
|
|
465
485
|
}
|
|
466
486
|
}
|
|
467
487
|
|
|
488
|
+
if ( st->carrier != Qnil ) {
|
|
489
|
+
ca_slab_prepare_backing(st);
|
|
490
|
+
}
|
|
491
|
+
|
|
468
492
|
/* The slab is a window onto the source when the fiber is contiguous and
|
|
469
493
|
a copy in the iterator's scratch when it is not, so writing through it
|
|
470
494
|
landed on one axis and vanished on the next. Nothing in the surface
|
|
@@ -861,7 +885,6 @@ ca_slab_reduce_setup (ca_slab_iter_state_t *st, CArray **out_src,
|
|
|
861
885
|
ca_size_t *out_n)
|
|
862
886
|
{
|
|
863
887
|
CArray *src;
|
|
864
|
-
CArray *out;
|
|
865
888
|
ca_size_t fiber_len;
|
|
866
889
|
ca_size_t out_dim[CA_RANK_MAX];
|
|
867
890
|
int8_t out_ndim;
|
|
@@ -904,7 +927,6 @@ ca_slab_reduce_setup (ca_slab_iter_state_t *st, CArray **out_src,
|
|
|
904
927
|
|
|
905
928
|
st->output = rb_carray_new(st->out_data_type, out_ndim, out_dim,
|
|
906
929
|
st->out_bytes, NULL);
|
|
907
|
-
TypedData_Get_Struct(st->output, CArray, &carray_data_type, out);
|
|
908
930
|
|
|
909
931
|
/* FIBER_CONTIG is naxes==1 only (T1 substrate contract). Multi-axis
|
|
910
932
|
omits the flag and uses bare CA_SLAB_AXES; T1 picks an in-src
|
|
@@ -1178,8 +1200,9 @@ slab_state_run_body (VALUE arg)
|
|
|
1178
1200
|
as it has a ptr. Before the scratch they point into is freed, the
|
|
1179
1201
|
input slab and its carrier are moved onto a copy of the last slab,
|
|
1180
1202
|
held by the carrier, and the internal output view lets go of its
|
|
1181
|
-
buffer.
|
|
1182
|
-
|
|
1203
|
+
buffer. The copy is made into the array ca_slab_prepare_backing set
|
|
1204
|
+
aside, so nothing here allocates. A slab that is a window onto the
|
|
1205
|
+
source itself points into the source and needs nothing. */
|
|
1183
1206
|
static void
|
|
1184
1207
|
slab_state_release_views (ca_slab_iter_state_t *st)
|
|
1185
1208
|
{
|
|
@@ -1196,12 +1219,12 @@ slab_state_release_views (ca_slab_iter_state_t *st)
|
|
|
1196
1219
|
if ( cw->ptr == NULL ) {
|
|
1197
1220
|
return;
|
|
1198
1221
|
}
|
|
1199
|
-
|
|
1200
|
-
bv
|
|
1201
|
-
|
|
1202
|
-
|
|
1222
|
+
bv = rb_ivar_get(st->carrier, rb_intern("__slab_backing__"));
|
|
1223
|
+
TypedData_Get_Struct(bv, CArray, &carray_data_type, backing);
|
|
1224
|
+
memcpy(backing->ptr, cw->ptr, (size_t) (cw->elements * cw->bytes));
|
|
1225
|
+
if ( cw->mask && cw->mask->ptr ) {
|
|
1226
|
+
memcpy(backing->mask->ptr, cw->mask->ptr, (size_t) cw->elements);
|
|
1203
1227
|
}
|
|
1204
|
-
rb_ivar_set(st->carrier, rb_intern("__slab_backing__"), bv);
|
|
1205
1228
|
if ( cs->ptr ) {
|
|
1206
1229
|
cs->ptr = backing->ptr;
|
|
1207
1230
|
}
|