carray 3.0.2 → 3.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +568 -0
- data/README.md +6 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +220 -0
- data/ext/ca_axis_group.c +201 -123
- data/ext/ca_binop_dispatch.c +46 -52
- data/ext/ca_binop_dispatch.h +1 -1
- data/ext/ca_categorical_iterator.c +249 -183
- data/ext/ca_compare.c +7 -12
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +38 -23
- data/ext/ca_kernel_iterator.c +1765 -2076
- data/ext/ca_kernel_iterator.h +584 -566
- data/ext/ca_monop_dispatch.c +86 -63
- data/ext/ca_monop_dispatch.h +5 -0
- data/ext/ca_obj_array.c +223 -56
- data/ext/ca_obj_bincmp.c +172 -138
- data/ext/ca_obj_binop.c +116 -230
- data/ext/ca_obj_bitarray.c +40 -26
- data/ext/ca_obj_bitfield.c +100 -68
- data/ext/ca_obj_block.c +19 -9
- data/ext/ca_obj_byte_swap.c +45 -46
- data/ext/ca_obj_const_string.c +269 -44
- data/ext/ca_obj_face.c +612 -89
- data/ext/ca_obj_face.h +111 -47
- data/ext/ca_obj_fake.c +36 -79
- data/ext/ca_obj_farray.c +7 -3
- data/ext/ca_obj_field.c +33 -8
- data/ext/ca_obj_fixlen_string.c +23 -24
- data/ext/ca_obj_grid.c +541 -210
- data/ext/ca_obj_meld.c +331 -111
- data/ext/ca_obj_moncmp.c +80 -65
- data/ext/ca_obj_monop.c +177 -149
- data/ext/ca_obj_object.c +664 -248
- data/ext/ca_obj_record.c +63 -23
- data/ext/ca_obj_reduce.c +18 -16
- data/ext/ca_obj_refer.c +140 -58
- data/ext/ca_obj_remap.c +85 -24
- data/ext/ca_obj_repeat.c +24 -9
- data/ext/ca_obj_roll.c +121 -16
- data/ext/ca_obj_select.c +61 -58
- data/ext/ca_obj_select_axis.c +73 -107
- data/ext/ca_obj_shift.c +32 -102
- data/ext/ca_obj_stack.c +372 -122
- data/ext/ca_obj_stride.c +348 -140
- data/ext/ca_obj_string.c +88 -22
- data/ext/ca_obj_tile.c +38 -21
- data/ext/ca_obj_time.c +45 -31
- data/ext/ca_obj_timedelta.c +43 -29
- data/ext/ca_obj_transpose.c +17 -6
- data/ext/ca_obj_triop.c +125 -141
- data/ext/ca_obj_window.c +330 -44
- data/ext/ca_op_ipower.c +24 -11
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +104 -81
- data/ext/ca_sweep_engine.h +7 -20
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +542 -0
- data/ext/carray.h +241 -92
- data/ext/carray_access.c +608 -276
- data/ext/carray_address_basis.c +494 -97
- data/ext/carray_attribute.c +129 -4
- data/ext/carray_bincount.c +39 -7
- data/ext/carray_broadcast.c +56 -19
- data/ext/carray_build_flags.h +1 -1
- data/ext/carray_call_cfunc.c +108 -28
- data/ext/carray_cast.c +1576 -223
- data/ext/carray_cast_func.rb +77 -24
- data/ext/carray_class.c +4 -3
- data/ext/carray_conversion.c +208 -75
- data/ext/carray_copy.c +82 -24
- data/ext/carray_core.c +646 -162
- data/ext/carray_count.c +171 -88
- data/ext/carray_element.c +94 -60
- data/ext/carray_factorize.c +670 -324
- data/ext/carray_generate.c +260 -83
- data/ext/carray_histogram.c +209 -106
- data/ext/carray_hold.c +14 -16
- data/ext/carray_index_classifier.c +422 -243
- data/ext/carray_internal.h +692 -3
- data/ext/carray_kernels_bincmp.c +7 -0
- data/ext/carray_kernels_binop.c +487 -120
- data/ext/carray_kernels_init.c +653 -50
- data/ext/carray_kernels_moncmp.c +15 -8
- data/ext/carray_kernels_monop.c +99 -43
- data/ext/carray_kernels_reduce_aggregate.c +3925 -6112
- data/ext/carray_kernels_reduce_boolean.c +112 -36
- data/ext/carray_kernels_reduce_cumulative.c +2127 -6903
- data/ext/carray_kernels_reduce_extreme.c +3032 -2892
- data/ext/carray_kernels_reduce_variance.c +439 -500
- data/ext/carray_kernels_scan.c +1097 -488
- data/ext/carray_kernels_search.c +3787 -2176
- data/ext/carray_kernels_sort.c +1200 -920
- data/ext/carray_kernels_triop.c +479 -7
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +967 -153
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +910 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +299 -100
- data/ext/carray_memory_view.c +872 -758
- data/ext/carray_operator.c +1171 -364
- data/ext/carray_order.c +505 -133
- data/ext/carray_partition.c +112 -65
- data/ext/carray_random.c +327 -239
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +346 -78
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +249 -86
- data/ext/carray_sort.c +224 -227
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +118 -39
- data/ext/carray_test.c +193 -69
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +579 -113
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +19 -4
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1202 -1014
- data/ext/ruby_carray.c +17 -5
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +160 -17
- data/lib/carray/autoload_carray.rb +23 -27
- data/lib/carray/autoload_method_extension.rb +20 -5
- data/lib/carray/axis_group.rb +360 -63
- data/lib/carray/basics.rb +162 -28
- data/lib/carray/bincount_nd.rb +18 -2
- data/lib/carray/block_iterator.rb +231 -58
- data/lib/carray/boolean_reduce.rb +34 -42
- data/lib/carray/categorical.rb +242 -52
- data/lib/carray/categorical_iterator.rb +437 -827
- data/lib/carray/complex.rb +41 -34
- data/lib/carray/conditional.rb +150 -14
- data/lib/carray/const_string.rb +59 -4
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +7 -1
- data/lib/carray/frame/column_verbs.rb +70 -0
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +82 -7
- data/lib/carray/frame/csv_parser.rb +688 -87
- data/lib/carray/frame/describe.rb +80 -0
- data/lib/carray/frame/frame.rb +369 -45
- data/lib/carray/frame/group.rb +631 -90
- data/lib/carray/frame/io.rb +506 -79
- data/lib/carray/frame/join.rb +411 -62
- data/lib/carray/frame/records.rb +116 -19
- data/lib/carray/frame/reshape.rb +455 -0
- data/lib/carray/frame/sort.rb +30 -18
- data/lib/carray/frame/verbs.rb +868 -61
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +4 -0
- data/lib/carray/fuse_source.rb +118 -2
- data/lib/carray/fusion.rb +257 -42
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +54 -13
- data/lib/carray/iterator.rb +99 -9
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +216 -193
- data/lib/carray/mask_gap_fill.rb +112 -92
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +52 -21
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +18 -2
- data/lib/carray/methods/bit_string.rb +15 -4
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +18 -10
- data/lib/carray/methods/factorize.rb +2 -2
- data/lib/carray/methods/gather_nd.rb +25 -5
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +140 -10
- data/lib/carray/methods/join.rb +2 -7
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +182 -45
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/repeat.rb +1 -20
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +11 -2
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +65 -17
- data/lib/carray/segment_iterator.rb +1221 -0
- data/lib/carray/serialize.rb +214 -30
- data/lib/carray/slab_iterator.rb +101 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +12 -4
- data/lib/carray/struct.rb +137 -58
- data/lib/carray/struct_builder.rb +124 -17
- data/lib/carray/time.rb +1222 -186
- data/lib/carray/window_iterator.rb +242 -81
- data/lib/carray.rb +9 -2
- data/yard-stubs/ca_obj_array.rb +4 -4
- data/yard-stubs/ca_obj_bitarray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +23 -12
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +5 -1
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +5 -4
- data/yard-stubs/ca_obj_roll.rb +2 -3
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +9 -5
- data/yard-stubs/carray_access.rb +11 -5
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_broadcast.rb +1 -1
- data/yard-stubs/carray_cast.rb +88 -43
- data/yard-stubs/carray_conversion.rb +15 -2
- data/yard-stubs/carray_copy.rb +12 -5
- data/yard-stubs/carray_core.rb +3 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +60 -12
- data/yard-stubs/carray_math.rb +52 -14
- data/yard-stubs/carray_median_percentile.rb +15 -8
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +61 -29
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +21 -9
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +10 -2
- data/yard-stubs/carray_sort.rb +49 -8
- data/yard-stubs/carray_test.rb +15 -3
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -5
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_kernels_map.c +0 -3467
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/ext/carray_sort.c
CHANGED
|
@@ -8,11 +8,12 @@
|
|
|
8
8
|
|
|
9
9
|
#include "ruby.h"
|
|
10
10
|
#include "carray.h"
|
|
11
|
-
#include "ca_for_buffer.h" /*
|
|
11
|
+
#include "ca_for_buffer.h" /* rb_ca_call_with_buffer */
|
|
12
12
|
#include "ca_kernel_iterator.h" /* CA_FOR_EACH_FIBER_INOUT (sort_copy) */
|
|
13
13
|
#include "ca_obj_face.h" /* CA_FACE_LIFT_IF_FACE */
|
|
14
14
|
#include "ca_sort_kernels.h" /* ca_sort_quick_* / ca_sort_merge_* / ca_partition_nan_* */
|
|
15
15
|
#include "ca_compare.h" /* ca_elem_cmp[] -- shared element comparators */
|
|
16
|
+
#include "carray_internal.h" /* ca_attach_window */
|
|
16
17
|
#include <math.h>
|
|
17
18
|
#include <float.h>
|
|
18
19
|
|
|
@@ -93,6 +94,40 @@ sort_addr_cmp (struct sort_addr_key *a, struct sort_addr_key *b)
|
|
|
93
94
|
return ( ia > ib ) ? 1 : -1; /* for stable sort */
|
|
94
95
|
}
|
|
95
96
|
|
|
97
|
+
/* An object key compares through <=>, which can raise, and a raise must
|
|
98
|
+
not unwind through libc's mergesort / qsort. Those keys sort with this
|
|
99
|
+
mergesort instead, whose frames hold nothing; the numeric ones keep
|
|
100
|
+
libc's, which their comparisons cannot leave. */
|
|
101
|
+
static void
|
|
102
|
+
sort_addr_merge (struct sort_addr_key *a, struct sort_addr_key *aux,
|
|
103
|
+
ca_size_t n, int (*cmp)(const void *, const void *))
|
|
104
|
+
CA_SORT_MERGE_BY_CMP(struct sort_addr_key)
|
|
105
|
+
|
|
106
|
+
typedef struct {
|
|
107
|
+
struct sort_addr_key *data;
|
|
108
|
+
struct sort_addr_key *aux; /* NULL: no object key, libc sorts */
|
|
109
|
+
ca_size_t elements;
|
|
110
|
+
} sort_addr_run_t;
|
|
111
|
+
|
|
112
|
+
static VALUE
|
|
113
|
+
sort_addr_run (VALUE arg)
|
|
114
|
+
{
|
|
115
|
+
sort_addr_run_t *r = (sort_addr_run_t *) arg;
|
|
116
|
+
if ( r->aux ) {
|
|
117
|
+
sort_addr_merge(r->data, r->aux, r->elements,
|
|
118
|
+
(int (*)(const void*,const void*)) sort_addr_cmp);
|
|
119
|
+
return Qnil;
|
|
120
|
+
}
|
|
121
|
+
#ifdef HAVE_MERGESORT
|
|
122
|
+
mergesort(r->data, r->elements, sizeof(struct sort_addr_key),
|
|
123
|
+
(int (*)(const void*,const void*)) sort_addr_cmp);
|
|
124
|
+
#else
|
|
125
|
+
qsort(r->data, r->elements, sizeof(struct sort_addr_key),
|
|
126
|
+
(int (*)(const void*,const void*)) sort_addr_cmp);
|
|
127
|
+
#endif
|
|
128
|
+
return Qnil;
|
|
129
|
+
}
|
|
130
|
+
|
|
96
131
|
/* CArray.sort_addr(*args, masked_position: :last) — multi-key lex
|
|
97
132
|
* sort. Returns a 1-D CA_SIZE array of indices that sorts the
|
|
98
133
|
* arguments in priority order (a > b > c):
|
|
@@ -104,34 +139,25 @@ sort_addr_cmp (struct sort_addr_key *a, struct sort_addr_key *b)
|
|
|
104
139
|
* an incomparable sentinel clustered at masked_position: (:last
|
|
105
140
|
* default, or :first); ties are broken by original index (stable). */
|
|
106
141
|
static VALUE
|
|
107
|
-
|
|
142
|
+
rb_ca_s_sort_addr_kw (int argc, VALUE *argv, VALUE ropt, VALUE self)
|
|
108
143
|
{
|
|
109
144
|
volatile VALUE out;
|
|
110
145
|
CArray *co;
|
|
111
|
-
struct cmp_base *base;
|
|
146
|
+
struct cmp_base base_s, *base = &base_s;
|
|
112
147
|
struct sort_addr_key *data;
|
|
148
|
+
volatile VALUE hlist = 0, hdata = 0, haux = 0, hmodes = 0;
|
|
149
|
+
sort_addr_run_t run;
|
|
150
|
+
char *modes;
|
|
151
|
+
int has_object = 0;
|
|
113
152
|
ca_size_t elements;
|
|
114
153
|
ca_size_t *q;
|
|
115
154
|
int j;
|
|
116
155
|
ca_size_t i;
|
|
117
156
|
|
|
118
|
-
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
119
157
|
VALUE vmasked_position = Qnil;
|
|
120
158
|
rb_scan_options(ropt, "masked_position", &vmasked_position);
|
|
121
|
-
int masked_last = 1
|
|
122
|
-
|
|
123
|
-
static ID sym_first = 0, sym_last = 0;
|
|
124
|
-
if ( !sym_first ) sym_first = rb_intern("first");
|
|
125
|
-
if ( !sym_last ) sym_last = rb_intern("last");
|
|
126
|
-
ID mp_id = SYM2ID(vmasked_position);
|
|
127
|
-
if ( mp_id == sym_last ) masked_last = 1;
|
|
128
|
-
else if ( mp_id == sym_first ) masked_last = 0;
|
|
129
|
-
else {
|
|
130
|
-
rb_raise(rb_eArgError,
|
|
131
|
-
"sort_addr: unknown masked_position %s (expected :first or :last)",
|
|
132
|
-
rb_id2name(mp_id));
|
|
133
|
-
}
|
|
134
|
-
}
|
|
159
|
+
int masked_last = NIL_P(vmasked_position) ? 1
|
|
160
|
+
: ca_symbol_choice(vmasked_position, "masked_position", "first", "last", NULL);
|
|
135
161
|
|
|
136
162
|
if ( argc <= 0 ) {
|
|
137
163
|
rb_raise(rb_eArgError, "no arg given");
|
|
@@ -146,53 +172,47 @@ rb_ca_s_sort_addr (int argc, VALUE *argv, VALUE self)
|
|
|
146
172
|
if ( elements != NUM2SIZE(rb_ca_elements(argv[j])) ) {
|
|
147
173
|
rb_raise(rb_eArgError, "elements mismatch");
|
|
148
174
|
}
|
|
149
|
-
/* Face gate: descend a Face to its storage and build attach / comparator
|
|
150
|
-
/ template output on that plain storage (this also removes the SEGV
|
|
151
|
-
from a face-lifted NULL-ptr index output). A fixlen storage sorts by
|
|
152
|
-
memcmp (the default order for fixlen, as for a plain fixlen array); a
|
|
153
|
-
numeric storage requires ORDERABLE so the numeric order equals the
|
|
154
|
-
surface order, else it raises. */
|
|
155
175
|
TypedData_Get_Struct(argv[j], CArray, &carray_data_type, ca_j);
|
|
156
176
|
if ( ca_is_face(ca_j) ) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
177
|
+
argv[j] = ca_order_key(argv[j], "sort_addr");
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
{
|
|
181
|
+
CArray *k;
|
|
182
|
+
TypedData_Get_Struct(argv[j], CArray, &carray_data_type, k);
|
|
183
|
+
if ( ca_is_complex_type(k) ) {
|
|
184
|
+
rb_raise(rb_eCADataTypeError,
|
|
185
|
+
"sort_addr: a %s key has no order (complex numbers are not "
|
|
186
|
+
"ordered); sort by its real part, imaginary part or abs",
|
|
187
|
+
ca_type_name[k->data_type]);
|
|
166
188
|
}
|
|
167
|
-
argv[j] = stripped;
|
|
168
189
|
}
|
|
169
190
|
}
|
|
170
191
|
|
|
171
|
-
|
|
192
|
+
/* Scratch the unwind collects: the keys are read inside an attach
|
|
193
|
+
window, and a comparison of object keys can raise. */
|
|
172
194
|
base->n = argc;
|
|
173
195
|
base->masked_last = masked_last;
|
|
174
|
-
base->ca =
|
|
196
|
+
base->ca = ALLOCV_N(CArray *, hlist, base->n);
|
|
197
|
+
modes = ALLOCV_N(char, hmodes, argc + 1);
|
|
175
198
|
|
|
176
199
|
for (j=0; j<argc; j++) {
|
|
177
|
-
CArray
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
ca_attach(ca);
|
|
200
|
+
TypedData_Get_Struct(argv[j], CArray, &carray_data_type, base->ca[j]);
|
|
201
|
+
has_object |= ( base->ca[j]->data_type == CA_OBJECT );
|
|
202
|
+
modes[j] = 'r';
|
|
181
203
|
}
|
|
204
|
+
modes[argc] = '\0';
|
|
182
205
|
|
|
183
|
-
data =
|
|
206
|
+
data = ALLOCV_N(struct sort_addr_key, hdata, elements);
|
|
184
207
|
for (i=0; i<elements; i++) {
|
|
185
208
|
data[i].i = i;
|
|
186
209
|
data[i].base = base;
|
|
187
210
|
}
|
|
188
211
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
qsort(data, elements, sizeof(struct sort_addr_key),
|
|
194
|
-
(int (*)(const void*,const void*)) sort_addr_cmp);
|
|
195
|
-
#endif
|
|
212
|
+
run.data = data;
|
|
213
|
+
run.aux = has_object ? ALLOCV_N(struct sort_addr_key, haux, elements) : NULL;
|
|
214
|
+
run.elements = elements;
|
|
215
|
+
ca_attach_window(argc, base->ca, modes, sort_addr_run, (VALUE) &run);
|
|
196
216
|
|
|
197
217
|
out = rb_ca_template_with_type(argv[0], INT2NUM(CA_SIZE), INT2NUM(0));
|
|
198
218
|
TypedData_Get_Struct(out, CArray, &carray_data_type, co);
|
|
@@ -203,27 +223,26 @@ rb_ca_s_sort_addr (int argc, VALUE *argv, VALUE self)
|
|
|
203
223
|
q++;
|
|
204
224
|
}
|
|
205
225
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
xfree(data);
|
|
211
|
-
xfree(base->ca);
|
|
212
|
-
xfree(base);
|
|
226
|
+
ALLOCV_END(haux);
|
|
227
|
+
ALLOCV_END(hdata);
|
|
228
|
+
ALLOCV_END(hmodes);
|
|
229
|
+
ALLOCV_END(hlist);
|
|
213
230
|
|
|
214
231
|
return out;
|
|
215
232
|
}
|
|
216
233
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
234
|
+
static VALUE
|
|
235
|
+
rb_ca_s_sort_addr (int argc, VALUE *argv, VALUE self)
|
|
236
|
+
{
|
|
237
|
+
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
238
|
+
return rb_ca_s_sort_addr_kw(argc, argv, ropt, self);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* Internal sort_addr kernel entries (C-level only, no Ruby binding;
|
|
242
|
+
* defined in the generated carray_kernels_sort.c). The _quick and
|
|
243
|
+
* _stable variants implement the kind: dispatch; both take an explicit
|
|
244
|
+
* masked_last so `sort` / `sort_copy` can pass the masked_position:
|
|
245
|
+
* kwarg through (see MkKernel.sort in mkkernel.rb). */
|
|
227
246
|
extern VALUE rb_ca_sort_addr_ki_quick_mp (VALUE self, VALUE vaxis, int masked_last);
|
|
228
247
|
extern VALUE rb_ca_sort_addr_ki_stable_mp (VALUE self, VALUE vaxis, int masked_last);
|
|
229
248
|
extern VALUE rb_ca_remap_new (VALUE cary, VALUE rmapper); /* ca_obj_remap.c (sort view) */
|
|
@@ -274,16 +293,12 @@ rb_ca_sort_addr_c (VALUE self, VALUE axis, int stable, int masked_last)
|
|
|
274
293
|
if ( NIL_P(axis) ) {
|
|
275
294
|
/* Legacy flat: equivalent to CArray.sort_addr(self, masked_position:).
|
|
276
295
|
kind: ignored for now (the flat path uses qsort/mergesort
|
|
277
|
-
internally).
|
|
278
|
-
|
|
279
|
-
type-checks the last positional arg, not rb_keyword_given_p), so
|
|
280
|
-
this raw C call is safe unlike the rb_scan_args "1:" pattern used
|
|
281
|
-
elsewhere in this file. */
|
|
282
|
-
VALUE kw = rb_hash_new();
|
|
296
|
+
internally). */
|
|
297
|
+
volatile VALUE kw = rb_hash_new();
|
|
283
298
|
rb_hash_aset(kw, ID2SYM(rb_intern("masked_position")),
|
|
284
299
|
masked_last ? ID2SYM(rb_intern("last")) : ID2SYM(rb_intern("first")));
|
|
285
|
-
VALUE flat_argv[
|
|
286
|
-
return
|
|
300
|
+
VALUE flat_argv[1] = { self };
|
|
301
|
+
return rb_ca_s_sort_addr_kw(1, flat_argv, kw, rb_cCArray);
|
|
287
302
|
}
|
|
288
303
|
return stable ? rb_ca_sort_addr_ki_stable_mp(self, axis, masked_last)
|
|
289
304
|
: rb_ca_sort_addr_ki_quick_mp (self, axis, masked_last);
|
|
@@ -302,35 +317,11 @@ rb_ca_sort_addr (int argc, VALUE *argv, VALUE self)
|
|
|
302
317
|
rb_scan_args(argc, argv, "0:", &opts);
|
|
303
318
|
rb_scan_options(opts, "axis,kind,masked_position", &axis, &kind, &vmasked_position);
|
|
304
319
|
|
|
305
|
-
int do_stable = 0
|
|
306
|
-
|
|
307
|
-
static ID sym_quick = 0, sym_stable = 0;
|
|
308
|
-
if ( ! sym_quick ) sym_quick = rb_intern("quick");
|
|
309
|
-
if ( ! sym_stable ) sym_stable = rb_intern("stable");
|
|
310
|
-
ID kind_id = SYM2ID(kind);
|
|
311
|
-
if ( kind_id == sym_quick ) do_stable = 0;
|
|
312
|
-
else if ( kind_id == sym_stable ) do_stable = 1;
|
|
313
|
-
else {
|
|
314
|
-
rb_raise(rb_eArgError,
|
|
315
|
-
"sort_addr: unknown kind %s (expected :quick or :stable)",
|
|
316
|
-
rb_id2name(kind_id));
|
|
317
|
-
}
|
|
318
|
-
}
|
|
320
|
+
int do_stable = NIL_P(kind) ? 0
|
|
321
|
+
: ca_symbol_choice(kind, "kind", "quick", "stable", NULL);
|
|
319
322
|
|
|
320
|
-
int masked_last = 1
|
|
321
|
-
|
|
322
|
-
static ID sym_first = 0, sym_last = 0;
|
|
323
|
-
if ( !sym_first ) sym_first = rb_intern("first");
|
|
324
|
-
if ( !sym_last ) sym_last = rb_intern("last");
|
|
325
|
-
ID mp_id = SYM2ID(vmasked_position);
|
|
326
|
-
if ( mp_id == sym_last ) masked_last = 1;
|
|
327
|
-
else if ( mp_id == sym_first ) masked_last = 0;
|
|
328
|
-
else {
|
|
329
|
-
rb_raise(rb_eArgError,
|
|
330
|
-
"sort_addr: unknown masked_position %s (expected :first or :last)",
|
|
331
|
-
rb_id2name(mp_id));
|
|
332
|
-
}
|
|
333
|
-
}
|
|
323
|
+
int masked_last = NIL_P(vmasked_position) ? 1
|
|
324
|
+
: ca_symbol_choice(vmasked_position, "masked_position", "first", "last", NULL);
|
|
334
325
|
|
|
335
326
|
return rb_ca_sort_addr_c(self, axis, do_stable, masked_last);
|
|
336
327
|
}
|
|
@@ -362,12 +353,58 @@ rb_ca_sort_addr (int argc, VALUE *argv, VALUE self)
|
|
|
362
353
|
*
|
|
363
354
|
* indices data_type: any integer kind (zero-copy if already CA_SIZE).
|
|
364
355
|
* Negative indices: Python-style (-1 = last), normalized internally.
|
|
365
|
-
* OOB indices: raises
|
|
356
|
+
* OOB indices: raises IndexError. Default axis: 0; negative axis
|
|
366
357
|
* Python-style.
|
|
367
358
|
*
|
|
368
359
|
* Returns: CArray of CA_SIZE, same shape as indices.
|
|
369
360
|
*/
|
|
370
361
|
|
|
362
|
+
typedef struct {
|
|
363
|
+
CArray *idx_ca;
|
|
364
|
+
ca_size_t *out_ptr;
|
|
365
|
+
ca_size_t *strides;
|
|
366
|
+
int axis;
|
|
367
|
+
ca_size_t axis_size;
|
|
368
|
+
boolean8_t *mask; /* the indices' mask, or NULL */
|
|
369
|
+
} axis2addr_ctx_t;
|
|
370
|
+
|
|
371
|
+
/* Body of rb_ca_axis2addr_c: one flat address per index cell. */
|
|
372
|
+
static void
|
|
373
|
+
axis2addr_body (void *user_data, void *ptr, ca_size_t n)
|
|
374
|
+
{
|
|
375
|
+
axis2addr_ctx_t *c = (axis2addr_ctx_t *) user_data;
|
|
376
|
+
ca_size_t *idx_ptr = (ca_size_t *) ptr;
|
|
377
|
+
int ndim = c->idx_ca->ndim;
|
|
378
|
+
ca_size_t coord[CA_RANK_MAX];
|
|
379
|
+
|
|
380
|
+
for ( int8_t j = 0; j < ndim; j++ ) coord[j] = 0;
|
|
381
|
+
for ( ca_size_t k = 0; k < n; k++ ) {
|
|
382
|
+
/* A masked index has no address: the cell keeps the mask (copied from
|
|
383
|
+
the indices) and is skipped here, its stored value unread. */
|
|
384
|
+
if ( c->mask && c->mask[k] ) {
|
|
385
|
+
c->out_ptr[k] = 0;
|
|
386
|
+
goto advance;
|
|
387
|
+
}
|
|
388
|
+
ca_size_t norm = ca_index_in_range(idx_ptr[k], c->axis_size, "index");
|
|
389
|
+
/* Compute flat addr: sum c_j * stride_j (with c_axis = norm). */
|
|
390
|
+
ca_size_t addr = 0;
|
|
391
|
+
for ( int8_t j = 0; j < ndim; j++ ) {
|
|
392
|
+
if ( j == c->axis ) {
|
|
393
|
+
addr += norm * c->strides[j];
|
|
394
|
+
} else {
|
|
395
|
+
addr += coord[j] * c->strides[j];
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
c->out_ptr[k] = addr;
|
|
399
|
+
advance:
|
|
400
|
+
/* Advance coord row-major (last axis ticks fastest). */
|
|
401
|
+
for ( int8_t j = (int8_t)(ndim - 1); j >= 0; j-- ) {
|
|
402
|
+
if ( ++coord[j] < c->idx_ca->dim[j] ) break;
|
|
403
|
+
coord[j] = 0;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
371
408
|
/* C-callable entry: skip rb_scan_args (call-frame state dependency).
|
|
372
409
|
* vaxis = Qnil treated as axis 0; Integer is taken as-is (negative
|
|
373
410
|
* axis normalized internally).
|
|
@@ -384,38 +421,34 @@ rb_ca_axis2addr_c (VALUE self, VALUE vindices, VALUE vaxis)
|
|
|
384
421
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
385
422
|
TypedData_Get_Struct(vindices, CArray, &carray_data_type, idx_ca);
|
|
386
423
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
int axis = (
|
|
390
|
-
if ( axis < 0 || axis >= ca->ndim ) {
|
|
391
|
-
rb_raise(rb_eIndexError,
|
|
392
|
-
"axis2addr: axis %d out of range for ndim %d",
|
|
393
|
-
axis_raw, (int) ca->ndim);
|
|
394
|
-
}
|
|
424
|
+
long axis_l = ca_normalize_axis_arg(NIL_P(vaxis) ? INT2FIX(0) : vaxis,
|
|
425
|
+
(int) ca->ndim, NULL);
|
|
426
|
+
int axis = (int) axis_l;
|
|
395
427
|
|
|
396
428
|
/* Shape rule: indices.ndim == self.ndim, dims match except at axis. */
|
|
397
429
|
if ( idx_ca->ndim != ca->ndim ) {
|
|
398
430
|
rb_raise(rb_eArgError,
|
|
399
|
-
"
|
|
400
|
-
(int) idx_ca->ndim, (int) ca->ndim);
|
|
431
|
+
"%s: indices.ndim (%d) must equal self.ndim (%d)",
|
|
432
|
+
ca_calling_method_name(), (int) idx_ca->ndim, (int) ca->ndim);
|
|
401
433
|
}
|
|
402
434
|
for ( int8_t j = 0; j < ca->ndim; j++ ) {
|
|
403
435
|
if ( j == axis ) continue;
|
|
404
436
|
if ( idx_ca->dim[j] != ca->dim[j] ) {
|
|
405
437
|
rb_raise(rb_eArgError,
|
|
406
|
-
"
|
|
438
|
+
"%s: indices.dim[%d] (%lld) must equal "
|
|
407
439
|
"self.dim[%d] (%lld)",
|
|
408
|
-
(int) j, (long long) idx_ca->dim[j],
|
|
440
|
+
ca_calling_method_name(), (int) j, (long long) idx_ca->dim[j],
|
|
409
441
|
(int) j, (long long) ca->dim[j]);
|
|
410
442
|
}
|
|
411
443
|
}
|
|
412
444
|
|
|
413
445
|
/* indices data_type: integer kind accepted; cast to CA_SIZE if needed
|
|
414
446
|
(zero-copy when already CA_SIZE via to_type identity). */
|
|
447
|
+
ca_check_index_array(vindices);
|
|
415
448
|
if ( ! ca_is_integer_type(idx_ca) ) {
|
|
416
449
|
rb_raise(rb_eArgError,
|
|
417
|
-
"
|
|
418
|
-
(
|
|
450
|
+
"%s: indices data_type must be integer kind (got %s)",
|
|
451
|
+
ca_calling_method_name(), ca_type_name[idx_ca->data_type]);
|
|
419
452
|
}
|
|
420
453
|
volatile VALUE vidx_cast = vindices;
|
|
421
454
|
CArray *idx_cast = idx_ca;
|
|
@@ -439,59 +472,26 @@ rb_ca_axis2addr_c (VALUE self, VALUE vindices, VALUE vaxis)
|
|
|
439
472
|
rb_ca_template_with_type(vidx_cast, INT2NUM(CA_SIZE), INT2NUM(0));
|
|
440
473
|
TypedData_Get_Struct(vout, CArray, &carray_data_type, out_ca);
|
|
441
474
|
|
|
442
|
-
/* out_ca is a freshly allocated entity
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
ca_size_t n;
|
|
461
|
-
CA_WITH_BUFFER(idx_cast, ca_size_t, idx_ptr, n) {
|
|
462
|
-
for ( int8_t j = 0; j < ndim; j++ ) coord[j] = 0;
|
|
463
|
-
for ( ca_size_t k = 0; k < n; k++ ) {
|
|
464
|
-
/* Negative normalize + OOB check (raises on out-of-bounds). */
|
|
465
|
-
ca_size_t raw = idx_ptr[k];
|
|
466
|
-
ca_size_t norm = (raw < 0) ? (raw + axis_size) : raw;
|
|
467
|
-
if ( norm < 0 || norm >= axis_size ) {
|
|
468
|
-
bad_k = k; bad_raw = raw;
|
|
469
|
-
break;
|
|
470
|
-
}
|
|
471
|
-
/* Compute flat addr: sum c_j * stride_j (with c_axis = norm). */
|
|
472
|
-
ca_size_t addr = 0;
|
|
473
|
-
for ( int8_t j = 0; j < ndim; j++ ) {
|
|
474
|
-
if ( j == axis ) {
|
|
475
|
-
addr += norm * strides[j];
|
|
476
|
-
} else {
|
|
477
|
-
addr += coord[j] * strides[j];
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
out_ptr[k] = addr;
|
|
481
|
-
/* Advance coord row-major (last axis ticks fastest). */
|
|
482
|
-
for ( int8_t j = (int8_t)(ndim - 1); j >= 0; j-- ) {
|
|
483
|
-
if ( ++coord[j] < idx_cast->dim[j] ) break;
|
|
484
|
-
coord[j] = 0;
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
if ( bad_k >= 0 ) {
|
|
490
|
-
rb_raise(rb_eRangeError,
|
|
491
|
-
"axis2addr: indices[%lld] = %lld out of range [0, %lld) "
|
|
492
|
-
"(after negative normalize)",
|
|
493
|
-
(long long) bad_k, (long long) bad_raw, (long long) axis_size);
|
|
475
|
+
/* out_ca is a freshly allocated entity of the indices' shape and cell
|
|
476
|
+
width, so the indices are copied into it (a view is gathered without
|
|
477
|
+
being attached) and turned into addresses in place: cell k is read
|
|
478
|
+
before it is written. */
|
|
479
|
+
axis2addr_ctx_t ctx;
|
|
480
|
+
ctx.idx_ca = idx_cast;
|
|
481
|
+
ctx.out_ptr = (ca_size_t *) out_ca->ptr;
|
|
482
|
+
ctx.strides = strides;
|
|
483
|
+
ctx.axis = axis;
|
|
484
|
+
ctx.axis_size = axis_size;
|
|
485
|
+
ctx.mask = NULL;
|
|
486
|
+
|
|
487
|
+
ca_copy_data(idx_cast, out_ca->ptr);
|
|
488
|
+
/* A masked index gives a masked address: readers propagate it (UNDEF in
|
|
489
|
+
that cell), writers skip it. */
|
|
490
|
+
if ( ca_has_mask(idx_cast) ) {
|
|
491
|
+
ca_copy_mask_overlay(out_ca, out_ca->elements, 1, idx_cast);
|
|
492
|
+
ctx.mask = (boolean8_t *) out_ca->mask->ptr;
|
|
494
493
|
}
|
|
494
|
+
axis2addr_body(&ctx, out_ca->ptr, out_ca->elements);
|
|
495
495
|
|
|
496
496
|
return vout;
|
|
497
497
|
}
|
|
@@ -510,6 +510,31 @@ rb_ca_axis2addr (int argc, VALUE *argv, VALUE self)
|
|
|
510
510
|
}
|
|
511
511
|
|
|
512
512
|
|
|
513
|
+
/* The array the order of v is read from, for a method that orders v's
|
|
514
|
+
cells (a sort, a selection, a ranking, an extremum by key). A plain
|
|
515
|
+
array is its own key. An ORDERABLE Face orders by its storage, so the
|
|
516
|
+
key is the storage. A Face that is not ORDERABLE but defines its own
|
|
517
|
+
#order (CAConstString, whose cells are offsets; CARecord, whose bytes
|
|
518
|
+
are no order) is keyed by that order, as a dense rank, so ties stay ties
|
|
519
|
+
and a masked cell stays masked. A Face that has no order (a CARecord
|
|
520
|
+
without order_by:) raises in that order; any other Face raises here. */
|
|
521
|
+
VALUE
|
|
522
|
+
ca_order_key (VALUE v, const char *name)
|
|
523
|
+
{
|
|
524
|
+
CArray *ca;
|
|
525
|
+
TypedData_Get_Struct(v, CArray, &carray_data_type, ca);
|
|
526
|
+
if ( ! ca_is_face(ca) ) {
|
|
527
|
+
return v;
|
|
528
|
+
}
|
|
529
|
+
if ( ca_face_orders_by_itself(v) ) {
|
|
530
|
+
VALUE opts = rb_hash_new();
|
|
531
|
+
rb_hash_aset(opts, ID2SYM(rb_intern("method")), ID2SYM(rb_intern("dense")));
|
|
532
|
+
return rb_funcallv_kw(v, rb_intern("order"), 1, &opts, RB_PASS_KEYWORDS);
|
|
533
|
+
}
|
|
534
|
+
ca_face_require_orderable(v, name, "order");
|
|
535
|
+
return rb_ca_strip_face_value(v);
|
|
536
|
+
}
|
|
537
|
+
|
|
513
538
|
/* ===== sort / sort_copy (value & view surface, sibling of the
|
|
514
539
|
sort_addr / axis2addr block above). =============== */
|
|
515
540
|
|
|
@@ -548,50 +573,24 @@ rb_ca_axis2addr (int argc, VALUE *argv, VALUE self)
|
|
|
548
573
|
* numeric, both no-axis and axis: forms.
|
|
549
574
|
*/
|
|
550
575
|
static VALUE
|
|
551
|
-
|
|
576
|
+
rb_ca_sorted_view_kw (VALUE rkw, VALUE self)
|
|
552
577
|
{
|
|
553
|
-
VALUE rkw = Qnil;
|
|
554
578
|
VALUE vaxis = Qnil;
|
|
555
579
|
VALUE vkind = Qnil;
|
|
556
580
|
VALUE vmasked_position = Qnil;
|
|
557
581
|
|
|
558
|
-
/*
|
|
559
|
-
rb_scan_args(argc, argv, "0:", &rkw);
|
|
582
|
+
/* `sort` accepts `axis:`, `kind:`, `masked_position:`. */
|
|
560
583
|
rb_scan_options(rkw, "axis,kind,masked_position", &vaxis, &vkind, &vmasked_position);
|
|
561
584
|
|
|
562
585
|
/* Resolve kind: -> do_stable. :quick (default) = introsort; :stable
|
|
563
586
|
= bottom-up mergesort. Both share the same pair layout and produce
|
|
564
587
|
identical orderings; only the algorithm differs. */
|
|
565
|
-
int do_stable = 0
|
|
566
|
-
|
|
567
|
-
static ID sym_quick = 0, sym_stable = 0;
|
|
568
|
-
if ( !sym_quick ) sym_quick = rb_intern("quick");
|
|
569
|
-
if ( !sym_stable ) sym_stable = rb_intern("stable");
|
|
570
|
-
ID kind_id = SYM2ID(vkind);
|
|
571
|
-
if ( kind_id == sym_quick ) do_stable = 0;
|
|
572
|
-
else if ( kind_id == sym_stable ) do_stable = 1;
|
|
573
|
-
else {
|
|
574
|
-
rb_raise(rb_eArgError,
|
|
575
|
-
"sort: unknown kind %s (expected :quick or :stable)",
|
|
576
|
-
rb_id2name(kind_id));
|
|
577
|
-
}
|
|
578
|
-
}
|
|
588
|
+
int do_stable = NIL_P(vkind) ? 0
|
|
589
|
+
: ca_symbol_choice(vkind, "kind", "quick", "stable", NULL);
|
|
579
590
|
|
|
580
591
|
/* Resolve masked_position: -> masked_last. :last (default) or :first. */
|
|
581
|
-
int masked_last = 1
|
|
582
|
-
|
|
583
|
-
static ID sym_first = 0, sym_last = 0;
|
|
584
|
-
if ( !sym_first ) sym_first = rb_intern("first");
|
|
585
|
-
if ( !sym_last ) sym_last = rb_intern("last");
|
|
586
|
-
ID mp_id = SYM2ID(vmasked_position);
|
|
587
|
-
if ( mp_id == sym_last ) masked_last = 1;
|
|
588
|
-
else if ( mp_id == sym_first ) masked_last = 0;
|
|
589
|
-
else {
|
|
590
|
-
rb_raise(rb_eArgError,
|
|
591
|
-
"sort: unknown masked_position %s (expected :first or :last)",
|
|
592
|
-
rb_id2name(mp_id));
|
|
593
|
-
}
|
|
594
|
-
}
|
|
592
|
+
int masked_last = NIL_P(vmasked_position) ? 1
|
|
593
|
+
: ca_symbol_choice(vmasked_position, "masked_position", "first", "last", NULL);
|
|
595
594
|
|
|
596
595
|
CArray *ca;
|
|
597
596
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
@@ -600,7 +599,7 @@ rb_ca_sorted_view (int argc, VALUE *argv, VALUE self)
|
|
|
600
599
|
before mask handling: rb_ca_flatten re-propagates the mask field
|
|
601
600
|
from the parent, so any mask stripping must happen on the post-
|
|
602
601
|
flatten target. */
|
|
603
|
-
VALUE target;
|
|
602
|
+
volatile VALUE target; /* cat points into it; the walk can run a GC */
|
|
604
603
|
VALUE vaxis_use;
|
|
605
604
|
if ( NIL_P(vaxis) ) {
|
|
606
605
|
target = rb_ca_flatten(self);
|
|
@@ -628,6 +627,14 @@ rb_ca_sorted_view (int argc, VALUE *argv, VALUE self)
|
|
|
628
627
|
}
|
|
629
628
|
}
|
|
630
629
|
|
|
630
|
+
static VALUE
|
|
631
|
+
rb_ca_sorted_view (int argc, VALUE *argv, VALUE self)
|
|
632
|
+
{
|
|
633
|
+
VALUE rkw = Qnil;
|
|
634
|
+
rb_scan_args(argc, argv, "0:", &rkw);
|
|
635
|
+
return rb_ca_sorted_view_kw(rkw, self);
|
|
636
|
+
}
|
|
637
|
+
|
|
631
638
|
/* sort_copy(axis: nil, kind: :quick, masked_position: :last) — eager
|
|
632
639
|
* counterpart to {sort}. Returns a fresh entity CArray of the same
|
|
633
640
|
* shape and data_type as self, with elements sorted along the given
|
|
@@ -667,19 +674,12 @@ rb_ca_sort_copy (int argc, VALUE *argv, VALUE self)
|
|
|
667
674
|
|
|
668
675
|
/* Resolve kind:: :quick (default) = portable textbook quicksort,
|
|
669
676
|
:stable = portable textbook bottom-up mergesort. */
|
|
670
|
-
int do_stable = 0
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
if ( kind_id == sym_quick ) do_stable = 0;
|
|
677
|
-
else if ( kind_id == sym_stable ) do_stable = 1;
|
|
678
|
-
else {
|
|
679
|
-
rb_raise(rb_eArgError,
|
|
680
|
-
"sort_copy: unknown kind %s (expected :quick or :stable)",
|
|
681
|
-
rb_id2name(kind_id));
|
|
682
|
-
}
|
|
677
|
+
int do_stable = NIL_P(vkind) ? 0
|
|
678
|
+
: ca_symbol_choice(vkind, "kind", "quick", "stable", NULL);
|
|
679
|
+
/* The unmasked path below has no use for masked_position:, but a value
|
|
680
|
+
sort would refuse is refused here too. */
|
|
681
|
+
if ( ! NIL_P(vmasked_position) ) {
|
|
682
|
+
ca_symbol_choice(vmasked_position, "masked_position", "first", "last", NULL);
|
|
683
683
|
}
|
|
684
684
|
|
|
685
685
|
CArray *ca;
|
|
@@ -691,13 +691,11 @@ rb_ca_sort_copy (int argc, VALUE *argv, VALUE self)
|
|
|
691
691
|
same shape/class contract as the fast path. */
|
|
692
692
|
if ( ca->data_type < CA_INT8 || ca->data_type > CA_FLOAT64
|
|
693
693
|
|| ca_has_mask(ca) ) {
|
|
694
|
-
VALUE sv_kw = rb_hash_new();
|
|
694
|
+
volatile VALUE sv_kw = rb_hash_new();
|
|
695
695
|
if ( !NIL_P(vaxis) ) rb_hash_aset(sv_kw, ID2SYM(rb_intern("axis")), vaxis);
|
|
696
696
|
if ( !NIL_P(vkind) ) rb_hash_aset(sv_kw, ID2SYM(rb_intern("kind")), vkind);
|
|
697
697
|
if ( !NIL_P(vmasked_position) ) rb_hash_aset(sv_kw, ID2SYM(rb_intern("masked_position")), vmasked_position);
|
|
698
|
-
VALUE
|
|
699
|
-
int sv_argc = ( NIL_P(vaxis) && NIL_P(vkind) && NIL_P(vmasked_position) ) ? 0 : 1;
|
|
700
|
-
VALUE obj = rb_ca_copy(rb_ca_sorted_view(sv_argc, sv_argv, self));
|
|
698
|
+
VALUE obj = rb_ca_copy(rb_ca_sorted_view_kw(sv_kw, self));
|
|
701
699
|
CA_FACE_LIFT_IF_FACE(obj, self, ca);
|
|
702
700
|
return obj;
|
|
703
701
|
}
|
|
@@ -705,7 +703,7 @@ rb_ca_sort_copy (int argc, VALUE *argv, VALUE self)
|
|
|
705
703
|
/* Build target view (flatten for no-arg, identity for axis: kwarg).
|
|
706
704
|
Unmasked past this point (guarded above), so no mask handling is
|
|
707
705
|
needed here -- see the analogous block in rb_ca_sorted_view. */
|
|
708
|
-
VALUE target;
|
|
706
|
+
volatile VALUE target; /* cat points into it; the walk can run a GC */
|
|
709
707
|
VALUE vaxis_use;
|
|
710
708
|
if ( NIL_P(vaxis) ) {
|
|
711
709
|
target = rb_ca_flatten(self);
|
|
@@ -719,12 +717,7 @@ rb_ca_sort_copy (int argc, VALUE *argv, VALUE self)
|
|
|
719
717
|
TypedData_Get_Struct(target, CArray, &carray_data_type, cat);
|
|
720
718
|
|
|
721
719
|
/* Normalize axis (negative -> +ndim, range check). */
|
|
722
|
-
int axis =
|
|
723
|
-
if ( axis < 0 ) axis += cat->ndim;
|
|
724
|
-
if ( axis < 0 || axis >= cat->ndim ) {
|
|
725
|
-
rb_raise(rb_eArgError, "sort_copy: axis %d out of range for ndim %d",
|
|
726
|
-
NUM2INT(vaxis_use), cat->ndim);
|
|
727
|
-
}
|
|
720
|
+
int axis = ca_normalize_axis_arg(vaxis_use, cat->ndim, NULL);
|
|
728
721
|
|
|
729
722
|
/* Allocate output: same shape and data_type as target
|
|
730
723
|
(bytes=0 = preserve native bytes). */
|
|
@@ -749,8 +742,10 @@ rb_ca_sort_copy (int argc, VALUE *argv, VALUE self)
|
|
|
749
742
|
the fiber loop and reused across fibers (all fibers share the
|
|
750
743
|
same axis length and data_type). */
|
|
751
744
|
void *aux = NULL;
|
|
745
|
+
volatile VALUE aux_holder = 0; /* 0, not Qnil: ALLOCV_END reads a non-zero holder */
|
|
752
746
|
if ( do_stable ) {
|
|
753
|
-
aux =
|
|
747
|
+
aux = ALLOCV_N(char, aux_holder,
|
|
748
|
+
(size_t) cat->dim[axis] * (size_t) bytes);
|
|
754
749
|
}
|
|
755
750
|
CA_FOR_EACH_FIBER_INOUT(st_in, st_out, cat, cao, (int8_t) axis,
|
|
756
751
|
CA_KERNEL_NO_MASK, pi, po, n) {
|
|
@@ -806,8 +801,10 @@ rb_ca_sort_copy (int argc, VALUE *argv, VALUE self)
|
|
|
806
801
|
}
|
|
807
802
|
}
|
|
808
803
|
}
|
|
809
|
-
|
|
804
|
+
ALLOCV_END(aux_holder);
|
|
810
805
|
|
|
806
|
+
RB_GC_GUARD(target);
|
|
807
|
+
rb_ca_inherit_attr(vout, self);
|
|
811
808
|
return vout;
|
|
812
809
|
}
|
|
813
810
|
|