carray 3.0.3 → 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 +264 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +1 -6
- 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 +205 -134
- data/ext/ca_compare.c +7 -18
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1234 -1994
- data/ext/ca_kernel_iterator.h +391 -437
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +96 -39
- data/ext/ca_obj_bincmp.c +24 -21
- data/ext/ca_obj_binop.c +15 -26
- data/ext/ca_obj_bitarray.c +3 -2
- data/ext/ca_obj_bitfield.c +5 -6
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +5 -6
- data/ext/ca_obj_const_string.c +173 -19
- data/ext/ca_obj_face.c +238 -57
- 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 +17 -5
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +406 -132
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +67 -57
- data/ext/ca_obj_object.c +157 -51
- data/ext/ca_obj_record.c +12 -7
- data/ext/ca_obj_reduce.c +13 -8
- data/ext/ca_obj_refer.c +25 -27
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +6 -5
- data/ext/ca_obj_select.c +14 -9
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +11 -1
- data/ext/ca_obj_stack.c +179 -34
- data/ext/ca_obj_stride.c +162 -115
- data/ext/ca_obj_string.c +71 -4
- data/ext/ca_obj_tile.c +6 -5
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +5 -3
- data/ext/ca_obj_triop.c +23 -32
- data/ext/ca_obj_window.c +190 -26
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +181 -75
- data/ext/carray_access.c +184 -96
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +89 -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 +142 -24
- data/ext/carray_cast_func.rb +46 -6
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +16 -7
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +147 -55
- data/ext/carray_count.c +50 -20
- data/ext/carray_element.c +76 -33
- data/ext/carray_factorize.c +118 -64
- data/ext/carray_generate.c +191 -50
- data/ext/carray_histogram.c +62 -17
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +336 -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 +10906 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +292 -72
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +124 -47
- data/ext/carray_order.c +384 -76
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +67 -13
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +63 -38
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +91 -28
- data/ext/carray_sort.c +35 -35
- data/ext/carray_struct.c +19 -18
- data/ext/carray_test.c +26 -5
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +246 -45
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +198 -240
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +126 -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 +78 -10
- 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 +165 -43
- data/lib/carray/categorical_iterator.rb +130 -27
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +14 -5
- 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/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 +246 -21
- data/lib/carray/frame/group.rb +510 -95
- data/lib/carray/frame/io.rb +115 -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 +11 -4
- 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 +182 -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 +53 -36
- 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 +313 -82
- data/lib/carray/serialize.rb +24 -10
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +8 -1
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +19 -8
- data/lib/carray/time.rb +726 -104
- 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_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_cast.rb +10 -0
- data/yard-stubs/carray_conversion.rb +2 -1
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +26 -2
- data/yard-stubs/carray_math.rb +27 -1
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +29 -18
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +14 -9
- 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;
|
|
@@ -535,27 +549,44 @@ ca_stable_id_name (ID id)
|
|
|
535
549
|
/* The method a delegating method answers for. A method that does its work
|
|
536
550
|
by calling others (median calls partition_index, mode calls sort) runs
|
|
537
551
|
them under ca_answer_as_caller, so an error they raise names the method
|
|
538
|
-
the user called. The outermost one wins.
|
|
539
|
-
|
|
552
|
+
the user called. The outermost one wins. The name is kept with the
|
|
553
|
+
Ruby thread (Thread#[], so per fiber): Ractors share native threads under
|
|
554
|
+
the M:N scheduler, and a native-thread-local variable leaks one Ractor's
|
|
555
|
+
name into another's message. */
|
|
556
|
+
static ID id_answering;
|
|
557
|
+
|
|
558
|
+
static const char *
|
|
559
|
+
ca_answering_name (void)
|
|
560
|
+
{
|
|
561
|
+
VALUE name = rb_thread_local_aref(rb_thread_current(), id_answering);
|
|
562
|
+
return NIL_P(name) ? NULL : ca_stable_id_name(SYM2ID(name));
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
static void
|
|
566
|
+
ca_set_answering_name (const char *name)
|
|
567
|
+
{
|
|
568
|
+
rb_thread_local_aset(rb_thread_current(), id_answering,
|
|
569
|
+
name ? ID2SYM(rb_intern(name)) : Qnil);
|
|
570
|
+
}
|
|
540
571
|
|
|
541
572
|
static VALUE
|
|
542
573
|
ca_answer_restore (VALUE unused)
|
|
543
574
|
{
|
|
544
|
-
|
|
575
|
+
ca_set_answering_name(NULL);
|
|
545
576
|
return Qnil;
|
|
546
577
|
}
|
|
547
578
|
|
|
579
|
+
/* A C method that does its work by calling others runs them through here.
|
|
580
|
+
It used to fix the name at entry; the name is now found from the frames
|
|
581
|
+
when an error is raised (ca_user_called_method_id), which also reaches
|
|
582
|
+
the outer method, so nothing is fixed and nothing is paid on the way in. */
|
|
548
583
|
VALUE
|
|
549
584
|
ca_answer_as_caller (VALUE (*body)(VALUE), VALUE arg)
|
|
550
585
|
{
|
|
551
|
-
|
|
552
|
-
return body(arg);
|
|
553
|
-
}
|
|
554
|
-
ca_answering_name = ca_calling_method_name();
|
|
555
|
-
return rb_ensure(body, arg, ca_answer_restore, Qnil);
|
|
586
|
+
return body(arg);
|
|
556
587
|
}
|
|
557
588
|
|
|
558
|
-
/* CArray.
|
|
589
|
+
/* CArray.__name_errors_after_method__(name) { ... }: the same for a method written in Ruby. */
|
|
559
590
|
static VALUE
|
|
560
591
|
rb_ca_s_answer_as_body (VALUE unused)
|
|
561
592
|
{
|
|
@@ -565,23 +596,137 @@ rb_ca_s_answer_as_body (VALUE unused)
|
|
|
565
596
|
static VALUE
|
|
566
597
|
rb_ca_s_answer_as (VALUE klass, VALUE name)
|
|
567
598
|
{
|
|
568
|
-
if ( ca_answering_name ) {
|
|
599
|
+
if ( ca_answering_name() ) {
|
|
569
600
|
return rb_yield(Qnil);
|
|
570
601
|
}
|
|
571
|
-
|
|
602
|
+
ca_set_answering_name(ca_stable_id_name(rb_to_id(name)));
|
|
572
603
|
return rb_ensure(rb_ca_s_answer_as_body, Qnil, ca_answer_restore, Qnil);
|
|
573
604
|
}
|
|
574
605
|
|
|
606
|
+
/* The directory the library's Ruby files are loaded from (lib/), set once
|
|
607
|
+
by lib/carray.rb as it loads, read only afterwards. */
|
|
608
|
+
static char *ca_library_root = NULL;
|
|
609
|
+
static long ca_library_root_len = 0;
|
|
610
|
+
|
|
611
|
+
/* CArray.library_root = dir (private): where the frames of the library's
|
|
612
|
+
own Ruby methods are. The first call wins. */
|
|
613
|
+
static VALUE
|
|
614
|
+
rb_ca_s_set_library_root (VALUE klass, VALUE dir)
|
|
615
|
+
{
|
|
616
|
+
if ( ca_library_root == NULL ) {
|
|
617
|
+
long len = RSTRING_LEN(StringValue(dir));
|
|
618
|
+
char *copy = ALLOC_N(char, len + 1);
|
|
619
|
+
memcpy(copy, RSTRING_PTR(dir), len);
|
|
620
|
+
copy[len] = '\0';
|
|
621
|
+
ca_library_root_len = len;
|
|
622
|
+
ca_library_root = copy;
|
|
623
|
+
}
|
|
624
|
+
return Qnil;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/* Whether a frame without a source file -- a C method -- is one of the
|
|
628
|
+
library's: a method of a CA* or CScalar class, or a CA_* conversion
|
|
629
|
+
function. A method of a core class (Array#map, Integer#times) is not. */
|
|
630
|
+
static int
|
|
631
|
+
ca_frame_is_library_cfunc (VALUE frame, VALUE name)
|
|
632
|
+
{
|
|
633
|
+
VALUE path = rb_profile_frame_classpath(frame);
|
|
634
|
+
if ( ! NIL_P(path) ) {
|
|
635
|
+
const char *p = RSTRING_PTR(path);
|
|
636
|
+
long n = RSTRING_LEN(path);
|
|
637
|
+
if ( ( n >= 2 && strncmp(p, "CA", 2) == 0 )
|
|
638
|
+
|| ( n >= 7 && strncmp(p, "CScalar", 7) == 0 ) ) {
|
|
639
|
+
return 1;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
return RSTRING_LEN(name) > 3 && strncmp(RSTRING_PTR(name), "CA_", 3) == 0;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/* The method the user called: going out from the innermost frame, the last
|
|
646
|
+
frame of the library -- a Ruby method under ca_library_root, or one of
|
|
647
|
+
its C methods -- before the user's own code (a block included) is
|
|
648
|
+
reached. A core C method the library calls on the way (Array#map) is
|
|
649
|
+
passed through. 0 when no frame of the library is found. */
|
|
650
|
+
#define CA_NAMING_FRAMES 64
|
|
651
|
+
|
|
652
|
+
static ID
|
|
653
|
+
ca_user_called_method_id (void)
|
|
654
|
+
{
|
|
655
|
+
ID id_initialize = rb_intern("initialize");
|
|
656
|
+
ID id_new = rb_intern("new");
|
|
657
|
+
VALUE frames[CA_NAMING_FRAMES];
|
|
658
|
+
int lines[CA_NAMING_FRAMES];
|
|
659
|
+
int n, i;
|
|
660
|
+
ID found = 0;
|
|
661
|
+
if ( ca_library_root == NULL ) {
|
|
662
|
+
return 0;
|
|
663
|
+
}
|
|
664
|
+
n = rb_profile_frames(0, CA_NAMING_FRAMES, frames, lines);
|
|
665
|
+
for (i = 0; i < n; i++) {
|
|
666
|
+
VALUE file = rb_profile_frame_absolute_path(frames[i]);
|
|
667
|
+
VALUE name, label;
|
|
668
|
+
if ( NIL_P(file) ) {
|
|
669
|
+
/* code evaluated with a file name (class_eval in the library) and the
|
|
670
|
+
core written in Ruby ("<internal:numeric>") have a path but no
|
|
671
|
+
absolute path; -e has a path outside the library */
|
|
672
|
+
file = rb_profile_frame_path(frames[i]);
|
|
673
|
+
}
|
|
674
|
+
if ( ! NIL_P(file) && strcmp(StringValueCStr(file), "<cfunc>") == 0 ) {
|
|
675
|
+
name = rb_profile_frame_method_name(frames[i]);
|
|
676
|
+
if ( NIL_P(name) ) {
|
|
677
|
+
continue;
|
|
678
|
+
}
|
|
679
|
+
if ( ca_frame_is_library_cfunc(frames[i], name) ) {
|
|
680
|
+
found = rb_to_id(name);
|
|
681
|
+
}
|
|
682
|
+
else if ( found == id_initialize && rb_to_id(name) == id_new ) {
|
|
683
|
+
found = id_new; /* Class#new around our initialize */
|
|
684
|
+
}
|
|
685
|
+
continue; /* a core C method passes */
|
|
686
|
+
}
|
|
687
|
+
if ( ! NIL_P(file) && strncmp(StringValueCStr(file), "<internal:", 10) == 0 ) {
|
|
688
|
+
continue; /* core written in Ruby (Integer#times) */
|
|
689
|
+
}
|
|
690
|
+
if ( NIL_P(file) /* eval without a file: the user's */
|
|
691
|
+
|| RSTRING_LEN(file) <= ca_library_root_len
|
|
692
|
+
|| strncmp(RSTRING_PTR(file), ca_library_root, ca_library_root_len) != 0
|
|
693
|
+
|| RSTRING_PTR(file)[ca_library_root_len] != '/' ) {
|
|
694
|
+
break;
|
|
695
|
+
}
|
|
696
|
+
/* A block of the library (an each inside a method, the autoload stub)
|
|
697
|
+
names nothing: the method around it is further out. A block whose
|
|
698
|
+
method is a class body is a method made by define_method, and its
|
|
699
|
+
frame does not carry the method's name, so the walk gives up and the
|
|
700
|
+
innermost C method is named, as before the walk. */
|
|
701
|
+
label = rb_profile_frame_label(frames[i]);
|
|
702
|
+
if ( ! NIL_P(label) && strncmp(StringValueCStr(label), "block ", 6) == 0 ) {
|
|
703
|
+
VALUE base = rb_profile_frame_base_label(frames[i]);
|
|
704
|
+
if ( ! NIL_P(base) && RSTRING_LEN(base) > 0 && RSTRING_PTR(base)[0] == '<' ) {
|
|
705
|
+
return 0;
|
|
706
|
+
}
|
|
707
|
+
continue;
|
|
708
|
+
}
|
|
709
|
+
name = rb_profile_frame_method_name(frames[i]);
|
|
710
|
+
if ( ! NIL_P(name) ) {
|
|
711
|
+
found = rb_to_id(name);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
return found;
|
|
715
|
+
}
|
|
716
|
+
|
|
575
717
|
const char *
|
|
576
718
|
ca_calling_method_name (void)
|
|
577
719
|
{
|
|
578
720
|
ID id;
|
|
579
721
|
const char *s;
|
|
580
722
|
size_t n;
|
|
581
|
-
if ( ca_answering_name ) {
|
|
582
|
-
return
|
|
723
|
+
if ( (s = ca_answering_name()) ) {
|
|
724
|
+
return s;
|
|
725
|
+
}
|
|
726
|
+
id = ca_user_called_method_id();
|
|
727
|
+
if ( ! id ) {
|
|
728
|
+
id = rb_frame_this_func();
|
|
583
729
|
}
|
|
584
|
-
id = rb_frame_this_func();
|
|
585
730
|
if ( ! id ) {
|
|
586
731
|
return "axis";
|
|
587
732
|
}
|
|
@@ -624,15 +769,22 @@ ca_shape_elements (int8_t ndim, const ca_size_t *dim, ca_size_t bytes)
|
|
|
624
769
|
return elements;
|
|
625
770
|
}
|
|
626
771
|
|
|
627
|
-
/* An index array is read as ca_size_t. A
|
|
628
|
-
|
|
629
|
-
|
|
772
|
+
/* An index array is read as ca_size_t. A float or complex one would be
|
|
773
|
+
cut to an integer on the way, so it is refused, as the indexer refuses
|
|
774
|
+
it. A uint64 one holding 2**63 or more would turn negative and count
|
|
775
|
+
from the end of the axis, so it is refused as the out-of-range index it
|
|
776
|
+
is. */
|
|
630
777
|
void
|
|
631
778
|
ca_check_index_array (VALUE v)
|
|
632
779
|
{
|
|
633
780
|
CArray *ca;
|
|
634
781
|
if ( ! rb_obj_is_carray(v) ) return;
|
|
635
782
|
GetCArray(v, ca);
|
|
783
|
+
if ( ca_is_float_type(ca) || ca_is_complex_type(ca) ) {
|
|
784
|
+
rb_raise(rb_eIndexError,
|
|
785
|
+
"data_type %s is invalid for an index (should be integer)",
|
|
786
|
+
ca_type_name[ca->data_type]);
|
|
787
|
+
}
|
|
636
788
|
if ( ca->data_type != CA_UINT64 || ca->elements == 0 ) return;
|
|
637
789
|
{
|
|
638
790
|
VALUE max = rb_funcall(v, rb_intern("max"), 0);
|
|
@@ -698,7 +850,7 @@ ca_min_count_arg (VALUE v, const char *name)
|
|
|
698
850
|
return n;
|
|
699
851
|
}
|
|
700
852
|
|
|
701
|
-
/* CArray.
|
|
853
|
+
/* CArray.__present_cells_needed_per_result_cell__(op, min_count, least): how many present cells a
|
|
702
854
|
result cell of `op` needs (ca_too_few_present), for a reduction written
|
|
703
855
|
in Ruby; it masks the cells whose count is below it. */
|
|
704
856
|
static VALUE
|
|
@@ -719,11 +871,10 @@ int
|
|
|
719
871
|
ca_symbol_choice (VALUE v, const char *arg, const char *c0, const char *c1,
|
|
720
872
|
const char *name)
|
|
721
873
|
{
|
|
722
|
-
const char *nm = name ? name : ca_calling_method_name();
|
|
723
874
|
ID id;
|
|
724
875
|
if ( ! SYMBOL_P(v) ) {
|
|
725
876
|
rb_raise(rb_eTypeError, "%s: %s must be a Symbol (got %"PRIsVALUE")",
|
|
726
|
-
|
|
877
|
+
name ? name : ca_calling_method_name(), arg, rb_obj_class(v));
|
|
727
878
|
}
|
|
728
879
|
id = SYM2ID(v);
|
|
729
880
|
if ( id == rb_intern(c0) ) {
|
|
@@ -733,7 +884,7 @@ ca_symbol_choice (VALUE v, const char *arg, const char *c0, const char *c1,
|
|
|
733
884
|
return 1;
|
|
734
885
|
}
|
|
735
886
|
rb_raise(rb_eArgError, "%s: unknown %s :%"PRIsVALUE" (expected :%s or :%s)",
|
|
736
|
-
|
|
887
|
+
name ? name : ca_calling_method_name(), arg, rb_id2str(id), c0, c1);
|
|
737
888
|
return 0;
|
|
738
889
|
}
|
|
739
890
|
|
|
@@ -776,7 +927,7 @@ ca_reduce_fill (VALUE result, VALUE fill, int whole)
|
|
|
776
927
|
return ( result == CA_UNDEF ) ? fill : result;
|
|
777
928
|
}
|
|
778
929
|
|
|
779
|
-
/* CArray.
|
|
930
|
+
/* CArray.__fill_undefined_result_cells__(result, fill_value): ca_reduce_fill for a
|
|
780
931
|
reduction written in Ruby. A fill_value of nil or UNDEF leaves the
|
|
781
932
|
undefined cells as they are. */
|
|
782
933
|
static VALUE
|
|
@@ -817,6 +968,38 @@ rb_ca_normalize_axis_for_ndim (long raw, int ndim, const char *name)
|
|
|
817
968
|
return (int) axis;
|
|
818
969
|
}
|
|
819
970
|
|
|
971
|
+
/* An array has at most CA_RANK_MAX axes, and every dim[] and strides[]
|
|
972
|
+
array in the library is that long. A constructor or view whose result
|
|
973
|
+
would have more -- a shape given, a rank computed -- calls this before it
|
|
974
|
+
writes a single dim, and is refused with ArgumentError naming the method,
|
|
975
|
+
the rank and the limit. `name` NULL names the method the user called. */
|
|
976
|
+
void
|
|
977
|
+
ca_check_rank_fits (long ndim, const char *name)
|
|
978
|
+
{
|
|
979
|
+
if ( ndim > CA_RANK_MAX ) {
|
|
980
|
+
rb_raise(rb_eArgError, "%s: ndim %ld exceeds CA_RANK_MAX %d",
|
|
981
|
+
name ? name : ca_calling_method_name(), ndim, CA_RANK_MAX);
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
/* The axis an `axis` argument names among `ndim` axes: the one rule every
|
|
986
|
+
entry that takes an axis from Ruby keeps. An Integer, negative counting
|
|
987
|
+
from the end; anything else raises TypeError, and an Integer outside
|
|
988
|
+
[-ndim, ndim) raises ArgumentError naming the value given -- a Bignum
|
|
989
|
+
too, since no ndim reaches it. `name` and the insertion-position use of
|
|
990
|
+
`ndim` are as for rb_ca_normalize_axis_for_ndim. */
|
|
991
|
+
int
|
|
992
|
+
ca_normalize_axis_arg (VALUE raxis, int ndim, const char *name)
|
|
993
|
+
{
|
|
994
|
+
ca_check_rank_fits(ndim, name); /* no array has the axes to name */
|
|
995
|
+
if ( RB_INTEGER_TYPE_P(raxis) && ! RB_FIXNUM_P(raxis) ) {
|
|
996
|
+
rb_raise(rb_eArgError,
|
|
997
|
+
"%s: axis %"PRIsVALUE" out of range for ndim %d",
|
|
998
|
+
name ? name : ca_calling_method_name(), raxis, ndim);
|
|
999
|
+
}
|
|
1000
|
+
return rb_ca_normalize_axis_for_ndim(ca_axis_integer(raxis, name), ndim, name);
|
|
1001
|
+
}
|
|
1002
|
+
|
|
820
1003
|
/* Self-bound wrapper: delegate to the kernel using self.ndim. Kept
|
|
821
1004
|
for backward compatibility with the existing instance method
|
|
822
1005
|
`CArray#normalize_axis`. */
|
|
@@ -825,7 +1008,7 @@ rb_ca_normalize_axis_value (VALUE self, VALUE raxis, const char *name)
|
|
|
825
1008
|
{
|
|
826
1009
|
CArray *ca;
|
|
827
1010
|
GetCArray(self, ca);
|
|
828
|
-
return
|
|
1011
|
+
return ca_normalize_axis_arg(raxis, (int) ca->ndim, name);
|
|
829
1012
|
}
|
|
830
1013
|
|
|
831
1014
|
/* Ruby-facing `CArray#normalize_axis(axis, name=nil)` — returns the
|
|
@@ -860,7 +1043,7 @@ rb_ca_s_normalize_axis (int argc, VALUE *argv, VALUE klass)
|
|
|
860
1043
|
int k;
|
|
861
1044
|
rb_scan_args(argc, argv, "21", &raxis, &rndim, &rname);
|
|
862
1045
|
name = NIL_P(rname) ? NULL : StringValueCStr(rname);
|
|
863
|
-
k =
|
|
1046
|
+
k = ca_normalize_axis_arg(raxis, NUM2INT(rndim), name);
|
|
864
1047
|
return INT2NUM(k);
|
|
865
1048
|
}
|
|
866
1049
|
|
|
@@ -880,7 +1063,7 @@ rb_ca_normalize_axes (int argc, VALUE *argv, VALUE self)
|
|
|
880
1063
|
const char *name;
|
|
881
1064
|
|
|
882
1065
|
rb_scan_args(argc, argv, "11", &raxes, &rname);
|
|
883
|
-
name = NIL_P(rname) ?
|
|
1066
|
+
name = NIL_P(rname) ? NULL : StringValueCStr(rname); /* NULL: looked up on error */
|
|
884
1067
|
GetCArray(self, ca);
|
|
885
1068
|
|
|
886
1069
|
if ( NIL_P(raxes) ) {
|
|
@@ -941,7 +1124,8 @@ rb_ca_guess_type (VALUE obj)
|
|
|
941
1124
|
/* Check before narrowing to int8_t, so the message names the id given. */
|
|
942
1125
|
long id = FIX2LONG(obj);
|
|
943
1126
|
if ( id <= CA_NONE || id >= CA_NTYPE ) {
|
|
944
|
-
rb_raise(rb_eArgError, "invalid data_type id %ld",
|
|
1127
|
+
rb_raise(rb_eArgError, "%s: invalid data_type id %ld",
|
|
1128
|
+
ca_calling_method_name(), id);
|
|
945
1129
|
}
|
|
946
1130
|
return (int8_t) id;
|
|
947
1131
|
}
|
|
@@ -968,7 +1152,8 @@ rb_ca_guess_type (VALUE obj)
|
|
|
968
1152
|
|
|
969
1153
|
inspect = rb_inspect(obj);
|
|
970
1154
|
rb_raise(rb_eArgError,
|
|
971
|
-
"<%s> is unknown data_type representation",
|
|
1155
|
+
"%s: <%s> is unknown data_type representation",
|
|
1156
|
+
ca_calling_method_name(), StringValuePtr(inspect));
|
|
972
1157
|
}
|
|
973
1158
|
|
|
974
1159
|
void
|
|
@@ -991,7 +1176,7 @@ rb_ca_guess_type_and_bytes (VALUE rtype, VALUE rbytes,
|
|
|
991
1176
|
}
|
|
992
1177
|
}
|
|
993
1178
|
else {
|
|
994
|
-
|
|
1179
|
+
CA_CHECK_DATA_TYPE_GIVEN(*data_type);
|
|
995
1180
|
*bytes = ca_sizeof[*data_type];
|
|
996
1181
|
}
|
|
997
1182
|
}
|
|
@@ -1187,11 +1372,25 @@ rb_set_options (VALUE ropt, const char *spec_in, ...)
|
|
|
1187
1372
|
}
|
|
1188
1373
|
|
|
1189
1374
|
|
|
1375
|
+
/* Whether this runs in the main Ractor: Init does, and leaves a value in
|
|
1376
|
+
its Ractor-local storage that no other Ractor has. */
|
|
1377
|
+
static rb_ractor_local_key_t ca_main_ractor_key;
|
|
1378
|
+
|
|
1379
|
+
int
|
|
1380
|
+
ca_in_main_ractor (void)
|
|
1381
|
+
{
|
|
1382
|
+
VALUE mark;
|
|
1383
|
+
return rb_ractor_local_storage_value_lookup(ca_main_ractor_key, &mark);
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1190
1386
|
void
|
|
1191
1387
|
Init_carray_utils (void)
|
|
1192
1388
|
{
|
|
1389
|
+
ca_main_ractor_key = rb_ractor_local_storage_value_newkey();
|
|
1390
|
+
rb_ractor_local_storage_value_set(ca_main_ractor_key, Qtrue);
|
|
1193
1391
|
ca_id_names = st_init_numtable();
|
|
1194
1392
|
rb_nativethread_lock_initialize(&ca_id_names_lock);
|
|
1393
|
+
id_answering = rb_intern("__carray_answering_method__");
|
|
1195
1394
|
id_begin = rb_intern("begin");
|
|
1196
1395
|
id_end = rb_intern("end");
|
|
1197
1396
|
id_excl_end = rb_intern("exclude_end?");
|
|
@@ -1203,11 +1402,13 @@ Init_carray_utils (void)
|
|
|
1203
1402
|
rb_define_method(rb_cCArray, "normalize_axes", rb_ca_normalize_axes, -1);
|
|
1204
1403
|
rb_define_singleton_method(rb_cCArray, "normalize_axis",
|
|
1205
1404
|
rb_ca_s_normalize_axis, -1);
|
|
1206
|
-
rb_define_singleton_method(rb_cCArray, "
|
|
1405
|
+
rb_define_singleton_method(rb_cCArray, "__present_cells_needed_per_result_cell__",
|
|
1207
1406
|
rb_ca_s_min_count_need, 3);
|
|
1208
|
-
rb_define_singleton_method(rb_cCArray, "
|
|
1407
|
+
rb_define_singleton_method(rb_cCArray, "__fill_undefined_result_cells__",
|
|
1209
1408
|
rb_ca_s_reduce_fill, 2);
|
|
1210
|
-
|
|
1409
|
+
rb_define_private_method(rb_singleton_class(rb_cCArray), "library_root=",
|
|
1410
|
+
rb_ca_s_set_library_root, 1);
|
|
1411
|
+
rb_define_singleton_method(rb_cCArray, "__name_errors_after_method__",
|
|
1211
1412
|
rb_ca_s_answer_as, 1);
|
|
1212
1413
|
|
|
1213
1414
|
}
|
data/ext/mk_call_cfunc.rb
CHANGED
|
@@ -127,6 +127,17 @@ def indent(s, prefix = " ")
|
|
|
127
127
|
s.each_line.map { |l| l.strip.empty? ? l : prefix + l }.join
|
|
128
128
|
end
|
|
129
129
|
|
|
130
|
+
# The operands are read through cx[] only once their structs are taken, and
|
|
131
|
+
# a caller may pass a view it made for the call and holds nowhere else
|
|
132
|
+
# (rb_ca_wrap_readonly(x, ...) as an argument): keep each one reachable until
|
|
133
|
+
# the walk is done. rcx0 is the return value and needs no guard.
|
|
134
|
+
def emit_operand_guards(n)
|
|
135
|
+
(1...n).each do |k|
|
|
136
|
+
$src.puts " RB_GC_GUARD(rcx#{k});"
|
|
137
|
+
end
|
|
138
|
+
$src.puts "" if n > 1
|
|
139
|
+
end
|
|
140
|
+
|
|
130
141
|
# --- raw ca_call_cfunc_N ----------------------------------------------------
|
|
131
142
|
#
|
|
132
143
|
# The per-cell loop runs in a walker function of its own, handed to
|
|
@@ -198,7 +209,7 @@ def emit_raw_common(n, r:)
|
|
|
198
209
|
$src.puts " TypedData_Get_Struct(rcx#{k}, CArray, &carray_data_type, cx[#{k}]);"
|
|
199
210
|
end
|
|
200
211
|
$src.puts ""
|
|
201
|
-
$src.puts <<~END_C
|
|
212
|
+
$src.puts indent(<<~END_C)
|
|
202
213
|
/* sweep engine: per-operand acquire (alias / xmalloc + ca_xfer_all),
|
|
203
214
|
operand pairing, mask OR across INPUTs, mask propagate to OUTPUTs.
|
|
204
215
|
Lifecycle template lives in ext/ca_sweep_engine.{c,h}. */
|
|
@@ -218,6 +229,9 @@ def emit_raw_common(n, r:)
|
|
|
218
229
|
ctx.userdata = #{r ? "userdata" : "NULL"};
|
|
219
230
|
ca_sweep_run(&state, #{name}_walk, (VALUE) &ctx);
|
|
220
231
|
|
|
232
|
+
END_C
|
|
233
|
+
emit_operand_guards(n)
|
|
234
|
+
$src.puts <<~END_C
|
|
221
235
|
return rcx0;
|
|
222
236
|
}
|
|
223
237
|
|
|
@@ -396,7 +410,7 @@ def emit_slab_body(n, name, walker, userdata)
|
|
|
396
410
|
$src.puts " TypedData_Get_Struct(rcx#{k}, CArray, &carray_data_type, cx[#{k}]);"
|
|
397
411
|
end
|
|
398
412
|
$src.puts ""
|
|
399
|
-
$src.puts <<~END_C
|
|
413
|
+
$src.puts indent(<<~END_C)
|
|
400
414
|
/* sweep engine, chunked path: per-operand acquire (attach for OUTPUT
|
|
401
415
|
and alias INPUT, arena chunk scratch for non-alias INPUT), broadcast
|
|
402
416
|
shape check, mask OR across INPUTs, mask propagate to OUTPUTs at
|
|
@@ -421,6 +435,9 @@ def emit_slab_body(n, name, walker, userdata)
|
|
|
421
435
|
ctx.userdata = #{userdata};
|
|
422
436
|
ca_sweep_run_chunked(&state, #{walker}, (VALUE) &ctx);
|
|
423
437
|
|
|
438
|
+
END_C
|
|
439
|
+
emit_operand_guards(n)
|
|
440
|
+
$src.puts <<~END_C
|
|
424
441
|
return rcx0;
|
|
425
442
|
}
|
|
426
443
|
|