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.
Files changed (180) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -1
  3. data/CHANGELOG.md +325 -3
  4. data/{NEWS.md → CHANGELOG.v1.md} +1 -1
  5. data/README.md +32 -32
  6. data/carray.gemspec +12 -8
  7. data/ext/ca_axis_group.c +55 -19
  8. data/ext/ca_binop_dispatch.c +5 -6
  9. data/ext/ca_binop_dispatch.h +0 -7
  10. data/ext/ca_categorical_iterator.c +13 -13
  11. data/ext/ca_for_each_element.h +6 -8
  12. data/ext/ca_group_iter.c +1 -1
  13. data/ext/ca_kernel_iterator.c +69 -23
  14. data/ext/ca_kernel_iterator.h +3 -10
  15. data/ext/ca_obj_bincmp.c +57 -27
  16. data/ext/ca_obj_binop.c +86 -30
  17. data/ext/ca_obj_const_string.c +3 -1
  18. data/ext/ca_obj_face.c +80 -0
  19. data/ext/ca_obj_face.h +33 -1
  20. data/ext/ca_obj_fake.c +11 -0
  21. data/ext/ca_obj_fixlen_string.c +3 -1
  22. data/ext/ca_obj_grid.c +11 -3
  23. data/ext/ca_obj_meld.c +13 -8
  24. data/ext/ca_obj_moncmp.c +33 -14
  25. data/ext/ca_obj_monop.c +19 -7
  26. data/ext/ca_obj_object.c +99 -4
  27. data/ext/ca_obj_record.c +3 -1
  28. data/ext/ca_obj_refer.c +30 -6
  29. data/ext/ca_obj_roll.c +13 -5
  30. data/ext/ca_obj_select_axis.c +16 -6
  31. data/ext/ca_obj_shift.c +3 -3
  32. data/ext/ca_obj_stride.c +106 -23
  33. data/ext/ca_obj_string.c +3 -1
  34. data/ext/ca_obj_tile.c +13 -5
  35. data/ext/ca_obj_time.c +3 -1
  36. data/ext/ca_obj_timedelta.c +3 -1
  37. data/ext/ca_obj_transpose.c +1 -1
  38. data/ext/ca_obj_triop.c +62 -23
  39. data/ext/ca_obj_window.c +86 -17
  40. data/ext/ca_op_cmplx64.h +123 -0
  41. data/ext/ca_op_ipower.c +0 -3
  42. data/ext/ca_sort_kernels.h +5 -5
  43. data/ext/ca_sweep_engine.c +78 -35
  44. data/ext/ca_sweep_engine.h +13 -4
  45. data/ext/ca_transform_common.c +7 -0
  46. data/ext/carray.h +127 -130
  47. data/ext/carray_access.c +56 -34
  48. data/ext/carray_bincount.c +8 -8
  49. data/ext/carray_broadcast.c +99 -6
  50. data/ext/carray_build_flags.h +3 -0
  51. data/ext/carray_call_cfunc.c +1491 -0
  52. data/ext/carray_call_cfunc.h +153 -0
  53. data/ext/carray_cast.c +69 -31
  54. data/ext/carray_conversion.c +22 -22
  55. data/ext/carray_copy.c +12 -2
  56. data/ext/carray_core.c +57 -10
  57. data/ext/carray_count.c +1 -1
  58. data/ext/carray_element.c +7 -7
  59. data/ext/carray_factorize.c +28 -28
  60. data/ext/carray_hold.c +1 -1
  61. data/ext/carray_index_classifier.c +7 -21
  62. data/ext/carray_internal.h +19 -3
  63. data/ext/carray_kernels_bincmp.c +1 -0
  64. data/ext/carray_kernels_binop.c +320 -298
  65. data/ext/carray_kernels_init.c +1095 -0
  66. data/ext/carray_kernels_map.c +1 -0
  67. data/ext/carray_kernels_moncmp.c +1 -0
  68. data/ext/carray_kernels_monop.c +412 -411
  69. data/ext/carray_kernels_reduce_aggregate.c +88 -87
  70. data/ext/carray_kernels_reduce_boolean.c +1 -0
  71. data/ext/carray_kernels_reduce_cumulative.c +54 -53
  72. data/ext/carray_kernels_reduce_extreme.c +51 -50
  73. data/ext/carray_kernels_reduce_variance.c +1 -0
  74. data/ext/carray_kernels_scan.c +1 -0
  75. data/ext/carray_kernels_search.c +93 -92
  76. data/ext/carray_kernels_sort.c +1 -0
  77. data/ext/carray_kernels_triop.c +1 -0
  78. data/ext/carray_lazy.c +175 -5
  79. data/ext/carray_mask.c +6 -5
  80. data/ext/carray_median_percentile.c +1 -1
  81. data/ext/carray_memory_view.c +46 -21
  82. data/ext/carray_operator.c +46 -49
  83. data/ext/carray_partition.c +4 -4
  84. data/ext/carray_random.c +7 -7
  85. data/ext/carray_scatter.c +1 -1
  86. data/ext/carray_sort.c +3 -3
  87. data/ext/carray_sort_kernel.c +10 -10
  88. data/ext/carray_test.c +1 -1
  89. data/ext/extconf.rb +18 -0
  90. data/ext/mk_call_cfunc.rb +243 -52
  91. data/ext/mkkernel.rb +354 -100
  92. data/ext/ruby_carray.c +18 -16
  93. data/ext/version.h +4 -4
  94. data/lib/carray/autoload_carray.rb +19 -0
  95. data/lib/carray/autoload_method_extension.rb +2 -1
  96. data/lib/carray/axis_group.rb +7 -7
  97. data/lib/carray/basics.rb +59 -59
  98. data/lib/carray/bincount_nd.rb +12 -12
  99. data/lib/carray/block_iterator.rb +24 -14
  100. data/lib/carray/categorical.rb +4 -4
  101. data/lib/carray/categorical_iterator.rb +98 -76
  102. data/lib/carray/conditional.rb +14 -14
  103. data/lib/carray/construct.rb +21 -0
  104. data/lib/carray/core_extensions.rb +62 -5
  105. data/lib/carray/data_type_extension.rb +18 -1
  106. data/lib/carray/frame/concat.rb +3 -3
  107. data/lib/carray/frame/convert.rb +1 -1
  108. data/lib/carray/frame/frame.rb +4 -11
  109. data/lib/carray/frame/io.rb +159 -2
  110. data/lib/carray/frame/sort.rb +1 -1
  111. data/lib/carray/frame/verbs.rb +18 -1
  112. data/lib/carray/fuse_source.rb +123 -0
  113. data/lib/carray/fusion.rb +218 -0
  114. data/lib/carray/histogram.rb +16 -16
  115. data/lib/carray/inspect.rb +1 -7
  116. data/lib/carray/iterator.rb +4 -3
  117. data/lib/carray/lazy.rb +125 -73
  118. data/lib/carray/meld_reduce.rb +2 -2
  119. data/lib/carray/methods/align_addr.rb +1 -1
  120. data/lib/carray/methods/composition.rb +1 -1
  121. data/lib/carray/methods/is_in.rb +12 -12
  122. data/lib/carray/methods/locate_addr.rb +6 -1
  123. data/lib/carray/methods/mask_duplicates.rb +1 -1
  124. data/lib/carray/methods/meshgrid.rb +4 -5
  125. data/lib/carray/methods/mode.rb +2 -2
  126. data/lib/carray/methods/nunique.rb +1 -1
  127. data/lib/carray/methods/snap.rb +7 -2
  128. data/lib/carray/methods/unique.rb +3 -3
  129. data/lib/carray/methods/value_counts.rb +2 -2
  130. data/lib/carray/runtime.rb +0 -19
  131. data/lib/carray/slab_iterator.rb +20 -7
  132. data/lib/carray/string_operation_extension.rb +5 -5
  133. data/lib/carray/time.rb +890 -491
  134. data/lib/carray/window_iterator.rb +285 -13
  135. data/lib/carray.rb +5 -5
  136. data/yard-stubs/ca_obj_array.rb +385 -0
  137. data/yard-stubs/ca_obj_bitarray.rb +38 -0
  138. data/yard-stubs/ca_obj_bitfield.rb +43 -0
  139. data/yard-stubs/ca_obj_block.rb +73 -0
  140. data/yard-stubs/ca_obj_byte_swap.rb +56 -0
  141. data/yard-stubs/ca_obj_fake.rb +31 -0
  142. data/yard-stubs/ca_obj_farray.rb +32 -0
  143. data/yard-stubs/ca_obj_field.rb +45 -0
  144. data/yard-stubs/ca_obj_grid.rb +35 -0
  145. data/yard-stubs/ca_obj_refer.rb +72 -0
  146. data/yard-stubs/ca_obj_roll.rb +45 -0
  147. data/yard-stubs/ca_obj_shift.rb +43 -0
  148. data/yard-stubs/ca_obj_stride.rb +181 -0
  149. data/yard-stubs/ca_obj_tile.rb +29 -0
  150. data/yard-stubs/ca_obj_transpose.rb +40 -0
  151. data/yard-stubs/ca_obj_window.rb +49 -0
  152. data/yard-stubs/carray_access.rb +131 -0
  153. data/yard-stubs/carray_attribute.rb +246 -0
  154. data/yard-stubs/carray_broadcast.rb +37 -0
  155. data/yard-stubs/carray_cast.rb +489 -0
  156. data/yard-stubs/carray_class.rb +65 -0
  157. data/yard-stubs/carray_conversion.rb +76 -0
  158. data/yard-stubs/carray_copy.rb +79 -0
  159. data/yard-stubs/carray_core.rb +114 -0
  160. data/yard-stubs/carray_count.rb +79 -0
  161. data/yard-stubs/carray_element.rb +108 -0
  162. data/yard-stubs/carray_generate.rb +66 -0
  163. data/yard-stubs/carray_lazy.rb +23 -0
  164. data/yard-stubs/carray_loop.rb +140 -0
  165. data/yard-stubs/carray_mask.rb +259 -0
  166. data/yard-stubs/carray_math.rb +132 -0
  167. data/yard-stubs/carray_mathfunc.rb +45 -0
  168. data/yard-stubs/carray_median_percentile.rb +89 -0
  169. data/yard-stubs/carray_memory_view.rb +163 -0
  170. data/yard-stubs/carray_order.rb +312 -0
  171. data/yard-stubs/carray_random.rb +89 -0
  172. data/yard-stubs/carray_scatter.rb +106 -0
  173. data/yard-stubs/carray_slab.rb +57 -0
  174. data/yard-stubs/carray_sort.rb +163 -0
  175. data/yard-stubs/carray_test.rb +85 -0
  176. data/yard-stubs/carray_undef.rb +64 -0
  177. data/yard-stubs/carray_utils.rb +97 -0
  178. data/yard-stubs/ruby_carray.rb +193 -0
  179. metadata +59 -10
  180. data/ext/ca_obj_unbound_repeat.c +0 -496
@@ -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 dtype + output has a mask (else no-op -- the hot path is
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 = ca_lazy_arena_acquire(ca1->bytes);
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 = ca_lazy_arena_acquire(chunk_n * ca1->bytes);
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 = ca_lazy_arena_acquire(ca2->bytes);
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 = ca_lazy_arena_acquire(chunk_n * ca2->bytes);
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
- /* shape compat: non-scalar self vs non-scalar other elements must match.
1039
- scalar self vs array other historically raises (mismatch). */
1040
- if ( !self_is_scalar && !other_is_scalar &&
1041
- ca1->elements != ca2->elements ) {
1042
- rb_raise(rb_eRuntimeError, "elements mismatch in binop (%" PRId64 " <-> %" PRId64 ")",
1043
- (ca_size_t) ca1->elements,
1044
- (ca_size_t) ca2->elements);
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 = ca_lazy_arena_acquire(ca1->bytes);
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 = ca_lazy_arena_acquire(chunk_n * ca1->bytes);
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 = ca_lazy_arena_acquire(ca2->bytes);
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 = ca_lazy_arena_acquire(chunk_n * ca2->bytes);
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 = ca_lazy_arena_acquire(ca3->bytes);
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 = ca_lazy_arena_acquire(chunk_n * ca3->bytes);
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
- /* element-count check (self is the destination) */
1396
- if ( ! rb_obj_is_cscalar(other2) && ca2->elements != ca1->elements ) {
1397
- rb_raise(rb_eRuntimeError, "elements mismatch in triop! (op2: %" PRId64 " != %" PRId64 ")",
1398
- (ca_size_t) ca2->elements, (ca_size_t) ca1->elements);
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) && ca3->elements != ca1->elements ) {
1401
- rb_raise(rb_eRuntimeError, "elements mismatch in triop! (op3: %" PRId64 " != %" PRId64 ")",
1402
- (ca_size_t) ca3->elements, (ca_size_t) ca1->elements);
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 = ca_lazy_arena_acquire(chunk_n * ca2->bytes);
1466
- s3_arena = ca_lazy_arena_acquire(chunk_n * ca3->bytes);
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 = ca_lazy_arena_acquire(chunk_n * b1);
1687
- s2_arena = ca_lazy_arena_acquire(chunk_n * b2);
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
 
@@ -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
- * dtype for the numeric paths.
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-dtype quickselect with inline cmp via the typed
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
- * dtypes): unmasked input takes the fast rb_ca_partition_copy_c path
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 dtypes. */
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-dtype branch below)
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 dtypes, `..` closed adds 1 to high (turns into half-open
113
- * for the sampler); for float dtypes, closed and half-open are
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 is_integer_dtype = (ca->data_type >= CA_INT8
116
+ int is_integer_type = (ca->data_type >= CA_INT8
117
117
  && ca->data_type <= CA_UINT64);
118
- if (is_integer_dtype) {
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 dtypes. Complex fills real + imag as
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 dtype come from
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
- dtype arithmetic (add / sub / mul / min / max): numeric only
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 dtypes, and the same masked_position:
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 dtypes. They are excluded from the value
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 dtypes only. Delegate to {sort} (which handles
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) ) {
@@ -1,8 +1,8 @@
1
1
  /* ---------------------------------------------------------------------------
2
2
 
3
- Portable textbook sort kernels: per-dtype quicksort + bottom-up
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 dtypes plus paired
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_<dtype>)
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_<dtype>)
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_<dtype> / ca_sort_merge_pair_<dtype>)
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_<dtype> + _pair_<dtype>)
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_<dtype>)
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-dtype instantiations ===========================================
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 dtypes only).
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_<dtype> by
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-dtype element-equality table `ca_eql[CA_NTYPE]`
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"