carray 3.0.3 → 3.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +264 -0
  3. data/README.md +3 -2
  4. data/carray.gemspec +1 -1
  5. data/ext/ca_axis_descriptor.h +27 -24
  6. data/ext/ca_axis_dispatch.c +1 -6
  7. data/ext/ca_axis_group.c +27 -27
  8. data/ext/ca_binop_dispatch.c +1 -29
  9. data/ext/ca_binop_dispatch.h +0 -1
  10. data/ext/ca_categorical_iterator.c +205 -134
  11. data/ext/ca_compare.c +7 -18
  12. data/ext/ca_group_iter.c +16 -17
  13. data/ext/ca_kernel_iterator.c +1234 -1994
  14. data/ext/ca_kernel_iterator.h +391 -437
  15. data/ext/ca_monop_dispatch.c +82 -59
  16. data/ext/ca_monop_dispatch.h +1 -0
  17. data/ext/ca_obj_array.c +96 -39
  18. data/ext/ca_obj_bincmp.c +24 -21
  19. data/ext/ca_obj_binop.c +15 -26
  20. data/ext/ca_obj_bitarray.c +3 -2
  21. data/ext/ca_obj_bitfield.c +5 -6
  22. data/ext/ca_obj_block.c +18 -9
  23. data/ext/ca_obj_byte_swap.c +5 -6
  24. data/ext/ca_obj_const_string.c +173 -19
  25. data/ext/ca_obj_face.c +238 -57
  26. data/ext/ca_obj_face.h +19 -0
  27. data/ext/ca_obj_fake.c +15 -29
  28. data/ext/ca_obj_farray.c +6 -3
  29. data/ext/ca_obj_field.c +17 -5
  30. data/ext/ca_obj_fixlen_string.c +2 -3
  31. data/ext/ca_obj_grid.c +406 -132
  32. data/ext/ca_obj_meld.c +172 -34
  33. data/ext/ca_obj_moncmp.c +23 -8
  34. data/ext/ca_obj_monop.c +67 -57
  35. data/ext/ca_obj_object.c +157 -51
  36. data/ext/ca_obj_record.c +12 -7
  37. data/ext/ca_obj_reduce.c +13 -8
  38. data/ext/ca_obj_refer.c +25 -27
  39. data/ext/ca_obj_remap.c +30 -9
  40. data/ext/ca_obj_repeat.c +9 -10
  41. data/ext/ca_obj_roll.c +6 -5
  42. data/ext/ca_obj_select.c +14 -9
  43. data/ext/ca_obj_select_axis.c +15 -47
  44. data/ext/ca_obj_shift.c +11 -1
  45. data/ext/ca_obj_stack.c +179 -34
  46. data/ext/ca_obj_stride.c +162 -115
  47. data/ext/ca_obj_string.c +71 -4
  48. data/ext/ca_obj_tile.c +6 -5
  49. data/ext/ca_obj_time.c +22 -6
  50. data/ext/ca_obj_timedelta.c +22 -6
  51. data/ext/ca_obj_transpose.c +5 -3
  52. data/ext/ca_obj_triop.c +23 -32
  53. data/ext/ca_obj_window.c +190 -26
  54. data/ext/ca_sweep_engine.c +2 -2
  55. data/ext/caframe_csv_reader.c +80 -1
  56. data/ext/carray.h +181 -75
  57. data/ext/carray_access.c +184 -96
  58. data/ext/carray_address_basis.c +343 -87
  59. data/ext/carray_attribute.c +89 -6
  60. data/ext/carray_bincount.c +10 -8
  61. data/ext/carray_broadcast.c +13 -8
  62. data/ext/carray_build_flags.h +3 -0
  63. data/ext/carray_call_cfunc.c +108 -0
  64. data/ext/carray_cast.c +142 -24
  65. data/ext/carray_cast_func.rb +46 -6
  66. data/ext/carray_class.c +4 -3
  67. data/ext/carray_config.h +28 -0
  68. data/ext/carray_conversion.c +16 -7
  69. data/ext/carray_copy.c +51 -14
  70. data/ext/carray_core.c +147 -55
  71. data/ext/carray_count.c +50 -20
  72. data/ext/carray_element.c +76 -33
  73. data/ext/carray_factorize.c +118 -64
  74. data/ext/carray_generate.c +191 -50
  75. data/ext/carray_histogram.c +62 -17
  76. data/ext/carray_hold.c +12 -15
  77. data/ext/carray_index_classifier.c +388 -176
  78. data/ext/carray_internal.h +336 -29
  79. data/ext/carray_kernels_bincmp.c +4453 -0
  80. data/ext/carray_kernels_binop.c +11368 -0
  81. data/ext/carray_kernels_init.c +1734 -0
  82. data/ext/carray_kernels_moncmp.c +2104 -0
  83. data/ext/carray_kernels_monop.c +18369 -0
  84. data/ext/carray_kernels_reduce_aggregate.c +23818 -0
  85. data/ext/carray_kernels_reduce_boolean.c +406 -0
  86. data/ext/carray_kernels_reduce_cumulative.c +10086 -0
  87. data/ext/carray_kernels_reduce_extreme.c +17634 -0
  88. data/ext/carray_kernels_reduce_variance.c +3849 -0
  89. data/ext/carray_kernels_scan.c +4302 -0
  90. data/ext/carray_kernels_search.c +33829 -0
  91. data/ext/carray_kernels_sort.c +10906 -0
  92. data/ext/carray_kernels_triop.c +1864 -0
  93. data/ext/carray_key_windows.c +216 -0
  94. data/ext/carray_lazy.c +170 -111
  95. data/ext/carray_mask.c +292 -72
  96. data/ext/carray_median_percentile.c +82 -28
  97. data/ext/carray_memory_view.c +669 -561
  98. data/ext/carray_operator.c +124 -47
  99. data/ext/carray_order.c +384 -76
  100. data/ext/carray_partition.c +28 -27
  101. data/ext/carray_random.c +67 -13
  102. data/ext/carray_round.c +273 -0
  103. data/ext/carray_scatter.c +63 -38
  104. data/ext/carray_segment.c +3 -3
  105. data/ext/carray_slab.c +91 -28
  106. data/ext/carray_sort.c +35 -35
  107. data/ext/carray_struct.c +19 -18
  108. data/ext/carray_test.c +26 -5
  109. data/ext/carray_undef.c +4 -0
  110. data/ext/carray_utils.c +246 -45
  111. data/ext/mk_call_cfunc.rb +19 -2
  112. data/ext/mkkernel.rb +198 -240
  113. data/ext/ruby_carray.c +10 -4
  114. data/ext/version.h +4 -4
  115. data/lib/carray/attribute.rb +126 -22
  116. data/lib/carray/autoload_carray.rb +8 -31
  117. data/lib/carray/autoload_method_extension.rb +14 -5
  118. data/lib/carray/axis_group.rb +255 -106
  119. data/lib/carray/basics.rb +78 -10
  120. data/lib/carray/bincount_nd.rb +12 -2
  121. data/lib/carray/block_iterator.rb +126 -23
  122. data/lib/carray/boolean_reduce.rb +17 -17
  123. data/lib/carray/categorical.rb +165 -43
  124. data/lib/carray/categorical_iterator.rb +130 -27
  125. data/lib/carray/complex.rb +5 -5
  126. data/lib/carray/conditional.rb +67 -18
  127. data/lib/carray/const_string.rb +14 -5
  128. data/lib/carray/construct.rb +15 -11
  129. data/lib/carray/data_type_extension.rb +1 -0
  130. data/lib/carray/distance_limit.rb +77 -0
  131. data/lib/carray/fixlen_string.rb +7 -1
  132. data/lib/carray/frame/column_verbs.rb +70 -0
  133. data/lib/carray/frame/convert.rb +69 -0
  134. data/lib/carray/frame/csv_parser.rb +111 -17
  135. data/lib/carray/frame/describe.rb +3 -2
  136. data/lib/carray/frame/frame.rb +246 -21
  137. data/lib/carray/frame/group.rb +510 -95
  138. data/lib/carray/frame/io.rb +115 -28
  139. data/lib/carray/frame/join.rb +312 -51
  140. data/lib/carray/frame/records.rb +83 -7
  141. data/lib/carray/frame/reshape.rb +42 -35
  142. data/lib/carray/frame/sort.rb +7 -19
  143. data/lib/carray/frame/verbs.rb +188 -48
  144. data/lib/carray/frame/windows.rb +117 -0
  145. data/lib/carray/frame.rb +2 -0
  146. data/lib/carray/fuse_source.rb +11 -4
  147. data/lib/carray/fusion.rb +40 -16
  148. data/lib/carray/histogram.rb +6 -1
  149. data/lib/carray/inspect.rb +31 -8
  150. data/lib/carray/iterator.rb +85 -7
  151. data/lib/carray/key_windows.rb +620 -0
  152. data/lib/carray/lazy.rb +182 -183
  153. data/lib/carray/mask_gap_fill.rb +63 -57
  154. data/lib/carray/meld_reduce.rb +12 -14
  155. data/lib/carray/methods/bin.rb +26 -18
  156. data/lib/carray/methods/bincount.rb +16 -0
  157. data/lib/carray/methods/bit_string.rb +1 -1
  158. data/lib/carray/methods/choose.rb +16 -3
  159. data/lib/carray/methods/composition.rb +3 -1
  160. data/lib/carray/methods/gather_nd.rb +14 -5
  161. data/lib/carray/methods/insert_block.rb +2 -2
  162. data/lib/carray/methods/is_between.rb +59 -0
  163. data/lib/carray/methods/is_in.rb +53 -36
  164. data/lib/carray/methods/join.rb +1 -6
  165. data/lib/carray/methods/lag.rb +49 -0
  166. data/lib/carray/methods/locate_addr.rb +47 -51
  167. data/lib/carray/methods/mode.rb +1 -1
  168. data/lib/carray/methods/nunique.rb +11 -6
  169. data/lib/carray/methods/resize.rb +3 -3
  170. data/lib/carray/methods/value_counts.rb +4 -11
  171. data/lib/carray/record_order.rb +3 -3
  172. data/lib/carray/rng.rb +3 -0
  173. data/lib/carray/runtime.rb +53 -8
  174. data/lib/carray/segment_iterator.rb +313 -82
  175. data/lib/carray/serialize.rb +24 -10
  176. data/lib/carray/slab_iterator.rb +50 -0
  177. data/lib/carray/string.rb +105 -5
  178. data/lib/carray/string_operation_extension.rb +8 -1
  179. data/lib/carray/struct.rb +9 -21
  180. data/lib/carray/struct_builder.rb +19 -8
  181. data/lib/carray/time.rb +726 -104
  182. data/lib/carray/window_iterator.rb +122 -16
  183. data/lib/carray.rb +7 -0
  184. data/yard-stubs/ca_obj_bitfield.rb +1 -1
  185. data/yard-stubs/ca_obj_field.rb +4 -0
  186. data/yard-stubs/ca_obj_grid.rb +21 -10
  187. data/yard-stubs/ca_obj_refer.rb +2 -1
  188. data/yard-stubs/ca_obj_roll.rb +2 -2
  189. data/yard-stubs/ca_obj_shift.rb +5 -1
  190. data/yard-stubs/ca_obj_tile.rb +1 -1
  191. data/yard-stubs/ca_obj_window.rb +8 -3
  192. data/yard-stubs/carray_access.rb +6 -1
  193. data/yard-stubs/carray_attribute.rb +0 -5
  194. data/yard-stubs/carray_cast.rb +10 -0
  195. data/yard-stubs/carray_conversion.rb +2 -1
  196. data/yard-stubs/carray_copy.rb +4 -2
  197. data/yard-stubs/carray_count.rb +4 -4
  198. data/yard-stubs/carray_element.rb +10 -4
  199. data/yard-stubs/carray_generate.rb +21 -1
  200. data/yard-stubs/carray_mask.rb +26 -2
  201. data/yard-stubs/carray_math.rb +27 -1
  202. data/yard-stubs/carray_median_percentile.rb +5 -2
  203. data/yard-stubs/carray_memory_view.rb +40 -23
  204. data/yard-stubs/carray_order.rb +29 -18
  205. data/yard-stubs/carray_random.rb +13 -4
  206. data/yard-stubs/carray_scatter.rb +14 -9
  207. data/yard-stubs/carray_slab.rb +9 -2
  208. data/yard-stubs/carray_sort.rb +6 -5
  209. data/yard-stubs/carray_test.rb +5 -3
  210. metadata +25 -3
  211. data/lib/carray/arrow_tensor.rb +0 -401
  212. data/lib/carray/table.rb +0 -108
data/ext/carray.h CHANGED
@@ -347,14 +347,12 @@ typedef struct {
347
347
  void (*detach) (void *ap);
348
348
  void (*fill_data) (void *ap, void *data);
349
349
  void (*create_mask) (void *ap);
350
- /* xfer protocol. Added at struct end so existing
351
- positional initializers leave it NULL automatically. dir = CA_XFER_GET /
352
- CA_XFER_PUT. */
350
+ /* xfer protocol. dir = CA_XFER_GET / CA_XFER_PUT. */
353
351
  void (*xfer_index) (void *ap, ca_size_t *idx, void *data, int dir);
354
352
  void (*xfer_addrs) (void *ap, ca_size_t n, ca_size_t *addrs,
355
353
  void *data, int dir);
356
- /* fold_stride: one compose-fold hop
357
- for sometimes-fold participants (CAWindow now; CAGrid/CSA/CATile later).
354
+ /* fold_stride: one compose-fold hop for the views that fold only
355
+ sometimes (CAWindow, CAGrid, CASelectAxis, CAStack, CAMeld).
358
356
  Compose *f into next_parent's byte space and return 1, or decline
359
357
  (leave *f / *next_parent untouched) and return 0 -> this view is the
360
358
  fold boundary. CAStride family leaves this NULL (handled open-inline
@@ -637,6 +635,13 @@ typedef struct {
637
635
  (count[k] == parent->dim[k] && start[k]
638
636
  == 0 for k >= 1). Embedded region
639
637
  must be contig in parent storage. */
638
+ /* A window over a parent that has no mask: the all-false mask its own
639
+ mask reads instead, so that masking the out-of-bounds cells gives the
640
+ parent no mask. Owned by this window; NULL otherwise. */
641
+ CArray *mask_standin;
642
+ /* On the mask of a window: the window whose mask it is, which holds the
643
+ stand-in and the parent whose mask replaces it. NULL otherwise. */
644
+ CArray *mask_owner;
640
645
  } CAWindow; /* 56 + 16*(ndim) + 1*(bytes) + 1*ndim + 24*ndim (bytes) */
641
646
 
642
647
  /* CAShift is a pure typedef of CAWindow. CAShift construction maps (shift[], roll[], fill,
@@ -681,17 +686,17 @@ typedef struct {
681
686
  dim[k] = parent->dim[k] * reps[k]. */
682
687
  } CATile; /* 56 + 8*(ndim) (bytes) */
683
688
 
684
- typedef CATile CARoll; /* T.4 will land CARoll-specific constructor +
685
- obj_type CA_OBJ_ROLL. Until then CARoll path
686
- is just CATile (= typedef body identical). */
689
+ typedef CATile CARoll; /* same layout as CATile, its own obj_type
690
+ CA_OBJ_ROLL (ext/ca_obj_roll.c) */
687
691
 
688
- /* CAStack: outer-axis-only stack view of K uniform-shape parents. shape = (K, *parent_shape),
689
- axis 0 maps to parent index, axes 1..ndim-1 are per-parent contig.
692
+ /* CAStack: stack view of K uniform-shape parents. The K axis sits at
693
+ k_axis in the view's shape (0 by default: shape = (K, *parent_shape));
694
+ the other axes are the parents' own.
690
695
  - parents stored as Ruby Array @parents on the wrapper object (= GC
691
696
  anchor); C-side tail `parents[]` is alias pointer array.
692
697
  - CAView.parent points to parents[0] (= legacy compat for paths that
693
698
  deref ca->parent without CAStack awareness).
694
- - dim[0] = n_parents; dim[1..ndim-1] = parents[0]->dim[0..ndim-2]. */
699
+ - dim[k_axis] = n_parents; the other dims are parents[0]->dim in order. */
695
700
  typedef struct {
696
701
  int16_t obj_type;
697
702
  int8_t data_type;
@@ -699,7 +704,7 @@ typedef struct {
699
704
  int32_t flags;
700
705
  ca_size_t bytes;
701
706
  ca_size_t elements; /* = n_parents * parents[0]->elements */
702
- ca_size_t *dim; /* ALLOC_N(ndim) = [n_parents, *parent->dim] */
707
+ ca_size_t *dim; /* ALLOC_N(ndim): parent->dim with n_parents at k_axis */
703
708
  char *ptr;
704
709
  CArray *mask;
705
710
  char *_pool; /* framework-managed pool buffer (NULL = legacy ALLOC_N path).
@@ -731,8 +736,7 @@ typedef struct {
731
736
  shape[meld_axis] = sum_k parents[k]->dim[meld_axis]
732
737
  All other axes must match across parents (uniform check at constructor).
733
738
 
734
- v0.1 stub: external-axis (meld_axis == 0) structural xfer_stride path only.
735
- Other paths raise NotImplementedError. */
739
+ meld_axis may be any axis. */
736
740
  typedef struct {
737
741
  int16_t obj_type;
738
742
  int8_t data_type;
@@ -869,8 +873,10 @@ extern const char * ca_type_name[CA_NTYPE];
869
873
  extern const int ca_cast_table[CA_NTYPE][CA_NTYPE];
870
874
  extern const int ca_cast_table2[CA_NTYPE][CA_NTYPE];
871
875
 
872
- /* data_type promotion reducer — pure function over ca_cast_table. Used by
873
- CArray.result_type and by the lazy view layer. See ext/carray_cast.c
876
+ /* data_type promotion reducer over ca_cast_table. Used by
877
+ CArray.result_type and by the lazy view layer. Raises ArgumentError for
878
+ a code outside the data types, and CArray::DataTypeError for a pair with
879
+ no common type. See ext/carray_cast.c
874
880
  for the definition; this is the single source of the promotion rule. */
875
881
  int8_t ca_promote_type (int8_t a, int8_t b);
876
882
 
@@ -878,7 +884,8 @@ int8_t ca_promote_type (int8_t a, int8_t b);
878
884
  Complex, etc.) — distinct from rb_ca_guess_type which interprets the
879
885
  object as a data_type *representation* (e.g. T_FIXNUM as a data_type code).
880
886
  Used by rb_ca_cast_self_or_other.
881
- CArray is not accepted (callers should use ca->data_type directly). */
887
+ A CArray, like any object it does not recognise, answers CA_OBJECT;
888
+ callers holding a CArray use ca->data_type. */
882
889
  int8_t ca_value_to_data_type (VALUE obj);
883
890
 
884
891
  /* Infer a data_type code from a MemoryView producer by parsing its format,
@@ -930,8 +937,6 @@ extern const rb_data_type_t cabyteswap_data_type;
930
937
  /* cafield_data_type was retired in 3.0 (Phase F: CAField is now a
931
938
  CAStride subclass; use castride_data_type). */
932
939
  extern const rb_data_type_t cagrid_data_type;
933
- /* camapping_data_type was retired in 3.0 (R.3: CAMapping removed; a[mapper]
934
- now builds a CAGrid/CAStride normalize chain). */
935
940
  extern const rb_data_type_t caobject_data_type;
936
941
  extern const rb_data_type_t careduce_data_type;
937
942
  extern const rb_data_type_t carefer_data_type;
@@ -942,7 +947,6 @@ extern const rb_data_type_t cawindow_data_type;
942
947
  extern const rb_data_type_t carray_mask_data_type;
943
948
  extern const rb_data_type_t cablock_mask_data_type;
944
949
  extern const rb_data_type_t cagrid_mask_data_type;
945
- extern const rb_data_type_t camapping_mask_data_type;
946
950
  extern const rb_data_type_t careduce_mask_data_type;
947
951
  extern const rb_data_type_t carefer_mask_data_type;
948
952
  extern const rb_data_type_t caselect_mask_data_type;
@@ -999,50 +1003,59 @@ extern VALUE rb_cCArrayObject;
999
1003
 
1000
1004
  #define CA_CHECK_DATA_TYPE(data_type) \
1001
1005
  do { \
1002
- if ( data_type <= CA_NONE || data_type >= CA_NTYPE ) { \
1003
- rb_raise(rb_eArgError, "invalid data_type id %i", data_type); \
1006
+ int ca_dt_ = (data_type); \
1007
+ if ( ca_dt_ <= CA_NONE || ca_dt_ >= CA_NTYPE ) { \
1008
+ rb_raise(rb_eArgError, "invalid data_type id %i", ca_dt_); \
1004
1009
  } \
1005
- if ( ! ca_valid[data_type] ) { \
1006
- rb_raise(rb_eCADataTypeError, "data_type %s is disabled", ca_type_name[data_type]); \
1010
+ if ( ! ca_valid[ca_dt_] ) { \
1011
+ rb_raise(rb_eCADataTypeError, "data_type %s is disabled", ca_type_name[ca_dt_]); \
1007
1012
  } \
1008
1013
  } while (0)
1009
1014
 
1010
1015
  #define CA_CHECK_DATA_TYPE_NUMERIC(data_type) \
1011
- if ( data_type <= CA_NONE || data_type >= CA_NTYPE || !ca_valid[data_type] || data_type == CA_FIXLEN || data_type == CA_OBJECT ) { \
1012
- rb_raise(rb_eCADataTypeError, "invalid numeric data type"); \
1013
- }
1016
+ do { \
1017
+ int ca_dt_ = (data_type); \
1018
+ if ( ca_dt_ <= CA_NONE || ca_dt_ >= CA_NTYPE || !ca_valid[ca_dt_] || \
1019
+ ca_dt_ == CA_FIXLEN || ca_dt_ == CA_OBJECT ) { \
1020
+ rb_raise(rb_eCADataTypeError, "invalid numeric data type"); \
1021
+ } \
1022
+ } while (0)
1014
1023
 
1015
1024
  #define CA_CHECK_RANK(ndim) \
1016
- if ( ndim <= 0 || ndim > CA_RANK_MAX ) { \
1017
- rb_raise(rb_eArgError, "invalid ndim"); \
1018
- }
1025
+ do { \
1026
+ if ( (ndim) <= 0 || (ndim) > CA_RANK_MAX ) { \
1027
+ rb_raise(rb_eArgError, "invalid ndim"); \
1028
+ } \
1029
+ } while (0)
1019
1030
 
1020
1031
  #define CA_CHECK_DIM(ndim, dim) \
1021
- { \
1032
+ do { \
1022
1033
  int8_t i_; \
1023
- for (i_=0; i_<ndim; i_++) { \
1024
- if ( dim[i_] < 0 ) { \
1034
+ for (i_=0; i_<(ndim); i_++) { \
1035
+ if ( (dim)[i_] < 0 ) { \
1025
1036
  rb_raise(rb_eArgError, "negative size dimension at %i-dim", i_); \
1026
1037
  } \
1027
1038
  } \
1028
- }
1039
+ } while (0)
1029
1040
 
1030
1041
  /* A fixlen cell is at least one byte wide. A zero-width cell has one
1031
1042
  possible value, and a strided view of it cannot say which cell is which:
1032
1043
  its byte strides are all zero. */
1033
1044
  #define CA_CHECK_BYTES(data_type, bytes) \
1034
- if ( data_type == CA_FIXLEN ) { \
1035
- if ( bytes <= 0 ) { \
1036
- rb_raise(rb_eArgError, \
1037
- "invalid bytes (a fixlen needs bytes: of 1 or more)"); \
1045
+ do { \
1046
+ if ( (data_type) == CA_FIXLEN ) { \
1047
+ if ( (bytes) <= 0 ) { \
1048
+ rb_raise(rb_eArgError, \
1049
+ "invalid bytes (a fixlen needs bytes: of 1 or more)"); \
1050
+ } \
1038
1051
  } \
1039
- } \
1040
- else { \
1041
- bytes = ca_sizeof[data_type]; \
1042
- if ( bytes <= 0 ) { \
1043
- rb_raise(rb_eArgError, "invalid bytes"); \
1052
+ else { \
1053
+ (bytes) = ca_sizeof[(data_type)]; \
1054
+ if ( (bytes) <= 0 ) { \
1055
+ rb_raise(rb_eArgError, "invalid bytes"); \
1056
+ } \
1044
1057
  } \
1045
- }
1058
+ } while (0)
1046
1059
 
1047
1060
  /* An index into `n` places, counted from the end when negative, outside of
1048
1061
  which IndexError is raised naming the method the user called, `what` the
@@ -1108,6 +1121,10 @@ rb_carray_num2cmplx (VALUE num)
1108
1121
  }
1109
1122
  if ( rb_respond_to(num, rb_intern("to_c")) ) {
1110
1123
  VALUE c = rb_funcall(num, rb_intern("to_c"), 0);
1124
+ if ( ! RB_TYPE_P(c, T_COMPLEX) ) {
1125
+ rb_raise(rb_eTypeError, "can't convert %"PRIsVALUE" to Complex (%"PRIsVALUE"#to_c gives %"PRIsVALUE")",
1126
+ rb_obj_class(num), rb_obj_class(num), rb_obj_class(c));
1127
+ }
1111
1128
  return CMPLX(NUM2DBL(rb_complex_real(c)), NUM2DBL(rb_complex_imag(c)));
1112
1129
  }
1113
1130
  if ( rb_respond_to(num, rb_intern("to_f")) ) {
@@ -1184,8 +1201,7 @@ enum {
1184
1201
  CA_IDX_SCALAR,
1185
1202
  CA_IDX_ALL,
1186
1203
  CA_IDX_BLOCK,
1187
- CA_IDX_SYMBOL,
1188
- CA_IDX_REPEAT
1204
+ CA_IDX_SYMBOL
1189
1205
  }; /* CA_INDEX_TYPE */
1190
1206
 
1191
1207
  typedef union {
@@ -1254,14 +1270,14 @@ VALUE rb_carray_new_safe (int8_t data_type,
1254
1270
  already hold a freshly decoded buffer and want to avoid a copy. The
1255
1271
  buffer must be ruby_xmalloc()'d and at least elements*bytes long; it
1256
1272
  is freed with xfree() when the array is collected. data_type must not
1257
- be CA_OBJECT. */
1273
+ be CA_OBJECT. When the call raises (a bad argument), the buffer stays
1274
+ the caller's. */
1258
1275
  CArray *carray_new_adopt (int8_t data_type,
1259
1276
  int8_t ndim, ca_size_t *dim, ca_size_t bytes, char *ptr);
1260
1277
  VALUE rb_carray_new_adopt (int8_t data_type,
1261
1278
  int8_t ndim, ca_size_t *dim, ca_size_t bytes, char *ptr);
1262
1279
 
1263
- /* Capstone helper: allocate
1264
- a reduction-output CArray for kernel_iterator authors. Computes
1280
+ /* Allocate a reduction-output CArray for kernel_iterator authors. Computes
1265
1281
  output shape = self.dim with slab axes removed (ascending order),
1266
1282
  collapses to shape [1] when fully reduced. See
1267
1283
  ext/carray_core.c for docstring + semantics. */
@@ -1272,10 +1288,10 @@ VALUE rb_ca_new_reduced (VALUE self, int8_t *slab_axes,
1272
1288
  VALUE rb_ca_new_reduced_bytes (VALUE self, int8_t *slab_axes, int8_t naxes,
1273
1289
  int32_t data_type, ca_size_t bytes, int keep_axis);
1274
1290
 
1275
- /* Capstone helper: parse
1276
- variadic axis argv into validated int8_t array. Accepts Integer
1277
- args or a single Array arg, normalises negative axes (Python-style),
1278
- range / duplicate / overflow checks all raise ArgumentError.
1291
+ /* Parse variadic axis argv into a validated int8_t array. Accepts Integer
1292
+ args or a single Array arg (no argument = every axis), counts negative
1293
+ axes from the end, and raises ArgumentError for an axis out of range or
1294
+ given twice.
1279
1295
  Returns the validated naxes. */
1280
1296
  int8_t rb_ca_parse_reduce_axes (int argc, VALUE *argv,
1281
1297
  CArray *ca, int8_t *out_axes);
@@ -1321,7 +1337,11 @@ VALUE rb_ca_farray (VALUE self);
1321
1337
 
1322
1338
  /* --- ca_obj_stride.c --- */
1323
1339
 
1324
- /* ca_stride_setup with ca == NULL runs its checks and returns 0 without
1340
+ /* The strides and base_offset are taken as given: they are not checked
1341
+ against the parent's extent, so a view that reaches outside it reads
1342
+ and writes outside it.
1343
+
1344
+ ca_stride_setup with ca == NULL runs its checks and returns 0 without
1325
1345
  writing. ca_stride_new calls it that way before it allocates, so a
1326
1346
  rejected argument leaves no struct behind; a subclass constructor can
1327
1347
  do the same through its own setup function. */
@@ -1394,8 +1414,16 @@ void ca_broadcast_pair (volatile VALUE *self, volatile VALUE *other);
1394
1414
  ca_install_obj_type(klass, &td, mask_klass, &mask_td,
1395
1415
  &my_func, sizeof(my_func));
1396
1416
 
1417
+ The table must reach at least through xfer_all: xfer_index, xfer_addrs
1418
+ and xfer_all have no default. fold_stride may be NULL (the view is a
1419
+ fold boundary); xfer_stride, the pool slots, fill_addrs and fill_stride
1420
+ fall back to a default when NULL. A shorter table raises RuntimeError.
1397
1421
  A func_size larger than this build's struct means the caller was compiled
1398
- against a newer carray; that is reported rather than truncated. */
1422
+ against a newer carray; that is reported rather than truncated.
1423
+
1424
+ The obj_type parameters of ca_array_alloc, ca_array_pool_alloc,
1425
+ ca_stride_setup and ca_stride_new are int8_t, so an obj_type is numbered
1426
+ below 128: an install that would number one at 128 or above raises. */
1399
1427
 
1400
1428
  int
1401
1429
  ca_install_obj_type (VALUE klass,
@@ -1462,19 +1490,24 @@ int ca_is_mask_array (void *ap);
1462
1490
  #define GetCArray(obj, ca) \
1463
1491
  TypedData_Get_Struct((obj), CArray, &carray_data_type, (ca))
1464
1492
 
1465
- /* True iff ca_attach(ca) is essentially O(1) — entity arrays (already
1466
- attached), CAWrap, CScalar, and CAStride-family views whose composed
1467
- strides are row-major contiguous (alias-attach path). Used by
1468
- kernel_iterator's L1 alias decision (ca_iter_can_alias level 1) and
1469
- by overlay-view dispatch. The name says the structural property
1470
- (= aliasable without materialise), not the perf characteristic. */
1493
+ /* True when ca_attach(ca) gives ca->ptr the cells in place, without
1494
+ materialising: entity arrays, CAWrap, CScalar, and CAStride-family
1495
+ views whose composed strides are row-major contiguous over an attached
1496
+ root (alias-attach path). It is not the same as "attach is O(1)": a
1497
+ Face attaches in O(1) by borrowing its parent and answers false, and a
1498
+ CASource entity that publishes its ptr only while attached answers
1499
+ true. Used by the kernel iterator's alias decision, the sweep engine,
1500
+ and the views and mask paths that skip a sync when nothing was copied. */
1471
1501
  int ca_attach_is_alias (void *ap);
1472
1502
 
1473
1503
  /* OR operand masks into
1474
1504
  ca_out->mask without ca_attach on operand masks (= gathers via
1475
- ca_xfer_all into arena scratch then byte OR-folds). ca_out must be
1476
- a freshly templated entity. For bang variant where ca_out IS one of
1477
- the operands, the existing mask is preserved as initial accumulator. */
1505
+ ca_xfer_all into arena scratch then byte OR-folds). ca_out's mask is
1506
+ written through its ptr, so ca_out is an entity or an attached view.
1507
+ Each operand other than a scalar has ca_out's number of elements
1508
+ (ArgumentError otherwise); n is at most 8. For bang variant where
1509
+ ca_out IS one of the operands, the existing mask is preserved as
1510
+ initial accumulator. */
1478
1511
  void ca_mask_overlay_safe (CArray *ca_out, int n, ...);
1479
1512
 
1480
1513
  #define ca_is_caobject(ca) ( (ca)->obj_type == CA_OBJ_OBJECT )
@@ -1524,20 +1557,30 @@ int ca_is_valid_index (void *ap, ca_size_t *idx);
1524
1557
  internally (views carry an attach refcount; entities do
1525
1558
  not).
1526
1559
  R5 (traffic) Attach hands you a buffer, not a live array. Use x->ptr;
1527
- a view derived from x composes past the buffer to the
1528
- root.
1560
+ a view derived from x may read past the buffer to the
1561
+ root (a CAStride-family view over a CAStride-family x
1562
+ does) or read the buffer (others), so writes to the
1563
+ buffer are not seen through derived views until x is
1564
+ synced.
1529
1565
  R6 (raising) ca_allocate and ca_attach that raise have taken
1530
1566
  nothing; ca_allocate_n and ca_attach_n take all of
1531
1567
  their arrays or none. Close a window with
1532
1568
  ca_sync_detach, which detaches even when the sync
1533
1569
  raises -- ca_sync then ca_detach leaves the window open
1534
- on a raise. Anything between that can raise (Ruby
1570
+ on a raise. ca_sync_detach syncs, so it raises on a
1571
+ read-only array; a window that only read closes with
1572
+ ca_detach. Anything between that can raise (Ruby
1535
1573
  called from inside the window) needs an ensure of its
1536
1574
  own.
1537
1575
  */
1538
1576
 
1577
+ /* ca_allocate opens a window for writing every cell: what the cells held
1578
+ before is not kept, also when the array is already attached (object cells
1579
+ are reset to 0 and the mask is cleared). */
1539
1580
  void ca_allocate (void *ap);
1540
1581
  void ca_attach (void *ca);
1582
+ /* Re-gather an attached view's buffer from its parent (one level: a parent
1583
+ that holds its own buffer is read as it is). */
1541
1584
  void ca_update (void *ca);
1542
1585
  void ca_sync (void *ca);
1543
1586
  void ca_detach (void *ca);
@@ -1549,17 +1592,70 @@ void ca_update_n (int n, ...);
1549
1592
  void ca_sync_n (int n, ...);
1550
1593
  void ca_detach_n (int n, ...);
1551
1594
 
1595
+ /* API : lending the addresses of cells
1596
+
1597
+ A kernel that reads cells by address itself -- a stencil reading
1598
+ a[i-1][j] and a[i+1][j] from its own loop -- needs, for each array, a
1599
+ pointer to cell (0, ..., 0) and the byte distance between neighbours
1600
+ along each axis. ca_with_address_bases lends that for the duration of
1601
+ `body`, whatever the arrays are, and puts back what the kernel wrote:
1602
+
1603
+ - an entity, or a view the engine can fold down to one (a slice, a
1604
+ transpose, a reshape), is addressed in place;
1605
+ - any other view (a selection, a conversion, a lazy expression) has
1606
+ the cells the kernel touches copied into a buffer, which is lent
1607
+ instead and, for a writable array, sent back afterwards: only the
1608
+ cells the kernel changed, through the view.
1609
+
1610
+ `box_start[i]` / `box_count[i]` (ndim values each) say which cells
1611
+ array i's kernel touches -- its loop range, widened by how far the
1612
+ kernel reaches (one cell each way for a[i-1] .. a[i+1]). They decide
1613
+ what the second case copies; the first case lends the whole array
1614
+ either way. Pass NULL for `box_start` and `box_count` (or for an
1615
+ entry of them) to lend the whole array. A box outside the array is
1616
+ refused. Address only the box, whichever way the array was lent.
1617
+
1618
+ `writable[i]` says whether the kernel writes array i (NULL: none is
1619
+ written); a read-only array is refused for writing. An object array
1620
+ is refused (its cells are Ruby values, not numbers), and so is a view
1621
+ with a mask that reinterprets the element size (its mask cells do not
1622
+ map one to one onto the parent's).
1623
+
1624
+ A masked array also lends its mask: one boolean8_t per cell (nonzero =
1625
+ masked), addressed with mask_strides the same way. A write to the
1626
+ mask is put back like a write to a cell. `mask` is NULL for an array
1627
+ with no mask.
1628
+
1629
+ `body` may raise: the arrays are still written back and closed.
1630
+ Returns what `body` returns. The CArray pointers must stay alive for
1631
+ the call (keep the VALUEs they came from). */
1632
+ typedef struct {
1633
+ char *ptr; /* cell (0, ..., 0) */
1634
+ ca_size_t strides[CA_RANK_MAX]; /* byte step along each axis */
1635
+ boolean8_t *mask; /* NULL when no mask */
1636
+ ca_size_t mask_strides[CA_RANK_MAX]; /* byte step in the mask */
1637
+ int writable;
1638
+ } ca_address_basis_t;
1639
+
1640
+ VALUE ca_with_address_bases (int32_t n, CArray **arrays, const int *writable,
1641
+ const ca_size_t *const *box_start,
1642
+ const ca_size_t *const *box_count,
1643
+ VALUE (*body)(ca_address_basis_t *bases,
1644
+ VALUE arg),
1645
+ VALUE arg);
1646
+
1552
1647
  /* API : copying */
1553
1648
 
1554
1649
  void *ca_clone (void *ap); /* use rb_obj_clone() */
1650
+ /* A CA_OBJECT copy holds VALUEs the GC does not see until the struct is
1651
+ wrapped, and wrapping allocates: for an object array use rb_ca_copy, which
1652
+ keeps them alive and returns the wrapped copy. */
1555
1653
  CArray *ca_copy (void *ap); /* use rb_ca_copy() */
1556
1654
  CArray *ca_template (void *ap); /* use rb_ca_template() */
1557
1655
  CArray *ca_template_safe (void *ap); /* use rb_ca_template() */
1558
1656
  CArray *ca_template_safe2 (void *ap, int8_t data_type, ca_size_t bytes);
1559
1657
  /* use rb_ca_template() */
1560
1658
 
1561
- /* ca_paste / ca_clip / ca_cut (sub-region copy in/out) removed in 3.0; see
1562
- lib/extras/crop_paste.rb for the Ruby thin wrapper replacements. */
1563
1659
  void ca_fill (void *ap, void *ptr);
1564
1660
 
1565
1661
  /* API : fetch, store */
@@ -1580,9 +1676,10 @@ void ca_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *data, int
1580
1676
  opportunistic engine dispatch. */
1581
1677
  int ca_xfer_addrs_is_sequential_run (ca_size_t n, ca_size_t *addrs,
1582
1678
  ca_size_t *base_out);
1583
- /* Y.1.e: resolve cand through identity CAStride compose-fold to find an
1679
+ /* Resolve cand through identity CAStride compose-fold to find an
1584
1680
  attached root. Returns cand if cand->ptr is set, cand is not CAStride
1585
- family, or no identity compose-fold path exists; otherwise returns the
1681
+ family, or no identity compose-fold path exists (the cells differ from
1682
+ the root's in data type, width or position); otherwise returns the
1586
1683
  resolved root (which has ptr). Used by view xfer_addrs slots to lift
1587
1684
  parent->ptr gate through view CAStride layers (= chain pattern). */
1588
1685
  CArray *ca_resolve_attached_root_via_identity (CArray *cand);
@@ -1658,6 +1755,8 @@ void ca_fill_stride_whole (void *ap, void *ptr);
1658
1755
  extern VALUE CA_UNDEF;
1659
1756
  extern VALUE CA_UNSPECIFIED;
1660
1757
 
1758
+ /* The mask's buffer, which a view's mask has only while attached: NULL
1759
+ otherwise. */
1661
1760
  boolean8_t *ca_mask_ptr (void *ap);
1662
1761
  int ca_has_mask (void *ap);
1663
1762
  int ca_is_any_masked (void *ap);
@@ -1674,7 +1773,7 @@ void ca_copy_mask_overwrite (void *ap, ca_size_t elements, int n, ...);
1674
1773
  ca_size_t ca_count_masked (void *ap);
1675
1774
  ca_size_t ca_count_not_masked (void *ap);
1676
1775
  void ca_unmask (void *ap, char *fill_value);
1677
- CArray *ca_unmasked_copy (void *ap, char *fill_value);
1776
+ CArray *ca_unmask_copy (void *ap, char *fill_value);
1678
1777
 
1679
1778
  /* API : cast, conversion */
1680
1779
 
@@ -1688,7 +1787,7 @@ void ca_ptr2val (void *ap1, void *ptr1, int8_t data_type2, void *ptr2);
1688
1787
  void ca_val2ptr (int8_t data_type1, void *ptr1, void *ap2, void *ptr2);
1689
1788
  void ca_val2val (int8_t data_type1, void *ptr1, int8_t data_type2, void *ptr2);
1690
1789
  VALUE ca_ptr2obj (void *ap, void *ptr); /* use rb_ca_ptr2obj() */
1691
- void ca_obj2ptr (void *ap, VALUE obj, void *ptr); /* use rb_ca_ptr2obj() */
1790
+ void ca_obj2ptr (void *ap, VALUE obj, void *ptr); /* use rb_ca_obj2ptr() */
1692
1791
 
1693
1792
  #define ca_wrap_writable(obj, data_type) \
1694
1793
  (obj = rb_ca_wrap_writable(obj, INT2NUM(data_type)), (CArray*) DATA_PTR(obj))
@@ -1738,6 +1837,8 @@ void rb_check_carray_object (VALUE arg);
1738
1837
 
1739
1838
  /* specific Data_Wrap_Struct for carray */
1740
1839
  VALUE ca_wrap_struct (void *ap);
1840
+ /* As ca_wrap_struct, under the class klass. klass is not checked: it must
1841
+ be a CArray class whose instances share ap's TypedData. */
1741
1842
  VALUE ca_wrap_struct_as (void *ap, VALUE klass);
1742
1843
 
1743
1844
  /* query data_type */
@@ -1746,7 +1847,8 @@ void rb_ca_guess_type_and_bytes (VALUE rtype, VALUE rbytes,
1746
1847
  int8_t *data_type, ca_size_t *bytes);
1747
1848
  int rb_ca_is_type (VALUE arg, int type);
1748
1849
 
1749
- /* scan index */
1850
+ /* scan index. info->range_check is read, not written: set it (1 to check
1851
+ each index against ca_dim) before the call. */
1750
1852
  void rb_ca_scan_index (int ca_ndim, ca_size_t *ca_dim, ca_size_t elements,
1751
1853
  long argc, VALUE *argv, CAIndexInfo *info);
1752
1854
 
@@ -1853,9 +1955,13 @@ VALUE rb_ca_fill_copy (VALUE self, VALUE val);
1853
1955
  /* address calculation */
1854
1956
  VALUE rb_ca_addr2index (VALUE self, VALUE raddr);
1855
1957
 
1856
- /* elemental access like ca[i,j,k] or ca[addr] */
1958
+ /* A cell's bytes (self's data type, self->bytes wide) as the value ca[i]
1959
+ gives for that cell: true or false for a boolean, the element for a
1960
+ Face, a record for a struct. The mask is not consulted. */
1857
1961
  VALUE rb_ca_ptr2obj (VALUE self, void *ptr);
1858
1962
  #define rb_ca_fetch_ptr(self, ptr) rb_ca_ptr2obj(self, ptr)
1963
+
1964
+ /* elemental access like ca[i,j,k] or ca[addr] */
1859
1965
  VALUE rb_ca_fetch_index (VALUE self, ca_size_t *idx);
1860
1966
  VALUE rb_ca_fetch_addr (VALUE self, ca_size_t addr);
1861
1967
  VALUE rb_ca_fetch (VALUE self, VALUE index);