carray 3.0.1 → 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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +520 -0
  3. data/README.md +2 -2
  4. data/carray.gemspec +1 -1
  5. data/ext/ca_axis_dispatch.c +33 -4
  6. data/ext/ca_axis_group.c +202 -96
  7. data/ext/ca_categorical_iterator.c +108 -54
  8. data/ext/ca_kernel_iterator.c +317 -51
  9. data/ext/ca_kernel_iterator.h +142 -35
  10. data/ext/ca_obj_array.c +62 -20
  11. data/ext/ca_obj_block.c +4 -4
  12. data/ext/ca_obj_const_string.c +85 -26
  13. data/ext/ca_obj_face.c +24 -0
  14. data/ext/ca_obj_face.h +15 -0
  15. data/ext/ca_obj_fixlen_string.c +18 -5
  16. data/ext/ca_obj_meld.c +123 -25
  17. data/ext/ca_obj_object.c +8 -0
  18. data/ext/ca_obj_select.c +49 -34
  19. data/ext/ca_obj_stack.c +3 -8
  20. data/ext/ca_obj_stride.c +72 -1
  21. data/ext/ca_obj_string.c +8 -4
  22. data/ext/ca_obj_window.c +8 -2
  23. data/ext/ca_op_ipower.c +1 -2
  24. data/ext/ca_rng_normal.h +42 -0
  25. data/ext/ca_rng_xoshiro256pp.h +105 -0
  26. data/ext/ca_sweep_engine.c +307 -143
  27. data/ext/ca_sweep_engine.h +26 -5
  28. data/ext/carray.h +21 -2
  29. data/ext/carray_access.c +32 -20
  30. data/ext/carray_address_basis.c +590 -0
  31. data/ext/carray_broadcast.c +3 -3
  32. data/ext/carray_call_cfunc.c +667 -483
  33. data/ext/carray_cast.c +115 -41
  34. data/ext/carray_copy.c +55 -30
  35. data/ext/carray_core.c +83 -3
  36. data/ext/carray_count.c +9 -10
  37. data/ext/carray_factorize.c +46 -25
  38. data/ext/carray_internal.h +17 -0
  39. data/ext/carray_kernels_reduce_aggregate.c +168 -0
  40. data/ext/carray_kernels_reduce_cumulative.c +270 -1
  41. data/ext/carray_kernels_reduce_extreme.c +554 -8
  42. data/ext/carray_kernels_scan.c +4 -4
  43. data/ext/carray_kernels_search.c +94 -14
  44. data/ext/carray_loop.c +7 -1
  45. data/ext/carray_mask.c +23 -8
  46. data/ext/carray_median_percentile.c +55 -0
  47. data/ext/carray_operator.c +4 -4
  48. data/ext/carray_order.c +1 -1
  49. data/ext/carray_random.c +384 -40
  50. data/ext/carray_slab.c +13 -0
  51. data/ext/carray_sort.c +20 -22
  52. data/ext/mk_call_cfunc.rb +103 -116
  53. data/ext/mkkernel.rb +297 -29
  54. data/ext/ruby_carray.c +10 -1
  55. data/ext/version.h +4 -4
  56. data/lib/carray/autoload_carray.rb +5 -3
  57. data/lib/carray/autoload_method_extension.rb +12 -0
  58. data/lib/carray/axis_group.rb +77 -0
  59. data/lib/carray/basics.rb +4 -0
  60. data/lib/carray/block_iterator.rb +92 -16
  61. data/lib/carray/categorical.rb +150 -33
  62. data/lib/carray/categorical_iterator.rb +207 -80
  63. data/lib/carray/const_string.rb +131 -27
  64. data/lib/carray/construct.rb +40 -0
  65. data/lib/carray/data_type_extension.rb +3 -0
  66. data/lib/carray/data_type_limits.rb +91 -0
  67. data/lib/carray/fixlen_string.rb +1 -1
  68. data/lib/carray/frame/csv_parser.rb +11 -4
  69. data/lib/carray/frame/frame.rb +81 -10
  70. data/lib/carray/frame/group.rb +36 -3
  71. data/lib/carray/frame/io.rb +67 -15
  72. data/lib/carray/frame/records.rb +18 -4
  73. data/lib/carray/frame/verbs.rb +14 -11
  74. data/lib/carray/inspect.rb +42 -9
  75. data/lib/carray/iterator.rb +143 -0
  76. data/lib/carray/lazy.rb +0 -37
  77. data/lib/carray/mask_gap_fill.rb +3 -1
  78. data/lib/carray/methods/discovery_along.rb +74 -0
  79. data/lib/carray/methods/factorize.rb +50 -0
  80. data/lib/carray/methods/is_in.rb +13 -2
  81. data/lib/carray/methods/locate_addr.rb +75 -2
  82. data/lib/carray/methods/mask_duplicates.rb +35 -1
  83. data/lib/carray/methods/nunique.rb +22 -1
  84. data/lib/carray/methods/repeat.rb +110 -0
  85. data/lib/carray/methods/unique.rb +41 -1
  86. data/lib/carray/rng.rb +86 -0
  87. data/lib/carray/slab_iterator.rb +58 -13
  88. data/lib/carray/string_operation_extension.rb +5 -1
  89. data/lib/carray/time.rb +18 -2
  90. data/lib/carray/window_iterator.rb +142 -20
  91. data/lib/carray.rb +2 -0
  92. data/yard-stubs/ca_obj_block.rb +2 -7
  93. data/yard-stubs/ca_obj_window.rb +10 -2
  94. data/yard-stubs/carray_access.rb +1 -1
  95. data/yard-stubs/carray_broadcast.rb +1 -1
  96. data/yard-stubs/carray_core.rb +0 -80
  97. data/yard-stubs/carray_count.rb +7 -2
  98. data/yard-stubs/carray_lazy.rb +205 -0
  99. data/yard-stubs/carray_math.rb +1486 -3
  100. data/yard-stubs/carray_median_percentile.rb +16 -2
  101. data/yard-stubs/carray_order.rb +9 -69
  102. data/yard-stubs/carray_slab.rb +9 -7
  103. data/yard-stubs/carray_sort.rb +7 -5
  104. metadata +9 -1
@@ -83,10 +83,10 @@ class CAWindowIterator < CAIterator
83
83
  def initialize (source, *ranges, bounds: :skip, fill_value: nil)
84
84
  if source.is_a?(CArray) && source.obj_type == CA_OBJ_WINDOW
85
85
  # Backward-compat: read geometry from a CAWindow view built by #window.
86
- # start[i] = lo, dim[i] (window width) = w, so hi = lo + w - 1.
86
+ # start[i] = lo, shape[i] (window width) = w, so hi = lo + w - 1.
87
87
  win = source
88
88
  @source = win.parent
89
- widths = win.count
89
+ widths = win.shape
90
90
  @ranges = win.start.each_with_index.map { |lo, i| lo..(lo + widths[i] - 1) }
91
91
  # The legacy #window default is FILL (constant), whose value is the
92
92
  # view's fill_value; map that to a :constant margin.
@@ -298,19 +298,113 @@ class CAWindowIterator < CAIterator
298
298
  # unchanged. `min_count:` / `fill_value:` pass straight to the core (the
299
299
  # boundary strictness + result fill knobs).
300
300
 
301
- # @overload sum(min_count: nil, fill_value: nil)
302
- # Rolling sum, delegating to `sliding_view.sum(axis: window_axes)`.
301
+ # @!method sum(min_count: nil, fill_value: nil)
302
+ # Rolling sum.
303
+ # @param min_count [Integer, nil] fewest cells that must be present
304
+ # for a result; a piece with fewer comes back masked.
305
+ # @param fill_value [Object, nil] value to put in place of a masked
306
+ # result instead of leaving it masked.
303
307
  # @return [CArray] reference-shaped (or shrunk, for :truncate)
304
- # @overload accumulate(min_count: nil, fill_value: nil)
305
- # Rolling sum in the source's own data type, wrapping at its width, as the
306
- # core `accumulate` does. `sum` answers in the type the core promotes to
307
- # (float64 for integers), which for a window over bytes moves eight times
308
- # the bytes; this is the spelling for staying in the type when the window
309
- # cannot overflow it.
308
+ # @!method accumulate(min_count: nil, fill_value: nil)
309
+ # Rolling sum kept in the source's own data type, wrapping at its
310
+ # width, as the core `accumulate` does -- `sum` answers in the type
311
+ # the core promotes to (float64 for integers).
312
+ # @param min_count [Integer, nil] fewest cells that must be present
313
+ # for a result; a piece with fewer comes back masked.
314
+ # @param fill_value [Object, nil] value to put in place of a masked
315
+ # result instead of leaving it masked.
316
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
317
+ # @!method prod(min_count: nil, fill_value: nil)
318
+ # Rolling product.
319
+ # @param min_count [Integer, nil] fewest cells that must be present
320
+ # for a result; a piece with fewer comes back masked.
321
+ # @param fill_value [Object, nil] value to put in place of a masked
322
+ # result instead of leaving it masked.
323
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
324
+ # @!method mean(min_count: nil, fill_value: nil)
325
+ # Rolling arithmetic mean.
326
+ # @param min_count [Integer, nil] fewest cells that must be present
327
+ # for a result; a piece with fewer comes back masked.
328
+ # @param fill_value [Object, nil] value to put in place of a masked
329
+ # result instead of leaving it masked.
330
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
331
+ # @!method min(min_count: nil, fill_value: nil)
332
+ # Rolling minimum.
333
+ # @param min_count [Integer, nil] fewest cells that must be present
334
+ # for a result; a piece with fewer comes back masked.
335
+ # @param fill_value [Object, nil] value to put in place of a masked
336
+ # result instead of leaving it masked.
337
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
338
+ # @!method max(min_count: nil, fill_value: nil)
339
+ # Rolling maximum.
340
+ # @param min_count [Integer, nil] fewest cells that must be present
341
+ # for a result; a piece with fewer comes back masked.
342
+ # @param fill_value [Object, nil] value to put in place of a masked
343
+ # result instead of leaving it masked.
344
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
345
+ # @!method variance(min_count: nil, fill_value: nil)
346
+ # Rolling sample variance (divisor `n - 1`).
347
+ # @param min_count [Integer, nil] fewest cells that must be present
348
+ # for a result; a piece with fewer comes back masked.
349
+ # @param fill_value [Object, nil] value to put in place of a masked
350
+ # result instead of leaving it masked.
351
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
352
+ # @!method stddev(min_count: nil, fill_value: nil)
353
+ # Rolling sample standard deviation (divisor `n - 1`).
354
+ # @param min_count [Integer, nil] fewest cells that must be present
355
+ # for a result; a piece with fewer comes back masked.
356
+ # @param fill_value [Object, nil] value to put in place of a masked
357
+ # result instead of leaving it masked.
358
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
359
+ # @!method all(min_count: nil, fill_value: nil)
360
+ # Whether every cell of each rolling is true.
361
+ # @param min_count [Integer, nil] fewest cells that must be present
362
+ # for a result; a piece with fewer comes back masked.
363
+ # @param fill_value [Object, nil] value to put in place of a masked
364
+ # result instead of leaving it masked.
365
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
366
+ # @!method any(min_count: nil, fill_value: nil)
367
+ # Whether any cell of each rolling is true.
368
+ # @param min_count [Integer, nil] fewest cells that must be present
369
+ # for a result; a piece with fewer comes back masked.
370
+ # @param fill_value [Object, nil] value to put in place of a masked
371
+ # result instead of leaving it masked.
372
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
373
+ # @!method variancep(min_count: nil, fill_value: nil)
374
+ # Rolling population variance (divisor `n`).
375
+ # @param min_count [Integer, nil] fewest cells that must be present
376
+ # for a result; a piece with fewer comes back masked.
377
+ # @param fill_value [Object, nil] value to put in place of a masked
378
+ # result instead of leaving it masked.
379
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
380
+ # @!method stddevp(min_count: nil, fill_value: nil)
381
+ # Rolling population standard deviation (divisor `n`).
382
+ # @param min_count [Integer, nil] fewest cells that must be present
383
+ # for a result; a piece with fewer comes back masked.
384
+ # @param fill_value [Object, nil] value to put in place of a masked
385
+ # result instead of leaving it masked.
386
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
387
+ # @!method minmax(min_count: nil, fill_value: nil)
388
+ # Rolling minimum and maximum, found in one pass.
389
+ # @param min_count [Integer, nil] fewest cells that must be present
390
+ # for a result; a piece with fewer comes back masked.
391
+ # @param fill_value [Object, nil] value to put in place of a masked
392
+ # result instead of leaving it masked.
393
+ # @return [Array<CArray>] the pair `[min, max]`, reference-shaped (or shrunk, for :truncate)
394
+ # @!method min_index(min_count: nil, fill_value: nil)
395
+ # Rolling position of the minimum, local to the window axes.
396
+ # @param min_count [Integer, nil] fewest cells that must be present
397
+ # for a result; a piece with fewer comes back masked.
398
+ # @param fill_value [Object, nil] value to put in place of a masked
399
+ # result instead of leaving it masked.
400
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
401
+ # @!method max_index(min_count: nil, fill_value: nil)
402
+ # Rolling position of the maximum, local to the window axes.
403
+ # @param min_count [Integer, nil] fewest cells that must be present
404
+ # for a result; a piece with fewer comes back masked.
405
+ # @param fill_value [Object, nil] value to put in place of a masked
406
+ # result instead of leaving it masked.
310
407
  # @return [CArray] reference-shaped (or shrunk, for :truncate)
311
- # The rest are analogous: prod / mean / min / max, sample and population
312
- # variance / stddev, all / any, fused minmax, and the window-local position
313
- # min_index / max_index (index within the window axes).
314
408
  [:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
315
409
  :variancep, :stddevp, :minmax, :min_index, :max_index].each do |op|
316
410
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
@@ -873,13 +967,41 @@ class CAWindowIterator < CAIterator
873
967
  "sort of source addresses is ill-defined."
874
968
  end
875
969
 
876
- # @overload cumsum
877
- # @overload cumprod
878
- # @overload cummax
879
- # @overload cummin
880
- # @overload cumcount
881
- # Not supported for a window iterator: a segment scan writes a per-cell
882
- # running statistic, which is single-valued only when each cell belongs to
970
+ # @!method cumsum
971
+ # Not supported for a window iterator. A segment scan writes a per-cell
972
+ # running sum, which is single-valued only when each cell belongs to
973
+ # exactly one piece. Overlapping windows put a cell in many windows, so
974
+ # there is no single running value. Raises NotImplementedError, exactly as
975
+ # {#map} / {#sort_addr} do (min / max reductions stay available: a single
976
+ # winner is well-defined).
977
+ # @raise [NotImplementedError]
978
+ # @!method cumprod
979
+ # Not supported for a window iterator. A segment scan writes a per-cell
980
+ # running product, which is single-valued only when each cell belongs to
981
+ # exactly one piece. Overlapping windows put a cell in many windows, so
982
+ # there is no single running value. Raises NotImplementedError, exactly as
983
+ # {#map} / {#sort_addr} do (min / max reductions stay available: a single
984
+ # winner is well-defined).
985
+ # @raise [NotImplementedError]
986
+ # @!method cummax
987
+ # Not supported for a window iterator. A segment scan writes a per-cell
988
+ # running maximum, which is single-valued only when each cell belongs to
989
+ # exactly one piece. Overlapping windows put a cell in many windows, so
990
+ # there is no single running value. Raises NotImplementedError, exactly as
991
+ # {#map} / {#sort_addr} do (min / max reductions stay available: a single
992
+ # winner is well-defined).
993
+ # @raise [NotImplementedError]
994
+ # @!method cummin
995
+ # Not supported for a window iterator. A segment scan writes a per-cell
996
+ # running minimum, which is single-valued only when each cell belongs to
997
+ # exactly one piece. Overlapping windows put a cell in many windows, so
998
+ # there is no single running value. Raises NotImplementedError, exactly as
999
+ # {#map} / {#sort_addr} do (min / max reductions stay available: a single
1000
+ # winner is well-defined).
1001
+ # @raise [NotImplementedError]
1002
+ # @!method cumcount
1003
+ # Not supported for a window iterator. A segment scan writes a per-cell
1004
+ # running count of present cells, which is single-valued only when each cell belongs to
883
1005
  # exactly one piece. Overlapping windows put a cell in many windows, so
884
1006
  # there is no single running value. Raises NotImplementedError, exactly as
885
1007
  # {#map} / {#sort_addr} do (min / max reductions stay available: a single
data/lib/carray.rb CHANGED
@@ -16,6 +16,7 @@ end
16
16
  # interpolation, so compute programs that never print a CArray skip it.
17
17
  require 'carray/construct'
18
18
  require 'carray/data_type_extension'
19
+ require 'carray/data_type_limits' # MIN / MAX / TINY / EPSILON on the typed classes
19
20
  # carray/stack is loaded lazily via autoload_carray (entry-method stubs).
20
21
  # CAStack is C-defined so its constant is always present; only the Ruby
21
22
  # composition surface (stack/meld/montage/split/append) needs the file.
@@ -29,6 +30,7 @@ require 'carray/meld_reduce' # CAMeld per-parent reduce fast path (sum/mean/m
29
30
  # carray/ordering CIFY (2026-06-21): translated to ext/carray_order.c
30
31
 
31
32
  require 'carray/math'
33
+ require 'carray/rng' # CArray::Rng: the generator its C is shared from
32
34
  # carray/clip_cast CIFY (2026-06-23): translated to ext/carray_cast.c
33
35
  require 'carray/complex' # real / imag accessors; MUST precede carray/lazy
34
36
  # (lazy aliases real/imag at load time)
@@ -10,7 +10,8 @@ class CABlock
10
10
  # @overload size0
11
11
  # Returns the parent dimension sizes that the block is carved
12
12
  # from (one Integer per axis). Distinct from `shape`, which is
13
- # the block's own shape (= `count` after step / stride logic).
13
+ # the block's own shape (= what it exposes after step / stride
14
+ # logic).
14
15
  # @return [Array<Integer>]
15
16
  def size0; end
16
17
 
@@ -26,12 +27,6 @@ class CABlock
26
27
  # @return [Array<Integer>]
27
28
  def step; end
28
29
 
29
- # @overload count
30
- # Returns the per-axis number of elements the block exposes.
31
- # Same as `shape`.
32
- # @return [Array<Integer>]
33
- def count; end
34
-
35
30
  # @overload offset
36
31
  # Returns the block's base flat offset into the parent (in
37
32
  # element units), set at construction and adjusted as start[]
@@ -20,7 +20,14 @@ class CArray
20
20
  # axis, which may extend past either end of the parent. Cells inside the
21
21
  # parent alias it, so writes through the view reach the parent; cells
22
22
  # outside take `fill_value` (default `0`), and `fill_value: UNDEF` masks
23
- # them instead.
23
+ # them instead. A write that lands outside the parent has no cell to land
24
+ # in and is discarded.
25
+ #
26
+ # A range wider than its axis is how an array is **padded**: `a.window(-1..
27
+ # a.dim0, -1..a.dim1)` puts a one-cell border all round, which is NumPy's
28
+ # `pad` with no allocation (`fill_value:` is its `constant`, `bounds:
29
+ # :nearest` its `edge`). {#windows} is the different, plural thing: one
30
+ # such window anchored on every cell, folded.
24
31
  #
25
32
  # Only unit-step ranges are accepted, and each range must run forward, so
26
33
  # the `0..-1` end-relative notation cannot be used here.
@@ -30,7 +37,8 @@ class CArray
30
37
  # must equal `self.ndim`.
31
38
  # @param fill_value [Object] value given to out-of-range cells; `UNDEF`
32
39
  # masks them instead.
33
- # @param bounds [String] what an out-of-range index means: `"fill"`
40
+ # @param bounds [String, Symbol] what an out-of-range index means; a
41
+ # Symbol says the same as the String, matching {#windows}: `"fill"`
34
42
  # (default) uses `fill_value`, `"nearest"` clamps to the edge cell,
35
43
  # `"ruby"` reads negative indices from the far end, `"strict"` raises.
36
44
  # `"mask"` masks the cell but warns — pass `fill_value: UNDEF` instead.
@@ -22,7 +22,7 @@ class CArray
22
22
  # - Integer CArray — fancy gather (index array); shape follows the
23
23
  # index array.
24
24
  # - `:_` — newaxis: insert a size-1 axis at this position.
25
- # - `:*` / `:%` — repeat / tiling sugar.
25
+ # - `:%` — repeat / tiling sugar.
26
26
  # - `:>` — slab axis: wrap the result in a `CASlabIterator`.
27
27
  # - a member name Symbol — project a struct field (see `CARecord`).
28
28
  #
@@ -25,7 +25,7 @@ class CArray
25
25
  # @return [CArray]
26
26
  # @raise [RuntimeError] if a source axis cannot be paired with a
27
27
  # target axis (cross-ndim expansion is intentionally strict —
28
- # see {CArray.broadcast} for the explicit-`:_` / `:*` axis
28
+ # see {CArray.broadcast} for the explicit-`:_` axis
29
29
  # declaration form).
30
30
  # @example
31
31
  # a = CArray.float64(3) { [1.0, 2.0, 3.0] }
@@ -3,64 +3,6 @@
3
3
  # See yard-stubs/README.md and yard-stubs/STYLE.md.
4
4
 
5
5
  class CArray
6
- # @!group Attach lifecycle
7
- #
8
- # The `attach` / `attach!` family is an internal lifecycle API used
9
- # by library authors writing CArray-aware C extensions. End users
10
- # should not normally need to call these methods — view algebra and
11
- # `CArray#[]` / `[]=` handle attach/sync transparently.
12
- #
13
- # The block-form `attach` (no sync on exit) and `attach!` (sync on
14
- # exit) wrap a body of code so that the underlying memory block is
15
- # guaranteed to be materialized while the block runs and is
16
- # released afterward. The dunder forms (`__attach__`, `__sync__`,
17
- # `__detach__`) expose the raw three-step protocol for callers that
18
- # cannot use a block.
19
-
20
- # @overload attach { ... }
21
- # Attaches `self`, yields, and detaches on block exit. No sync
22
- # is performed.
23
- # @yield
24
- # @return [Object] the block's return value.
25
- def attach; end
26
-
27
- # @overload attach! { ... }
28
- # Attaches `self`, yields, then syncs and detaches on block exit.
29
- # Use this form when the block mutates `self.ptr` and you need
30
- # the changes flushed back to the parent.
31
- # @yield
32
- # @return [Object] the block's return value.
33
- def attach!; end
34
-
35
- # @private
36
- # @overload __attach__
37
- # Raw attach: materializes the memory block of `self` and leaves
38
- # it attached. Caller is responsible for the matching
39
- # `__detach__` (and `__sync__`, if changes were made).
40
- #
41
- # Prefer the block form {#attach!} unless block scope is
42
- # impossible.
43
- # @return [self]
44
- # @api private
45
- def __attach__; end
46
-
47
- # @private
48
- # @overload __sync__
49
- # Raw sync: writes any pending changes in `self.ptr` back to the
50
- # parent. Requires `self` to be currently attached.
51
- # @return [self]
52
- # @api private
53
- def __sync__; end
54
-
55
- # @private
56
- # @overload __detach__
57
- # Raw detach: releases the memory block paired with `__attach__`.
58
- # @return [self]
59
- # @api private
60
- def __detach__; end
61
-
62
- # @!endgroup
63
-
64
6
  # @!group Attributes
65
7
 
66
8
  # @overload members
@@ -89,26 +31,4 @@ class CArray
89
31
  def fields_at(*names); end
90
32
 
91
33
  # @!endgroup
92
-
93
- class << self
94
- # @!group Attach lifecycle
95
-
96
- # @overload attach(*arrays) { ... }
97
- # Attaches every CArray in `arrays`, yields, and detaches them
98
- # in reverse order on block exit. No sync is performed.
99
- # @param arrays [Array<CArray>]
100
- # @yield
101
- # @return [Object] the block's return value.
102
- def attach(*arrays); end
103
-
104
- # @overload attach!(*arrays) { ... }
105
- # Attaches every CArray in `arrays`, yields, then syncs and
106
- # detaches each on block exit.
107
- # @param arrays [Array<CArray>]
108
- # @yield
109
- # @return [Object] the block's return value.
110
- def attach!(*arrays); end
111
-
112
- # @!endgroup
113
- end
114
34
  end
@@ -40,7 +40,10 @@ class CArray
40
40
  # stores 0/1, so `count(1)` == `count(true)`. Any other value
41
41
  # (`2`, `1.0`, `nil`, …) raises `TypeError`.
42
42
  # - `self` is numeric, `v` is scalar: `v` must be numeric (true /
43
- # false are rejected).
43
+ # false are rejected -- they are the boolean array's domain).
44
+ # - `self.data_type == :object`, `v` is scalar: cells equal to `v`
45
+ # by Ruby `==`, so `count(1)` and `count(1.0)` agree, and `true` /
46
+ # `false` / `nil` are ordinary values to count.
44
47
  #
45
48
  # When `axis` is `nil` (default), reduces over all axes and
46
49
  # returns an `Integer`. Otherwise reduces along the given
@@ -50,7 +53,9 @@ class CArray
50
53
  # identity `0`, so the count over no cells is `0`, not `UNDEF`
51
54
  # (pass `min_count:` to get `UNDEF` below a threshold instead).
52
55
  #
53
- # `:fixlen` and `:object` data types raise `CArray::DataTypeError`.
56
+ # `:fixlen` compares the whole cell by `memcmp`, with a short String
57
+ # query padded out to the cell width -- so a 4-byte cell holding
58
+ # `"a\0\0\0"` is counted by `count("a")`.
54
59
  #
55
60
  # A time array counts by its own values: `CATime` / `CATimedelta`
56
61
  # descend to their storage and reconcile `v` into their unit, so `v`
@@ -21,3 +21,208 @@ class CArray
21
21
  def lazy; end
22
22
  # @!endgroup
23
23
  end
24
+
25
+ class CAMonOp
26
+ # @!group Copy and conversion
27
+
28
+ # @overload to_ca
29
+ # Evaluates the expression and returns the result as a new entity.
30
+ #
31
+ # A one-operand element-wise operation holds no data of its own, so there is nothing to
32
+ # hand over unevaluated: unlike `CArray#to_ca`, which returns
33
+ # `self`, this materialises -- the Ruby `Enumerable#to_a` /
34
+ # lazy `force` convention.
35
+ #
36
+ # The entity is detached from the operands, so writes to it reach
37
+ # nothing. `writable: true` is therefore refused rather than
38
+ # answered with a result that would swallow them.
39
+ # @param writable [Boolean] whether the caller needs writes to
40
+ # land back in the source; only `false` can be satisfied.
41
+ # @return [CArray] a newly evaluated entity.
42
+ # @raise [RuntimeError] when `writable: true` is requested.
43
+ def to_ca(writable: false); end
44
+
45
+ # @overload copy
46
+ # Evaluates the expression and returns the result as a new entity.
47
+ #
48
+ # If an expression evaluator is registered through
49
+ # {CArray.expression_evaluator} it is asked first; the ordinary
50
+ # element-wise walk is what happens when it declines, when none is
51
+ # registered, or when the array is small enough that walking is
52
+ # the faster answer.
53
+ # @return [CArray] a newly evaluated entity.
54
+ def copy; end
55
+
56
+ # @!endgroup
57
+ end
58
+
59
+ class CABinOp
60
+ # @!group Copy and conversion
61
+
62
+ # @overload to_ca
63
+ # Evaluates the expression and returns the result as a new entity.
64
+ #
65
+ # A two-operand element-wise operation holds no data of its own, so there is nothing to
66
+ # hand over unevaluated: unlike `CArray#to_ca`, which returns
67
+ # `self`, this materialises -- the Ruby `Enumerable#to_a` /
68
+ # lazy `force` convention.
69
+ #
70
+ # The entity is detached from the operands, so writes to it reach
71
+ # nothing. `writable: true` is therefore refused rather than
72
+ # answered with a result that would swallow them.
73
+ # @param writable [Boolean] whether the caller needs writes to
74
+ # land back in the source; only `false` can be satisfied.
75
+ # @return [CArray] a newly evaluated entity.
76
+ # @raise [RuntimeError] when `writable: true` is requested.
77
+ def to_ca(writable: false); end
78
+
79
+ # @overload copy
80
+ # Evaluates the expression and returns the result as a new entity.
81
+ #
82
+ # If an expression evaluator is registered through
83
+ # {CArray.expression_evaluator} it is asked first; the ordinary
84
+ # element-wise walk is what happens when it declines, when none is
85
+ # registered, or when the array is small enough that walking is
86
+ # the faster answer.
87
+ # @return [CArray] a newly evaluated entity.
88
+ def copy; end
89
+
90
+ # @!endgroup
91
+ end
92
+
93
+ class CATriOp
94
+ # @!group Copy and conversion
95
+
96
+ # @overload to_ca
97
+ # Evaluates the expression and returns the result as a new entity.
98
+ #
99
+ # A three-operand element-wise operation holds no data of its own, so there is nothing to
100
+ # hand over unevaluated: unlike `CArray#to_ca`, which returns
101
+ # `self`, this materialises -- the Ruby `Enumerable#to_a` /
102
+ # lazy `force` convention.
103
+ #
104
+ # The entity is detached from the operands, so writes to it reach
105
+ # nothing. `writable: true` is therefore refused rather than
106
+ # answered with a result that would swallow them.
107
+ # @param writable [Boolean] whether the caller needs writes to
108
+ # land back in the source; only `false` can be satisfied.
109
+ # @return [CArray] a newly evaluated entity.
110
+ # @raise [RuntimeError] when `writable: true` is requested.
111
+ def to_ca(writable: false); end
112
+
113
+ # @overload copy
114
+ # Evaluates the expression and returns the result as a new entity.
115
+ #
116
+ # If an expression evaluator is registered through
117
+ # {CArray.expression_evaluator} it is asked first; the ordinary
118
+ # element-wise walk is what happens when it declines, when none is
119
+ # registered, or when the array is small enough that walking is
120
+ # the faster answer.
121
+ # @return [CArray] a newly evaluated entity.
122
+ def copy; end
123
+
124
+ # @!endgroup
125
+ end
126
+
127
+ class CAMonCmp
128
+ # @!group Copy and conversion
129
+
130
+ # @overload to_ca
131
+ # Evaluates the expression and returns the result as a new entity.
132
+ #
133
+ # A one-operand element-wise predicate holds no data of its own, so there is nothing to
134
+ # hand over unevaluated: unlike `CArray#to_ca`, which returns
135
+ # `self`, this materialises -- the Ruby `Enumerable#to_a` /
136
+ # lazy `force` convention.
137
+ #
138
+ # The entity is detached from the operands, so writes to it reach
139
+ # nothing. `writable: true` is therefore refused rather than
140
+ # answered with a result that would swallow them.
141
+ # @param writable [Boolean] whether the caller needs writes to
142
+ # land back in the source; only `false` can be satisfied.
143
+ # @return [CArray] a newly evaluated entity.
144
+ # @raise [RuntimeError] when `writable: true` is requested.
145
+ def to_ca(writable: false); end
146
+
147
+ # @overload copy
148
+ # Evaluates the expression and returns the result as a new entity.
149
+ #
150
+ # If an expression evaluator is registered through
151
+ # {CArray.expression_evaluator} it is asked first; the ordinary
152
+ # element-wise walk is what happens when it declines, when none is
153
+ # registered, or when the array is small enough that walking is
154
+ # the faster answer.
155
+ # @return [CArray] a newly evaluated entity.
156
+ def copy; end
157
+
158
+ # @!endgroup
159
+ end
160
+
161
+ class CABinCmp
162
+ # @!group Copy and conversion
163
+
164
+ # @overload to_ca
165
+ # Evaluates the expression and returns the result as a new entity.
166
+ #
167
+ # A two-operand element-wise comparison holds no data of its own, so there is nothing to
168
+ # hand over unevaluated: unlike `CArray#to_ca`, which returns
169
+ # `self`, this materialises -- the Ruby `Enumerable#to_a` /
170
+ # lazy `force` convention.
171
+ #
172
+ # The entity is detached from the operands, so writes to it reach
173
+ # nothing. `writable: true` is therefore refused rather than
174
+ # answered with a result that would swallow them.
175
+ # @param writable [Boolean] whether the caller needs writes to
176
+ # land back in the source; only `false` can be satisfied.
177
+ # @return [CArray] a newly evaluated entity.
178
+ # @raise [RuntimeError] when `writable: true` is requested.
179
+ def to_ca(writable: false); end
180
+
181
+ # @overload copy
182
+ # Evaluates the expression and returns the result as a new entity.
183
+ #
184
+ # If an expression evaluator is registered through
185
+ # {CArray.expression_evaluator} it is asked first; the ordinary
186
+ # element-wise walk is what happens when it declines, when none is
187
+ # registered, or when the array is small enough that walking is
188
+ # the faster answer.
189
+ # @return [CArray] a newly evaluated entity.
190
+ def copy; end
191
+
192
+ # @!endgroup
193
+ end
194
+
195
+ class CALazyMarker
196
+ # @!group Copy and conversion
197
+
198
+ # @overload to_ca
199
+ # Evaluates the expression and returns the result as a new entity.
200
+ #
201
+ # A lazy marker holds no data of its own, so there is nothing to
202
+ # hand over unevaluated: unlike `CArray#to_ca`, which returns
203
+ # `self`, this materialises -- the Ruby `Enumerable#to_a` /
204
+ # lazy `force` convention.
205
+ #
206
+ # The entity is detached from the operands, so writes to it reach
207
+ # nothing. `writable: true` is therefore refused rather than
208
+ # answered with a result that would swallow them.
209
+ # @param writable [Boolean] whether the caller needs writes to
210
+ # land back in the source; only `false` can be satisfied.
211
+ # @return [CArray] a newly evaluated entity.
212
+ # @raise [RuntimeError] when `writable: true` is requested.
213
+ def to_ca(writable: false); end
214
+
215
+ # @overload copy
216
+ # Evaluates the expression and returns the result as a new entity.
217
+ #
218
+ # If an expression evaluator is registered through
219
+ # {CArray.expression_evaluator} it is asked first; the ordinary
220
+ # element-wise walk is what happens when it declines, when none is
221
+ # registered, or when the array is small enough that walking is
222
+ # the faster answer.
223
+ # @return [CArray] a newly evaluated entity.
224
+ def copy; end
225
+
226
+ # @!endgroup
227
+ end
228
+