carray 3.0.3 → 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 +469 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_array_pool.c +25 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +14 -26
- data/ext/ca_axis_group.c +27 -27
- data/ext/ca_binop_dispatch.c +1 -29
- data/ext/ca_binop_dispatch.h +0 -1
- data/ext/ca_categorical_iterator.c +231 -153
- data/ext/ca_compare.c +9 -20
- data/ext/ca_composite_dispatch.c +9 -9
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1240 -2000
- data/ext/ca_kernel_iterator.h +502 -519
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +152 -45
- data/ext/ca_obj_bincmp.c +25 -21
- data/ext/ca_obj_binop.c +16 -26
- data/ext/ca_obj_bitarray.c +8 -3
- data/ext/ca_obj_bitfield.c +63 -49
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +7 -7
- data/ext/ca_obj_const_string.c +188 -22
- data/ext/ca_obj_face.c +280 -58
- data/ext/ca_obj_face.h +19 -0
- data/ext/ca_obj_fake.c +15 -29
- data/ext/ca_obj_farray.c +6 -3
- data/ext/ca_obj_field.c +30 -8
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +455 -134
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +113 -67
- data/ext/ca_obj_object.c +210 -52
- data/ext/ca_obj_record.c +15 -7
- data/ext/ca_obj_reduce.c +17 -8
- data/ext/ca_obj_refer.c +42 -35
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +31 -10
- data/ext/ca_obj_select.c +48 -14
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +41 -7
- data/ext/ca_obj_stack.c +180 -34
- data/ext/ca_obj_stride.c +190 -134
- data/ext/ca_obj_string.c +80 -4
- data/ext/ca_obj_tile.c +32 -11
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +13 -7
- data/ext/ca_obj_triop.c +26 -32
- data/ext/ca_obj_window.c +267 -74
- data/ext/ca_op_ipower.c +4 -4
- data/ext/ca_sort_kernels.h +6 -3
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +214 -75
- data/ext/carray_access.c +200 -99
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +113 -6
- data/ext/carray_bincount.c +10 -8
- data/ext/carray_broadcast.c +13 -8
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +108 -0
- data/ext/carray_cast.c +375 -96
- data/ext/carray_cast_func.rb +90 -20
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +18 -9
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +150 -55
- data/ext/carray_count.c +56 -20
- data/ext/carray_element.c +81 -33
- data/ext/carray_factorize.c +138 -84
- data/ext/carray_generate.c +199 -52
- data/ext/carray_histogram.c +63 -18
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +348 -29
- data/ext/carray_kernels_bincmp.c +4453 -0
- data/ext/carray_kernels_binop.c +11368 -0
- data/ext/carray_kernels_init.c +1734 -0
- data/ext/carray_kernels_moncmp.c +2104 -0
- data/ext/carray_kernels_monop.c +18369 -0
- data/ext/carray_kernels_reduce_aggregate.c +23818 -0
- data/ext/carray_kernels_reduce_boolean.c +406 -0
- data/ext/carray_kernels_reduce_cumulative.c +10086 -0
- data/ext/carray_kernels_reduce_extreme.c +17634 -0
- data/ext/carray_kernels_reduce_variance.c +3849 -0
- data/ext/carray_kernels_scan.c +4302 -0
- data/ext/carray_kernels_search.c +33829 -0
- data/ext/carray_kernels_sort.c +10897 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +220 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +337 -94
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +129 -52
- data/ext/carray_order.c +604 -77
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +85 -31
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +87 -45
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +123 -37
- data/ext/carray_sort.c +259 -51
- data/ext/carray_sort_kernel.c +5 -7
- data/ext/carray_struct.c +54 -61
- data/ext/carray_test.c +26 -5
- data/ext/carray_time_text.c +4 -2
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +309 -66
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +403 -350
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +139 -22
- data/lib/carray/autoload_carray.rb +8 -31
- data/lib/carray/autoload_method_extension.rb +14 -5
- data/lib/carray/axis_group.rb +255 -106
- data/lib/carray/basics.rb +105 -17
- data/lib/carray/bincount_nd.rb +12 -2
- data/lib/carray/block_iterator.rb +126 -23
- data/lib/carray/boolean_reduce.rb +17 -17
- data/lib/carray/categorical.rb +195 -59
- data/lib/carray/categorical_iterator.rb +132 -29
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +24 -5
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +9 -1
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +48 -3
- data/lib/carray/frame/column_verbs.rb +71 -0
- data/lib/carray/frame/concat.rb +17 -3
- data/lib/carray/frame/convert.rb +69 -0
- data/lib/carray/frame/csv_parser.rb +111 -17
- data/lib/carray/frame/describe.rb +3 -2
- data/lib/carray/frame/frame.rb +252 -28
- data/lib/carray/frame/group.rb +603 -101
- data/lib/carray/frame/io.rb +117 -28
- data/lib/carray/frame/join.rb +312 -51
- data/lib/carray/frame/records.rb +83 -7
- data/lib/carray/frame/reshape.rb +42 -35
- data/lib/carray/frame/sort.rb +7 -19
- data/lib/carray/frame/verbs.rb +188 -48
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +42 -6
- data/lib/carray/fusion.rb +40 -16
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +31 -8
- data/lib/carray/iterator.rb +85 -7
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +217 -183
- data/lib/carray/mask_gap_fill.rb +63 -57
- data/lib/carray/meld_reduce.rb +12 -14
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +16 -0
- data/lib/carray/methods/bit_string.rb +1 -1
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +3 -1
- data/lib/carray/methods/gather_nd.rb +14 -5
- data/lib/carray/methods/insert_block.rb +2 -2
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +61 -37
- data/lib/carray/methods/join.rb +1 -6
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +47 -51
- data/lib/carray/methods/mode.rb +1 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/resize.rb +3 -3
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +3 -3
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +53 -8
- data/lib/carray/segment_iterator.rb +323 -88
- data/lib/carray/serialize.rb +45 -14
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/stack.rb +15 -12
- data/lib/carray/string.rb +113 -5
- data/lib/carray/string_operation_extension.rb +21 -6
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +24 -11
- data/lib/carray/time.rb +819 -158
- data/lib/carray/window_iterator.rb +122 -16
- data/lib/carray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +4 -0
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +2 -1
- data/yard-stubs/ca_obj_roll.rb +2 -2
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_transpose.rb +5 -4
- data/yard-stubs/ca_obj_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +3 -6
- data/yard-stubs/carray_cast.rb +12 -0
- data/yard-stubs/carray_conversion.rb +7 -2
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +17 -10
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +32 -3
- data/yard-stubs/carray_math.rb +41 -5
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +129 -22
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +17 -10
- data/yard-stubs/carray_slab.rb +9 -2
- data/yard-stubs/carray_sort.rb +6 -5
- data/yard-stubs/carray_test.rb +5 -3
- metadata +25 -3
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/ext/carray_utils.c
CHANGED
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
|
|
18
18
|
#include "ruby/st.h"
|
|
19
19
|
#include "ruby/thread_native.h"
|
|
20
|
+
#include "ruby/ractor.h"
|
|
21
|
+
#include "ruby/debug.h" /* rb_profile_frames: the method the user called */
|
|
20
22
|
|
|
21
23
|
static ID id_begin, id_end, id_excl_end;
|
|
22
24
|
#define RANGE_BEG(r) (rb_funcall(r, id_begin, 0))
|
|
@@ -56,7 +58,8 @@ ca_set_iterator (int n, ...)
|
|
|
56
58
|
max = ca->elements;
|
|
57
59
|
}
|
|
58
60
|
else if ( max != ca->elements ) {
|
|
59
|
-
rb_raise(rb_eArgError, "data size mismatch in operation"
|
|
61
|
+
rb_raise(rb_eArgError, "%s: data size mismatch in operation",
|
|
62
|
+
ca_calling_method_name());
|
|
60
63
|
}
|
|
61
64
|
}
|
|
62
65
|
}
|
|
@@ -158,7 +161,7 @@ ca_parse_range (VALUE arg, ca_size_t size,
|
|
|
158
161
|
}
|
|
159
162
|
*poffset = start;
|
|
160
163
|
*pcount = llabs(last - start) + 1;
|
|
161
|
-
*pstep = 1;
|
|
164
|
+
*pstep = ( last >= start ) ? 1 : -1;
|
|
162
165
|
}
|
|
163
166
|
#ifdef HAVE_RB_ARITHMETIC_SEQUENCE_EXTRACT
|
|
164
167
|
else if ( rb_obj_is_kind_of(arg, rb_cArithSeq) ) { /* ca[--,ArithSeq,--]*/
|
|
@@ -172,6 +175,7 @@ ca_parse_range (VALUE arg, ca_size_t size,
|
|
|
172
175
|
if ( step == 0 ) {
|
|
173
176
|
rb_raise(rb_eArgError, "step should not be 0");
|
|
174
177
|
}
|
|
178
|
+
CA_CHECK_INDEX(start, size);
|
|
175
179
|
if ( last < 0 ) {
|
|
176
180
|
last += size;
|
|
177
181
|
}
|
|
@@ -181,7 +185,6 @@ ca_parse_range (VALUE arg, ca_size_t size,
|
|
|
181
185
|
if ( last < 0 || last >= size ) {
|
|
182
186
|
ca_index_out_of_range(last, size, "index");
|
|
183
187
|
}
|
|
184
|
-
CA_CHECK_INDEX(start, size);
|
|
185
188
|
if ( (last - start) * step < 0 ) {
|
|
186
189
|
count = 1;
|
|
187
190
|
}
|
|
@@ -189,7 +192,9 @@ ca_parse_range (VALUE arg, ca_size_t size,
|
|
|
189
192
|
count = llabs(last - start)/llabs(step) + 1;
|
|
190
193
|
}
|
|
191
194
|
bound = start + (count - 1)*step;
|
|
192
|
-
|
|
195
|
+
if ( count > 0 && ( bound < 0 || bound >= size ) ) {
|
|
196
|
+
ca_index_out_of_range(bound, size, "index");
|
|
197
|
+
}
|
|
193
198
|
*poffset = start;
|
|
194
199
|
*pcount = count;
|
|
195
200
|
*pstep = step;
|
|
@@ -211,8 +216,9 @@ ca_parse_range (VALUE arg, ca_size_t size,
|
|
|
211
216
|
start = 0;
|
|
212
217
|
count = (size-1)/llabs(step) + 1;
|
|
213
218
|
bound = start + (count - 1)*step;
|
|
214
|
-
|
|
215
|
-
|
|
219
|
+
if ( count > 0 && ( bound < 0 || bound >= size ) ) {
|
|
220
|
+
ca_index_out_of_range(bound, size, "index");
|
|
221
|
+
}
|
|
216
222
|
*poffset = start;
|
|
217
223
|
*pcount = count;
|
|
218
224
|
*pstep = step;
|
|
@@ -225,6 +231,7 @@ ca_parse_range (VALUE arg, ca_size_t size,
|
|
|
225
231
|
if ( step == 0 ) {
|
|
226
232
|
rb_raise(rb_eArgError, "step should not be 0");
|
|
227
233
|
}
|
|
234
|
+
CA_CHECK_INDEX(start, size);
|
|
228
235
|
if ( last < 0 ) {
|
|
229
236
|
last += size;
|
|
230
237
|
}
|
|
@@ -234,7 +241,6 @@ ca_parse_range (VALUE arg, ca_size_t size,
|
|
|
234
241
|
if ( last < 0 || last >= size ) {
|
|
235
242
|
ca_index_out_of_range(last, size, "index");
|
|
236
243
|
}
|
|
237
|
-
CA_CHECK_INDEX(start, size);
|
|
238
244
|
if ( (last - start) * step < 0 ) {
|
|
239
245
|
count = 1;
|
|
240
246
|
}
|
|
@@ -242,7 +248,9 @@ ca_parse_range (VALUE arg, ca_size_t size,
|
|
|
242
248
|
count = llabs(last - start)/llabs(step) + 1;
|
|
243
249
|
}
|
|
244
250
|
bound = start + (count - 1)*step;
|
|
245
|
-
|
|
251
|
+
if ( count > 0 && ( bound < 0 || bound >= size ) ) {
|
|
252
|
+
ca_index_out_of_range(bound, size, "index");
|
|
253
|
+
}
|
|
246
254
|
*poffset = start;
|
|
247
255
|
*pcount = count;
|
|
248
256
|
*pstep = step;
|
|
@@ -259,6 +267,7 @@ ca_parse_range (VALUE arg, ca_size_t size,
|
|
|
259
267
|
if ( step == 0 ) {
|
|
260
268
|
rb_raise(rb_eArgError, "step should not be 0");
|
|
261
269
|
}
|
|
270
|
+
CA_CHECK_INDEX(start, size);
|
|
262
271
|
if ( last < 0 ) {
|
|
263
272
|
last += size;
|
|
264
273
|
}
|
|
@@ -268,7 +277,6 @@ ca_parse_range (VALUE arg, ca_size_t size,
|
|
|
268
277
|
if ( last < 0 || last >= size ) {
|
|
269
278
|
ca_index_out_of_range(last, size, "index");
|
|
270
279
|
}
|
|
271
|
-
CA_CHECK_INDEX(start, size);
|
|
272
280
|
if ( (last - start) * step < 0 ) {
|
|
273
281
|
count = 1;
|
|
274
282
|
}
|
|
@@ -276,7 +284,9 @@ ca_parse_range (VALUE arg, ca_size_t size,
|
|
|
276
284
|
count = llabs(last - start)/llabs(step) + 1;
|
|
277
285
|
}
|
|
278
286
|
bound = start + (count - 1)*step;
|
|
279
|
-
|
|
287
|
+
if ( count > 0 && ( bound < 0 || bound >= size ) ) {
|
|
288
|
+
ca_index_out_of_range(bound, size, "index");
|
|
289
|
+
}
|
|
280
290
|
*poffset = start;
|
|
281
291
|
*pcount = count;
|
|
282
292
|
*pstep = step;
|
|
@@ -285,9 +295,11 @@ ca_parse_range (VALUE arg, ca_size_t size,
|
|
|
285
295
|
else { /* [i,n] */
|
|
286
296
|
start = NUM2SIZE(arg0);
|
|
287
297
|
count = NUM2SIZE(arg1);
|
|
288
|
-
bound = start + (count - 1);
|
|
289
298
|
CA_CHECK_INDEX(start, size);
|
|
290
|
-
|
|
299
|
+
bound = start + (count - 1);
|
|
300
|
+
if ( count > 0 && ( bound < 0 || bound >= size ) ) {
|
|
301
|
+
ca_index_out_of_range(bound, size, "index");
|
|
302
|
+
}
|
|
291
303
|
*poffset = start;
|
|
292
304
|
*pcount = count;
|
|
293
305
|
*pstep = 1;
|
|
@@ -300,9 +312,11 @@ ca_parse_range (VALUE arg, ca_size_t size,
|
|
|
300
312
|
if ( step == 0 ) {
|
|
301
313
|
rb_raise(rb_eArgError, "step should not be 0");
|
|
302
314
|
}
|
|
303
|
-
bound = start + (count - 1)*step;
|
|
304
315
|
CA_CHECK_INDEX(start, size);
|
|
305
|
-
|
|
316
|
+
bound = start + (count - 1)*step;
|
|
317
|
+
if ( count > 0 && ( bound < 0 || bound >= size ) ) {
|
|
318
|
+
ca_index_out_of_range(bound, size, "index");
|
|
319
|
+
}
|
|
306
320
|
*poffset = start;
|
|
307
321
|
*pcount = count;
|
|
308
322
|
*pstep = step;
|
|
@@ -357,6 +371,10 @@ ca_parse_range_without_check (VALUE arg, ca_size_t size,
|
|
|
357
371
|
last = NUM2SIZE(x.end);
|
|
358
372
|
excl = RTEST(x.exclude_end);
|
|
359
373
|
step = NUM2SIZE(x.step);
|
|
374
|
+
if ( step == 0 ) {
|
|
375
|
+
rb_raise(rb_eArgError, "%s: step should not be 0",
|
|
376
|
+
ca_calling_method_name());
|
|
377
|
+
}
|
|
360
378
|
if ( excl ) {
|
|
361
379
|
last += ( (last>=start) ? -1 : 1 );
|
|
362
380
|
}
|
|
@@ -377,6 +395,10 @@ ca_parse_range_without_check (VALUE arg, ca_size_t size,
|
|
|
377
395
|
if ( NIL_P(arg0) ) { /* [nil,k] */
|
|
378
396
|
start = 0;
|
|
379
397
|
step = NUM2SIZE(arg1);
|
|
398
|
+
if ( step == 0 ) {
|
|
399
|
+
rb_raise(rb_eArgError, "%s: step should not be 0",
|
|
400
|
+
ca_calling_method_name());
|
|
401
|
+
}
|
|
380
402
|
count = (size-1)/llabs(step) + 1;
|
|
381
403
|
*poffset = start;
|
|
382
404
|
*pcount = count;
|
|
@@ -387,6 +409,10 @@ ca_parse_range_without_check (VALUE arg, ca_size_t size,
|
|
|
387
409
|
last = NUM2SIZE(RANGE_END(arg0));
|
|
388
410
|
excl = RTEST(RANGE_EXCL(arg0));
|
|
389
411
|
step = NUM2SIZE(arg1);
|
|
412
|
+
if ( step == 0 ) {
|
|
413
|
+
rb_raise(rb_eArgError, "%s: step should not be 0",
|
|
414
|
+
ca_calling_method_name());
|
|
415
|
+
}
|
|
390
416
|
if ( excl ) {
|
|
391
417
|
last += ( (last>=start) ? -1 : 1 );
|
|
392
418
|
}
|
|
@@ -404,6 +430,10 @@ ca_parse_range_without_check (VALUE arg, ca_size_t size,
|
|
|
404
430
|
last = NUM2SIZE(x.end);
|
|
405
431
|
excl = RTEST(x.exclude_end);
|
|
406
432
|
step = NUM2SIZE(x.step);
|
|
433
|
+
if ( step == 0 ) {
|
|
434
|
+
rb_raise(rb_eArgError, "%s: step should not be 0",
|
|
435
|
+
ca_calling_method_name());
|
|
436
|
+
}
|
|
407
437
|
if ( excl ) {
|
|
408
438
|
last += ( (last>=start) ? -1 : 1 );
|
|
409
439
|
}
|
|
@@ -535,27 +565,44 @@ ca_stable_id_name (ID id)
|
|
|
535
565
|
/* The method a delegating method answers for. A method that does its work
|
|
536
566
|
by calling others (median calls partition_index, mode calls sort) runs
|
|
537
567
|
them under ca_answer_as_caller, so an error they raise names the method
|
|
538
|
-
the user called. The outermost one wins.
|
|
539
|
-
|
|
568
|
+
the user called. The outermost one wins. The name is kept with the
|
|
569
|
+
Ruby thread (Thread#[], so per fiber): Ractors share native threads under
|
|
570
|
+
the M:N scheduler, and a native-thread-local variable leaks one Ractor's
|
|
571
|
+
name into another's message. */
|
|
572
|
+
static ID id_answering;
|
|
573
|
+
|
|
574
|
+
static const char *
|
|
575
|
+
ca_answering_name (void)
|
|
576
|
+
{
|
|
577
|
+
VALUE name = rb_thread_local_aref(rb_thread_current(), id_answering);
|
|
578
|
+
return NIL_P(name) ? NULL : ca_stable_id_name(SYM2ID(name));
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
static void
|
|
582
|
+
ca_set_answering_name (const char *name)
|
|
583
|
+
{
|
|
584
|
+
rb_thread_local_aset(rb_thread_current(), id_answering,
|
|
585
|
+
name ? ID2SYM(rb_intern(name)) : Qnil);
|
|
586
|
+
}
|
|
540
587
|
|
|
541
588
|
static VALUE
|
|
542
589
|
ca_answer_restore (VALUE unused)
|
|
543
590
|
{
|
|
544
|
-
|
|
591
|
+
ca_set_answering_name(NULL);
|
|
545
592
|
return Qnil;
|
|
546
593
|
}
|
|
547
594
|
|
|
595
|
+
/* A C method that does its work by calling others runs them through here.
|
|
596
|
+
It used to fix the name at entry; the name is now found from the frames
|
|
597
|
+
when an error is raised (ca_user_called_method_id), which also reaches
|
|
598
|
+
the outer method, so nothing is fixed and nothing is paid on the way in. */
|
|
548
599
|
VALUE
|
|
549
600
|
ca_answer_as_caller (VALUE (*body)(VALUE), VALUE arg)
|
|
550
601
|
{
|
|
551
|
-
|
|
552
|
-
return body(arg);
|
|
553
|
-
}
|
|
554
|
-
ca_answering_name = ca_calling_method_name();
|
|
555
|
-
return rb_ensure(body, arg, ca_answer_restore, Qnil);
|
|
602
|
+
return body(arg);
|
|
556
603
|
}
|
|
557
604
|
|
|
558
|
-
/* CArray.
|
|
605
|
+
/* CArray.__name_errors_after_method__(name) { ... }: the same for a method written in Ruby. */
|
|
559
606
|
static VALUE
|
|
560
607
|
rb_ca_s_answer_as_body (VALUE unused)
|
|
561
608
|
{
|
|
@@ -565,23 +612,137 @@ rb_ca_s_answer_as_body (VALUE unused)
|
|
|
565
612
|
static VALUE
|
|
566
613
|
rb_ca_s_answer_as (VALUE klass, VALUE name)
|
|
567
614
|
{
|
|
568
|
-
if ( ca_answering_name ) {
|
|
615
|
+
if ( ca_answering_name() ) {
|
|
569
616
|
return rb_yield(Qnil);
|
|
570
617
|
}
|
|
571
|
-
|
|
618
|
+
ca_set_answering_name(ca_stable_id_name(rb_to_id(name)));
|
|
572
619
|
return rb_ensure(rb_ca_s_answer_as_body, Qnil, ca_answer_restore, Qnil);
|
|
573
620
|
}
|
|
574
621
|
|
|
622
|
+
/* The directory the library's Ruby files are loaded from (lib/), set once
|
|
623
|
+
by lib/carray.rb as it loads, read only afterwards. */
|
|
624
|
+
static char *ca_library_root = NULL;
|
|
625
|
+
static long ca_library_root_len = 0;
|
|
626
|
+
|
|
627
|
+
/* CArray.library_root = dir (private): where the frames of the library's
|
|
628
|
+
own Ruby methods are. The first call wins. */
|
|
629
|
+
static VALUE
|
|
630
|
+
rb_ca_s_set_library_root (VALUE klass, VALUE dir)
|
|
631
|
+
{
|
|
632
|
+
if ( ca_library_root == NULL ) {
|
|
633
|
+
long len = RSTRING_LEN(StringValue(dir));
|
|
634
|
+
char *copy = ALLOC_N(char, len + 1);
|
|
635
|
+
memcpy(copy, RSTRING_PTR(dir), len);
|
|
636
|
+
copy[len] = '\0';
|
|
637
|
+
ca_library_root_len = len;
|
|
638
|
+
ca_library_root = copy;
|
|
639
|
+
}
|
|
640
|
+
return Qnil;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/* Whether a frame without a source file -- a C method -- is one of the
|
|
644
|
+
library's: a method of a CA* or CScalar class, or a CA_* conversion
|
|
645
|
+
function. A method of a core class (Array#map, Integer#times) is not. */
|
|
646
|
+
static int
|
|
647
|
+
ca_frame_is_library_cfunc (VALUE frame, VALUE name)
|
|
648
|
+
{
|
|
649
|
+
VALUE path = rb_profile_frame_classpath(frame);
|
|
650
|
+
if ( ! NIL_P(path) ) {
|
|
651
|
+
const char *p = RSTRING_PTR(path);
|
|
652
|
+
long n = RSTRING_LEN(path);
|
|
653
|
+
if ( ( n >= 2 && strncmp(p, "CA", 2) == 0 )
|
|
654
|
+
|| ( n >= 7 && strncmp(p, "CScalar", 7) == 0 ) ) {
|
|
655
|
+
return 1;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
return RSTRING_LEN(name) > 3 && strncmp(RSTRING_PTR(name), "CA_", 3) == 0;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
/* The method the user called: going out from the innermost frame, the last
|
|
662
|
+
frame of the library -- a Ruby method under ca_library_root, or one of
|
|
663
|
+
its C methods -- before the user's own code (a block included) is
|
|
664
|
+
reached. A core C method the library calls on the way (Array#map) is
|
|
665
|
+
passed through. 0 when no frame of the library is found. */
|
|
666
|
+
#define CA_NAMING_FRAMES 64
|
|
667
|
+
|
|
668
|
+
static ID
|
|
669
|
+
ca_user_called_method_id (void)
|
|
670
|
+
{
|
|
671
|
+
ID id_initialize = rb_intern("initialize");
|
|
672
|
+
ID id_new = rb_intern("new");
|
|
673
|
+
VALUE frames[CA_NAMING_FRAMES];
|
|
674
|
+
int lines[CA_NAMING_FRAMES];
|
|
675
|
+
int n, i;
|
|
676
|
+
ID found = 0;
|
|
677
|
+
if ( ca_library_root == NULL ) {
|
|
678
|
+
return 0;
|
|
679
|
+
}
|
|
680
|
+
n = rb_profile_frames(0, CA_NAMING_FRAMES, frames, lines);
|
|
681
|
+
for (i = 0; i < n; i++) {
|
|
682
|
+
VALUE file = rb_profile_frame_absolute_path(frames[i]);
|
|
683
|
+
VALUE name, label;
|
|
684
|
+
if ( NIL_P(file) ) {
|
|
685
|
+
/* code evaluated with a file name (class_eval in the library) and the
|
|
686
|
+
core written in Ruby ("<internal:numeric>") have a path but no
|
|
687
|
+
absolute path; -e has a path outside the library */
|
|
688
|
+
file = rb_profile_frame_path(frames[i]);
|
|
689
|
+
}
|
|
690
|
+
if ( ! NIL_P(file) && strcmp(StringValueCStr(file), "<cfunc>") == 0 ) {
|
|
691
|
+
name = rb_profile_frame_method_name(frames[i]);
|
|
692
|
+
if ( NIL_P(name) ) {
|
|
693
|
+
continue;
|
|
694
|
+
}
|
|
695
|
+
if ( ca_frame_is_library_cfunc(frames[i], name) ) {
|
|
696
|
+
found = rb_to_id(name);
|
|
697
|
+
}
|
|
698
|
+
else if ( found == id_initialize && rb_to_id(name) == id_new ) {
|
|
699
|
+
found = id_new; /* Class#new around our initialize */
|
|
700
|
+
}
|
|
701
|
+
continue; /* a core C method passes */
|
|
702
|
+
}
|
|
703
|
+
if ( ! NIL_P(file) && strncmp(StringValueCStr(file), "<internal:", 10) == 0 ) {
|
|
704
|
+
continue; /* core written in Ruby (Integer#times) */
|
|
705
|
+
}
|
|
706
|
+
if ( NIL_P(file) /* eval without a file: the user's */
|
|
707
|
+
|| RSTRING_LEN(file) <= ca_library_root_len
|
|
708
|
+
|| strncmp(RSTRING_PTR(file), ca_library_root, ca_library_root_len) != 0
|
|
709
|
+
|| RSTRING_PTR(file)[ca_library_root_len] != '/' ) {
|
|
710
|
+
break;
|
|
711
|
+
}
|
|
712
|
+
/* A block of the library (an each inside a method, the autoload stub)
|
|
713
|
+
names nothing: the method around it is further out. A block whose
|
|
714
|
+
method is a class body is a method made by define_method, and its
|
|
715
|
+
frame does not carry the method's name, so the walk gives up and the
|
|
716
|
+
innermost C method is named, as before the walk. */
|
|
717
|
+
label = rb_profile_frame_label(frames[i]);
|
|
718
|
+
if ( ! NIL_P(label) && strncmp(StringValueCStr(label), "block ", 6) == 0 ) {
|
|
719
|
+
VALUE base = rb_profile_frame_base_label(frames[i]);
|
|
720
|
+
if ( ! NIL_P(base) && RSTRING_LEN(base) > 0 && RSTRING_PTR(base)[0] == '<' ) {
|
|
721
|
+
return 0;
|
|
722
|
+
}
|
|
723
|
+
continue;
|
|
724
|
+
}
|
|
725
|
+
name = rb_profile_frame_method_name(frames[i]);
|
|
726
|
+
if ( ! NIL_P(name) ) {
|
|
727
|
+
found = rb_to_id(name);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
return found;
|
|
731
|
+
}
|
|
732
|
+
|
|
575
733
|
const char *
|
|
576
734
|
ca_calling_method_name (void)
|
|
577
735
|
{
|
|
578
736
|
ID id;
|
|
579
737
|
const char *s;
|
|
580
738
|
size_t n;
|
|
581
|
-
if ( ca_answering_name ) {
|
|
582
|
-
return
|
|
739
|
+
if ( (s = ca_answering_name()) ) {
|
|
740
|
+
return s;
|
|
741
|
+
}
|
|
742
|
+
id = ca_user_called_method_id();
|
|
743
|
+
if ( ! id ) {
|
|
744
|
+
id = rb_frame_this_func();
|
|
583
745
|
}
|
|
584
|
-
id = rb_frame_this_func();
|
|
585
746
|
if ( ! id ) {
|
|
586
747
|
return "axis";
|
|
587
748
|
}
|
|
@@ -624,15 +785,22 @@ ca_shape_elements (int8_t ndim, const ca_size_t *dim, ca_size_t bytes)
|
|
|
624
785
|
return elements;
|
|
625
786
|
}
|
|
626
787
|
|
|
627
|
-
/* An index array is read as ca_size_t. A
|
|
628
|
-
|
|
629
|
-
|
|
788
|
+
/* An index array is read as ca_size_t. A float or complex one would be
|
|
789
|
+
cut to an integer on the way, so it is refused, as the indexer refuses
|
|
790
|
+
it. A uint64 one holding 2**63 or more would turn negative and count
|
|
791
|
+
from the end of the axis, so it is refused as the out-of-range index it
|
|
792
|
+
is. */
|
|
630
793
|
void
|
|
631
794
|
ca_check_index_array (VALUE v)
|
|
632
795
|
{
|
|
633
796
|
CArray *ca;
|
|
634
797
|
if ( ! rb_obj_is_carray(v) ) return;
|
|
635
798
|
GetCArray(v, ca);
|
|
799
|
+
if ( ca_is_float_type(ca) || ca_is_complex_type(ca) ) {
|
|
800
|
+
rb_raise(rb_eIndexError,
|
|
801
|
+
"data_type %s is invalid for an index (should be integer)",
|
|
802
|
+
ca_type_name[ca->data_type]);
|
|
803
|
+
}
|
|
636
804
|
if ( ca->data_type != CA_UINT64 || ca->elements == 0 ) return;
|
|
637
805
|
{
|
|
638
806
|
VALUE max = rb_funcall(v, rb_intern("max"), 0);
|
|
@@ -698,7 +866,7 @@ ca_min_count_arg (VALUE v, const char *name)
|
|
|
698
866
|
return n;
|
|
699
867
|
}
|
|
700
868
|
|
|
701
|
-
/* CArray.
|
|
869
|
+
/* CArray.__present_cells_needed_per_result_cell__(op, min_count, least): how many present cells a
|
|
702
870
|
result cell of `op` needs (ca_too_few_present), for a reduction written
|
|
703
871
|
in Ruby; it masks the cells whose count is below it. */
|
|
704
872
|
static VALUE
|
|
@@ -719,11 +887,10 @@ int
|
|
|
719
887
|
ca_symbol_choice (VALUE v, const char *arg, const char *c0, const char *c1,
|
|
720
888
|
const char *name)
|
|
721
889
|
{
|
|
722
|
-
const char *nm = name ? name : ca_calling_method_name();
|
|
723
890
|
ID id;
|
|
724
891
|
if ( ! SYMBOL_P(v) ) {
|
|
725
892
|
rb_raise(rb_eTypeError, "%s: %s must be a Symbol (got %"PRIsVALUE")",
|
|
726
|
-
|
|
893
|
+
name ? name : ca_calling_method_name(), arg, rb_obj_class(v));
|
|
727
894
|
}
|
|
728
895
|
id = SYM2ID(v);
|
|
729
896
|
if ( id == rb_intern(c0) ) {
|
|
@@ -733,7 +900,7 @@ ca_symbol_choice (VALUE v, const char *arg, const char *c0, const char *c1,
|
|
|
733
900
|
return 1;
|
|
734
901
|
}
|
|
735
902
|
rb_raise(rb_eArgError, "%s: unknown %s :%"PRIsVALUE" (expected :%s or :%s)",
|
|
736
|
-
|
|
903
|
+
name ? name : ca_calling_method_name(), arg, rb_id2str(id), c0, c1);
|
|
737
904
|
return 0;
|
|
738
905
|
}
|
|
739
906
|
|
|
@@ -771,12 +938,21 @@ ca_reduce_fill (VALUE result, VALUE fill, int whole)
|
|
|
771
938
|
if ( ca_has_mask(cr) ) {
|
|
772
939
|
result = rb_ca_mask_fill_copy(result, fill);
|
|
773
940
|
}
|
|
941
|
+
else if ( cr->elements > 0 ) {
|
|
942
|
+
/* No cell needed the fill, but a fill the result cannot hold is
|
|
943
|
+
refused all the same, not only when some cell happens to be
|
|
944
|
+
undefined: it goes into a one-cell array of the result's kind. */
|
|
945
|
+
volatile VALUE one = rb_funcall(rb_funcall(result, rb_intern("flatten"), 0),
|
|
946
|
+
rb_intern("[]"), 1,
|
|
947
|
+
rb_range_new(INT2FIX(0), INT2FIX(0), 0));
|
|
948
|
+
rb_ca_store_addr(rb_ca_template(one), 0, fill);
|
|
949
|
+
}
|
|
774
950
|
return whole ? rb_ca_fetch_addr(result, 0) : result;
|
|
775
951
|
}
|
|
776
952
|
return ( result == CA_UNDEF ) ? fill : result;
|
|
777
953
|
}
|
|
778
954
|
|
|
779
|
-
/* CArray.
|
|
955
|
+
/* CArray.__fill_undefined_result_cells__(result, fill_value): ca_reduce_fill for a
|
|
780
956
|
reduction written in Ruby. A fill_value of nil or UNDEF leaves the
|
|
781
957
|
undefined cells as they are. */
|
|
782
958
|
static VALUE
|
|
@@ -817,6 +993,38 @@ rb_ca_normalize_axis_for_ndim (long raw, int ndim, const char *name)
|
|
|
817
993
|
return (int) axis;
|
|
818
994
|
}
|
|
819
995
|
|
|
996
|
+
/* An array has at most CA_RANK_MAX axes, and every dim[] and strides[]
|
|
997
|
+
array in the library is that long. A constructor or view whose result
|
|
998
|
+
would have more -- a shape given, a rank computed -- calls this before it
|
|
999
|
+
writes a single dim, and is refused with ArgumentError naming the method,
|
|
1000
|
+
the rank and the limit. `name` NULL names the method the user called. */
|
|
1001
|
+
void
|
|
1002
|
+
ca_check_rank_fits (long ndim, const char *name)
|
|
1003
|
+
{
|
|
1004
|
+
if ( ndim > CA_RANK_MAX ) {
|
|
1005
|
+
rb_raise(rb_eArgError, "%s: ndim %ld exceeds CA_RANK_MAX %d",
|
|
1006
|
+
name ? name : ca_calling_method_name(), ndim, CA_RANK_MAX);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
/* The axis an `axis` argument names among `ndim` axes: the one rule every
|
|
1011
|
+
entry that takes an axis from Ruby keeps. An Integer, negative counting
|
|
1012
|
+
from the end; anything else raises TypeError, and an Integer outside
|
|
1013
|
+
[-ndim, ndim) raises ArgumentError naming the value given -- a Bignum
|
|
1014
|
+
too, since no ndim reaches it. `name` and the insertion-position use of
|
|
1015
|
+
`ndim` are as for rb_ca_normalize_axis_for_ndim. */
|
|
1016
|
+
int
|
|
1017
|
+
ca_normalize_axis_arg (VALUE raxis, int ndim, const char *name)
|
|
1018
|
+
{
|
|
1019
|
+
ca_check_rank_fits(ndim, name); /* no array has the axes to name */
|
|
1020
|
+
if ( RB_INTEGER_TYPE_P(raxis) && ! RB_FIXNUM_P(raxis) ) {
|
|
1021
|
+
rb_raise(rb_eArgError,
|
|
1022
|
+
"%s: axis %"PRIsVALUE" out of range for ndim %d",
|
|
1023
|
+
name ? name : ca_calling_method_name(), raxis, ndim);
|
|
1024
|
+
}
|
|
1025
|
+
return rb_ca_normalize_axis_for_ndim(ca_axis_integer(raxis, name), ndim, name);
|
|
1026
|
+
}
|
|
1027
|
+
|
|
820
1028
|
/* Self-bound wrapper: delegate to the kernel using self.ndim. Kept
|
|
821
1029
|
for backward compatibility with the existing instance method
|
|
822
1030
|
`CArray#normalize_axis`. */
|
|
@@ -825,7 +1033,7 @@ rb_ca_normalize_axis_value (VALUE self, VALUE raxis, const char *name)
|
|
|
825
1033
|
{
|
|
826
1034
|
CArray *ca;
|
|
827
1035
|
GetCArray(self, ca);
|
|
828
|
-
return
|
|
1036
|
+
return ca_normalize_axis_arg(raxis, (int) ca->ndim, name);
|
|
829
1037
|
}
|
|
830
1038
|
|
|
831
1039
|
/* Ruby-facing `CArray#normalize_axis(axis, name=nil)` — returns the
|
|
@@ -860,7 +1068,7 @@ rb_ca_s_normalize_axis (int argc, VALUE *argv, VALUE klass)
|
|
|
860
1068
|
int k;
|
|
861
1069
|
rb_scan_args(argc, argv, "21", &raxis, &rndim, &rname);
|
|
862
1070
|
name = NIL_P(rname) ? NULL : StringValueCStr(rname);
|
|
863
|
-
k =
|
|
1071
|
+
k = ca_normalize_axis_arg(raxis, NUM2INT(rndim), name);
|
|
864
1072
|
return INT2NUM(k);
|
|
865
1073
|
}
|
|
866
1074
|
|
|
@@ -880,7 +1088,7 @@ rb_ca_normalize_axes (int argc, VALUE *argv, VALUE self)
|
|
|
880
1088
|
const char *name;
|
|
881
1089
|
|
|
882
1090
|
rb_scan_args(argc, argv, "11", &raxes, &rname);
|
|
883
|
-
name = NIL_P(rname) ?
|
|
1091
|
+
name = NIL_P(rname) ? NULL : StringValueCStr(rname); /* NULL: looked up on error */
|
|
884
1092
|
GetCArray(self, ca);
|
|
885
1093
|
|
|
886
1094
|
if ( NIL_P(raxes) ) {
|
|
@@ -941,7 +1149,8 @@ rb_ca_guess_type (VALUE obj)
|
|
|
941
1149
|
/* Check before narrowing to int8_t, so the message names the id given. */
|
|
942
1150
|
long id = FIX2LONG(obj);
|
|
943
1151
|
if ( id <= CA_NONE || id >= CA_NTYPE ) {
|
|
944
|
-
rb_raise(rb_eArgError, "invalid data_type id %ld",
|
|
1152
|
+
rb_raise(rb_eArgError, "%s: invalid data_type id %ld",
|
|
1153
|
+
ca_calling_method_name(), id);
|
|
945
1154
|
}
|
|
946
1155
|
return (int8_t) id;
|
|
947
1156
|
}
|
|
@@ -968,7 +1177,8 @@ rb_ca_guess_type (VALUE obj)
|
|
|
968
1177
|
|
|
969
1178
|
inspect = rb_inspect(obj);
|
|
970
1179
|
rb_raise(rb_eArgError,
|
|
971
|
-
"<%s> is unknown data_type representation",
|
|
1180
|
+
"%s: <%s> is unknown data_type representation",
|
|
1181
|
+
ca_calling_method_name(), StringValuePtr(inspect));
|
|
972
1182
|
}
|
|
973
1183
|
|
|
974
1184
|
void
|
|
@@ -991,7 +1201,7 @@ rb_ca_guess_type_and_bytes (VALUE rtype, VALUE rbytes,
|
|
|
991
1201
|
}
|
|
992
1202
|
}
|
|
993
1203
|
else {
|
|
994
|
-
|
|
1204
|
+
CA_CHECK_DATA_TYPE_GIVEN(*data_type);
|
|
995
1205
|
*bytes = ca_sizeof[*data_type];
|
|
996
1206
|
}
|
|
997
1207
|
}
|
|
@@ -1068,11 +1278,36 @@ rb_hash_has_key(VALUE hash, VALUE key)
|
|
|
1068
1278
|
return Qfalse;
|
|
1069
1279
|
}
|
|
1070
1280
|
|
|
1281
|
+
/* The next comma-separated key of a spec, its length in *len, or NULL
|
|
1282
|
+
past the last key. The spec is read in place: a copy to cut up would
|
|
1283
|
+
be a C allocation, and its failure has nowhere to go but to drop every
|
|
1284
|
+
keyword. */
|
|
1285
|
+
static const char *
|
|
1286
|
+
option_key (const char **sp, long *len)
|
|
1287
|
+
{
|
|
1288
|
+
const char *p = *sp, *end;
|
|
1289
|
+
|
|
1290
|
+
if ( p == NULL ) {
|
|
1291
|
+
return NULL;
|
|
1292
|
+
}
|
|
1293
|
+
end = strchr(p, ',');
|
|
1294
|
+
if ( end ) {
|
|
1295
|
+
*len = end - p;
|
|
1296
|
+
*sp = end + 1;
|
|
1297
|
+
}
|
|
1298
|
+
else {
|
|
1299
|
+
*len = (long) strlen(p);
|
|
1300
|
+
*sp = NULL;
|
|
1301
|
+
}
|
|
1302
|
+
return p;
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1071
1305
|
void
|
|
1072
1306
|
rb_scan_options (VALUE ropt, const char *spec_in, ...)
|
|
1073
1307
|
{
|
|
1074
1308
|
VALUE *vp;
|
|
1075
|
-
char *sp, *tok
|
|
1309
|
+
const char *sp, *tok;
|
|
1310
|
+
long len;
|
|
1076
1311
|
int has_option = 0;
|
|
1077
1312
|
va_list vals;
|
|
1078
1313
|
|
|
@@ -1087,22 +1322,19 @@ rb_scan_options (VALUE ropt, const char *spec_in, ...)
|
|
|
1087
1322
|
}
|
|
1088
1323
|
|
|
1089
1324
|
va_start(vals, spec_in);
|
|
1090
|
-
sp =
|
|
1091
|
-
tok =
|
|
1092
|
-
while ( tok != NULL ) {
|
|
1325
|
+
sp = spec_in;
|
|
1326
|
+
while ( ( tok = option_key(&sp, &len) ) != NULL ) {
|
|
1093
1327
|
vp = va_arg(vals, VALUE*);
|
|
1094
1328
|
if ( has_option ) {
|
|
1095
|
-
VALUE key = ID2SYM(
|
|
1329
|
+
VALUE key = ID2SYM(rb_intern2(tok, len));
|
|
1096
1330
|
if ( rb_hash_has_key(ropt, key) ) {
|
|
1097
1331
|
*vp = rb_hash_aref(ropt, key);
|
|
1098
1332
|
}
|
|
1099
1333
|
/* key absent: leave *vp unchanged (caller's pre-initialized default) */
|
|
1100
1334
|
}
|
|
1101
1335
|
/* opts == Qnil: leave all *vp unchanged */
|
|
1102
|
-
tok = strsep1(&sp, ',');
|
|
1103
1336
|
}
|
|
1104
1337
|
va_end(vals);
|
|
1105
|
-
free(spec);
|
|
1106
1338
|
|
|
1107
1339
|
/* Strict: reject any key not named in spec, matching Ruby's native
|
|
1108
1340
|
keyword-argument behaviour ("unknown keyword: :foo"). Every call
|
|
@@ -1115,15 +1347,12 @@ rb_scan_options (VALUE ropt, const char *spec_in, ...)
|
|
|
1115
1347
|
VALUE key = rb_ary_entry(keys, i);
|
|
1116
1348
|
VALUE kname = SYMBOL_P(key) ? rb_sym2str(key) : rb_obj_as_string(key);
|
|
1117
1349
|
const char *kn = StringValueCStr(kname);
|
|
1118
|
-
|
|
1350
|
+
long kn_len = RSTRING_LEN(kname);
|
|
1119
1351
|
int found = 0;
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
if ( strcmp(tok2, kn) == 0 ) { found = 1; break; }
|
|
1124
|
-
tok2 = strsep1(&sp2, ',');
|
|
1352
|
+
sp = spec_in;
|
|
1353
|
+
while ( ( tok = option_key(&sp, &len) ) != NULL ) {
|
|
1354
|
+
if ( len == kn_len && memcmp(tok, kn, len) == 0 ) { found = 1; break; }
|
|
1125
1355
|
}
|
|
1126
|
-
free(spec2);
|
|
1127
1356
|
if ( ! found ) {
|
|
1128
1357
|
rb_raise(rb_eArgError, "unknown keyword: %"PRIsVALUE, rb_inspect(key));
|
|
1129
1358
|
}
|
|
@@ -1156,7 +1385,8 @@ void
|
|
|
1156
1385
|
rb_set_options (VALUE ropt, const char *spec_in, ...)
|
|
1157
1386
|
{
|
|
1158
1387
|
VALUE rval;
|
|
1159
|
-
char *sp, *tok
|
|
1388
|
+
const char *sp, *tok;
|
|
1389
|
+
long len;
|
|
1160
1390
|
int has_option = 0;
|
|
1161
1391
|
va_list vals;
|
|
1162
1392
|
|
|
@@ -1171,27 +1401,38 @@ rb_set_options (VALUE ropt, const char *spec_in, ...)
|
|
|
1171
1401
|
}
|
|
1172
1402
|
|
|
1173
1403
|
va_start(vals, spec_in);
|
|
1174
|
-
sp =
|
|
1175
|
-
tok =
|
|
1176
|
-
while ( tok != NULL ) {
|
|
1404
|
+
sp = spec_in;
|
|
1405
|
+
while ( ( tok = option_key(&sp, &len) ) != NULL ) {
|
|
1177
1406
|
rval = va_arg(vals, VALUE);
|
|
1178
1407
|
if ( has_option ) {
|
|
1179
|
-
rb_hash_aset(ropt, ID2SYM(
|
|
1408
|
+
rb_hash_aset(ropt, ID2SYM(rb_intern2(tok, len)), rval);
|
|
1180
1409
|
}
|
|
1181
|
-
tok = strsep1(&sp, ',');
|
|
1182
1410
|
}
|
|
1183
1411
|
va_end(vals);
|
|
1184
|
-
free(spec);
|
|
1185
1412
|
|
|
1186
1413
|
return;
|
|
1187
1414
|
}
|
|
1188
1415
|
|
|
1189
1416
|
|
|
1417
|
+
/* Whether this runs in the main Ractor: Init does, and leaves a value in
|
|
1418
|
+
its Ractor-local storage that no other Ractor has. */
|
|
1419
|
+
static rb_ractor_local_key_t ca_main_ractor_key;
|
|
1420
|
+
|
|
1421
|
+
int
|
|
1422
|
+
ca_in_main_ractor (void)
|
|
1423
|
+
{
|
|
1424
|
+
VALUE mark;
|
|
1425
|
+
return rb_ractor_local_storage_value_lookup(ca_main_ractor_key, &mark);
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1190
1428
|
void
|
|
1191
1429
|
Init_carray_utils (void)
|
|
1192
1430
|
{
|
|
1431
|
+
ca_main_ractor_key = rb_ractor_local_storage_value_newkey();
|
|
1432
|
+
rb_ractor_local_storage_value_set(ca_main_ractor_key, Qtrue);
|
|
1193
1433
|
ca_id_names = st_init_numtable();
|
|
1194
1434
|
rb_nativethread_lock_initialize(&ca_id_names_lock);
|
|
1435
|
+
id_answering = rb_intern("__carray_answering_method__");
|
|
1195
1436
|
id_begin = rb_intern("begin");
|
|
1196
1437
|
id_end = rb_intern("end");
|
|
1197
1438
|
id_excl_end = rb_intern("exclude_end?");
|
|
@@ -1203,11 +1444,13 @@ Init_carray_utils (void)
|
|
|
1203
1444
|
rb_define_method(rb_cCArray, "normalize_axes", rb_ca_normalize_axes, -1);
|
|
1204
1445
|
rb_define_singleton_method(rb_cCArray, "normalize_axis",
|
|
1205
1446
|
rb_ca_s_normalize_axis, -1);
|
|
1206
|
-
rb_define_singleton_method(rb_cCArray, "
|
|
1447
|
+
rb_define_singleton_method(rb_cCArray, "__present_cells_needed_per_result_cell__",
|
|
1207
1448
|
rb_ca_s_min_count_need, 3);
|
|
1208
|
-
rb_define_singleton_method(rb_cCArray, "
|
|
1449
|
+
rb_define_singleton_method(rb_cCArray, "__fill_undefined_result_cells__",
|
|
1209
1450
|
rb_ca_s_reduce_fill, 2);
|
|
1210
|
-
|
|
1451
|
+
rb_define_private_method(rb_singleton_class(rb_cCArray), "library_root=",
|
|
1452
|
+
rb_ca_s_set_library_root, 1);
|
|
1453
|
+
rb_define_singleton_method(rb_cCArray, "__name_errors_after_method__",
|
|
1211
1454
|
rb_ca_s_answer_as, 1);
|
|
1212
1455
|
|
|
1213
1456
|
}
|