carray 3.0.0 → 3.0.1
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/.yardopts +2 -1
- data/CHANGELOG.md +325 -3
- data/{NEWS.md → CHANGELOG.v1.md} +1 -1
- data/README.md +32 -32
- data/carray.gemspec +12 -8
- data/ext/ca_axis_group.c +55 -19
- data/ext/ca_binop_dispatch.c +5 -6
- data/ext/ca_binop_dispatch.h +0 -7
- data/ext/ca_categorical_iterator.c +13 -13
- data/ext/ca_for_each_element.h +6 -8
- data/ext/ca_group_iter.c +1 -1
- data/ext/ca_kernel_iterator.c +69 -23
- data/ext/ca_kernel_iterator.h +3 -10
- data/ext/ca_obj_bincmp.c +57 -27
- data/ext/ca_obj_binop.c +86 -30
- data/ext/ca_obj_const_string.c +3 -1
- data/ext/ca_obj_face.c +80 -0
- data/ext/ca_obj_face.h +33 -1
- data/ext/ca_obj_fake.c +11 -0
- data/ext/ca_obj_fixlen_string.c +3 -1
- data/ext/ca_obj_grid.c +11 -3
- data/ext/ca_obj_meld.c +13 -8
- data/ext/ca_obj_moncmp.c +33 -14
- data/ext/ca_obj_monop.c +19 -7
- data/ext/ca_obj_object.c +99 -4
- data/ext/ca_obj_record.c +3 -1
- data/ext/ca_obj_refer.c +30 -6
- data/ext/ca_obj_roll.c +13 -5
- data/ext/ca_obj_select_axis.c +16 -6
- data/ext/ca_obj_shift.c +3 -3
- data/ext/ca_obj_stride.c +106 -23
- data/ext/ca_obj_string.c +3 -1
- data/ext/ca_obj_tile.c +13 -5
- data/ext/ca_obj_time.c +3 -1
- data/ext/ca_obj_timedelta.c +3 -1
- data/ext/ca_obj_transpose.c +1 -1
- data/ext/ca_obj_triop.c +62 -23
- data/ext/ca_obj_window.c +86 -17
- data/ext/ca_op_cmplx64.h +123 -0
- data/ext/ca_op_ipower.c +0 -3
- data/ext/ca_sort_kernels.h +5 -5
- data/ext/ca_sweep_engine.c +78 -35
- data/ext/ca_sweep_engine.h +13 -4
- data/ext/ca_transform_common.c +7 -0
- data/ext/carray.h +127 -130
- data/ext/carray_access.c +56 -34
- data/ext/carray_bincount.c +8 -8
- data/ext/carray_broadcast.c +99 -6
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +1491 -0
- data/ext/carray_call_cfunc.h +153 -0
- data/ext/carray_cast.c +69 -31
- data/ext/carray_conversion.c +22 -22
- data/ext/carray_copy.c +12 -2
- data/ext/carray_core.c +57 -10
- data/ext/carray_count.c +1 -1
- data/ext/carray_element.c +7 -7
- data/ext/carray_factorize.c +28 -28
- data/ext/carray_hold.c +1 -1
- data/ext/carray_index_classifier.c +7 -21
- data/ext/carray_internal.h +19 -3
- data/ext/carray_kernels_bincmp.c +1 -0
- data/ext/carray_kernels_binop.c +320 -298
- data/ext/carray_kernels_init.c +1095 -0
- data/ext/carray_kernels_map.c +1 -0
- data/ext/carray_kernels_moncmp.c +1 -0
- data/ext/carray_kernels_monop.c +412 -411
- data/ext/carray_kernels_reduce_aggregate.c +88 -87
- data/ext/carray_kernels_reduce_boolean.c +1 -0
- data/ext/carray_kernels_reduce_cumulative.c +54 -53
- data/ext/carray_kernels_reduce_extreme.c +51 -50
- data/ext/carray_kernels_reduce_variance.c +1 -0
- data/ext/carray_kernels_scan.c +1 -0
- data/ext/carray_kernels_search.c +93 -92
- data/ext/carray_kernels_sort.c +1 -0
- data/ext/carray_kernels_triop.c +1 -0
- data/ext/carray_lazy.c +175 -5
- data/ext/carray_mask.c +6 -5
- data/ext/carray_median_percentile.c +1 -1
- data/ext/carray_memory_view.c +46 -21
- data/ext/carray_operator.c +46 -49
- data/ext/carray_partition.c +4 -4
- data/ext/carray_random.c +7 -7
- data/ext/carray_scatter.c +1 -1
- data/ext/carray_sort.c +3 -3
- data/ext/carray_sort_kernel.c +10 -10
- data/ext/carray_test.c +1 -1
- data/ext/extconf.rb +18 -0
- data/ext/mk_call_cfunc.rb +243 -52
- data/ext/mkkernel.rb +354 -100
- data/ext/ruby_carray.c +18 -16
- data/ext/version.h +4 -4
- data/lib/carray/autoload_carray.rb +19 -0
- data/lib/carray/autoload_method_extension.rb +2 -1
- data/lib/carray/axis_group.rb +7 -7
- data/lib/carray/basics.rb +59 -59
- data/lib/carray/bincount_nd.rb +12 -12
- data/lib/carray/block_iterator.rb +24 -14
- data/lib/carray/categorical.rb +4 -4
- data/lib/carray/categorical_iterator.rb +98 -76
- data/lib/carray/conditional.rb +14 -14
- data/lib/carray/construct.rb +21 -0
- data/lib/carray/core_extensions.rb +62 -5
- data/lib/carray/data_type_extension.rb +18 -1
- data/lib/carray/frame/concat.rb +3 -3
- data/lib/carray/frame/convert.rb +1 -1
- data/lib/carray/frame/frame.rb +4 -11
- data/lib/carray/frame/io.rb +159 -2
- data/lib/carray/frame/sort.rb +1 -1
- data/lib/carray/frame/verbs.rb +18 -1
- data/lib/carray/fuse_source.rb +123 -0
- data/lib/carray/fusion.rb +218 -0
- data/lib/carray/histogram.rb +16 -16
- data/lib/carray/inspect.rb +1 -7
- data/lib/carray/iterator.rb +4 -3
- data/lib/carray/lazy.rb +125 -73
- data/lib/carray/meld_reduce.rb +2 -2
- data/lib/carray/methods/align_addr.rb +1 -1
- data/lib/carray/methods/composition.rb +1 -1
- data/lib/carray/methods/is_in.rb +12 -12
- data/lib/carray/methods/locate_addr.rb +6 -1
- data/lib/carray/methods/mask_duplicates.rb +1 -1
- data/lib/carray/methods/meshgrid.rb +4 -5
- data/lib/carray/methods/mode.rb +2 -2
- data/lib/carray/methods/nunique.rb +1 -1
- data/lib/carray/methods/snap.rb +7 -2
- data/lib/carray/methods/unique.rb +3 -3
- data/lib/carray/methods/value_counts.rb +2 -2
- data/lib/carray/runtime.rb +0 -19
- data/lib/carray/slab_iterator.rb +20 -7
- data/lib/carray/string_operation_extension.rb +5 -5
- data/lib/carray/time.rb +890 -491
- data/lib/carray/window_iterator.rb +285 -13
- data/lib/carray.rb +5 -5
- data/yard-stubs/ca_obj_array.rb +385 -0
- data/yard-stubs/ca_obj_bitarray.rb +38 -0
- data/yard-stubs/ca_obj_bitfield.rb +43 -0
- data/yard-stubs/ca_obj_block.rb +73 -0
- data/yard-stubs/ca_obj_byte_swap.rb +56 -0
- data/yard-stubs/ca_obj_fake.rb +31 -0
- data/yard-stubs/ca_obj_farray.rb +32 -0
- data/yard-stubs/ca_obj_field.rb +45 -0
- data/yard-stubs/ca_obj_grid.rb +35 -0
- data/yard-stubs/ca_obj_refer.rb +72 -0
- data/yard-stubs/ca_obj_roll.rb +45 -0
- data/yard-stubs/ca_obj_shift.rb +43 -0
- data/yard-stubs/ca_obj_stride.rb +181 -0
- data/yard-stubs/ca_obj_tile.rb +29 -0
- data/yard-stubs/ca_obj_transpose.rb +40 -0
- data/yard-stubs/ca_obj_window.rb +49 -0
- data/yard-stubs/carray_access.rb +131 -0
- data/yard-stubs/carray_attribute.rb +246 -0
- data/yard-stubs/carray_broadcast.rb +37 -0
- data/yard-stubs/carray_cast.rb +489 -0
- data/yard-stubs/carray_class.rb +65 -0
- data/yard-stubs/carray_conversion.rb +76 -0
- data/yard-stubs/carray_copy.rb +79 -0
- data/yard-stubs/carray_core.rb +114 -0
- data/yard-stubs/carray_count.rb +79 -0
- data/yard-stubs/carray_element.rb +108 -0
- data/yard-stubs/carray_generate.rb +66 -0
- data/yard-stubs/carray_lazy.rb +23 -0
- data/yard-stubs/carray_loop.rb +140 -0
- data/yard-stubs/carray_mask.rb +259 -0
- data/yard-stubs/carray_math.rb +132 -0
- data/yard-stubs/carray_mathfunc.rb +45 -0
- data/yard-stubs/carray_median_percentile.rb +89 -0
- data/yard-stubs/carray_memory_view.rb +163 -0
- data/yard-stubs/carray_order.rb +312 -0
- data/yard-stubs/carray_random.rb +89 -0
- data/yard-stubs/carray_scatter.rb +106 -0
- data/yard-stubs/carray_slab.rb +57 -0
- data/yard-stubs/carray_sort.rb +163 -0
- data/yard-stubs/carray_test.rb +85 -0
- data/yard-stubs/carray_undef.rb +64 -0
- data/yard-stubs/carray_utils.rb +97 -0
- data/yard-stubs/ruby_carray.rb +193 -0
- metadata +59 -10
- data/ext/ca_obj_unbound_repeat.c +0 -496
data/ext/carray_operator.c
CHANGED
|
@@ -12,6 +12,22 @@
|
|
|
12
12
|
|
|
13
13
|
#include "carray.h"
|
|
14
14
|
#include "carray_internal.h" /* ca_lazy_arena_* */
|
|
15
|
+
|
|
16
|
+
/* Operand scratch for a chunked / gathered kernel run.
|
|
17
|
+
|
|
18
|
+
For CA_OBJECT the scratch holds VALUEs, and an object-lane kernel
|
|
19
|
+
calls rb_funcall per cell -- a collection in the middle would free
|
|
20
|
+
whatever the gather pulled in from a lazy operand, since those cells
|
|
21
|
+
exist nowhere else. The object form of the arena acquire keeps the
|
|
22
|
+
slot marked until it is released. */
|
|
23
|
+
static void *
|
|
24
|
+
ca_op_acquire_operand_scratch (CArray *ca, ca_size_t n_elements)
|
|
25
|
+
{
|
|
26
|
+
return ( ca->data_type == CA_OBJECT )
|
|
27
|
+
? ca_lazy_arena_acquire_object(n_elements)
|
|
28
|
+
: ca_lazy_arena_acquire(n_elements * ca->bytes);
|
|
29
|
+
}
|
|
30
|
+
|
|
15
31
|
#include "ca_obj_face.h" /* ca_face_reconcile_comparison (comparison Face gate) */
|
|
16
32
|
|
|
17
33
|
VALUE rb_mCAMath;
|
|
@@ -324,8 +340,6 @@ rb_ca_call_monop (VALUE self, ca_monop_func_t func[])
|
|
|
324
340
|
}
|
|
325
341
|
}
|
|
326
342
|
|
|
327
|
-
out = rb_ca_rewrap_unbound_repeat(self, out);
|
|
328
|
-
|
|
329
343
|
return out;
|
|
330
344
|
}
|
|
331
345
|
|
|
@@ -479,8 +493,6 @@ rb_ca_call_monop_typed (VALUE self, ca_monop_func_t func[],
|
|
|
479
493
|
}
|
|
480
494
|
}
|
|
481
495
|
|
|
482
|
-
out = rb_ca_rewrap_unbound_repeat(self, out);
|
|
483
|
-
|
|
484
496
|
return out;
|
|
485
497
|
}
|
|
486
498
|
|
|
@@ -543,7 +555,7 @@ kleene_gather_bool (CArray *ca, boolean8_t *vbuf, boolean8_t *mbuf, ca_size_t n)
|
|
|
543
555
|
undetermined cells (U|U, U&U, U|F, U&T) keep the blind mask. All other
|
|
544
556
|
cells were already correct from the value kernel.
|
|
545
557
|
|
|
546
|
-
Gate: boolean
|
|
558
|
+
Gate: boolean data type + output has a mask (else no-op -- the hot path is
|
|
547
559
|
untouched, integer bitwise stays blind). `out` is a fresh entity, so
|
|
548
560
|
out->ptr / out->mask->ptr are writable without attach. */
|
|
549
561
|
VALUE
|
|
@@ -870,8 +882,6 @@ rb_ca_call_binop (volatile VALUE self, volatile VALUE other,
|
|
|
870
882
|
}
|
|
871
883
|
}
|
|
872
884
|
|
|
873
|
-
out = rb_ca_rewrap_unbound_repeat(self, out);
|
|
874
|
-
out = rb_ca_rewrap_unbound_repeat(other, out);
|
|
875
885
|
return out;
|
|
876
886
|
}
|
|
877
887
|
/* else fall through to the use_chunked / ALLOCV path */
|
|
@@ -907,8 +917,6 @@ rb_ca_call_binop (volatile VALUE self, volatile VALUE other,
|
|
|
907
917
|
if ( a2 ) { ca_detach(ca2); } else { ALLOCV_END(h2); }
|
|
908
918
|
if ( a1 ) { ca_detach(ca1); } else { ALLOCV_END(h1); }
|
|
909
919
|
|
|
910
|
-
out = rb_ca_rewrap_unbound_repeat(self, out);
|
|
911
|
-
out = rb_ca_rewrap_unbound_repeat(other, out);
|
|
912
920
|
return out;
|
|
913
921
|
}
|
|
914
922
|
|
|
@@ -936,7 +944,7 @@ rb_ca_call_binop (volatile VALUE self, volatile VALUE other,
|
|
|
936
944
|
p1_src = (char *) ca1->ptr;
|
|
937
945
|
attached1 = 1;
|
|
938
946
|
} else {
|
|
939
|
-
s1_arena =
|
|
947
|
+
s1_arena = ca_op_acquire_operand_scratch(ca1, 1);
|
|
940
948
|
ca_xfer_all(ca1, s1_arena, CA_XFER_GET);
|
|
941
949
|
p1_src = (char *) s1_arena;
|
|
942
950
|
}
|
|
@@ -945,7 +953,7 @@ rb_ca_call_binop (volatile VALUE self, volatile VALUE other,
|
|
|
945
953
|
p1_src = (char *) ca1->ptr;
|
|
946
954
|
attached1 = 1;
|
|
947
955
|
} else {
|
|
948
|
-
s1_arena =
|
|
956
|
+
s1_arena = ca_op_acquire_operand_scratch(ca1, chunk_n);
|
|
949
957
|
p1_src = (char *) s1_arena;
|
|
950
958
|
gather_per_chunk1 = 1;
|
|
951
959
|
}
|
|
@@ -957,7 +965,7 @@ rb_ca_call_binop (volatile VALUE self, volatile VALUE other,
|
|
|
957
965
|
p2_src = (char *) ca2->ptr;
|
|
958
966
|
attached2 = 1;
|
|
959
967
|
} else {
|
|
960
|
-
s2_arena =
|
|
968
|
+
s2_arena = ca_op_acquire_operand_scratch(ca2, 1);
|
|
961
969
|
ca_xfer_all(ca2, s2_arena, CA_XFER_GET);
|
|
962
970
|
p2_src = (char *) s2_arena;
|
|
963
971
|
}
|
|
@@ -966,7 +974,7 @@ rb_ca_call_binop (volatile VALUE self, volatile VALUE other,
|
|
|
966
974
|
p2_src = (char *) ca2->ptr;
|
|
967
975
|
attached2 = 1;
|
|
968
976
|
} else {
|
|
969
|
-
s2_arena =
|
|
977
|
+
s2_arena = ca_op_acquire_operand_scratch(ca2, chunk_n);
|
|
970
978
|
p2_src = (char *) s2_arena;
|
|
971
979
|
gather_per_chunk2 = 1;
|
|
972
980
|
}
|
|
@@ -1005,10 +1013,6 @@ rb_ca_call_binop (volatile VALUE self, volatile VALUE other,
|
|
|
1005
1013
|
ca_lazy_arena_exit();
|
|
1006
1014
|
}
|
|
1007
1015
|
|
|
1008
|
-
out = rb_ca_rewrap_unbound_repeat(self, out);
|
|
1009
|
-
|
|
1010
|
-
out = rb_ca_rewrap_unbound_repeat(other, out);
|
|
1011
|
-
|
|
1012
1016
|
return out;
|
|
1013
1017
|
}
|
|
1014
1018
|
|
|
@@ -1035,13 +1039,13 @@ rb_ca_call_binop_bang (VALUE self, VALUE other, ca_binop_func_t func[])
|
|
|
1035
1039
|
self_is_scalar = RTEST(rb_obj_is_cscalar(self));
|
|
1036
1040
|
other_is_scalar = RTEST(rb_obj_is_cscalar(other));
|
|
1037
1041
|
|
|
1038
|
-
/*
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1042
|
+
/* self is the write target, so its shape is the result's by definition
|
|
1043
|
+
and the destination rule applies (the same one assignment uses), not
|
|
1044
|
+
the symmetric one a binary operation is held to. */
|
|
1045
|
+
if ( !self_is_scalar && !other_is_scalar ) {
|
|
1046
|
+
ca_broadcast_to_destination(self, &other);
|
|
1047
|
+
TypedData_Get_Struct(other, CArray, &carray_data_type, ca2);
|
|
1048
|
+
other_is_scalar = RTEST(rb_obj_is_cscalar(other));
|
|
1045
1049
|
}
|
|
1046
1050
|
if ( self_is_scalar && !other_is_scalar &&
|
|
1047
1051
|
ca1->elements != ca2->elements ) {
|
|
@@ -1291,14 +1295,14 @@ rb_ca_call_triop (VALUE self, VALUE other2, VALUE other3,
|
|
|
1291
1295
|
if ( ca_attach_is_alias(ca1) ) {
|
|
1292
1296
|
ca_attach(ca1); p1_src = (char *) ca1->ptr; att1 = 1;
|
|
1293
1297
|
} else {
|
|
1294
|
-
s1_arena =
|
|
1298
|
+
s1_arena = ca_op_acquire_operand_scratch(ca1, 1);
|
|
1295
1299
|
ca_xfer_all(ca1, s1_arena, CA_XFER_GET);
|
|
1296
1300
|
p1_src = (char *) s1_arena;
|
|
1297
1301
|
}
|
|
1298
1302
|
} else if ( ca_attach_is_alias(ca1) ) {
|
|
1299
1303
|
ca_attach(ca1); p1_src = (char *) ca1->ptr; att1 = 1;
|
|
1300
1304
|
} else {
|
|
1301
|
-
s1_arena =
|
|
1305
|
+
s1_arena = ca_op_acquire_operand_scratch(ca1, chunk_n);
|
|
1302
1306
|
p1_src = (char *) s1_arena; gpc1 = 1;
|
|
1303
1307
|
}
|
|
1304
1308
|
/* ca2 acquire (mirror) */
|
|
@@ -1306,14 +1310,14 @@ rb_ca_call_triop (VALUE self, VALUE other2, VALUE other3,
|
|
|
1306
1310
|
if ( ca_attach_is_alias(ca2) ) {
|
|
1307
1311
|
ca_attach(ca2); p2_src = (char *) ca2->ptr; att2 = 1;
|
|
1308
1312
|
} else {
|
|
1309
|
-
s2_arena =
|
|
1313
|
+
s2_arena = ca_op_acquire_operand_scratch(ca2, 1);
|
|
1310
1314
|
ca_xfer_all(ca2, s2_arena, CA_XFER_GET);
|
|
1311
1315
|
p2_src = (char *) s2_arena;
|
|
1312
1316
|
}
|
|
1313
1317
|
} else if ( ca_attach_is_alias(ca2) ) {
|
|
1314
1318
|
ca_attach(ca2); p2_src = (char *) ca2->ptr; att2 = 1;
|
|
1315
1319
|
} else {
|
|
1316
|
-
s2_arena =
|
|
1320
|
+
s2_arena = ca_op_acquire_operand_scratch(ca2, chunk_n);
|
|
1317
1321
|
p2_src = (char *) s2_arena; gpc2 = 1;
|
|
1318
1322
|
}
|
|
1319
1323
|
/* ca3 acquire (mirror) */
|
|
@@ -1321,14 +1325,14 @@ rb_ca_call_triop (VALUE self, VALUE other2, VALUE other3,
|
|
|
1321
1325
|
if ( ca_attach_is_alias(ca3) ) {
|
|
1322
1326
|
ca_attach(ca3); p3_src = (char *) ca3->ptr; att3 = 1;
|
|
1323
1327
|
} else {
|
|
1324
|
-
s3_arena =
|
|
1328
|
+
s3_arena = ca_op_acquire_operand_scratch(ca3, 1);
|
|
1325
1329
|
ca_xfer_all(ca3, s3_arena, CA_XFER_GET);
|
|
1326
1330
|
p3_src = (char *) s3_arena;
|
|
1327
1331
|
}
|
|
1328
1332
|
} else if ( ca_attach_is_alias(ca3) ) {
|
|
1329
1333
|
ca_attach(ca3); p3_src = (char *) ca3->ptr; att3 = 1;
|
|
1330
1334
|
} else {
|
|
1331
|
-
s3_arena =
|
|
1335
|
+
s3_arena = ca_op_acquire_operand_scratch(ca3, chunk_n);
|
|
1332
1336
|
p3_src = (char *) s3_arena; gpc3 = 1;
|
|
1333
1337
|
}
|
|
1334
1338
|
|
|
@@ -1367,10 +1371,6 @@ rb_ca_call_triop (VALUE self, VALUE other2, VALUE other3,
|
|
|
1367
1371
|
}
|
|
1368
1372
|
}
|
|
1369
1373
|
|
|
1370
|
-
out = rb_ca_rewrap_unbound_repeat(self, out);
|
|
1371
|
-
out = rb_ca_rewrap_unbound_repeat(other2, out);
|
|
1372
|
-
out = rb_ca_rewrap_unbound_repeat(other3, out);
|
|
1373
|
-
|
|
1374
1374
|
return out;
|
|
1375
1375
|
}
|
|
1376
1376
|
|
|
@@ -1392,14 +1392,15 @@ rb_ca_call_triop_bang (VALUE self, VALUE other2, VALUE other3,
|
|
|
1392
1392
|
TypedData_Get_Struct(other2, CArray, &carray_data_type, ca2);
|
|
1393
1393
|
TypedData_Get_Struct(other3, CArray, &carray_data_type, ca3);
|
|
1394
1394
|
|
|
1395
|
-
/*
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1395
|
+
/* self is the write target, so the destination rule applies to each
|
|
1396
|
+
input operand in turn (the same one assignment uses). */
|
|
1397
|
+
if ( ! rb_obj_is_cscalar(other2) ) {
|
|
1398
|
+
ca_broadcast_to_destination(self, &other2);
|
|
1399
|
+
TypedData_Get_Struct(other2, CArray, &carray_data_type, ca2);
|
|
1399
1400
|
}
|
|
1400
|
-
if ( ! rb_obj_is_cscalar(other3)
|
|
1401
|
-
|
|
1402
|
-
|
|
1401
|
+
if ( ! rb_obj_is_cscalar(other3) ) {
|
|
1402
|
+
ca_broadcast_to_destination(self, &other3);
|
|
1403
|
+
TypedData_Get_Struct(other3, CArray, &carray_data_type, ca3);
|
|
1403
1404
|
}
|
|
1404
1405
|
|
|
1405
1406
|
/* self IS the output (= write target; attach legit per refined invariant) */
|
|
@@ -1462,8 +1463,8 @@ rb_ca_call_triop_bang (VALUE self, VALUE other2, VALUE other3,
|
|
|
1462
1463
|
}
|
|
1463
1464
|
|
|
1464
1465
|
ca_lazy_arena_enter();
|
|
1465
|
-
s2_arena =
|
|
1466
|
-
s3_arena =
|
|
1466
|
+
s2_arena = ca_op_acquire_operand_scratch(ca2, chunk_n);
|
|
1467
|
+
s3_arena = ca_op_acquire_operand_scratch(ca3, chunk_n);
|
|
1467
1468
|
|
|
1468
1469
|
for ( off = 0; off < n_total; off += chunk_n ) {
|
|
1469
1470
|
ca_size_t n_done = (off + chunk_n > n_total) ? n_total - off
|
|
@@ -1535,8 +1536,6 @@ rb_ca_call_moncmp (VALUE self, ca_moncmp_func_t func[])
|
|
|
1535
1536
|
EAGER_RELEASE_INPUT(ca1, h1, attached1);
|
|
1536
1537
|
}
|
|
1537
1538
|
|
|
1538
|
-
out = rb_ca_rewrap_unbound_repeat(self, out);
|
|
1539
|
-
|
|
1540
1539
|
return out;
|
|
1541
1540
|
}
|
|
1542
1541
|
|
|
@@ -1683,8 +1682,8 @@ rb_ca_call_bincmp (volatile VALUE self, volatile VALUE other,
|
|
|
1683
1682
|
}
|
|
1684
1683
|
|
|
1685
1684
|
ca_lazy_arena_enter();
|
|
1686
|
-
s1_arena =
|
|
1687
|
-
s2_arena =
|
|
1685
|
+
s1_arena = ca_op_acquire_operand_scratch(ca1, chunk_n);
|
|
1686
|
+
s2_arena = ca_op_acquire_operand_scratch(ca2, chunk_n);
|
|
1688
1687
|
|
|
1689
1688
|
for ( off = 0; off < n_kernel; off += chunk_n ) {
|
|
1690
1689
|
ca_size_t n_done = (off + chunk_n > n_kernel) ? n_kernel - off
|
|
@@ -1708,8 +1707,6 @@ rb_ca_call_bincmp (volatile VALUE self, volatile VALUE other,
|
|
|
1708
1707
|
}
|
|
1709
1708
|
}
|
|
1710
1709
|
|
|
1711
|
-
out = rb_ca_rewrap_unbound_repeat(self, out);
|
|
1712
|
-
|
|
1713
1710
|
return out;
|
|
1714
1711
|
}
|
|
1715
1712
|
|
data/ext/carray_partition.c
CHANGED
|
@@ -41,7 +41,7 @@ extern VALUE rb_ca_partition_addr_ki_mp (VALUE self, VALUE vaxis, VALUE vkth, in
|
|
|
41
41
|
* Comparator-based dispatch keeps this routine data_type-generic (used
|
|
42
42
|
* by the CA_FIXLEN partition_copy path); the mkkernel-generated
|
|
43
43
|
* partition_index_quickselect_* functions inline the comparator per
|
|
44
|
-
*
|
|
44
|
+
* data type for the numeric paths.
|
|
45
45
|
*
|
|
46
46
|
* `swap_tmp` and `pivot` must be caller-provided scratch buffers of size
|
|
47
47
|
* `bytes` (used for cell swaps via memcpy; avoids alloca / per-swap
|
|
@@ -222,7 +222,7 @@ rb_ca_partition_copy_c (VALUE self, VALUE vkth, VALUE vaxis)
|
|
|
222
222
|
CArray *cao;
|
|
223
223
|
TypedData_Get_Struct(vout, CArray, &carray_data_type, cao);
|
|
224
224
|
|
|
225
|
-
/* Numeric path: per-
|
|
225
|
+
/* Numeric path: per-type quickselect with inline cmp via the typed
|
|
226
226
|
ca_partition_quick_* kernels (avoids the function-pointer
|
|
227
227
|
indirection of the comparator-based ca_quickselect_bytes).
|
|
228
228
|
Float NaN policy = pre-partition NaN to tail (same convention as
|
|
@@ -271,7 +271,7 @@ rb_ca_partition_copy_c (VALUE self, VALUE vkth, VALUE vaxis)
|
|
|
271
271
|
|
|
272
272
|
/* masked_position: -aware twin of {rb_ca_partition_copy_c}. Masked
|
|
273
273
|
* cells are an incomparable sentinel (same role NaN plays for float
|
|
274
|
-
*
|
|
274
|
+
* data types): unmasked input takes the fast rb_ca_partition_copy_c path
|
|
275
275
|
* unchanged; masked input delegates to {partition} (which handles the
|
|
276
276
|
* masked_position split via partition_addr_ki_mp) + copy, mirroring the
|
|
277
277
|
* CA_FIXLEN / CA_OBJECT delegation pattern already used by sort_copy.
|
|
@@ -381,7 +381,7 @@ rb_ca_partitioned_view (int argc, VALUE *argv, VALUE self)
|
|
|
381
381
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
382
382
|
|
|
383
383
|
/* CA_FIXLEN flows through the same partition_addr_ki fixlen dialect
|
|
384
|
-
as numeric; masked_position: applies uniformly across
|
|
384
|
+
as numeric; masked_position: applies uniformly across data types. */
|
|
385
385
|
VALUE target = self;
|
|
386
386
|
|
|
387
387
|
/* partition_addr_ki_mp validates axis + kth, splits masked cells to
|
data/ext/carray_random.c
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
(rb_random_*).
|
|
10
10
|
|
|
11
11
|
Dispatch:
|
|
12
|
-
random! -> uniform fill (per-
|
|
12
|
+
random! -> uniform fill (per-type branch below)
|
|
13
13
|
randomn! -> standard normal via Box-Muller (float / complex only)
|
|
14
14
|
shuffle! -> Fisher-Yates over the flat buffer, or per-slice
|
|
15
15
|
when axis: is given (byte-chunk swap)
|
|
@@ -109,13 +109,13 @@ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
/* Materialize (low, high) as the correct scalar type and validate.
|
|
112
|
-
* For integer
|
|
113
|
-
* for the sampler); for float
|
|
112
|
+
* For integer data types, `..` closed adds 1 to high (turns into half-open
|
|
113
|
+
* for the sampler); for float data types, closed and half-open are
|
|
114
114
|
* equivalent so no adjustment. */
|
|
115
115
|
if (!is_default) {
|
|
116
|
-
int
|
|
116
|
+
int is_integer_type = (ca->data_type >= CA_INT8
|
|
117
117
|
&& ca->data_type <= CA_UINT64);
|
|
118
|
-
if (
|
|
118
|
+
if (is_integer_type) {
|
|
119
119
|
low_long = NUM2LONG(low_val);
|
|
120
120
|
high_long = NUM2LONG(high_val);
|
|
121
121
|
if (high_is_closed) high_long += 1;
|
|
@@ -290,7 +290,7 @@ box_muller_pair(VALUE rng, double *r1, double *r2)
|
|
|
290
290
|
/* CArray#randomn!(rng:) — fill self with standard normal N(0, 1)
|
|
291
291
|
* samples in-place via Box-Muller, returning self.
|
|
292
292
|
*
|
|
293
|
-
* Restricted to float / complex
|
|
293
|
+
* Restricted to float / complex data types. Complex fills real + imag as
|
|
294
294
|
* two independent normals per cell. */
|
|
295
295
|
static VALUE
|
|
296
296
|
rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
@@ -484,7 +484,7 @@ rb_ca_shuffle(int argc, VALUE *argv, VALUE self)
|
|
|
484
484
|
/* ---- random (copy) ----------------------------------------------------- */
|
|
485
485
|
|
|
486
486
|
/* CArray#random([low,] [high], rng:) — non-bang variant: return a
|
|
487
|
-
* newly templated array filled uniformly. Shape and
|
|
487
|
+
* newly templated array filled uniformly. Shape and data type come from
|
|
488
488
|
* CArray#template, so the receiver is only consulted for those.
|
|
489
489
|
* Accepts the same argument forms as {rb_ca_random_bang}. */
|
|
490
490
|
static VALUE
|
data/ext/carray_scatter.c
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
duplicates unbuffered (sequential) — collisions accumulate
|
|
10
10
|
mask pair skipped when any of addrs[i] / vals[i] / self[addrs[i]] is masked
|
|
11
11
|
cast vals silently cast to self.data_type
|
|
12
|
-
|
|
12
|
+
data type arithmetic (add / sub / mul / min / max): numeric only
|
|
13
13
|
(boolean / object / fixlen → CADataTypeError; the bang
|
|
14
14
|
cannot widen self, same rationale as fma! / fms!)
|
|
15
15
|
replace: numeric or boolean (assignment, no widening)
|
data/ext/carray_sort.c
CHANGED
|
@@ -46,7 +46,7 @@ struct sort_addr_key {
|
|
|
46
46
|
/* Multi-key comparator for CArray.sort_addr: compares keys in priority
|
|
47
47
|
* order, original index breaks ties (stable). Masked cells are an
|
|
48
48
|
* incomparable sentinel clustered at base->masked_last's end (same
|
|
49
|
-
* role NaN plays for float
|
|
49
|
+
* role NaN plays for float data types, and the same masked_position:
|
|
50
50
|
* contract as the sort/partition family's :sentinel kernel mode --
|
|
51
51
|
* see MASKED_POSITION rev1 in mkkernel.rb's MkKernel.sort doc).
|
|
52
52
|
*
|
|
@@ -531,7 +531,7 @@ rb_ca_axis2addr (int argc, VALUE *argv, VALUE self)
|
|
|
531
531
|
* worst case.
|
|
532
532
|
*
|
|
533
533
|
* Mask handling: masked cells are an incomparable sentinel, the same
|
|
534
|
-
* role NaN plays for float
|
|
534
|
+
* role NaN plays for float data types. They are excluded from the value
|
|
535
535
|
* comparison and clustered at one end of each fiber; masked_position:
|
|
536
536
|
* picks which end (:last, default, or :first). Relative order within
|
|
537
537
|
* the masked cluster is unspecified (same contract as the < / > regions
|
|
@@ -678,7 +678,7 @@ rb_ca_sort_copy (int argc, VALUE *argv, VALUE self)
|
|
|
678
678
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
679
679
|
|
|
680
680
|
/* CA_FIXLEN and masked input: the per-fiber path below covers
|
|
681
|
-
unmasked numeric
|
|
681
|
+
unmasked numeric data types only. Delegate to {sort} (which handles
|
|
682
682
|
both the fixlen dialect and the masked_position split) + copy to
|
|
683
683
|
get the same shape/class contract as the fast path. */
|
|
684
684
|
if ( ca_is_fixlen_type(ca) || ca_has_mask(ca) ) {
|
data/ext/carray_sort_kernel.c
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/* ---------------------------------------------------------------------------
|
|
2
2
|
|
|
3
|
-
Portable textbook sort kernels: per-
|
|
3
|
+
Portable textbook sort kernels: per-type quicksort + bottom-up
|
|
4
4
|
mergesort with inline comparison (no function-pointer indirection
|
|
5
|
-
like libc qsort / mergesort). All 10 numeric
|
|
5
|
+
like libc qsort / mergesort). All 10 numeric data types plus paired
|
|
6
6
|
forms for argsort.
|
|
7
7
|
|
|
8
8
|
Internal C API only (no Ruby surface, no Init function). Declared
|
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
|
|
13
13
|
Algorithms:
|
|
14
14
|
|
|
15
|
-
* quicksort (ca_sort_quick_<
|
|
15
|
+
* quicksort (ca_sort_quick_<type>)
|
|
16
16
|
median-of-3 pivot, Hoare partition, strict `<`, insertion-sort
|
|
17
17
|
base (threshold 16), smaller-side recursion / larger-side
|
|
18
18
|
iterate (stack O(log n)). Depth-limit escape to mergesort for
|
|
19
19
|
worst-case O(n log n).
|
|
20
20
|
|
|
21
|
-
* mergesort (ca_sort_merge_<
|
|
21
|
+
* mergesort (ca_sort_merge_<type>)
|
|
22
22
|
Bottom-up, ping-pong (cur / next) per pass with no inter-pass
|
|
23
23
|
memcpy. Strict `<` (stable: equal -> take-left). Insertion-
|
|
24
24
|
sort pre-pass that converts the input into R=16-wide sorted
|
|
@@ -27,18 +27,18 @@
|
|
|
27
27
|
skip the merge loop; no run-state machine, distinct from
|
|
28
28
|
Timsort galloping).
|
|
29
29
|
|
|
30
|
-
* paired forms (ca_sort_quick_pair_<
|
|
30
|
+
* paired forms (ca_sort_quick_pair_<type> / ca_sort_merge_pair_<type>)
|
|
31
31
|
Same algorithms over (value, index) pairs for argsort
|
|
32
32
|
(sort_index / sort_addr). Stable tie-break by index is built
|
|
33
33
|
into the comparison, so quicksort is effectively stable for
|
|
34
34
|
argsort even though the algorithm itself is not.
|
|
35
35
|
|
|
36
|
-
* NaN partitioning (ca_partition_nan_<
|
|
36
|
+
* NaN partitioning (ca_partition_nan_<type> + _pair_<type>)
|
|
37
37
|
float32 / float64 only. One-pass Hoare-style partition that
|
|
38
38
|
separates `[finite | NaN]` regions so the downstream sort
|
|
39
39
|
kernel can operate on the finite slice with plain `<`.
|
|
40
40
|
|
|
41
|
-
* value-level quickselect (ca_partition_quick_<
|
|
41
|
+
* value-level quickselect (ca_partition_quick_<type>)
|
|
42
42
|
median-of-3 + Hoare + insertion base + one-sided recursion
|
|
43
43
|
into the side containing kth (quickselect property, expected
|
|
44
44
|
O(n)). Depth-limit escape to mergesort matches the sort
|
|
@@ -402,13 +402,13 @@ ca_sort_quick_pair_##SUFFIX (ca_pair_##SUFFIX *a, ca_size_t n) \
|
|
|
402
402
|
struct ca_sort_pair_##SUFFIX##_eat_semicolon
|
|
403
403
|
|
|
404
404
|
|
|
405
|
-
/* ===== Per-
|
|
405
|
+
/* ===== Per-type instantiations ===========================================
|
|
406
406
|
`<` is well-defined and IEEE-stable for all numeric C types used
|
|
407
407
|
here; NaN handling for f32 / f64 lives in the pre-partition pass
|
|
408
408
|
below. */
|
|
409
409
|
|
|
410
410
|
/* ---------------------------------------------------------------------------
|
|
411
|
-
NaN pre-partition (float
|
|
411
|
+
NaN pre-partition (float data types only).
|
|
412
412
|
|
|
413
413
|
One-pass Hoare-style partition that separates `a[0..n)` into
|
|
414
414
|
`[finite | NaN]` regions in place, returning the finite count k
|
|
@@ -447,7 +447,7 @@ struct ca_partition_nan_##SUFFIX##_eat_semicolon
|
|
|
447
447
|
DEFINE_PARTITION_NAN(float32_t, f32);
|
|
448
448
|
DEFINE_PARTITION_NAN(double, f64);
|
|
449
449
|
|
|
450
|
-
/* Pair variant for argsort: separates ca_pair_<
|
|
450
|
+
/* Pair variant for argsort: separates ca_pair_<type> by
|
|
451
451
|
isnan(v.value). Returns the finite count.
|
|
452
452
|
|
|
453
453
|
Stable within both finite and NaN regions (original order
|
data/ext/carray_test.c
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
- internal check_* / has_same_* helpers used across ext/ sources
|
|
5
5
|
- Ruby surface: valid_index? / valid_addr? / same_shape? / == /
|
|
6
6
|
eql? / hash / freeze (docs in yard-stubs/carray_test.rb)
|
|
7
|
-
- per-
|
|
7
|
+
- per-type element-equality table `ca_eql[CA_NTYPE]`
|
|
8
8
|
- `ca_compare_common` shared body for `==` and `eql?`
|
|
9
9
|
|
|
10
10
|
---------------------------------------------------------------------------- */
|
data/ext/extconf.rb
CHANGED
|
@@ -63,6 +63,17 @@ end
|
|
|
63
63
|
|
|
64
64
|
$CFLAGS += " -Wall"
|
|
65
65
|
|
|
66
|
+
# --- the flags that decide the numbers
|
|
67
|
+
#
|
|
68
|
+
# Two compilations of the same C do not have to agree on the last bit: what
|
|
69
|
+
# the compiler is allowed to fuse or reorder is decided by the flags it was
|
|
70
|
+
# given. Anything computing what these kernels compute, somewhere other
|
|
71
|
+
# than in them, has to be built the same way to arrive at the same answer,
|
|
72
|
+
# so the flags that bear on it are recorded and handed out as
|
|
73
|
+
# CArray::BUILD_FLAGS. Optimisation and architecture only -- warnings,
|
|
74
|
+
# defines and link options change nothing about the arithmetic.
|
|
75
|
+
$carray_build_flags = [RbConfig::CONFIG["optflags"].to_s.strip]
|
|
76
|
+
|
|
66
77
|
# --- in-build flag (CARRAY_BUILD)
|
|
67
78
|
#
|
|
68
79
|
# Marks a translation unit as part of carray itself, i.e. recompiled whenever
|
|
@@ -121,6 +132,7 @@ simd_probe = <<~C
|
|
|
121
132
|
C
|
|
122
133
|
if try_compile(simd_probe, "-fopenmp-simd")
|
|
123
134
|
$CFLAGS += " -fopenmp-simd"
|
|
135
|
+
$carray_build_flags << "-fopenmp-simd"
|
|
124
136
|
$stderr.puts "carray: -fopenmp-simd enabled (SIMD reduction license)"
|
|
125
137
|
end
|
|
126
138
|
|
|
@@ -151,11 +163,17 @@ if enable_config("march-native", default_on)
|
|
|
151
163
|
arch_probe = "int main(void) { return 0; }\n"
|
|
152
164
|
if try_compile(arch_probe, "-march=native")
|
|
153
165
|
$CFLAGS += " -march=native"
|
|
166
|
+
$carray_build_flags << "-march=native"
|
|
154
167
|
$stderr.puts "carray: -march=native enabled (build-machine ISA extensions)"
|
|
155
168
|
else
|
|
156
169
|
$stderr.puts "carray: -march=native probe FAILED, keeping baseline SIMD"
|
|
157
170
|
end
|
|
158
171
|
end
|
|
172
|
+
File.write("carray_build_flags.h",
|
|
173
|
+
"/* GENERATED by extconf.rb: the flags this build's arithmetic\n" \
|
|
174
|
+
" was compiled with. See CArray::BUILD_FLAGS. */\n" \
|
|
175
|
+
"#define CA_BUILD_FLAGS #{$carray_build_flags.join(" ").inspect}\n")
|
|
176
|
+
|
|
159
177
|
# $CFLAGS += " -m128bit-long-double" ### gcc only
|
|
160
178
|
# $CFLAGS += " -Wno-absolute-value"
|
|
161
179
|
# $LDFLAGS += " -L/usr/local/opt/llvm/lib -Wl,-rpath,/usr/local/opt/llvm/lib"
|