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_cast_func.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
data_type = []
|
|
2
|
+
type_const = {}
|
|
2
3
|
%w[
|
|
3
4
|
CA_FIXLEN
|
|
4
5
|
CA_BOOLEAN
|
|
@@ -20,8 +21,22 @@ data_type = []
|
|
|
20
21
|
].each_with_index do |name, i|
|
|
21
22
|
eval("#{name} = #{i}")
|
|
22
23
|
data_type.push(i)
|
|
24
|
+
type_const[i] = name
|
|
23
25
|
end
|
|
24
26
|
|
|
27
|
+
# The open interval (lo, hi) of doubles whose integer part a type holds:
|
|
28
|
+
# a cast truncates toward zero, so -128.5 still fits int8.
|
|
29
|
+
INTEGER_TRUNC_RANGE = {
|
|
30
|
+
CA_INT8 => ["-129.0", "128.0"],
|
|
31
|
+
CA_UINT8 => ["-1.0", "256.0"],
|
|
32
|
+
CA_INT16 => ["-32769.0", "32768.0"],
|
|
33
|
+
CA_UINT16 => ["-1.0", "65536.0"],
|
|
34
|
+
CA_INT32 => ["-2147483649.0", "2147483648.0"],
|
|
35
|
+
CA_UINT32 => ["-1.0", "4294967296.0"],
|
|
36
|
+
CA_INT64 => ["-9223372036854775808.0", "9223372036854775808.0"],
|
|
37
|
+
CA_UINT64 => ["-1.0", "18446744073709551616.0"],
|
|
38
|
+
}
|
|
39
|
+
|
|
25
40
|
ctype = {
|
|
26
41
|
CA_FIXLEN => "fixlen",
|
|
27
42
|
CA_BOOLEAN => "boolean8_t",
|
|
@@ -40,6 +55,12 @@ ctype = {
|
|
|
40
55
|
CA_OBJECT => "VALUE"
|
|
41
56
|
}
|
|
42
57
|
|
|
58
|
+
# The type a cast reads and writes a cell through. A view's cells need not
|
|
59
|
+
# be aligned to their size (a struct member at offset 1, a refer with a
|
|
60
|
+
# byte offset), so a pointer to a multi-byte cell is the unaligned typedef
|
|
61
|
+
# from carray.h; ctype stays the plain name the functions are called by.
|
|
62
|
+
utype = Hash.new { |h, c| h[c] = %w[fixlen boolean8_t int8_t uint8_t].include?(c) ? c : "ca_u_#{c}" }
|
|
63
|
+
|
|
43
64
|
obj2cval = {
|
|
44
65
|
CA_FIXLEN => nil,
|
|
45
66
|
CA_BOOLEAN => "OBJ2BOOL",
|
|
@@ -254,7 +275,7 @@ FIXLEN.each do |type1|
|
|
|
254
275
|
{
|
|
255
276
|
char *p1 = ptr1;
|
|
256
277
|
ca_size_t bytes;
|
|
257
|
-
|
|
278
|
+
ca_u_VALUE *p2 = ptr2;
|
|
258
279
|
if ( a1 == NULL ) {
|
|
259
280
|
rb_raise(rb_eRuntimeError, "[BUG] failed to cast fixlen -> object");
|
|
260
281
|
}
|
|
@@ -289,8 +310,8 @@ puts
|
|
|
289
310
|
static void
|
|
290
311
|
ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
|
|
291
312
|
{
|
|
292
|
-
#{ctype1} *p1 = ptr1;
|
|
293
|
-
#{ctype2} *p2 = ptr2;
|
|
313
|
+
#{utype[ctype1]} *p1 = ptr1;
|
|
314
|
+
#{utype[ctype2]} *p2 = ptr2;
|
|
294
315
|
#{ctype1} q;
|
|
295
316
|
if ( m ) {
|
|
296
317
|
while ( n-- ) {
|
|
@@ -300,7 +321,8 @@ puts
|
|
|
300
321
|
*p2 = q;
|
|
301
322
|
}
|
|
302
323
|
else {
|
|
303
|
-
rb_raise(rb_eRangeError, "out of range to cast to boolean (0 or 1)"
|
|
324
|
+
rb_raise(rb_eRangeError, "%s: out of range to cast to boolean (0 or 1)",
|
|
325
|
+
ca_calling_method_name());
|
|
304
326
|
}
|
|
305
327
|
}
|
|
306
328
|
p1++; p2++; m++;
|
|
@@ -313,7 +335,8 @@ puts
|
|
|
313
335
|
*p2 = q;
|
|
314
336
|
}
|
|
315
337
|
else {
|
|
316
|
-
rb_raise(rb_eRangeError, "out of range to cast to boolean (0 or 1)"
|
|
338
|
+
rb_raise(rb_eRangeError, "%s: out of range to cast to boolean (0 or 1)",
|
|
339
|
+
ca_calling_method_name());
|
|
317
340
|
}
|
|
318
341
|
p1++; p2++;
|
|
319
342
|
}
|
|
@@ -332,15 +355,54 @@ puts
|
|
|
332
355
|
ctype1 = ctype[type1]
|
|
333
356
|
ctype2 = ctype[type2]
|
|
334
357
|
CA_CAST_TABLE[type1][type2] = "ca_cast_#{ctype1}_#{ctype2}"
|
|
335
|
-
|
|
358
|
+
# float / complex -> integer: a NaN, an infinity, or a value whose
|
|
359
|
+
# integer part the type cannot hold has no integer, and C leaves its
|
|
360
|
+
# conversion undefined (x86 gives the type's minimum, ARM saturates). A
|
|
361
|
+
# cell that is not masked refuses it before anything is written.
|
|
362
|
+
# #to_type masks such cells first (UNDEF), so only a store, a view and a
|
|
363
|
+
# single cell reach the raise. The range is the open interval of values
|
|
364
|
+
# that truncate into the type, in double; for int64 the lower end is
|
|
365
|
+
# taken as closed, since -2**63-1 rounds to -2**63 in double.
|
|
366
|
+
nan_check = ""
|
|
367
|
+
if (FLOAT+[CA_CMPLX64, CA_CMPLX128]).include?(type1) && INTEGER.include?(type2)
|
|
368
|
+
complex = [CA_CMPLX64, CA_CMPLX128].include?(type1)
|
|
369
|
+
real = complex ? "creal(q1[k])" : "q1[k]"
|
|
370
|
+
lo, hi = INTEGER_TRUNC_RANGE[type2]
|
|
371
|
+
lo_cmp = ( type2 == CA_INT64 ) ? ">=" : ">"
|
|
372
|
+
fits = "( v #{lo_cmp} #{lo} && v < #{hi} )"
|
|
373
|
+
fits = "( #{fits} && ! isnan(cimag(q1[k])) )" if complex
|
|
374
|
+
nan_check = <<-END_CHECK.gsub(/^ {6}/, '')
|
|
375
|
+
for (k=0; k<n; k++) {
|
|
376
|
+
double v = (double) #{real};
|
|
377
|
+
if ( ( ! m || ! m[k] ) && ! #{fits} ) {
|
|
378
|
+
if ( isfinite(v)#{complex ? " && ! isnan(cimag(q1[k]))" : ""} ) {
|
|
379
|
+
rb_raise(rb_eRangeError, "%s: %.17g is out of range for %s",
|
|
380
|
+
ca_calling_method_name(), v, ca_type_name[#{type_const[type2]}]);
|
|
381
|
+
}
|
|
382
|
+
rb_raise(rb_eFloatDomainError, "%s: %s cannot be converted to %s",
|
|
383
|
+
ca_calling_method_name(), isinf(v) ? "an infinity" : "NaN",
|
|
384
|
+
ca_type_name[#{type_const[type2]}]);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
END_CHECK
|
|
388
|
+
end
|
|
389
|
+
# int64 / uint64 -> float32 / cmplx64 goes through double, as a Ruby
|
|
390
|
+
# Integer stored into a float32 cell does (Integer#to_f). Converting in
|
|
391
|
+
# one step rounds once where the compiler keeps the loop scalar and twice
|
|
392
|
+
# where it vectorises it through double, so the answer for a value past
|
|
393
|
+
# 2**53 would depend on its place in the array.
|
|
394
|
+
via = ( [CA_INT64, CA_UINT64].include?(type1) &&
|
|
395
|
+
[CA_FLOAT32, CA_CMPLX64].include?(type2) ) ? "(double) " : ""
|
|
396
|
+
puts <<-END_DEF.gsub(/^ {6}/, '').sub("@@NAN_CHECK@@\n", nan_check).gsub("@@VIA@@", via)
|
|
336
397
|
static void
|
|
337
398
|
ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
|
|
338
399
|
{
|
|
339
|
-
#{ctype1} *q1 = ptr1;
|
|
340
|
-
#{ctype1} *p1 = q1;
|
|
341
|
-
#{ctype2} *q2 = ptr2;
|
|
342
|
-
#{ctype2} *p2 = q2;
|
|
400
|
+
#{utype[ctype1]} *q1 = ptr1;
|
|
401
|
+
#{utype[ctype1]} *p1 = q1;
|
|
402
|
+
#{utype[ctype2]} *q2 = ptr2;
|
|
403
|
+
#{utype[ctype2]} *p2 = q2;
|
|
343
404
|
ca_size_t k;
|
|
405
|
+
@@NAN_CHECK@@
|
|
344
406
|
if ( m ) {
|
|
345
407
|
boolean8_t *pm = m;
|
|
346
408
|
for (k=0; k<n; k++) {
|
|
@@ -348,7 +410,7 @@ puts
|
|
|
348
410
|
if ( ! *pm ) {
|
|
349
411
|
p1 = q1 + k;
|
|
350
412
|
p2 = q2 + k;
|
|
351
|
-
*p2 = (#{ctype2})
|
|
413
|
+
*p2 = (#{ctype2}) @@VIA@@*p1;
|
|
352
414
|
}
|
|
353
415
|
}
|
|
354
416
|
}
|
|
@@ -356,7 +418,7 @@ puts
|
|
|
356
418
|
for (k=0; k<n; k++) {
|
|
357
419
|
p1 = q1 + k;
|
|
358
420
|
p2 = q2 + k;
|
|
359
|
-
*p2 = (#{ctype2})
|
|
421
|
+
*p2 = (#{ctype2}) @@VIA@@*p1;
|
|
360
422
|
}
|
|
361
423
|
}
|
|
362
424
|
return;
|
|
@@ -380,8 +442,8 @@ puts
|
|
|
380
442
|
static void
|
|
381
443
|
ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
|
|
382
444
|
{
|
|
383
|
-
#{ctype1} *p1 = ptr1;
|
|
384
|
-
|
|
445
|
+
#{utype[ctype1]} *p1 = ptr1;
|
|
446
|
+
ca_u_VALUE *p2 = ptr2;
|
|
385
447
|
if ( m ) {
|
|
386
448
|
while ( n-- ) {
|
|
387
449
|
if ( !*m ) { *p2 = (VALUE) #{conv}(*p1); }
|
|
@@ -409,7 +471,7 @@ OBJECT.each do |type1|
|
|
|
409
471
|
static void
|
|
410
472
|
ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
|
|
411
473
|
{
|
|
412
|
-
|
|
474
|
+
ca_u_VALUE *p1 = ptr1;
|
|
413
475
|
char *p2 = ptr2;
|
|
414
476
|
ca_size_t bytes;
|
|
415
477
|
if ( a2 == NULL ) {
|
|
@@ -478,9 +540,17 @@ OBJECT.each do |type1|
|
|
|
478
540
|
read_ok = "( RB_TYPE_P(*p1, T_STRING) ? " \
|
|
479
541
|
"ca_decimal_string_to(*p1, #{type_name}, p2) : " \
|
|
480
542
|
"( #{conv_ok}(*p1, &tmp) ? ( *p2 = (#{ctype2}) tmp, 1 ) : 0 ) )"
|
|
543
|
+
# A store refuses an integer the cell cannot hold
|
|
544
|
+
# (ca_obj2integer_fitting); to_type, above, keeps the C conversion.
|
|
545
|
+
store_conv = if INTEGER.include?(type2)
|
|
546
|
+
num = [CA_UINT8, CA_UINT16, CA_UINT32, CA_UINT64].include?(type2) ? "rb_num2ull" : "NUM2LL"
|
|
547
|
+
"#{num}(ca_obj2integer_fitting(*p1, #{type_name}))"
|
|
548
|
+
else
|
|
549
|
+
"#{conv}(*p1)"
|
|
550
|
+
end
|
|
481
551
|
read = "if ( RB_TYPE_P(*p1, T_STRING) ) { " \
|
|
482
552
|
"ca_decimal_string_store(*p1, #{type_name}, p2); } " \
|
|
483
|
-
"else { *p2 = (#{ctype2}) #{
|
|
553
|
+
"else { *p2 = (#{ctype2}) #{store_conv}; }"
|
|
484
554
|
else
|
|
485
555
|
read_ok = "( #{conv_ok}(*p1, &tmp) ? ( *p2 = (#{ctype2}) tmp, 1 ) : 0 )"
|
|
486
556
|
read = "*p2 = (#{ctype2}) #{conv}(*p1);"
|
|
@@ -489,8 +559,8 @@ OBJECT.each do |type1|
|
|
|
489
559
|
static void
|
|
490
560
|
ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
|
|
491
561
|
{
|
|
492
|
-
|
|
493
|
-
#{ctype2} *p2 = ptr2;
|
|
562
|
+
ca_u_VALUE *p1 = ptr1;
|
|
563
|
+
#{utype[ctype2]} *p2 = ptr2;
|
|
494
564
|
#{oktype2} tmp;
|
|
495
565
|
if ( m ) {
|
|
496
566
|
while ( n-- ) {
|
|
@@ -517,8 +587,8 @@ OBJECT.each do |type1|
|
|
|
517
587
|
static void
|
|
518
588
|
ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
|
|
519
589
|
{
|
|
520
|
-
|
|
521
|
-
#{ctype2} *p2 = ptr2;
|
|
590
|
+
ca_u_VALUE *p1 = ptr1;
|
|
591
|
+
#{utype[ctype2]} *p2 = ptr2;
|
|
522
592
|
if ( m ) {
|
|
523
593
|
while ( n-- ) {
|
|
524
594
|
if ( !*m ) { *p2 = (#{ctype2}) #{conv}(*p1); }
|
data/ext/carray_class.c
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
---------------------------------------------------------------------------- */
|
|
7
7
|
|
|
8
8
|
#include "carray.h"
|
|
9
|
+
#include "carray_internal.h" /* CA_CHECK_*_GIVEN */
|
|
9
10
|
|
|
10
11
|
/* ------------------------------------------------------------------- */
|
|
11
12
|
/* Symbol cache for data_type code → Symbol lookup.
|
|
@@ -25,7 +26,7 @@ ID ca_data_type_sym[CA_NTYPE];
|
|
|
25
26
|
VALUE
|
|
26
27
|
rb_ca_data_type_to_sym (int8_t data_type)
|
|
27
28
|
{
|
|
28
|
-
|
|
29
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type);
|
|
29
30
|
return ID2SYM(ca_data_type_sym[data_type]);
|
|
30
31
|
}
|
|
31
32
|
|
|
@@ -69,7 +70,7 @@ static VALUE
|
|
|
69
70
|
rb_ca_s_data_type_name (VALUE klass, VALUE type)
|
|
70
71
|
{
|
|
71
72
|
int8_t data_type = rb_ca_guess_type(type);
|
|
72
|
-
|
|
73
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type);
|
|
73
74
|
return rb_str_new2(ca_type_name[data_type]);
|
|
74
75
|
}
|
|
75
76
|
|
|
@@ -84,7 +85,7 @@ static VALUE
|
|
|
84
85
|
rb_ca_s_data_type_code (VALUE klass, VALUE type)
|
|
85
86
|
{
|
|
86
87
|
int8_t data_type = rb_ca_guess_type(type);
|
|
87
|
-
|
|
88
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type);
|
|
88
89
|
return INT2NUM(data_type);
|
|
89
90
|
}
|
|
90
91
|
|
data/ext/carray_config.h
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#ifndef CARRAY_CONFIG_H
|
|
2
|
+
#define CARRAY_CONFIG_H
|
|
3
|
+
#define HAVE_SYS_TYPES_H 1
|
|
4
|
+
#define HAVE_STDINT_H 1
|
|
5
|
+
#define HAVE_TYPE_INT8_T 1
|
|
6
|
+
#define HAVE_TYPE_UINT8_T 1
|
|
7
|
+
#define HAVE_TYPE_INT16_T 1
|
|
8
|
+
#define HAVE_TYPE_UINT16_T 1
|
|
9
|
+
#define HAVE_TYPE_INT32_T 1
|
|
10
|
+
#define HAVE_TYPE_UINT32_T 1
|
|
11
|
+
#define HAVE_TYPE_INT64_T 1
|
|
12
|
+
#define HAVE_TYPE_UINT64_T 1
|
|
13
|
+
#define HAVE_TYPE_LONG_LONG 1
|
|
14
|
+
#define HAVE_TYPE_FLOAT 1
|
|
15
|
+
#define HAVE_TYPE_DOUBLE 1
|
|
16
|
+
#define HAVE_COMPLEX_H 1
|
|
17
|
+
#define HAVE_TYPE_FLOAT_COMPLEX 1
|
|
18
|
+
#define HAVE_TYPE_DOUBLE_COMPLEX 1
|
|
19
|
+
#define HAVE_TGMATH_H 1
|
|
20
|
+
#define HAVE_ATAN2 1
|
|
21
|
+
#define HAVE_HYPOT 1
|
|
22
|
+
#define HAVE_LGAMMA 1
|
|
23
|
+
#define HAVE_EXPM1 1
|
|
24
|
+
#define HAVE_MERGESORT 1
|
|
25
|
+
#define HAVE_STRPTIME 1
|
|
26
|
+
#define HAVE_RB_ARITHMETIC_SEQUENCE_EXTRACT 1
|
|
27
|
+
#define HAVE_RUBY_MEMORY_VIEW_H 1
|
|
28
|
+
#endif
|
data/ext/carray_conversion.c
CHANGED
|
@@ -30,14 +30,14 @@
|
|
|
30
30
|
/* Leaf macro: data type-specialized inner loop. Produces `n` VALUE objects
|
|
31
31
|
from a contig ptr base + element width, storing into `dst` (Ruby Array). */
|
|
32
32
|
#define TO_A_LEAF_LOOP(T, TO_VALUE) do { \
|
|
33
|
-
const T *src = (const T *) base; \
|
|
33
|
+
const CA_U(T) *src = (const CA_U(T) *) base; \
|
|
34
34
|
for (li = 0; li < n; li++) { \
|
|
35
35
|
rb_ary_store(dst, li, TO_VALUE(src[li])); \
|
|
36
36
|
} \
|
|
37
37
|
} while (0)
|
|
38
38
|
|
|
39
39
|
#define TO_A_LEAF_LOOP_MASKED(T, TO_VALUE) do { \
|
|
40
|
-
const T *src = (const T *) base; \
|
|
40
|
+
const CA_U(T) *src = (const CA_U(T) *) base; \
|
|
41
41
|
for (li = 0; li < n; li++) { \
|
|
42
42
|
rb_ary_store(dst, li, mask[li] ? CA_UNDEF : TO_VALUE(src[li])); \
|
|
43
43
|
} \
|
|
@@ -480,10 +480,16 @@ rb_ca_load_binary (VALUE self, VALUE io)
|
|
|
480
480
|
case T_STRING:
|
|
481
481
|
if ( ca_length(ca) != RSTRING_LEN(io) ) {
|
|
482
482
|
rb_raise(rb_eArgError,
|
|
483
|
-
"data size mismatch (got %" PRId64 " bytes, expected %" PRId64 ")",
|
|
484
|
-
(ca_size_t) RSTRING_LEN(io), (ca_size_t) ca_length(ca));
|
|
483
|
+
"%s: data size mismatch (got %" PRId64 " bytes, expected %" PRId64 ")",
|
|
484
|
+
ca_calling_method_name(), (ca_size_t) RSTRING_LEN(io), (ca_size_t) ca_length(ca));
|
|
485
|
+
}
|
|
486
|
+
if ( ca->data_type == CA_BOOLEAN ) {
|
|
487
|
+
io = rb_str_dup(io);
|
|
488
|
+
rb_str_modify(io);
|
|
489
|
+
ca_boolean_normalize_bytes(RSTRING_PTR(io), ca->elements);
|
|
485
490
|
}
|
|
486
491
|
ca_sync_data(ca, RSTRING_PTR(io));
|
|
492
|
+
RB_GC_GUARD(io);
|
|
487
493
|
return self;
|
|
488
494
|
break;
|
|
489
495
|
default:
|
|
@@ -511,6 +517,9 @@ rb_ca_load_binary (VALUE self, VALUE io)
|
|
|
511
517
|
memcpy(ca->ptr + off, RSTRING_PTR(r), want);
|
|
512
518
|
off += want;
|
|
513
519
|
}
|
|
520
|
+
if ( ca->data_type == CA_BOOLEAN ) {
|
|
521
|
+
ca_boolean_normalize_bytes(ca->ptr, ca->elements);
|
|
522
|
+
}
|
|
514
523
|
ca_sync_detach(ca);
|
|
515
524
|
}
|
|
516
525
|
else {
|
|
@@ -540,7 +549,7 @@ rb_ca_load_binary (VALUE self, VALUE io)
|
|
|
540
549
|
to float. Its digits are those of the decimal (at most 9, which a double
|
|
541
550
|
holds), so Float#to_s writes them. */
|
|
542
551
|
static double
|
|
543
|
-
|
|
552
|
+
ca_double_of_shortest_decimal_of_float32 (float x)
|
|
544
553
|
{
|
|
545
554
|
char buf[32];
|
|
546
555
|
int lo = 1, hi = 9;
|
|
@@ -576,7 +585,7 @@ ca_float32_shortest (float x)
|
|
|
576
585
|
double its shortest decimal reads as, for to_csv to write that decimal.
|
|
577
586
|
The mask is kept. */
|
|
578
587
|
static VALUE
|
|
579
|
-
|
|
588
|
+
rb_ca_widen_keeping_shortest_decimal (VALUE self)
|
|
580
589
|
{
|
|
581
590
|
volatile VALUE out, holder = 0;
|
|
582
591
|
CArray *ca, *co;
|
|
@@ -591,7 +600,7 @@ rb_ca_shortest_float64 (VALUE self)
|
|
|
591
600
|
type = CA_CMPLX128;
|
|
592
601
|
}
|
|
593
602
|
else {
|
|
594
|
-
rb_raise(rb_eCADataTypeError, "
|
|
603
|
+
rb_raise(rb_eCADataTypeError, "__widen_keeping_shortest_decimal__ takes float32 or cmplx64");
|
|
595
604
|
}
|
|
596
605
|
n = ca->elements * (ca->data_type == CA_CMPLX64 ? 2 : 1);
|
|
597
606
|
out = rb_carray_new_safe(type, ca->ndim, ca->dim, 0, NULL);
|
|
@@ -601,7 +610,7 @@ rb_ca_shortest_float64 (VALUE self)
|
|
|
601
610
|
double *dst = (double *) co->ptr;
|
|
602
611
|
ca_copy_data(ca, (char *) src);
|
|
603
612
|
for (i = 0; i < n; i++) {
|
|
604
|
-
dst[i] =
|
|
613
|
+
dst[i] = ca_double_of_shortest_decimal_of_float32(src[i]);
|
|
605
614
|
}
|
|
606
615
|
ALLOCV_END(holder);
|
|
607
616
|
}
|
|
@@ -627,7 +636,7 @@ Init_carray_conversion (void)
|
|
|
627
636
|
rb_define_method(rb_cCArray, "dump_binary", rb_ca_dump_binary, -1);
|
|
628
637
|
rb_define_method(rb_cCArray, "to_s", rb_ca_to_s, 0);
|
|
629
638
|
rb_define_method(rb_cCArray, "load_binary", rb_ca_load_binary, 1);
|
|
630
|
-
rb_define_method(rb_cCArray, "
|
|
639
|
+
rb_define_method(rb_cCArray, "__widen_keeping_shortest_decimal__", rb_ca_widen_keeping_shortest_decimal, 0);
|
|
631
640
|
|
|
632
641
|
/* CAREFUL: do not bind #to_ary — implicit array coercion in Ruby core
|
|
633
642
|
(splat / multiple assignment / Array()) then triggers on any CArray
|
data/ext/carray_copy.c
CHANGED
|
@@ -36,6 +36,42 @@ ca_fill_or_free (CArray *co, VALUE (*fill)(VALUE), VALUE arg)
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
void
|
|
40
|
+
ca_fill_or_xfree (void *buf, VALUE (*fill)(VALUE), VALUE arg)
|
|
41
|
+
{
|
|
42
|
+
int tag = 0;
|
|
43
|
+
rb_protect(fill, arg, &tag);
|
|
44
|
+
if ( tag ) {
|
|
45
|
+
xfree(buf);
|
|
46
|
+
rb_jump_tag(tag);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
void
|
|
51
|
+
ca_fill_or_detach (int n, CArray **list, VALUE (*fill)(VALUE), VALUE arg)
|
|
52
|
+
{
|
|
53
|
+
int tag = 0;
|
|
54
|
+
int k;
|
|
55
|
+
rb_protect(fill, arg, &tag);
|
|
56
|
+
if ( tag ) {
|
|
57
|
+
for ( k = 0; k < n; k++ ) {
|
|
58
|
+
ca_detach(list[k]);
|
|
59
|
+
}
|
|
60
|
+
rb_jump_tag(tag);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
VALUE
|
|
65
|
+
ca_view_inherit_mask (VALUE view)
|
|
66
|
+
{
|
|
67
|
+
CArray *ca = (CArray *) view;
|
|
68
|
+
CArray *parent = ((CAView *) ca)->parent;
|
|
69
|
+
if ( parent && ca_has_mask(parent) ) {
|
|
70
|
+
ca_create_mask(ca);
|
|
71
|
+
}
|
|
72
|
+
return Qnil;
|
|
73
|
+
}
|
|
74
|
+
|
|
39
75
|
static VALUE
|
|
40
76
|
ca_copy_fill (VALUE arg)
|
|
41
77
|
{
|
|
@@ -173,7 +209,7 @@ rb_ca_to_ca (int argc, VALUE *argv, VALUE self)
|
|
|
173
209
|
CArray *ca;
|
|
174
210
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
175
211
|
if ( ca_is_readonly(ca) ) {
|
|
176
|
-
|
|
212
|
+
ca_refuse_read_only();
|
|
177
213
|
}
|
|
178
214
|
}
|
|
179
215
|
return self;
|
|
@@ -220,7 +256,7 @@ CArray *
|
|
|
220
256
|
ca_template_safe2 (void *ap, int8_t data_type, ca_size_t bytes)
|
|
221
257
|
{
|
|
222
258
|
CArray *ca = (CArray *) ap;
|
|
223
|
-
|
|
259
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type);
|
|
224
260
|
if ( ca_is_scalar(ca) ) {
|
|
225
261
|
return (CArray*) cscalar_new(data_type, bytes, NULL);
|
|
226
262
|
}
|
|
@@ -261,6 +297,19 @@ rb_ca_template_kw (int argc, VALUE *argv, VALUE ropt, VALUE self)
|
|
|
261
297
|
obj = ca_wrap_struct(co);
|
|
262
298
|
}
|
|
263
299
|
|
|
300
|
+
/* Preserve the Face identity only for a same-type template (no explicit
|
|
301
|
+
* retype). A retype (template(:boolean)) is a different-typed buffer and
|
|
302
|
+
* must not be re-wrapped as the Face. A same-type template of a Face with
|
|
303
|
+
* a valid blank form (CARecord carries its data_class through the struct
|
|
304
|
+
* tail; identity Faces alias same-type storage) is lifted so the class is
|
|
305
|
+
* preserved. A Face with no valid blank form (CAConstString's content-
|
|
306
|
+
* defined offset+buffer) overrides `template` in Ruby to return a plain
|
|
307
|
+
* array instead of a broken same-class shell. The lift comes before the
|
|
308
|
+
* block initialiser so its values are stored through the Face. */
|
|
309
|
+
if ( NIL_P(rtype) ) {
|
|
310
|
+
CA_FACE_LIFT_IF_FACE(obj, self, ca);
|
|
311
|
+
}
|
|
312
|
+
|
|
264
313
|
if ( rb_block_given_p() ) {
|
|
265
314
|
if ( rb_proc_arity(rb_block_proc()) == 0 ) {
|
|
266
315
|
volatile VALUE rval = rb_yield_values2(0, NULL);
|
|
@@ -283,18 +332,6 @@ rb_ca_template_kw (int argc, VALUE *argv, VALUE ropt, VALUE self)
|
|
|
283
332
|
}
|
|
284
333
|
}
|
|
285
334
|
|
|
286
|
-
/* Preserve the Face identity only for a same-type template (no explicit
|
|
287
|
-
* retype). A retype (template(:boolean)) is a different-typed buffer and
|
|
288
|
-
* must not be re-wrapped as the Face. A same-type template of a Face with
|
|
289
|
-
* a valid blank form (CARecord carries its data_class through the struct
|
|
290
|
-
* tail; identity Faces alias same-type storage) is lifted so the class is
|
|
291
|
-
* preserved. A Face with no valid blank form (CAConstString's content-
|
|
292
|
-
* defined offset+buffer) overrides `template` in Ruby to return a plain
|
|
293
|
-
* array instead of a broken same-class shell. */
|
|
294
|
-
if ( NIL_P(rtype) ) {
|
|
295
|
-
CA_FACE_LIFT_IF_FACE(obj, self, ca);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
335
|
return obj;
|
|
299
336
|
}
|
|
300
337
|
|