carray 3.0.0 → 3.0.2

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 (202) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -1
  3. data/CHANGELOG.md +845 -3
  4. data/{NEWS.md → CHANGELOG.v1.md} +1 -1
  5. data/README.md +33 -33
  6. data/carray.gemspec +12 -8
  7. data/ext/ca_axis_dispatch.c +33 -4
  8. data/ext/ca_axis_group.c +256 -114
  9. data/ext/ca_binop_dispatch.c +5 -6
  10. data/ext/ca_binop_dispatch.h +0 -7
  11. data/ext/ca_categorical_iterator.c +121 -67
  12. data/ext/ca_for_each_element.h +6 -8
  13. data/ext/ca_group_iter.c +1 -1
  14. data/ext/ca_kernel_iterator.c +386 -74
  15. data/ext/ca_kernel_iterator.h +145 -45
  16. data/ext/ca_obj_array.c +62 -20
  17. data/ext/ca_obj_bincmp.c +57 -27
  18. data/ext/ca_obj_binop.c +86 -30
  19. data/ext/ca_obj_block.c +4 -4
  20. data/ext/ca_obj_const_string.c +88 -27
  21. data/ext/ca_obj_face.c +104 -0
  22. data/ext/ca_obj_face.h +48 -1
  23. data/ext/ca_obj_fake.c +11 -0
  24. data/ext/ca_obj_fixlen_string.c +21 -6
  25. data/ext/ca_obj_grid.c +11 -3
  26. data/ext/ca_obj_meld.c +125 -22
  27. data/ext/ca_obj_moncmp.c +33 -14
  28. data/ext/ca_obj_monop.c +19 -7
  29. data/ext/ca_obj_object.c +107 -4
  30. data/ext/ca_obj_record.c +3 -1
  31. data/ext/ca_obj_refer.c +30 -6
  32. data/ext/ca_obj_roll.c +13 -5
  33. data/ext/ca_obj_select.c +49 -34
  34. data/ext/ca_obj_select_axis.c +16 -6
  35. data/ext/ca_obj_shift.c +3 -3
  36. data/ext/ca_obj_stack.c +3 -8
  37. data/ext/ca_obj_stride.c +178 -24
  38. data/ext/ca_obj_string.c +11 -5
  39. data/ext/ca_obj_tile.c +13 -5
  40. data/ext/ca_obj_time.c +3 -1
  41. data/ext/ca_obj_timedelta.c +3 -1
  42. data/ext/ca_obj_transpose.c +1 -1
  43. data/ext/ca_obj_triop.c +62 -23
  44. data/ext/ca_obj_window.c +94 -19
  45. data/ext/ca_op_cmplx64.h +123 -0
  46. data/ext/ca_op_ipower.c +1 -5
  47. data/ext/ca_rng_normal.h +42 -0
  48. data/ext/ca_rng_xoshiro256pp.h +105 -0
  49. data/ext/ca_sort_kernels.h +5 -5
  50. data/ext/ca_sweep_engine.c +362 -155
  51. data/ext/ca_sweep_engine.h +39 -9
  52. data/ext/ca_transform_common.c +7 -0
  53. data/ext/carray.h +148 -132
  54. data/ext/carray_access.c +83 -49
  55. data/ext/carray_address_basis.c +590 -0
  56. data/ext/carray_bincount.c +8 -8
  57. data/ext/carray_broadcast.c +102 -9
  58. data/ext/carray_build_flags.h +3 -0
  59. data/ext/carray_call_cfunc.c +2010 -335
  60. data/ext/carray_call_cfunc.h +153 -0
  61. data/ext/carray_cast.c +184 -72
  62. data/ext/carray_conversion.c +22 -22
  63. data/ext/carray_copy.c +67 -32
  64. data/ext/carray_core.c +140 -13
  65. data/ext/carray_count.c +10 -11
  66. data/ext/carray_element.c +7 -7
  67. data/ext/carray_factorize.c +72 -51
  68. data/ext/carray_hold.c +1 -1
  69. data/ext/carray_index_classifier.c +7 -21
  70. data/ext/carray_internal.h +36 -3
  71. data/ext/carray_kernels_bincmp.c +1 -0
  72. data/ext/carray_kernels_binop.c +320 -298
  73. data/ext/carray_kernels_init.c +1095 -0
  74. data/ext/carray_kernels_map.c +1 -0
  75. data/ext/carray_kernels_moncmp.c +1 -0
  76. data/ext/carray_kernels_monop.c +412 -411
  77. data/ext/carray_kernels_reduce_aggregate.c +256 -87
  78. data/ext/carray_kernels_reduce_boolean.c +1 -0
  79. data/ext/carray_kernels_reduce_cumulative.c +324 -54
  80. data/ext/carray_kernels_reduce_extreme.c +605 -58
  81. data/ext/carray_kernels_reduce_variance.c +1 -0
  82. data/ext/carray_kernels_scan.c +5 -4
  83. data/ext/carray_kernels_search.c +187 -106
  84. data/ext/carray_kernels_sort.c +1 -0
  85. data/ext/carray_kernels_triop.c +1 -0
  86. data/ext/carray_lazy.c +175 -5
  87. data/ext/carray_loop.c +7 -1
  88. data/ext/carray_mask.c +29 -13
  89. data/ext/carray_median_percentile.c +56 -1
  90. data/ext/carray_memory_view.c +46 -21
  91. data/ext/carray_operator.c +50 -53
  92. data/ext/carray_order.c +1 -1
  93. data/ext/carray_partition.c +4 -4
  94. data/ext/carray_random.c +391 -47
  95. data/ext/carray_scatter.c +1 -1
  96. data/ext/carray_slab.c +13 -0
  97. data/ext/carray_sort.c +22 -24
  98. data/ext/carray_sort_kernel.c +10 -10
  99. data/ext/carray_test.c +1 -1
  100. data/ext/extconf.rb +18 -0
  101. data/ext/mk_call_cfunc.rb +323 -145
  102. data/ext/mkkernel.rb +651 -129
  103. data/ext/ruby_carray.c +28 -17
  104. data/ext/version.h +4 -4
  105. data/lib/carray/autoload_carray.rb +24 -3
  106. data/lib/carray/autoload_method_extension.rb +14 -1
  107. data/lib/carray/axis_group.rb +84 -7
  108. data/lib/carray/basics.rb +63 -59
  109. data/lib/carray/bincount_nd.rb +12 -12
  110. data/lib/carray/block_iterator.rb +111 -25
  111. data/lib/carray/categorical.rb +154 -37
  112. data/lib/carray/categorical_iterator.rb +300 -151
  113. data/lib/carray/conditional.rb +14 -14
  114. data/lib/carray/const_string.rb +131 -27
  115. data/lib/carray/construct.rb +61 -0
  116. data/lib/carray/core_extensions.rb +62 -5
  117. data/lib/carray/data_type_extension.rb +21 -1
  118. data/lib/carray/data_type_limits.rb +91 -0
  119. data/lib/carray/fixlen_string.rb +1 -1
  120. data/lib/carray/frame/concat.rb +3 -3
  121. data/lib/carray/frame/convert.rb +1 -1
  122. data/lib/carray/frame/csv_parser.rb +11 -4
  123. data/lib/carray/frame/frame.rb +85 -21
  124. data/lib/carray/frame/group.rb +36 -3
  125. data/lib/carray/frame/io.rb +224 -15
  126. data/lib/carray/frame/records.rb +18 -4
  127. data/lib/carray/frame/sort.rb +1 -1
  128. data/lib/carray/frame/verbs.rb +32 -12
  129. data/lib/carray/fuse_source.rb +123 -0
  130. data/lib/carray/fusion.rb +218 -0
  131. data/lib/carray/histogram.rb +16 -16
  132. data/lib/carray/inspect.rb +43 -16
  133. data/lib/carray/iterator.rb +147 -3
  134. data/lib/carray/lazy.rb +88 -73
  135. data/lib/carray/mask_gap_fill.rb +3 -1
  136. data/lib/carray/meld_reduce.rb +2 -2
  137. data/lib/carray/methods/align_addr.rb +1 -1
  138. data/lib/carray/methods/composition.rb +1 -1
  139. data/lib/carray/methods/discovery_along.rb +74 -0
  140. data/lib/carray/methods/factorize.rb +50 -0
  141. data/lib/carray/methods/is_in.rb +25 -14
  142. data/lib/carray/methods/locate_addr.rb +81 -3
  143. data/lib/carray/methods/mask_duplicates.rb +36 -2
  144. data/lib/carray/methods/meshgrid.rb +4 -5
  145. data/lib/carray/methods/mode.rb +2 -2
  146. data/lib/carray/methods/nunique.rb +23 -2
  147. data/lib/carray/methods/repeat.rb +110 -0
  148. data/lib/carray/methods/snap.rb +7 -2
  149. data/lib/carray/methods/unique.rb +44 -4
  150. data/lib/carray/methods/value_counts.rb +2 -2
  151. data/lib/carray/rng.rb +86 -0
  152. data/lib/carray/runtime.rb +0 -19
  153. data/lib/carray/slab_iterator.rb +77 -19
  154. data/lib/carray/string_operation_extension.rb +10 -6
  155. data/lib/carray/time.rb +906 -491
  156. data/lib/carray/window_iterator.rb +421 -27
  157. data/lib/carray.rb +7 -5
  158. data/yard-stubs/ca_obj_array.rb +385 -0
  159. data/yard-stubs/ca_obj_bitarray.rb +38 -0
  160. data/yard-stubs/ca_obj_bitfield.rb +43 -0
  161. data/yard-stubs/ca_obj_block.rb +68 -0
  162. data/yard-stubs/ca_obj_byte_swap.rb +56 -0
  163. data/yard-stubs/ca_obj_fake.rb +31 -0
  164. data/yard-stubs/ca_obj_farray.rb +32 -0
  165. data/yard-stubs/ca_obj_field.rb +45 -0
  166. data/yard-stubs/ca_obj_grid.rb +35 -0
  167. data/yard-stubs/ca_obj_refer.rb +72 -0
  168. data/yard-stubs/ca_obj_roll.rb +45 -0
  169. data/yard-stubs/ca_obj_shift.rb +43 -0
  170. data/yard-stubs/ca_obj_stride.rb +181 -0
  171. data/yard-stubs/ca_obj_tile.rb +29 -0
  172. data/yard-stubs/ca_obj_transpose.rb +40 -0
  173. data/yard-stubs/ca_obj_window.rb +57 -0
  174. data/yard-stubs/carray_access.rb +131 -0
  175. data/yard-stubs/carray_attribute.rb +246 -0
  176. data/yard-stubs/carray_broadcast.rb +37 -0
  177. data/yard-stubs/carray_cast.rb +489 -0
  178. data/yard-stubs/carray_class.rb +65 -0
  179. data/yard-stubs/carray_conversion.rb +76 -0
  180. data/yard-stubs/carray_copy.rb +79 -0
  181. data/yard-stubs/carray_core.rb +34 -0
  182. data/yard-stubs/carray_count.rb +84 -0
  183. data/yard-stubs/carray_element.rb +108 -0
  184. data/yard-stubs/carray_generate.rb +66 -0
  185. data/yard-stubs/carray_lazy.rb +228 -0
  186. data/yard-stubs/carray_loop.rb +140 -0
  187. data/yard-stubs/carray_mask.rb +259 -0
  188. data/yard-stubs/carray_math.rb +1615 -0
  189. data/yard-stubs/carray_mathfunc.rb +45 -0
  190. data/yard-stubs/carray_median_percentile.rb +103 -0
  191. data/yard-stubs/carray_memory_view.rb +163 -0
  192. data/yard-stubs/carray_order.rb +252 -0
  193. data/yard-stubs/carray_random.rb +89 -0
  194. data/yard-stubs/carray_scatter.rb +106 -0
  195. data/yard-stubs/carray_slab.rb +59 -0
  196. data/yard-stubs/carray_sort.rb +165 -0
  197. data/yard-stubs/carray_test.rb +85 -0
  198. data/yard-stubs/carray_undef.rb +64 -0
  199. data/yard-stubs/carray_utils.rb +97 -0
  200. data/yard-stubs/ruby_carray.rb +193 -0
  201. metadata +67 -10
  202. data/ext/ca_obj_unbound_repeat.c +0 -496
@@ -0,0 +1,106 @@
1
+ # DOCUMENTATION ONLY — DO NOT REQUIRE.
2
+ # Stubs for methods defined in ext/carray_scatter.c.
3
+ # See yard-stubs/README.md and yard-stubs/STYLE.md.
4
+
5
+ class CArray
6
+ # @!group Scatter and generation
7
+ #
8
+ # The `scatter_*!` family applies an in-place reduction at each
9
+ # `addrs[i]` position from a paired `vals[i]` (or scalar). The
10
+ # accumulate variants (`scatter_add!` / `scatter_sub!` /
11
+ # `scatter_mul!` / `scatter_min!` / `scatter_max!`) apply duplicate
12
+ # addresses in sequence (unbuffered). {#scatter_replace!} is the
13
+ # last-write variant, equivalent to `self[addrs] = vals` but
14
+ # bypasses the CAGrid view chain.
15
+ #
16
+ # Shared contract:
17
+ #
18
+ # - `addrs` is a CArray of any integer type (coerced to
19
+ # `CA_SIZE`) or a Ruby Array.
20
+ # - `vals` is a CArray of length matching `addrs` (coerced to
21
+ # `self.data_type`), or a Numeric scalar broadcast to all
22
+ # addresses.
23
+ # - Out-of-range `addrs[i]` (`< 0` or `>= self.elements`) raises
24
+ # `IndexError`.
25
+ # - `self.data_type` must be numeric.
26
+ #
27
+ # Mask policy differs between the accumulate family and
28
+ # {#scatter_replace!}: the accumulate variants skip the pair when
29
+ # any of `addrs[i]`, `vals[i]`, or `self[addrs[i]]` is masked (an
30
+ # unknown source can't accumulate). {#scatter_replace!} instead
31
+ # overwrites the target (masked `vals[i]` flips the target to
32
+ # masked, valid `vals[i]` clears the target's mask), matching the
33
+ # `self[addrs] = vals` indexer.
34
+
35
+ # @overload scatter_add!(addrs, vals)
36
+ # For each `i`, applies `self[addrs[i]] += vals[i]`
37
+ # (or `+= vals` if `vals` is scalar). Mutates `self`.
38
+ # @param addrs [CArray, Array<Integer>]
39
+ # @param vals [CArray, Numeric]
40
+ # @return [self]
41
+ # @raise [IndexError] for out-of-range addresses.
42
+ # @raise [CArray::DataTypeError] for non-numeric `data_type`.
43
+ def scatter_add!(addrs, vals); end
44
+
45
+ # @overload scatter_sub!(addrs, vals)
46
+ # For each `i`, applies `self[addrs[i]] -= vals[i]`. Same
47
+ # contract as {#scatter_add!}.
48
+ # @param addrs [CArray, Array<Integer>]
49
+ # @param vals [CArray, Numeric]
50
+ # @return [self]
51
+ def scatter_sub!(addrs, vals); end
52
+
53
+ # @overload scatter_mul!(addrs, vals)
54
+ # For each `i`, applies `self[addrs[i]] *= vals[i]`. Duplicate
55
+ # addresses multiply.
56
+ #
57
+ # NaN/inf follow standard C arithmetic propagation (no
58
+ # `fmin`-style missing-value rule). Integer overflow wraps.
59
+ #
60
+ # Typical uses: Bayesian likelihood patch update, scatter blend,
61
+ # log-domain → linear product, weight composition.
62
+ # @param addrs [CArray, Array<Integer>]
63
+ # @param vals [CArray, Numeric]
64
+ # @return [self]
65
+ def scatter_mul!(addrs, vals); end
66
+
67
+ # @overload scatter_min!(addrs, vals)
68
+ # For each `i`, applies
69
+ # `self[addrs[i]] = min(self[addrs[i]], vals[i])`.
70
+ #
71
+ # For float `data_type`, NaN follows the `fmin` rule (NaN is
72
+ # treated as missing: `min(NaN, v) → v`, `min(x, NaN) → x`).
73
+ # @param addrs [CArray, Array<Integer>]
74
+ # @param vals [CArray, Numeric]
75
+ # @return [self]
76
+ def scatter_min!(addrs, vals); end
77
+
78
+ # @overload scatter_max!(addrs, vals)
79
+ # For each `i`, applies
80
+ # `self[addrs[i]] = max(self[addrs[i]], vals[i])`. For float
81
+ # `data_type`, NaN follows the `fmax` rule.
82
+ # @param addrs [CArray, Array<Integer>]
83
+ # @param vals [CArray, Numeric]
84
+ # @return [self]
85
+ def scatter_max!(addrs, vals); end
86
+
87
+ # @overload scatter_replace!(addrs, vals)
88
+ # For each `i`, applies `self[addrs[i]] = vals[i]` (or `= vals`
89
+ # if scalar). Duplicate addresses resolve to last-write-wins.
90
+ #
91
+ # Semantically equivalent to `self[addrs] = vals` but bypasses
92
+ # the CAGrid view chain (which snapshot-copies `addrs` and
93
+ # allocates view state); useful in hot loops where a scatter
94
+ # result is written back many times.
95
+ #
96
+ # Unlike the arithmetic `scatter_*!` family, `self` may be
97
+ # **boolean** (assignment does not widen), and `true` / `false`
98
+ # are accepted as scalar `vals` alongside numeric scalars.
99
+ #
100
+ # @param addrs [CArray, Array<Integer>]
101
+ # @param vals [CArray, Numeric, true, false]
102
+ # @return [self]
103
+ def scatter_replace!(addrs, vals); end
104
+
105
+ # @!endgroup
106
+ end
@@ -0,0 +1,59 @@
1
+ # DOCUMENTATION ONLY — DO NOT REQUIRE.
2
+ # Stubs for methods defined in ext/carray_slab.c.
3
+ # See yard-stubs/README.md and yard-stubs/STYLE.md.
4
+ #
5
+ # The slab-iteration family walks `self` in slabs (sub-arrays) taken along
6
+ # a chosen set of axes. See the @see links for the full walkthrough.
7
+
8
+ class CArray
9
+ # @!group Iteration
10
+
11
+ # @overload each_slab(axis:)
12
+ # Yields each slab of `self` (a view along the axes NOT in `axis`) to
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.
18
+ # @overload each_slab(axis:)
19
+ # Returns an Enumerator when no block is given.
20
+ # @param axis [Integer, Array<Integer>, nil] the slab axis or axes
21
+ # (`nil` = the whole view as a single slab).
22
+ # @return [self, Enumerator]
23
+ # @see file:docs/topics/SlabIterator.md SlabIterator
24
+ # @see file:guides/users/11_slab_iteration.md Slab iteration
25
+ def each_slab(axis:); end
26
+
27
+ # @overload map_slab(axis:, data_type: nil)
28
+ # Returns a new CArray built by replacing each slab of `self` with the
29
+ # block's result. The block receives the slab view and must return a
30
+ # value of the same shape as the slab (a CArray or scalar); the results
31
+ # are written into the output at the same positions.
32
+ # @param axis [Integer, Array<Integer>, nil] the slab axis or axes.
33
+ # @param data_type [Symbol, Integer, Class, nil] output data type
34
+ # (defaults to `self`'s data type).
35
+ # @return [CArray]
36
+ # @raise [ArgumentError] when the block result's shape does not match
37
+ # the slab.
38
+ # @see file:docs/topics/SlabIterator.md SlabIterator
39
+ def map_slab(axis:, data_type: nil); end
40
+
41
+ # @overload reduce_slab(axis:, data_type: nil)
42
+ # Per-slab form (no `init:`): the block receives each slab view and
43
+ # returns a scalar; the scalars fill an output CArray with the slab
44
+ # axes collapsed. Returning a CArray from the block is an error (use
45
+ # `slab[0]`, `slab.sum`, etc. to extract a scalar).
46
+ # @overload reduce_slab(axis:, init:, data_type: nil)
47
+ # Per-element form (`init:` given): the block receives `(acc, x)` for
48
+ # each element of the slab and returns the new accumulator; the final
49
+ # accumulator per slab fills the output.
50
+ # @param axis [Integer, Array<Integer>, nil] the slab axis or axes.
51
+ # @param init [Object] the initial accumulator (selects the
52
+ # per-element form).
53
+ # @param data_type [Symbol, Integer, Class, nil] output data type.
54
+ # @return [CArray] the reduced array (slab axes collapsed).
55
+ # @see file:docs/topics/SlabIterator.md SlabIterator
56
+ def reduce_slab(axis:, init: nil, data_type: nil); end
57
+
58
+ # @!endgroup
59
+ end
@@ -0,0 +1,165 @@
1
+ # DOCUMENTATION ONLY — DO NOT REQUIRE.
2
+ # Stubs for methods defined in ext/carray_sort.c.
3
+ # See yard-stubs/README.md and yard-stubs/STYLE.md.
4
+
5
+ class CArray
6
+ # @!group Sorting and searching
7
+
8
+ # @overload sort_addr(*keys, masked_position: :last)
9
+ # Returns a 1-D CArray of `:int64` indices that lex-sort `keys`
10
+ # in priority order (`keys[0]` is highest priority,
11
+ # `keys[1]` breaks ties, etc.). All `keys` must share the same
12
+ # element count.
13
+ #
14
+ # Masked cells are an incomparable sentinel clustered at
15
+ # `masked_position:` (`:last`, default, or `:first`), applied
16
+ # uniformly across all `keys`. Ties are broken by original index
17
+ # (stable).
18
+ #
19
+ # @example
20
+ # idx = CArray.sort_addr(a, b, c) # priority: a > b > c
21
+ # a[idx]; b[idx]; c[idx]
22
+ #
23
+ # @param keys [Array<CArray>] one or more CArrays, all of the
24
+ # same element count.
25
+ # @param masked_position [Symbol] `:last` (default) or `:first`.
26
+ # @return [CArray] flat `:int64` indices, shape `[a.elements]`.
27
+ # @raise [ArgumentError] when no key is given or element counts
28
+ # differ.
29
+ def self.sort_addr(*keys, masked_position: :last); end
30
+
31
+ # @overload sort(axis: nil, kind: :quick, masked_position: :last)
32
+ # Returns a `CARemap` view of `self` whose elements are sorted
33
+ # along `axis`. When `axis` is omitted, `self` is first
34
+ # flattened to 1-D and the entire array is sorted (so the
35
+ # result is a 1-D view regardless of `self.ndim`).
36
+ #
37
+ # `kind:` selects the sorting algorithm. Both kinds are stable
38
+ # (tie-broken by fiber-local index); the choice is a
39
+ # performance characteristic only:
40
+ #
41
+ # - `:quick` (default) — portable textbook introsort with
42
+ # mergesort escape. Faster on random data.
43
+ # - `:stable` — portable bottom-up mergesort with insertion
44
+ # pre-pass. Predictable worst case.
45
+ #
46
+ # Masked cells are an incomparable sentinel (the same role NaN
47
+ # plays for float data types): they are excluded from the value
48
+ # comparison and clustered at one end of each fiber.
49
+ # `masked_position:` picks which end (`:last`, default, or
50
+ # `:first`); relative order within the masked cluster is
51
+ # unspecified. Masked cells keep their masked-ness at the
52
+ # clustered position (the `CARemap` gather carries the mask bit
53
+ # through, no separate output-mask step needed).
54
+ #
55
+ # Supports numeric (`i8`..`f64`), `CA_FIXLEN` (via memcmp
56
+ # lexicographic order), and `CA_OBJECT` (via `<=>` per pair) --
57
+ # all through the same view path, `masked_position:` included.
58
+ # @param axis [Integer, nil]
59
+ # @param kind [Symbol] `:quick` or `:stable`.
60
+ # @param masked_position [Symbol] `:last` (default) or `:first`.
61
+ # @return [CArray] sorted view.
62
+ def sort(axis: nil, kind: :quick, masked_position: :last); end
63
+
64
+ # @overload sort_copy(axis: nil, kind: :quick, masked_position: :last)
65
+ # Eager-copy counterpart of {#sort}: returns a fresh entity
66
+ # CArray with the same shape and `data_type` as `self`, sorted
67
+ # along `axis`. Use this when you want an independent array
68
+ # rather than a view.
69
+ #
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}).
77
+ # @param axis [Integer, nil]
78
+ # @param kind [Symbol] `:quick` or `:stable`.
79
+ # @param masked_position [Symbol] `:last` (default) or `:first`.
80
+ # @return [CArray]
81
+ def sort_copy(axis: nil, kind: :quick, masked_position: :last); end
82
+
83
+ # @overload sort_addr(axis: nil, kind: :quick, masked_position: :last)
84
+ # Returns view-flat addresses that index a sort.
85
+ #
86
+ # - With no kwarg (`a.sort_addr`): returns a CArray of `:int64`
87
+ # flat addresses shaped like `self` (NOT flattened -- the
88
+ # legacy 1-key case of `CArray.sort_addr`'s multi-key lex
89
+ # sort). `kind:` has no effect on this form.
90
+ # - With `axis:` (e.g. `a.sort_addr(axis: 0)`): returns
91
+ # per-fiber view-flat addresses along the given axis, output
92
+ # shape == `self.shape`.
93
+ #
94
+ # `kind:` selects the sort algorithm for the `axis:` path:
95
+ #
96
+ # - `:quick` (default) — introsort with mergesort escape.
97
+ # - `:stable` — bottom-up mergesort.
98
+ #
99
+ # Both kinds are algorithmically stable (pair sort with index
100
+ # tie-break); `kind:` chooses the performance characteristic.
101
+ #
102
+ # `masked_position:` (`:last` default, or `:first`) picks which
103
+ # end masked cells cluster to. Effective on both forms: the
104
+ # `axis:` path forwards to the `sort`/`sort_index` kernel family;
105
+ # the no-`axis:` path forwards to `CArray.sort_addr`'s own
106
+ # masked-position-aware comparator.
107
+ #
108
+ # Companion of {#axis2addr} (axis-local indices to view-flat
109
+ # addresses) and {#sort} (the view counterpart).
110
+ # @param axis [Integer, nil]
111
+ # @param kind [Symbol] `:quick` or `:stable`.
112
+ # @param masked_position [Symbol] `:last` (default) or `:first`.
113
+ # @return [CArray] `:int64` addresses.
114
+ # @raise [ArgumentError] when `kind:` is neither `:quick` nor
115
+ # `:stable`.
116
+ def sort_addr(axis: nil, kind: :quick, masked_position: :last); end
117
+
118
+ # @!group Index and address conversion
119
+
120
+ # @overload axis2addr(indices, axis: 0)
121
+ # Converts per-fiber axis-local indices into row-major
122
+ # view-flat addresses into `self`. For each cell at coord
123
+ # `c = (c_0, ..., c_(n-1))` in `indices`:
124
+ #
125
+ # addr[c] = sum over `j != axis` of c_j * stride_j +
126
+ # indices[c] * stride_axis
127
+ #
128
+ # where strides are row-major over `self.shape`.
129
+ #
130
+ # Canonical converter between the two axis-position
131
+ # representations the `*_index` / `*_addr` kernel families
132
+ # produce:
133
+ #
134
+ # @example
135
+ # a.min_index(axis: k) # axis-local scalar per fiber
136
+ # a.min_addr(axis: k) # view-flat address per fiber
137
+ # flat = key.axis2addr(key.min_index(axis: k), axis: k)
138
+ # # flat == key.min_addr(axis: k)
139
+ #
140
+ # Sits underneath `#take_along_axis`: the heavy "axis-local
141
+ # -> view-flat" arithmetic lives here, and `take_along_axis`
142
+ # is a one-liner on top of `flatten[axis2addr(...)]`.
143
+ #
144
+ # Shape rule: `indices.ndim == self.ndim`, and
145
+ # `indices.dim[j] == self.dim[j]` for all `j != axis`;
146
+ # `indices.dim[axis]` is free.
147
+ #
148
+ # `indices` data_type: any integer kind (zero-copy when
149
+ # already `:int64`). Negative indices: Python-style
150
+ # (`-1` == last). Out-of-range indices raise `RangeError`.
151
+ # Negative `axis:` is Python-style.
152
+ #
153
+ # @param indices [CArray] integer-typed axis-local positions.
154
+ # @param axis [Integer] axis along which `indices` are
155
+ # interpreted.
156
+ # @return [CArray] `:int64` view-flat addresses, same shape as
157
+ # `indices`.
158
+ # @raise [RangeError] when an index is out of range after
159
+ # negative normalization.
160
+ # @raise [ArgumentError] for shape / ndim / data_type
161
+ # violations.
162
+ def axis2addr(indices, axis: 0); end
163
+
164
+ # @!endgroup
165
+ end
@@ -0,0 +1,85 @@
1
+ # DOCUMENTATION ONLY — DO NOT REQUIRE.
2
+ # Stubs for methods defined in ext/carray_test.c.
3
+ # See yard-stubs/README.md and yard-stubs/STYLE.md.
4
+
5
+ class CArray
6
+ # @!group Index and address conversion
7
+
8
+ # @overload valid_index?(*idx)
9
+ # Returns `true` if the given index tuple is in range for `self`.
10
+ # The number of indices must equal `ndim`.
11
+ # @param idx [Array<Integer>] one index per axis.
12
+ # @return [Boolean]
13
+ # @raise [ArgumentError] if the number of indices does not match
14
+ # `ndim`.
15
+ def valid_index?(*idx); end
16
+
17
+ # @overload valid_addr?(addr)
18
+ # Returns `true` if `addr` is in range `0...elements` for `self`.
19
+ # @param addr [Integer] flat address into the contiguous element
20
+ # sequence.
21
+ # @return [Boolean]
22
+ def valid_addr?(addr); end
23
+
24
+ # @overload same_shape?(other)
25
+ # Returns `true` if `other` has the same shape as `self`.
26
+ # @param other [CArray]
27
+ # @return [Boolean]
28
+ def same_shape?(other); end
29
+
30
+ # @!endgroup
31
+
32
+ # @!group Equality and hashing
33
+
34
+ # @overload ==(other)
35
+ # Returns `true` if `other` is a CArray with the same shape,
36
+ # `data_class`, `data_type`, mask state, and elementwise values as
37
+ # `self`. NaN values compare unequal (IEEE semantics), so two
38
+ # arrays with NaN at the same position are not `==`.
39
+ # @param other [Object]
40
+ # @return [Boolean]
41
+ def ==(other); end
42
+
43
+ # @overload eql?(other)
44
+ # Returns `true` under Hash-invariant semantics: `data_class`,
45
+ # `data_type`, shape, and mask state must all match, and elements
46
+ # are compared bitwise (for numeric types) or via `Object#eql?`
47
+ # (for `:object` arrays). Unlike `==`, `NaN.eql?(NaN)` holds, so
48
+ # two mask-free arrays with NaN at the same positions are `eql?`.
49
+ #
50
+ # Guarantees `a.eql?(b)` ⇒ `a.hash == b.hash`.
51
+ # @param other [Object]
52
+ # @return [Boolean]
53
+ def eql?(other); end
54
+
55
+ # @overload hash
56
+ # Returns the Hash key value for `self`. Mixes `data_type`,
57
+ # `ndim`, `bytes`, `elements`, shape, scalar-ness, and mask
58
+ # presence; for unmasked arrays, samples the leading 64 bytes of
59
+ # data. Masked arrays skip the data sample.
60
+ # @return [Integer]
61
+ def hash; end
62
+
63
+ # @!endgroup
64
+
65
+ # @!group Equality and hashing
66
+
67
+ # @overload freeze
68
+ # Freezes `self` and marks it read-only. Subsequent mutations
69
+ # raise `FrozenError`.
70
+ # @return [self]
71
+ def freeze; end
72
+
73
+ # @overload set_read_only_flag
74
+ # Marks `self` read-only (sets `CA_FLAG_READ_ONLY`) without
75
+ # freezing the Ruby object, so subsequent mutations raise
76
+ # `RuntimeError` while `frozen?` stays false and views / Faces
77
+ # derived from `self` can still memoise. One-way: there is no
78
+ # method to clear the flag. Use `#copy` for a writable copy (a
79
+ # copy does not inherit the flag). Contrast `#freeze`, which also
80
+ # freezes the Ruby object.
81
+ # @return [self]
82
+ def set_read_only_flag; end
83
+
84
+ # @!endgroup
85
+ end
@@ -0,0 +1,64 @@
1
+ # DOCUMENTATION ONLY — DO NOT REQUIRE.
2
+ # Stubs for the UNDEF sentinel and UndefClass defined in
3
+ # ext/carray_undef.c. See yard-stubs/README.md and yard-stubs/STYLE.md.
4
+
5
+ # Singleton class of the {UNDEF} sentinel value. Not instantiable
6
+ # (`UndefClass.new` is undef'd after the single instance is created
7
+ # in `Init_carray_undef`).
8
+ #
9
+ # The class is private API in practice: read and write the sentinel
10
+ # through the top-level `UNDEF` constant rather than touching the
11
+ # class directly.
12
+ class UndefClass
13
+ # @overload inspect
14
+ # Returns the literal string `"UNDEF"`.
15
+ # @return [String]
16
+ def inspect; end
17
+
18
+ # @overload to_s
19
+ # Returns the literal string `"UNDEF"`. Display works (so
20
+ # `puts UNDEF` shows `"UNDEF"`); numeric coercion via {#to_f}
21
+ # / {#to_i} raises.
22
+ # @return [String]
23
+ def to_s; end
24
+
25
+ # @overload to_f
26
+ # Raises `TypeError`. Numeric coercion of UNDEF is rejected so
27
+ # that accidental arithmetic on a masked sentinel surfaces as an
28
+ # error rather than silently producing `0.0` / `NaN`.
29
+ # @raise [TypeError]
30
+ def to_f; end
31
+
32
+ # @overload to_i
33
+ # Raises `TypeError`. Same rationale as {#to_f}.
34
+ # @raise [TypeError]
35
+ def to_i; end
36
+
37
+ # @overload to_int
38
+ # Alias of {#to_i}. Raises `TypeError`.
39
+ # @raise [TypeError]
40
+ def to_int; end
41
+
42
+ # @overload ==(other)
43
+ # Returns `true` only when `other` is the same UNDEF singleton
44
+ # (identity comparison). No coercion or value equality.
45
+ # @param other [Object]
46
+ # @return [Boolean]
47
+ def ==(other); end
48
+ end
49
+
50
+ # Top-level sentinel used by mask-bearing CArray APIs to mean
51
+ # "masked / no value here" without choosing a numeric sentinel
52
+ # (NaN, `-1`, etc.) that might collide with valid data.
53
+ #
54
+ # Identity semantics: every reference to `UNDEF` is the same Ruby
55
+ # object, pinned against the compacting GC so the C extension can
56
+ # safely use raw pointer comparison to detect it.
57
+ #
58
+ # @example mask a cell during construction
59
+ # a = CArray.int32(3) { |i| (i == 1) ? UNDEF : i * 10 }
60
+ # a.to_a # => [0, nil, 20] # UNDEF surfaces as nil after to_a
61
+ #
62
+ # @example check whether an element is masked
63
+ # a[1] == UNDEF # => true
64
+ UNDEF = UndefClass.new
@@ -0,0 +1,97 @@
1
+ # DOCUMENTATION ONLY — DO NOT REQUIRE.
2
+ # Stubs for methods defined in ext/carray_utils.c.
3
+ # See yard-stubs/README.md and yard-stubs/STYLE.md.
4
+
5
+ class CArray
6
+ # @!group Index and address conversion
7
+
8
+ # @overload normalize_axis(axis, name = nil)
9
+ # Returns the canonical non-negative integer axis index in
10
+ # `[0, ndim)` for `self`. Accepts Python-style negative indices
11
+ # (`-1` ⇒ `ndim-1`).
12
+ # @param axis [Integer] axis index, possibly negative.
13
+ # @param name [String, nil] argument name to embed in error
14
+ # messages (e.g. `"axis"`, `"at"`).
15
+ # @return [Integer]
16
+ # @raise [ArgumentError] if `axis` is outside `[-ndim, ndim)`.
17
+ def normalize_axis(axis, name = nil); end
18
+
19
+ # @overload normalize_axes(axes, name = nil)
20
+ # Returns an Array of canonical non-negative axis indices in
21
+ # input order. Accepts:
22
+ #
23
+ # - `nil` ⇒ all axes `[0, 1, ..., ndim-1]`
24
+ # - `Integer` ⇒ `[normalize_axis(axis)]`
25
+ # - `Array<Integer>` ⇒ each normalized, preserving input order
26
+ #
27
+ # @param axes [Integer, Array<Integer>, nil]
28
+ # @param name [String, nil] argument name for error messages.
29
+ # @return [Array<Integer>]
30
+ # @raise [ArgumentError] on out-of-range or duplicate axes.
31
+ def normalize_axes(axes, name = nil); end
32
+
33
+ # @!endgroup
34
+
35
+ class << self
36
+ # @!group Index and address conversion
37
+
38
+ # @overload normalize_axis(axis, ndim, name = nil)
39
+ # Class-method form of {CArray#normalize_axis} that operates on
40
+ # an explicit `ndim` rather than a CArray instance. Range is
41
+ # `[0, ndim)`.
42
+ #
43
+ # For an insertion position (valid range `[0, old_ndim]`
44
+ # inclusive), pass `old_ndim + 1` as `ndim`. Used by class-level
45
+ # callers such as `CArray.stack(list, axis:)` that must
46
+ # normalize before any instance is available, and by
47
+ # composition helpers in `lib/carray/compose.rb`.
48
+ # @param axis [Integer]
49
+ # @param ndim [Integer]
50
+ # @param name [String, nil]
51
+ # @return [Integer]
52
+ def normalize_axis(axis, ndim, name = nil); end
53
+
54
+ # @!endgroup
55
+
56
+ # @!group Type guessing
57
+
58
+ # @overload guess_type_and_bytes(type_spec, bytes = nil)
59
+ # Resolves a user-supplied type spec into the pair
60
+ # `[data_type_code, bytes]`. `data_type_code` is the internal
61
+ # `int8_t` numeric code (see {CArray.data_type_code}); `bytes`
62
+ # is the per-element byte size (`0` for non-`:fixlen`).
63
+ # @param type_spec [Symbol, Integer, Class, String]
64
+ # @param bytes [Integer, nil] element byte size, used only for
65
+ # `:fixlen`.
66
+ # @return [Array(Integer, Integer)]
67
+ def guess_type_and_bytes(type_spec, bytes = nil); end
68
+
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
+ end
97
+ end