carray 3.0.1 → 3.0.3

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 (229) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +824 -0
  3. data/README.md +5 -6
  4. data/carray.gemspec +1 -1
  5. data/ext/ca_axis_dispatch.c +258 -4
  6. data/ext/ca_axis_group.c +368 -184
  7. data/ext/ca_binop_dispatch.c +54 -32
  8. data/ext/ca_binop_dispatch.h +1 -0
  9. data/ext/ca_categorical_iterator.c +90 -41
  10. data/ext/ca_compare.c +8 -2
  11. data/ext/ca_for_buffer.h +21 -68
  12. data/ext/ca_group_iter.c +27 -11
  13. data/ext/ca_kernel_iterator.c +960 -245
  14. data/ext/ca_kernel_iterator.h +352 -181
  15. data/ext/ca_monop_dispatch.c +4 -4
  16. data/ext/ca_monop_dispatch.h +4 -0
  17. data/ext/ca_obj_array.c +194 -42
  18. data/ext/ca_obj_bincmp.c +152 -121
  19. data/ext/ca_obj_binop.c +107 -210
  20. data/ext/ca_obj_bitarray.c +37 -24
  21. data/ext/ca_obj_bitfield.c +95 -62
  22. data/ext/ca_obj_block.c +5 -4
  23. data/ext/ca_obj_byte_swap.c +40 -40
  24. data/ext/ca_obj_const_string.c +180 -50
  25. data/ext/ca_obj_face.c +428 -62
  26. data/ext/ca_obj_face.h +107 -47
  27. data/ext/ca_obj_fake.c +21 -50
  28. data/ext/ca_obj_farray.c +1 -0
  29. data/ext/ca_obj_field.c +16 -3
  30. data/ext/ca_obj_fixlen_string.c +39 -26
  31. data/ext/ca_obj_grid.c +181 -124
  32. data/ext/ca_obj_meld.c +235 -55
  33. data/ext/ca_obj_moncmp.c +61 -61
  34. data/ext/ca_obj_monop.c +125 -107
  35. data/ext/ca_obj_object.c +551 -233
  36. data/ext/ca_obj_record.c +51 -16
  37. data/ext/ca_obj_reduce.c +5 -8
  38. data/ext/ca_obj_refer.c +117 -33
  39. data/ext/ca_obj_remap.c +57 -17
  40. data/ext/ca_obj_repeat.c +21 -5
  41. data/ext/ca_obj_roll.c +115 -11
  42. data/ext/ca_obj_select.c +88 -75
  43. data/ext/ca_obj_select_axis.c +58 -60
  44. data/ext/ca_obj_shift.c +22 -102
  45. data/ext/ca_obj_stack.c +223 -123
  46. data/ext/ca_obj_stride.c +267 -35
  47. data/ext/ca_obj_string.c +25 -22
  48. data/ext/ca_obj_tile.c +32 -16
  49. data/ext/ca_obj_time.c +23 -25
  50. data/ext/ca_obj_timedelta.c +21 -23
  51. data/ext/ca_obj_transpose.c +12 -3
  52. data/ext/ca_obj_triop.c +110 -117
  53. data/ext/ca_obj_window.c +157 -29
  54. data/ext/ca_op_ipower.c +25 -13
  55. data/ext/ca_op_powi.h +57 -30
  56. data/ext/ca_pow5_table.h +656 -0
  57. data/ext/ca_rng_normal.h +42 -0
  58. data/ext/ca_rng_xoshiro256pp.h +105 -0
  59. data/ext/ca_sort_kernels.h +70 -0
  60. data/ext/ca_sweep_engine.c +385 -198
  61. data/ext/ca_sweep_engine.h +31 -23
  62. data/ext/ca_triop_dispatch.c +4 -1
  63. data/ext/ca_triop_dispatch.h +5 -2
  64. data/ext/caframe_csv_reader.c +463 -0
  65. data/ext/carray.h +90 -28
  66. data/ext/carray_access.c +487 -231
  67. data/ext/carray_address_basis.c +731 -0
  68. data/ext/carray_attribute.c +45 -3
  69. data/ext/carray_bincount.c +32 -2
  70. data/ext/carray_broadcast.c +49 -17
  71. data/ext/carray_call_cfunc.c +667 -511
  72. data/ext/carray_cast.c +1556 -247
  73. data/ext/carray_cast_func.rb +34 -21
  74. data/ext/carray_conversion.c +197 -73
  75. data/ext/carray_copy.c +84 -38
  76. data/ext/carray_core.c +591 -119
  77. data/ext/carray_count.c +148 -96
  78. data/ext/carray_element.c +18 -27
  79. data/ext/carray_factorize.c +604 -291
  80. data/ext/carray_generate.c +76 -40
  81. data/ext/carray_histogram.c +152 -94
  82. data/ext/carray_hold.c +2 -1
  83. data/ext/carray_index_classifier.c +63 -96
  84. data/ext/carray_internal.h +400 -1
  85. data/ext/carray_lazy.c +834 -79
  86. data/ext/carray_loop.c +88 -66
  87. data/ext/carray_mask.c +705 -324
  88. data/ext/carray_math_kernel.h +1 -0
  89. data/ext/carray_median_percentile.c +263 -63
  90. data/ext/carray_memory_view.c +254 -248
  91. data/ext/carray_operator.c +1093 -363
  92. data/ext/carray_order.c +133 -69
  93. data/ext/carray_partition.c +102 -56
  94. data/ext/carray_random.c +582 -204
  95. data/ext/carray_scatter.c +308 -65
  96. data/ext/carray_segment.c +257 -0
  97. data/ext/carray_slab.c +183 -70
  98. data/ext/carray_sort.c +235 -240
  99. data/ext/carray_sort_kernel.c +8 -1
  100. data/ext/carray_struct.c +99 -21
  101. data/ext/carray_test.c +167 -64
  102. data/ext/carray_time_text.c +1182 -0
  103. data/ext/carray_utils.c +363 -98
  104. data/ext/extconf.rb +27 -2
  105. data/ext/mk_call_cfunc.rb +103 -118
  106. data/ext/mk_pow5_table.rb +35 -0
  107. data/ext/mkkernel.rb +1349 -851
  108. data/ext/ruby_carray.c +17 -2
  109. data/ext/version.h +4 -4
  110. data/ext/version.rb +4 -2
  111. data/lib/carray/attribute.rb +39 -0
  112. data/lib/carray/autoload_carray.rb +24 -3
  113. data/lib/carray/autoload_method_extension.rb +18 -0
  114. data/lib/carray/axis_group.rb +245 -20
  115. data/lib/carray/basics.rb +95 -25
  116. data/lib/carray/bincount_nd.rb +6 -0
  117. data/lib/carray/block_iterator.rb +200 -54
  118. data/lib/carray/boolean_reduce.rb +21 -29
  119. data/lib/carray/categorical.rb +244 -59
  120. data/lib/carray/categorical_iterator.rb +391 -757
  121. data/lib/carray/complex.rb +36 -29
  122. data/lib/carray/conditional.rb +94 -7
  123. data/lib/carray/const_string.rb +177 -27
  124. data/lib/carray/construct.rb +40 -0
  125. data/lib/carray/data_type_extension.rb +3 -0
  126. data/lib/carray/data_type_limits.rb +91 -0
  127. data/lib/carray/fixlen_string.rb +1 -1
  128. data/lib/carray/frame/concat.rb +157 -6
  129. data/lib/carray/frame/convert.rb +13 -7
  130. data/lib/carray/frame/csv_parser.rb +590 -76
  131. data/lib/carray/frame/describe.rb +79 -0
  132. data/lib/carray/frame/frame.rb +205 -35
  133. data/lib/carray/frame/group.rb +199 -40
  134. data/lib/carray/frame/io.rb +452 -60
  135. data/lib/carray/frame/join.rb +134 -46
  136. data/lib/carray/frame/records.rb +54 -19
  137. data/lib/carray/frame/reshape.rb +448 -0
  138. data/lib/carray/frame/sort.rb +26 -2
  139. data/lib/carray/frame/verbs.rb +726 -56
  140. data/lib/carray/frame.rb +2 -0
  141. data/lib/carray/fuse_source.rb +111 -2
  142. data/lib/carray/fusion.rb +229 -38
  143. data/lib/carray/inspect.rb +71 -20
  144. data/lib/carray/iterator.rb +157 -2
  145. data/lib/carray/lazy.rb +54 -67
  146. data/lib/carray/mask_gap_fill.rb +66 -50
  147. data/lib/carray/math.rb +32 -19
  148. data/lib/carray/meld_reduce.rb +40 -7
  149. data/lib/carray/methods/align_addr.rb +8 -4
  150. data/lib/carray/methods/bincount.rb +2 -2
  151. data/lib/carray/methods/bit_string.rb +14 -3
  152. data/lib/carray/methods/composition.rb +16 -10
  153. data/lib/carray/methods/discovery_along.rb +74 -0
  154. data/lib/carray/methods/factorize.rb +50 -0
  155. data/lib/carray/methods/gather_nd.rb +13 -2
  156. data/lib/carray/methods/insert_block.rb +9 -14
  157. data/lib/carray/methods/is_in.rb +130 -6
  158. data/lib/carray/methods/join.rb +1 -1
  159. data/lib/carray/methods/locate_addr.rb +235 -21
  160. data/lib/carray/methods/mask_duplicates.rb +35 -1
  161. data/lib/carray/methods/mode.rb +18 -1
  162. data/lib/carray/methods/nunique.rb +22 -1
  163. data/lib/carray/methods/repeat.rb +91 -0
  164. data/lib/carray/methods/resize.rb +21 -23
  165. data/lib/carray/methods/snap.rb +34 -12
  166. data/lib/carray/methods/unique.rb +52 -3
  167. data/lib/carray/record_order.rb +208 -0
  168. data/lib/carray/rng.rb +86 -0
  169. data/lib/carray/runtime.rb +14 -11
  170. data/lib/carray/segment_iterator.rb +990 -0
  171. data/lib/carray/serialize.rb +197 -27
  172. data/lib/carray/slab_iterator.rb +109 -40
  173. data/lib/carray/stack.rb +10 -4
  174. data/lib/carray/string_operation_extension.rb +9 -4
  175. data/lib/carray/struct.rb +142 -51
  176. data/lib/carray/struct_builder.rb +110 -14
  177. data/lib/carray/table.rb +2 -2
  178. data/lib/carray/time.rb +535 -105
  179. data/lib/carray/window_iterator.rb +259 -82
  180. data/lib/carray.rb +4 -2
  181. data/yard-stubs/ca_obj_array.rb +4 -4
  182. data/yard-stubs/ca_obj_bitarray.rb +7 -0
  183. data/yard-stubs/ca_obj_bitfield.rb +23 -12
  184. data/yard-stubs/ca_obj_block.rb +2 -7
  185. data/yard-stubs/ca_obj_fake.rb +1 -1
  186. data/yard-stubs/ca_obj_field.rb +1 -1
  187. data/yard-stubs/ca_obj_refer.rb +3 -3
  188. data/yard-stubs/ca_obj_roll.rb +0 -1
  189. data/yard-stubs/ca_obj_stride.rb +10 -7
  190. data/yard-stubs/ca_obj_transpose.rb +1 -1
  191. data/yard-stubs/ca_obj_window.rb +11 -4
  192. data/yard-stubs/carray_access.rb +6 -5
  193. data/yard-stubs/carray_broadcast.rb +2 -2
  194. data/yard-stubs/carray_cast.rb +78 -43
  195. data/yard-stubs/carray_conversion.rb +13 -1
  196. data/yard-stubs/carray_copy.rb +8 -3
  197. data/yard-stubs/carray_core.rb +3 -83
  198. data/yard-stubs/carray_count.rb +16 -2
  199. data/yard-stubs/carray_lazy.rb +210 -1
  200. data/yard-stubs/carray_loop.rb +4 -1
  201. data/yard-stubs/carray_mask.rb +34 -10
  202. data/yard-stubs/carray_math.rb +1499 -4
  203. data/yard-stubs/carray_median_percentile.rb +26 -8
  204. data/yard-stubs/carray_order.rb +43 -82
  205. data/yard-stubs/carray_scatter.rb +10 -3
  206. data/yard-stubs/carray_segment.rb +72 -0
  207. data/yard-stubs/carray_slab.rb +11 -8
  208. data/yard-stubs/carray_sort.rb +50 -8
  209. data/yard-stubs/carray_test.rb +10 -0
  210. data/yard-stubs/carray_utils.rb +0 -26
  211. metadata +19 -19
  212. data/ext/ca_for_each_element.h +0 -239
  213. data/ext/carray_build_flags.h +0 -3
  214. data/ext/carray_config.h +0 -28
  215. data/ext/carray_kernels_bincmp.c +0 -4446
  216. data/ext/carray_kernels_binop.c +0 -11001
  217. data/ext/carray_kernels_init.c +0 -1131
  218. data/ext/carray_kernels_map.c +0 -3467
  219. data/ext/carray_kernels_moncmp.c +0 -2097
  220. data/ext/carray_kernels_monop.c +0 -18313
  221. data/ext/carray_kernels_reduce_aggregate.c +0 -25837
  222. data/ext/carray_kernels_reduce_boolean.c +0 -330
  223. data/ext/carray_kernels_reduce_cumulative.c +0 -14593
  224. data/ext/carray_kernels_reduce_extreme.c +0 -16948
  225. data/ext/carray_kernels_reduce_variance.c +0 -3910
  226. data/ext/carray_kernels_scan.c +0 -3693
  227. data/ext/carray_kernels_search.c +0 -32138
  228. data/ext/carray_kernels_sort.c +0 -10626
  229. data/ext/carray_kernels_triop.c +0 -1392
@@ -9,9 +9,16 @@ class CArray
9
9
  # Returns the median of `self` along `axis` (or over all elements
10
10
  # when `axis` is `nil`).
11
11
  #
12
- # Numeric arrays return a `Float`; `CA_OBJECT` arrays return the
13
- # result of Ruby `+` / `/` on the stored objects. Fixlen arrays
14
- # raise, since no numeric midpoint is defined.
12
+ # Numeric arrays return a `Float`. A `CA_OBJECT` array answers in
13
+ # its elements' own terms: the middle element itself, or the
14
+ # average of two as `(lo + hi) * (1/2)`, so an Integer, Rational or
15
+ # BigDecimal median is exact (`CA_OBJECT([1, 2]).median` is `3/2`).
16
+ # Fixlen arrays raise, since no numeric midpoint is defined.
17
+ #
18
+ # An even number of elements has no middle one, only the average of
19
+ # two -- so an object array whose elements cannot be averaged (a
20
+ # column of Strings) has a median at odd length and raises at even.
21
+ # `percentile(50, method: :lower)` names an element either way.
15
22
  #
16
23
  # Masked cells are excluded. Per-axis, each fiber uses only its own
17
24
  # present values; a fully masked fiber reduces to `UNDEF`. If the
@@ -27,7 +34,8 @@ class CArray
27
34
  # count is below `min_count`.
28
35
  # @param keep_axis [Boolean]
29
36
  # @return [Float, CArray, Object]
30
- # @raise [CArray::DataTypeError] for fixlen data_type.
37
+ # @raise [CArray::DataTypeError] for fixlen data_type, or for an even
38
+ # number of elements whose objects cannot be averaged.
31
39
  # @raise [ArgumentError] on negative `min_count`.
32
40
  def median(*); end
33
41
 
@@ -52,9 +60,17 @@ class CArray
52
60
  # - `:nearest` — round-half-to-even to the nearer neighbor.
53
61
  # - `:midpoint` — arithmetic mean of the two neighbors.
54
62
  #
55
- # Numeric arrays produce `Float` results; `CA_OBJECT` arrays
56
- # apply Ruby `+` / `/` / `*` on the stored objects. Fixlen
57
- # arrays raise.
63
+ # The first three pick an element and the last two compute one, so
64
+ # only the first three apply to a `CA_OBJECT` array whose elements
65
+ # have no arithmetic: `:linear` and `:midpoint` raise there, and do
66
+ # so only when the requested `p` actually falls between two
67
+ # elements (`percentile(50)` of five Strings still answers).
68
+ #
69
+ # Numeric arrays produce `Float` results. A `CA_OBJECT` array
70
+ # answers in its elements' own terms: a pick (`:lower`, `:higher`,
71
+ # `:nearest`) is the element itself, and `:linear` / `:midpoint`
72
+ # use the elements' arithmetic with an exact Rational weight, so an
73
+ # exact element gives an exact answer. Fixlen arrays raise.
58
74
  #
59
75
  # Masking, `min_count`, `fill_value`, and `keep_axis` follow the
60
76
  # same rules as {#median}.
@@ -67,7 +83,9 @@ class CArray
67
83
  # `:nearest`, `:midpoint`.
68
84
  # @param keep_axis [Boolean]
69
85
  # @return [Float, CArray, Object, Array<Float>, Array<CArray>, Array<Object>]
70
- # @raise [CArray::DataTypeError] for fixlen data_type.
86
+ # @raise [CArray::DataTypeError] for fixlen data_type, or when an
87
+ # interpolating `method` is asked to interpolate between objects
88
+ # that have no arithmetic.
71
89
  # @raise [ArgumentError] on empty `p` list, `p` outside `[0, 100]`,
72
90
  # empty axis, unknown `method`, or invalid option combinations.
73
91
  def percentile(*); end
@@ -30,13 +30,16 @@ class CArray
30
30
  # sort / sort_copy stubs live in yard-stubs/carray_sort.rb (same
31
31
  # file split as ext/carray_sort.c <-> ext/carray_order.c).
32
32
 
33
- # @overload partition(kth, axis: 0, masked_position: :last)
33
+ # @overload partition(kth, axis: nil, masked_position: :last)
34
34
  # Returns a `CARemap` view of `self` permuted along `axis` so that
35
35
  # the element at fiber-local position `kth` is in its final sorted
36
36
  # place, every element before it is `<=` it, and every element
37
37
  # after it is `>=` it. Order within the two regions is unspecified.
38
38
  # Average `O(n)` per fiber via quickselect.
39
39
  #
40
+ # Without `axis:` (or with `axis: nil`) `self` is flattened and
41
+ # treated as one fiber, as {#sort} does; the result is 1-D.
42
+ #
40
43
  # Negative `kth` counts from the end of the fiber
41
44
  # (`-self.shape[axis] <= kth < self.shape[axis]`).
42
45
  #
@@ -52,32 +55,39 @@ class CArray
52
55
  # among unmasked values.
53
56
  #
54
57
  # @param kth [Integer] target fiber-local position along `axis`.
55
- # @param axis [Integer]
58
+ # @param axis [Integer, nil] `nil` partitions the whole array.
56
59
  # @param masked_position [Symbol] `:last` (default) or `:first`.
57
60
  # @return [CArray] `CARemap` view of `self`.
58
61
  # @raise [ArgumentError] when `kth` is out of range.
59
- def partition(kth, axis: 0, masked_position: :last); end
62
+ def partition(kth, axis: nil, masked_position: :last); end
60
63
 
61
- # @overload partition_copy(kth, axis: 0, masked_position: :last)
62
- # Returns a fresh entity `CArray` with the same shape as `self`,
63
- # partitioned along `axis` by the same rule as {#partition}.
64
+ # @overload partition_copy(kth, axis: nil, masked_position: :last)
65
+ # Returns a fresh entity `CArray` partitioned along `axis` by the
66
+ # same rule as {#partition}: the shape of `self`, or 1-D when `axis`
67
+ # is omitted.
64
68
  # Bypasses the `CARemap` scatter layer for cases where an entity
65
69
  # is wanted directly. Same dispatch (numeric / boolean / `CA_FIXLEN` /
66
70
  # `CA_OBJECT`), same `kth` and `masked_position:` semantics.
67
71
  # Masked input delegates to {#partition} + copy.
68
72
  #
73
+ # A Face partitions in its surface order and comes back as the same
74
+ # Face: one whose storage order is its surface order is selected on its
75
+ # storage, a fixlen storage by byte order. A Face whose storage order is
76
+ # not its surface order (e.g. {CACategorical}) raises.
77
+ #
69
78
  # Float NaN policy: NaN cells are pre-partitioned to the tail. If
70
79
  # `kth` falls within the finite slice, quickselect runs over the
71
80
  # finite cells; otherwise the kth cell is already NaN.
72
81
  #
73
82
  # @param kth [Integer]
74
- # @param axis [Integer]
83
+ # @param axis [Integer, nil] `nil` partitions the whole array.
75
84
  # @param masked_position [Symbol] `:last` (default) or `:first`.
76
85
  # @return [CArray] fresh entity.
77
- # @raise [ArgumentError] same conditions as {#partition}.
78
- def partition_copy(kth, axis: 0, masked_position: :last); end
86
+ # @raise [ArgumentError] same conditions as {#partition}, or a Face that
87
+ # is not orderable by its storage.
88
+ def partition_copy(kth, axis: nil, masked_position: :last); end
79
89
 
80
- # @overload order(axis: nil, descending: false, method: :ordinal)
90
+ # @overload order(axis: nil, descending: false, method: :ordinal, kind: :quick)
81
91
  # Returns each cell's rank among the other cells along `axis`
82
92
  # (`0` = smallest). When `axis` is omitted, `self` is flattened
83
93
  # first (global rank). Sugar over `rank_index` (built on the
@@ -105,9 +115,11 @@ class CArray
105
115
  # @param axis [Integer, nil]
106
116
  # @param descending [Boolean]
107
117
  # @param method [Symbol] `:ordinal` (default) or `:dense`.
118
+ # @param kind [Symbol] `:quick` (default) or `:stable`, as for
119
+ # {#sort_index}; a performance choice only.
108
120
  # @return [CArray] `:int64` ranks, shape == `self.shape`.
109
121
  # @raise [ArgumentError] when `method:` is neither `:ordinal` nor `:dense`.
110
- def order(axis: nil, descending: false, method: :ordinal); end
122
+ def order(axis: nil, descending: false, method: :ordinal, kind: :quick); end
111
123
 
112
124
  # @!endgroup
113
125
 
@@ -121,7 +133,7 @@ class CArray
121
133
  # with `UNDEF` at positions where the value is not present.
122
134
  # @param val [Numeric, CArray]
123
135
  # @return [Integer, CArray, nil]
124
- # @raise [RuntimeError] if `self` has any masked element.
136
+ # @raise [ArgumentError] if `self` has any masked element.
125
137
  # @overload bsearch(val, axis:)
126
138
  # Per-fiber binary search along `axis`. Returns a CArray of
127
139
  # axis-local positions, one per fiber.
@@ -148,6 +160,14 @@ class CArray
148
160
  # to `val`. For float types, `eps` (default machine epsilon)
149
161
  # sets the tolerance. Returns `nil` if no match.
150
162
  #
163
+ # `val` is compared in the type both share, as `self.eq(val)`
164
+ # compares: an integer array searched with a Float is compared in
165
+ # float64 (so `3.9` does not match `3`, and `eps` applies), and an
166
+ # Integer that does not fit an integer array raises `RangeError`.
167
+ # The same holds for {#bsearch} and {#search_nearest}. On an
168
+ # `:object` array a cell matches when it is `==` to `val`, as {#eq}
169
+ # compares (so `1` matches `1.0`, which {#is_in} does not).
170
+ #
151
171
  # `self` need not be sorted; this is a linear scan. For sorted
152
172
  # data prefer {#bsearch}.
153
173
  # @param val [Object]
@@ -170,10 +190,17 @@ class CArray
170
190
 
171
191
  # @overload search_nearest(val)
172
192
  # Returns the flat address of the element of `self` whose value
173
- # is closest to `val`. For `:object` arrays, uses
174
- # `val.distance(other)` to compare.
193
+ # is closest to `val`.
194
+ #
195
+ # In an `:object` array the distance is `val.distance(other)` when
196
+ # `val` answers `#distance`, and `(val - other).abs` when it is a
197
+ # number. Anything else -- a String, say -- has no distance and
198
+ # raises `CArray::DataTypeError`; use {#search} or {#bsearch} for an
199
+ # exact match.
175
200
  # @param val [Object]
176
201
  # @return [Integer, nil]
202
+ # @raise [CArray::DataTypeError] when `val` is neither a number nor
203
+ # answers `#distance`.
177
204
  # @overload search_nearest(val, axis:)
178
205
  # Per-fiber nearest-value search along `axis`. Returns
179
206
  # axis-local positions.
@@ -189,73 +216,6 @@ class CArray
189
216
  # @return [CArray]
190
217
  def search_nearest_addr(val, axis: nil); end
191
218
 
192
- # @overload locate_addr(ref)
193
- # Returns, for each element of `self`, the flat address into `ref`
194
- # where the value first occurs, or `UNDEF` where it is not present.
195
- # Builds a value-to-first-address map from `ref` in one pass (an
196
- # open-addressing hash, the same substrate as {#unique} /
197
- # {#value_counts}), then probes each element of `self`; no sort,
198
- # peak memory `O(distinct ref values)`.
199
- #
200
- # The return is `ref`'s flat address (0 to `ref.elements - 1`),
201
- # so a multi-dimensional `ref` still yields a `self`-shaped
202
- # result of flat addresses; downstream reads (`ref[addr]`,
203
- # `model_var[addr]`, ...) apply it as a flat gather.
204
- #
205
- # Works on numeric, `CA_OBJECT`, and `CA_FIXLEN` values, matching
206
- # the value-hash discovery family: numeric follows `==` with all
207
- # NaN collapsed to one value and `-0.0 == +0.0`; object follows
208
- # Ruby `hash` / `eql?` with Float NaN collapsed; fixlen follows
209
- # byte equality. When `ref` holds duplicate values the returned
210
- # address is the earliest (appearance-order) occurrence. Masked
211
- # cells of `ref` do not enter the map but still occupy their flat
212
- # address; masked cells of `self` are `UNDEF` in the result.
213
- #
214
- # Typical use is time-axis lookup: compute the address once
215
- # against a reference axis, then reuse it to gather from many
216
- # `ref`-shaped variables without repeating the lookup.
217
- #
218
- # Implemented in Ruby (see `lib/carray/methods/locate_addr.rb`)
219
- # over the `__locate_addr__` hash-lane kernel; `self` is coerced
220
- # to `ref`'s data type within the same family (cross-family raises).
221
- # @param ref [CArray] reference values to match against; any
222
- # shape (used as flat).
223
- # @return [CArray] `:int64` flat addresses into `ref`, same shape
224
- # as `self`; unmatched cells are masked.
225
- def locate_addr(ref); end
226
-
227
- # @overload locate_nearest_addr(ref, direction: :round, tolerance: nil)
228
- # Returns, for each element of `self`, the flat address into `ref`
229
- # of the nearest reference value. Continuous sibling of
230
- # {#locate_addr}; uses `linear_section` + rounding for non-exact
231
- # matching against a sorted `ref`.
232
- #
233
- # Out-of-range cells of `self` (outside `ref`'s span) mask through
234
- # the pipeline: `linear_section` returns NaN, `mask_invalid`
235
- # propagates that as `UNDEF`, rounding and the int64 cast carry
236
- # the mask, and `project` scatters it into the final positions.
237
- # `mask_invalid` runs before rounding because `CArray#round` maps
238
- # NaN to 0 and would otherwise silently match `ref[0]`.
239
- #
240
- # `tolerance:` (default `nil`) sets a maximum accepted absolute
241
- # distance between `self[i]` and its matched `ref` value. When
242
- # `|ref[addr] - self[i]| > tolerance`, the result cell is masked.
243
- # Use for accuracy-controlled matching (e.g. "an observation
244
- # snaps to a time step only if within N seconds").
245
- #
246
- # Implemented in Ruby (see `lib/carray/methods/locate_addr.rb`).
247
- # @param ref [CArray] 1-D sorted reference grid to match against.
248
- # @param direction [Symbol] `:round`, `:floor`, or `:ceil` —
249
- # rounding applied to the fractional position.
250
- # @param tolerance [Numeric, nil] maximum accepted `|self - ref|`
251
- # distance; cells beyond this are masked. `nil` disables the
252
- # check.
253
- # @return [CArray] `:int64` flat addresses into `ref`, same shape
254
- # as `self`; out-of-range and beyond-tolerance cells are masked.
255
- # @raise [ArgumentError] when `direction` is not one of the
256
- # accepted symbols.
257
- def locate_nearest_addr(ref, direction: :round, tolerance: nil); end
258
-
259
219
  # @!endgroup
260
220
 
261
221
  # @!group Sorting and searching
@@ -266,7 +226,8 @@ class CArray
266
226
  # bracketing samples. The integer part of the returned address is
267
227
  # the index of the lower bracket, the fractional part is the
268
228
  # interpolation weight toward the next sample. Out-of-range `val`
269
- # returns NaN.
229
+ # returns NaN. A one-point axis has no segment: `val` equal to the
230
+ # point is at 0, any other value is out of range.
270
231
  #
271
232
  # `self` is coerced to `:float64` if it is not already. When
272
233
  # `axis: nil`, `self` is flattened to 1-D first.
@@ -19,10 +19,13 @@ class CArray
19
19
  # `CA_SIZE`) or a Ruby Array.
20
20
  # - `vals` is a CArray of length matching `addrs` (coerced to
21
21
  # `self.data_type`), or a Numeric scalar broadcast to all
22
- # addresses.
22
+ # addresses. A complex `self` also takes a Complex scalar.
23
23
  # - Out-of-range `addrs[i]` (`< 0` or `>= self.elements`) raises
24
- # `IndexError`.
25
- # - `self.data_type` must be numeric.
24
+ # `IndexError`. The pairs before it stay applied, through a view
25
+ # as well.
26
+ # - `self.data_type` must be numeric. Complex is accepted by
27
+ # every variant except {#scatter_min!} and {#scatter_max!},
28
+ # since complex values have no order.
26
29
  #
27
30
  # Mask policy differs between the accumulate family and
28
31
  # {#scatter_replace!}: the accumulate variants skip the pair when
@@ -73,6 +76,8 @@ class CArray
73
76
  # @param addrs [CArray, Array<Integer>]
74
77
  # @param vals [CArray, Numeric]
75
78
  # @return [self]
79
+ # @raise [CArray::DataTypeError] for a non-numeric or complex
80
+ # `data_type`.
76
81
  def scatter_min!(addrs, vals); end
77
82
 
78
83
  # @overload scatter_max!(addrs, vals)
@@ -82,6 +87,8 @@ class CArray
82
87
  # @param addrs [CArray, Array<Integer>]
83
88
  # @param vals [CArray, Numeric]
84
89
  # @return [self]
90
+ # @raise [CArray::DataTypeError] for a non-numeric or complex
91
+ # `data_type`.
85
92
  def scatter_max!(addrs, vals); end
86
93
 
87
94
  # @overload scatter_replace!(addrs, vals)
@@ -0,0 +1,72 @@
1
+ # DOCUMENTATION ONLY — DO NOT REQUIRE.
2
+ # Stubs for methods defined in ext/carray_segment.c.
3
+ # See yard-stubs/README.md and yard-stubs/STYLE.md.
4
+
5
+ class CArray
6
+ # @!group Index and address conversion
7
+ #
8
+ # A flat sequence cut into consecutive segments has three
9
+ # representations, and these methods convert between them:
10
+ #
11
+ # lengths [2, 0, 3] one count per segment
12
+ # offsets [0, 2, 2, 5] every boundary, both ends included
13
+ # segment index [0, 0, 2, 2, 2] the segment each element is in
14
+ #
15
+ # Segment `c` spans `offsets[c]...offsets[c + 1]`, so there is no
16
+ # special case for the last segment and none for an empty one.
17
+ #
18
+ # Both methods compute in int64 and return int64, so a total beyond
19
+ # 2**53 stays exact. They accept a CArray of any integer or boolean
20
+ # data type (views included, read in flatten order) or an Array of
21
+ # Integers, and refuse masked cells: a masked length is not a count,
22
+ # and a masked offset is not a position.
23
+
24
+ # @overload segment_offsets(lengths:)
25
+ # Returns the boundaries of segments with the given lengths: `0`
26
+ # first, then the running total. `k` lengths give `k + 1` offsets,
27
+ # so no lengths give `[0]`.
28
+ #
29
+ # CArray.segment_offsets(lengths: [2, 0, 3]) # => [0, 2, 2, 5]
30
+ #
31
+ # @param lengths [CArray, Array<Integer>] one count per segment.
32
+ # @return [CArray] int64, one element more than `lengths`.
33
+ # @raise [ArgumentError] for a negative length, a masked length,
34
+ # or a non-Integer in an Array.
35
+ # @raise [CArray::DataTypeError] for a non-integer data type.
36
+ # @raise [RangeError] when the total overflows int64.
37
+ def self.segment_offsets(lengths:); end
38
+
39
+ # @overload segment_index(lengths:)
40
+ # Returns, for each element of the cut sequence, the segment it
41
+ # belongs to. A segment of length 0 contributes no elements, so
42
+ # its number does not appear.
43
+ #
44
+ # CArray.segment_index(lengths: [2, 0, 3]) # => [0, 0, 2, 2, 2]
45
+ #
46
+ # The same as `CArray.int64(k).seq.repeat(lengths)`, as an owned
47
+ # array rather than a view.
48
+ # @param lengths [CArray, Array<Integer>] one count per segment.
49
+ # @return [CArray] int64, `lengths.sum` elements.
50
+ #
51
+ # @overload segment_index(offsets:)
52
+ # The same from boundaries. The offsets need not start at 0: the
53
+ # offsets of a range cut out of a longer table start where that
54
+ # range starts, and the result then covers
55
+ # `offsets[0]...offsets[-1]` with the segments numbered from 0.
56
+ #
57
+ # CArray.segment_index(offsets: [0, 2, 2, 5]) # => [0, 0, 2, 2, 2]
58
+ # CArray.segment_index(offsets: [4, 6, 6, 9]) # => [0, 0, 2, 2, 2]
59
+ #
60
+ # @param offsets [CArray, Array<Integer>] `k + 1` non-decreasing
61
+ # boundaries.
62
+ # @return [CArray] int64, `offsets[-1] - offsets[0]` elements.
63
+ #
64
+ # @raise [ArgumentError] for a negative length, decreasing or empty
65
+ # offsets, a masked cell, a non-Integer in an Array, or unless
66
+ # exactly one of `lengths:` and `offsets:` is given.
67
+ # @raise [CArray::DataTypeError] for a non-integer data type.
68
+ # @raise [RangeError] when the total length overflows int64.
69
+ def self.segment_index(lengths: nil, offsets: nil); end
70
+
71
+ # @!endgroup
72
+ end
@@ -10,30 +10,33 @@ class CArray
10
10
 
11
11
  # @overload each_slab(axis:)
12
12
  # Yields each slab of `self` (a view along the axes NOT in `axis`) to
13
- # the block and returns `self`. The slab is a live view valid only
14
- # for the duration of the block — capturing it across iterations sees
15
- # the last slab's data.
13
+ # the block and returns `self`. The slab is valid only for the
14
+ # duration of the block — capturing it across iterations sees the last
15
+ # slab's data — and it is read-only: writing through it raises. To
16
+ # produce values per slab use `map_slab` or `reduce_slab`; to write in
17
+ # place, assign through the array itself.
16
18
  # @overload each_slab(axis:)
17
19
  # Returns an Enumerator when no block is given.
18
20
  # @param axis [Integer, Array<Integer>, nil] the slab axis or axes
19
21
  # (`nil` = the whole view as a single slab).
20
22
  # @return [self, Enumerator]
21
- # @see file:docs/SlabIterator.md SlabIterator
22
- # @see file:docs/drafts/11_slab_iteration.md Slab iteration
23
+ # @see file:docs/topics/SlabIterator.md SlabIterator
24
+ # @see file:guides/users/11_slab_iteration.md Slab iteration
23
25
  def each_slab(axis:); end
24
26
 
25
27
  # @overload map_slab(axis:, data_type: nil)
26
28
  # Returns a new CArray built by replacing each slab of `self` with the
27
29
  # block's result. The block receives the slab view and must return a
28
30
  # value of the same shape as the slab (a CArray or scalar); the results
29
- # are written into the output at the same positions.
31
+ # are written into the output at the same positions, and a masked
32
+ # cell of the block's result is masked in the output.
30
33
  # @param axis [Integer, Array<Integer>, nil] the slab axis or axes.
31
34
  # @param data_type [Symbol, Integer, Class, nil] output data type
32
35
  # (defaults to `self`'s data type).
33
36
  # @return [CArray]
34
37
  # @raise [ArgumentError] when the block result's shape does not match
35
38
  # the slab.
36
- # @see file:docs/SlabIterator.md SlabIterator
39
+ # @see file:docs/topics/SlabIterator.md SlabIterator
37
40
  def map_slab(axis:, data_type: nil); end
38
41
 
39
42
  # @overload reduce_slab(axis:, data_type: nil)
@@ -50,7 +53,7 @@ class CArray
50
53
  # per-element form).
51
54
  # @param data_type [Symbol, Integer, Class, nil] output data type.
52
55
  # @return [CArray] the reduced array (slab axes collapsed).
53
- # @see file:docs/SlabIterator.md SlabIterator
56
+ # @see file:docs/topics/SlabIterator.md SlabIterator
54
57
  def reduce_slab(axis:, init: nil, data_type: nil); end
55
58
 
56
59
  # @!endgroup
@@ -67,11 +67,13 @@ class CArray
67
67
  # along `axis`. Use this when you want an independent array
68
68
  # rather than a view.
69
69
  #
70
- # Unmasked numeric paths use a per-fiber gather + sort +
71
- # scatter, bypassing the `CARemap` scatter layer that `sort`
72
- # uses. `CA_FIXLEN` and masked input both materialize the
73
- # `sort` view instead (same shape, ordering, and
74
- # `masked_position:` semantics as {#sort}).
70
+ # It takes whatever {#sort} takes: numeric (`i8`..`f64`),
71
+ # `CA_BOOLEAN`, `CA_FIXLEN` and `CA_OBJECT`, masked or not.
72
+ #
73
+ # Unmasked `i8`..`f64` uses a per-fiber gather + sort + scatter,
74
+ # bypassing the `CARemap` scatter layer that `sort` uses.
75
+ # Everything else materializes the `sort` view instead (same
76
+ # shape, ordering, and `masked_position:` semantics as {#sort}).
75
77
  # @param axis [Integer, nil]
76
78
  # @param kind [Symbol] `:quick` or `:stable`.
77
79
  # @param masked_position [Symbol] `:last` (default) or `:first`.
@@ -113,6 +115,43 @@ class CArray
113
115
  # `:stable`.
114
116
  def sort_addr(axis: nil, kind: :quick, masked_position: :last); end
115
117
 
118
+ # @overload sort_index(axis: nil, kind: :quick, masked_position: :last)
119
+ # Returns, for each fiber along `axis`, the positions within the
120
+ # fiber that put it in ascending order: `:int64`, shaped like
121
+ # `self`. For a 1-D array, `a[a.sort_index]` is `a` sorted.
122
+ #
123
+ # Without `axis:` (or with `axis: nil`) `self` is flattened and
124
+ # treated as one fiber, as {#sort} does: the result is 1-D with
125
+ # `self.elements` entries, and `a.flatten[a.sort_index]` is
126
+ # `a.sort`.
127
+ #
128
+ # The sort is **stable**: cells that compare equal keep their
129
+ # input order, whichever `kind:` is chosen, so sorting by one key
130
+ # and then stably by another orders by the second key first and
131
+ # the first within it. `kind:` is a performance characteristic
132
+ # only:
133
+ #
134
+ # - `:quick` (default) — introsort with mergesort escape.
135
+ # - `:stable` — bottom-up mergesort.
136
+ #
137
+ # NaN and masked cells cannot be compared with the rest and are
138
+ # placed at one end of each fiber: NaN after the numbers, masked
139
+ # cells at the end `masked_position:` names (`:last`, default, or
140
+ # `:first`). Relative order within the masked cells is unspecified.
141
+ #
142
+ # Takes numeric data types, boolean, `CA_FIXLEN` (byte order),
143
+ # `CA_OBJECT` (`<=>` per pair), and an ordered Face such as
144
+ # `CATime`. Complex values have no order.
145
+ # @param axis [Integer, nil] axis along which fibers run; negative
146
+ # counts from the end. `nil` sorts the whole array.
147
+ # @param kind [Symbol] `:quick` or `:stable`.
148
+ # @param masked_position [Symbol] `:last` (default) or `:first`.
149
+ # @return [CArray] `:int64` positions within each fiber.
150
+ # @raise [ArgumentError] when `kind:` is neither `:quick` nor
151
+ # `:stable`, or `axis` is out of range.
152
+ # @raise [CArray::DataTypeError] for a complex `data_type`.
153
+ def sort_index(axis: nil, kind: :quick, masked_position: :last); end
154
+
116
155
  # @!group Index and address conversion
117
156
 
118
157
  # @overload axis2addr(indices, axis: 0)
@@ -145,15 +184,18 @@ class CArray
145
184
  #
146
185
  # `indices` data_type: any integer kind (zero-copy when
147
186
  # already `:int64`). Negative indices: Python-style
148
- # (`-1` == last). Out-of-range indices raise `RangeError`.
149
- # Negative `axis:` is Python-style.
187
+ # (`-1` == last). Out-of-range indices raise `IndexError`.
188
+ # Negative `axis:` is Python-style. A masked index gives a
189
+ # masked address (its stored value is not read), so
190
+ # `take_along_axis` answers `UNDEF` there and `put_along_axis`
191
+ # writes nothing there.
150
192
  #
151
193
  # @param indices [CArray] integer-typed axis-local positions.
152
194
  # @param axis [Integer] axis along which `indices` are
153
195
  # interpreted.
154
196
  # @return [CArray] `:int64` view-flat addresses, same shape as
155
197
  # `indices`.
156
- # @raise [RangeError] when an index is out of range after
198
+ # @raise [IndexError] when an index is out of range after
157
199
  # negative normalization.
158
200
  # @raise [ArgumentError] for shape / ndim / data_type
159
201
  # violations.
@@ -36,6 +36,13 @@ class CArray
36
36
  # `data_class`, `data_type`, mask state, and elementwise values as
37
37
  # `self`. NaN values compare unequal (IEEE semantics), so two
38
38
  # arrays with NaN at the same position are not `==`.
39
+ #
40
+ # A Face (a time, string or categorical array) equals only a Face of
41
+ # its own class, and is compared by its values: two time arrays of
42
+ # different units holding the same instants are `==`, as are two
43
+ # categoricals with the same labels at each cell whatever the order
44
+ # of their vocabularies. A Face is never `==` to an array that is not
45
+ # one, even when the bytes match.
39
46
  # @param other [Object]
40
47
  # @return [Boolean]
41
48
  def ==(other); end
@@ -46,6 +53,9 @@ class CArray
46
53
  # are compared bitwise (for numeric types) or via `Object#eql?`
47
54
  # (for `:object` arrays). Unlike `==`, `NaN.eql?(NaN)` holds, so
48
55
  # two mask-free arrays with NaN at the same positions are `eql?`.
56
+ # Two Faces are `eql?` only when they are of the same class, share
57
+ # their state (a time array's unit, a categorical's labels) and hold
58
+ # the same storage.
49
59
  #
50
60
  # Guarantees `a.eql?(b)` ⇒ `a.hash == b.hash`.
51
61
  # @param other [Object]
@@ -67,31 +67,5 @@ class CArray
67
67
  def guess_type_and_bytes(type_spec, bytes = nil); end
68
68
 
69
69
  # @!endgroup
70
-
71
- # @!group String scanning (internal)
72
-
73
- # @overload _scan_float(str, fill_value = nil)
74
- # Parses `str` as a single double-precision float. Returns
75
- # `fill_value` (or `NaN` if `fill_value` is nil) when `str` is
76
- # `nil` or unparseable. Internal helper used by text-format I/O
77
- # readers; end users should prefer Ruby's `Float()` /
78
- # `String#to_f`.
79
- # @param str [String, nil]
80
- # @param fill_value [Float, nil]
81
- # @return [Float]
82
- # @api private
83
- def _scan_float(str, fill_value = nil); end
84
-
85
- # @overload _scan_int(str, fill_value = nil)
86
- # Parses `str` as a single integer. Returns `fill_value`
87
- # (or `0` if `fill_value` is nil) when `str` is `nil` or
88
- # unparseable. Internal helper used by text-format I/O readers.
89
- # @param str [String, nil]
90
- # @param fill_value [Integer, nil]
91
- # @return [Integer]
92
- # @api private
93
- def _scan_int(str, fill_value = nil); end
94
-
95
- # @!endgroup
96
70
  end
97
71
  end