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
@@ -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.
@@ -104,6 +104,7 @@ class CAWindowIterator < CAIterator
104
104
  "windows: expected #{@source.ndim} ranges (one per axis), " \
105
105
  "got #{@ranges.size}"
106
106
  end
107
+ @ranges = @ranges.each_with_index.map { |r, k| window_offsets(r, k) }
107
108
 
108
109
  @sndim = @source.ndim
109
110
  @widths = @ranges.map { |r| r.end - r.begin + 1 }
@@ -158,11 +159,38 @@ class CAWindowIterator < CAIterator
158
159
  # the padded entity.
159
160
  # @return [CArray]
160
161
  def sliding_view
161
- @sliding_view ||= anchored_buffer.sliding_windows(*@widths)
162
+ @sliding_view ||= @shape.include?(0) ? no_windows : anchored_buffer.sliding_windows(*@widths)
162
163
  end
163
164
 
164
165
  private
165
166
 
167
+ # An axis's offsets as an inclusive Integer range, as Ruby reads the range
168
+ # given (`-1...1` is the offsets -1 and 0).
169
+ def window_offsets (r, k)
170
+ unless r.is_a?(Range) && r.begin.is_a?(Integer) && r.end.is_a?(Integer)
171
+ raise TypeError,
172
+ "windows: axis #{k} takes a Range of Integer offsets, got #{r.inspect}"
173
+ end
174
+ last = r.exclude_end? ? r.end - 1 : r.end
175
+ if last < r.begin
176
+ raise ArgumentError, "windows: axis #{k} offsets #{r.inspect} are empty"
177
+ end
178
+ r.begin..last
179
+ end
180
+
181
+ # With no anchors (an empty source, or a :truncate window wider than the
182
+ # source) there is nothing to slide over, and sliding_windows refuses a
183
+ # window wider than its buffer. The view is then an empty one of the same
184
+ # shape: the source's unit tiles cut to the output and stretched along the
185
+ # window axes, so every reduction answers with an empty array of its type.
186
+ def no_windows
187
+ unit = @source.block_view(*[1] * @sndim)
188
+ cut = @shape.each_with_index.map { |n, k| n == unit.shape[k] ? nil : 0...n }
189
+ unit = unit[*cut, *[nil] * @sndim] unless cut.all?(&:nil?)
190
+ view = unit.broadcast_to(*(@shape + @widths))
191
+ @source.face? ? view.face_lift(@source) : view
192
+ end
193
+
166
194
  # The stretch of the padded buffer the windows are taken from: it begins at
167
195
  # the first window and holds one window per anchor. For a window that covers
168
196
  # its own anchor and a boundary policy that pads, that is the whole buffer.
@@ -210,10 +238,11 @@ class CAWindowIterator < CAIterator
210
238
  # One allocation, the source copied into the interior region, then the
211
239
  # margins filled per mode.
212
240
  def pad_source (src, lefts, rights, mode, value)
241
+ return pad_face(src, lefts, rights, mode, value) if src.face?
213
242
  nd = src.ndim
214
243
  shape = src.shape
215
244
  pshape = nd.times.map { |i| shape[i] + lefts[i] + rights[i] }
216
- pad = CArray.new(src.data_type, pshape)
245
+ pad = CArray.new(src.data_type, pshape, bytes: src.bytes)
217
246
 
218
247
  # Fill the whole buffer first, then overwrite the interior with the source.
219
248
  case mode
@@ -222,8 +251,8 @@ class CAWindowIterator < CAIterator
222
251
  when :masked
223
252
  pad[] = UNDEF
224
253
  when :edge
225
- # Provisional fill; the edge margins are written below from the source.
226
- pad[] = 0
254
+ # Nothing to fill: every margin cell is written from the source below
255
+ # (a provisional 0 cannot be stored in a fixlen buffer).
227
256
  end
228
257
 
229
258
  interior = nd.times.map { |i| lefts[i]...(lefts[i] + shape[i]) }
@@ -234,6 +263,23 @@ class CAWindowIterator < CAIterator
234
263
  pad
235
264
  end
236
265
 
266
+ # A Face is padded on its storage and put back on at the end, so the margins
267
+ # hold storage -- UNDEF, a copy of an edge cell, or a `:constant` value the
268
+ # Face has turned into storage -- and the reductions over the windows are
269
+ # the Face's own. A buffer of the Face's surface type could not take the
270
+ # margin values at all.
271
+ def pad_face (src, lefts, rights, mode, value)
272
+ storage = src.__send__(:__face_storage__)
273
+ if mode == :constant && !value.nil?
274
+ cell = src.__send__(:__blank_like__, [1])
275
+ cell[0] = value
276
+ padded = pad_source(storage, lefts, rights, :constant, cell.parent[0])
277
+ else
278
+ padded = pad_source(storage, lefts, rights, mode, value)
279
+ end
280
+ padded.face_lift(src)
281
+ end
282
+
237
283
  # Edge-replicate the margins of a padded buffer whose interior already holds
238
284
  # the source. Per axis, the left margin rows copy the first interior row and
239
285
  # the right margin rows copy the last; done axis by axis over the whole
@@ -298,24 +344,112 @@ class CAWindowIterator < CAIterator
298
344
  # unchanged. `min_count:` / `fill_value:` pass straight to the core (the
299
345
  # boundary strictness + result fill knobs).
300
346
 
301
- # @overload sum(min_count: nil, fill_value: nil)
302
- # Rolling sum, delegating to `sliding_view.sum(axis: window_axes)`.
347
+ # @!method sum(min_count: nil, fill_value: nil)
348
+ # Rolling sum.
349
+ # @param min_count [Integer, nil] fewest cells that must be present
350
+ # for a result; a piece with fewer comes back masked.
351
+ # @param fill_value [Object, nil] value to put in place of a masked
352
+ # result instead of leaving it masked.
353
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
354
+ # @!method accumulate(min_count: nil, fill_value: nil)
355
+ # Rolling sum kept in the source's own data type, wrapping at its
356
+ # width, as the core `accumulate` does -- `sum` answers in the type
357
+ # the core promotes to (float64 for integers).
358
+ # @param min_count [Integer, nil] fewest cells that must be present
359
+ # for a result; a piece with fewer comes back masked.
360
+ # @param fill_value [Object, nil] value to put in place of a masked
361
+ # result instead of leaving it masked.
362
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
363
+ # @!method prod(min_count: nil, fill_value: nil)
364
+ # Rolling product.
365
+ # @param min_count [Integer, nil] fewest cells that must be present
366
+ # for a result; a piece with fewer comes back masked.
367
+ # @param fill_value [Object, nil] value to put in place of a masked
368
+ # result instead of leaving it masked.
369
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
370
+ # @!method mean(min_count: nil, fill_value: nil)
371
+ # Rolling arithmetic mean.
372
+ # @param min_count [Integer, nil] fewest cells that must be present
373
+ # for a result; a piece with fewer comes back masked.
374
+ # @param fill_value [Object, nil] value to put in place of a masked
375
+ # result instead of leaving it masked.
376
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
377
+ # @!method min(min_count: nil, fill_value: nil)
378
+ # Rolling minimum.
379
+ # @param min_count [Integer, nil] fewest cells that must be present
380
+ # for a result; a piece with fewer comes back masked.
381
+ # @param fill_value [Object, nil] value to put in place of a masked
382
+ # result instead of leaving it masked.
303
383
  # @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.
384
+ # @!method max(min_count: nil, fill_value: nil)
385
+ # Rolling maximum.
386
+ # @param min_count [Integer, nil] fewest cells that must be present
387
+ # for a result; a piece with fewer comes back masked.
388
+ # @param fill_value [Object, nil] value to put in place of a masked
389
+ # result instead of leaving it masked.
310
390
  # @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
- [:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
391
+ # @!method variance(min_count: nil, fill_value: nil)
392
+ # Rolling sample variance (divisor `n - 1`).
393
+ # @param min_count [Integer, nil] fewest cells that must be present
394
+ # for a result; a piece with fewer comes back masked.
395
+ # @param fill_value [Object, nil] value to put in place of a masked
396
+ # result instead of leaving it masked.
397
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
398
+ # @!method stddev(min_count: nil, fill_value: nil)
399
+ # Rolling sample standard deviation (divisor `n - 1`).
400
+ # @param min_count [Integer, nil] fewest cells that must be present
401
+ # for a result; a piece with fewer comes back masked.
402
+ # @param fill_value [Object, nil] value to put in place of a masked
403
+ # result instead of leaving it masked.
404
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
405
+ # @!method all
406
+ # Whether every cell of each rolling is true.
407
+ # Takes no `min_count:` or `fill_value:`, as the core `all` does not.
408
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
409
+ # @!method any
410
+ # Whether any cell of each rolling is true.
411
+ # Takes no `min_count:` or `fill_value:`, as the core `any` does not.
412
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
413
+ # @!method variancep(min_count: nil, fill_value: nil)
414
+ # Rolling population variance (divisor `n`).
415
+ # @param min_count [Integer, nil] fewest cells that must be present
416
+ # for a result; a piece with fewer comes back masked.
417
+ # @param fill_value [Object, nil] value to put in place of a masked
418
+ # result instead of leaving it masked.
419
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
420
+ # @!method stddevp(min_count: nil, fill_value: nil)
421
+ # Rolling population standard deviation (divisor `n`).
422
+ # @param min_count [Integer, nil] fewest cells that must be present
423
+ # for a result; a piece with fewer comes back masked.
424
+ # @param fill_value [Object, nil] value to put in place of a masked
425
+ # result instead of leaving it masked.
426
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
427
+ # @!method minmax(min_count: nil, fill_value: nil)
428
+ # Rolling minimum and maximum, found in one pass.
429
+ # @param min_count [Integer, nil] fewest cells that must be present
430
+ # for a result; a piece with fewer comes back masked.
431
+ # @param fill_value [Object, nil] value to put in place of a masked
432
+ # result instead of leaving it masked.
433
+ # @return [Array<CArray>] the pair `[min, max]`, reference-shaped (or shrunk, for :truncate)
434
+ # @!method min_index(min_count: nil, fill_value: nil)
435
+ # Rolling position of the minimum, local to the window axes.
436
+ # @param min_count [Integer, nil] fewest cells that must be present
437
+ # for a result; a piece with fewer comes back masked.
438
+ # @param fill_value [Object, nil] value to put in place of a masked
439
+ # result instead of leaving it masked.
440
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
441
+ # @!method max_index(min_count: nil, fill_value: nil)
442
+ # Rolling position of the maximum, local to the window axes.
443
+ # @param min_count [Integer, nil] fewest cells that must be present
444
+ # for a result; a piece with fewer comes back masked.
445
+ # @param fill_value [Object, nil] value to put in place of a masked
446
+ # result instead of leaving it masked.
447
+ # @return [CArray] reference-shaped (or shrunk, for :truncate)
448
+ [:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev,
315
449
  :variancep, :stddevp, :minmax, :min_index, :max_index].each do |op|
316
450
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
317
451
  def #{op} (min_count: nil, fill_value: nil)
318
- folded = fold_by_offset(:#{op}, min_count, fill_value)
452
+ folded = @shape.include?(0) ? nil : fold_by_offset(:#{op}, min_count, fill_value)
319
453
  return folded unless folded.nil?
320
454
  kw = {}
321
455
  kw[:min_count] = min_count unless min_count.nil?
@@ -325,6 +459,19 @@ class CAWindowIterator < CAIterator
325
459
  RUBY
326
460
  end
327
461
 
462
+ # all / any take no min_count: or fill_value:, as the core ones do not.
463
+ [:all, :any].each do |op|
464
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
465
+ def #{op} (**kw)
466
+ if kw.empty?
467
+ folded = @shape.include?(0) ? nil : fold_by_offset(:#{op}, nil)
468
+ return folded unless folded.nil?
469
+ end
470
+ sliding_view.#{op}(axis: @window_axes, **CAIterator.reduce_keywords(:#{op}, kw))
471
+ end
472
+ RUBY
473
+ end
474
+
328
475
  # @overload min_addr
329
476
  # Rolling flat SOURCE address of the window minimum — which source cell holds
330
477
  # it, so `source.reshape(source.elements)[sw.min_addr]` are the window minima.
@@ -334,12 +481,12 @@ class CAWindowIterator < CAIterator
334
481
  # source cell it replicates, and with `bounds: :constant` (or `fill_value:`)
335
482
  # a winning margin cell has no source address and is a masked result.
336
483
  # @return [CArray] reference-shaped (or shrunk, for :truncate)
337
- def min_addr; window_winner_addr(:min_index); end
484
+ def min_addr (**kw); window_winner_addr(:min_index, kw); end
338
485
 
339
486
  # @overload max_addr
340
487
  # Rolling flat source address of the window maximum. See {#min_addr}.
341
488
  # @return [CArray] reference-shaped (or shrunk, for :truncate)
342
- def max_addr; window_winner_addr(:max_index); end
489
+ def max_addr (**kw); window_winner_addr(:max_index, kw); end
343
490
 
344
491
  private
345
492
 
@@ -376,16 +523,22 @@ class CAWindowIterator < CAIterator
376
523
  # Runs the fold by offset, or returns nil when this window is not one it can
377
524
  # answer for -- in which case the caller delegates as before.
378
525
  def fold_by_offset (op, min_count, fill_value = nil)
526
+ return nil unless CArray.__fast_paths_enabled__
527
+ need = CArray.__min_count_need__(op, min_count, 0)
379
528
  return nil unless op == :mean || OFFSET_FOLD.key?(op)
529
+ # The elementwise kernels act on a Face's storage; its reductions are its own.
530
+ return nil if @source.face?
380
531
  return nil if @widths.any? { |width| width > OFFSET_FOLD_MAX_WIDTH }
381
532
  return nil if neutral_value(op).nil?
533
+ # pmin / pmax let NaN lose, so a window holding only NaN would fold to the
534
+ # neutral value; the core answers NaN there.
535
+ return nil if (op == :min || op == :max) && source_has_nan?
382
536
 
383
537
  folded = op == :mean ? fold_mean : accumulate_offsets(op)
384
538
  folded = mask_empty_windows(folded) if EMPTY_WINDOW_IS_UNDEFINED.include?(op)
385
- folded = apply_min_count(folded, min_count)
539
+ folded = apply_min_count(folded, need)
386
540
  # A `fill_value:` on the call replaces a result that came out undefined.
387
- folded = folded.strip_mask(fill_value) if !fill_value.nil? && folded.has_mask?
388
- folded
541
+ CArray.__reduce_fill__(folded, fill_value)
389
542
  end
390
543
 
391
544
  # The mean is the sum over the same offsets, divided by the number of cells
@@ -446,14 +599,19 @@ class CAWindowIterator < CAIterator
446
599
  end
447
600
  end
448
601
 
449
- # `min_count` asks for a result only where the window held that many cells.
450
- def apply_min_count (folded, min_count)
451
- return folded if min_count.nil?
602
+ def source_has_nan?
603
+ return false unless @source.float? || @source.data_type == CA_OBJECT
604
+ @source.is_nan.any
605
+ end
606
+
607
+ # A result only where the window held `need` cells (CArray.__min_count_need__).
608
+ def apply_min_count (folded, need)
609
+ return folded if need == 0
452
610
  counts = window_cell_counts
453
611
  if counts.is_a?(Integer)
454
- folded[] = UNDEF if counts < min_count
612
+ folded[] = UNDEF if counts < need
455
613
  else
456
- folded[counts.lt(min_count)] = UNDEF
614
+ folded[counts.lt(need)] = UNDEF
457
615
  end
458
616
  folded
459
617
  end
@@ -550,7 +708,7 @@ class CAWindowIterator < CAIterator
550
708
  def offset_fold_data_type (op)
551
709
  @offset_fold_data_type ||= {}
552
710
  @offset_fold_data_type[op] ||=
553
- CArray.new(@source.data_type, [1, 1]).send(op, axis: [1]).data_type
711
+ CArray.new(@source.data_type, [1, 1], bytes: @source.bytes).send(op, axis: [1]).data_type
554
712
  end
555
713
 
556
714
  # Every offset within the window, as a list of per-axis positions into the
@@ -568,8 +726,9 @@ class CAWindowIterator < CAIterator
568
726
  # offset is the range's begin for a padded margin, 0 for :truncate). A margin
569
727
  # winner (coordinate out of bounds) resolves per the boundary policy:
570
728
  # :nearest clamps to the edge source cell, :constant / :skip mask the result.
571
- def window_winner_addr (idx_op)
572
- mi = send(idx_op) # window-local flat index
729
+ def window_winner_addr (idx_op, kw = {})
730
+ kw = CAIterator.reduce_keywords(idx_op, kw)
731
+ mi = send(idx_op, **kw.slice(:min_count)) # window-local flat index
573
732
  n = @source.shape
574
733
  wstride = Array.new(@sndim); acc = 1
575
734
  (@sndim - 1).downto(0) { |i| wstride[i] = acc; acc *= @widths[i] }
@@ -593,7 +752,7 @@ class CAWindowIterator < CAIterator
593
752
  end
594
753
  addr[oob] = UNDEF unless @bounds == :nearest
595
754
  addr[mi.is_masked.eq(1)] = UNDEF if mi.has_mask?
596
- addr
755
+ CArray.__reduce_fill__(addr, kw[:fill_value])
597
756
  end
598
757
 
599
758
  public
@@ -603,26 +762,29 @@ class CAWindowIterator < CAIterator
603
762
  # cells (the effective tap count, which drops near a :skip edge);
604
763
  # `count(UNDEF)` counts masked cells; `count(v)` counts cells equal to `v`.
605
764
  # @return [CArray]
606
- def count (*args)
607
- return count_not_masked if args.empty?
765
+ def count (*args, **kw)
766
+ return count_not_masked(**kw) if args.empty?
608
767
  # The sliding_windows view is a CAStride, so its #count is not shadowed;
609
768
  # dispatch CArray#count explicitly anyway, matching the family regularity.
610
- CArray.instance_method(:count).bind_call(sliding_view, *args, axis: @window_axes)
769
+ CArray.instance_method(:count).bind_call(sliding_view, *args, axis: @window_axes,
770
+ **CAIterator.reduce_keywords(:count, kw))
611
771
  end
612
772
 
613
773
  # @overload count_not_masked
614
774
  # Rolling count of present (non-masked) cells -- the denominator of a
615
775
  # renormalizing convolution.
616
776
  # @return [CArray]
617
- def count_not_masked
618
- sliding_view.count_not_masked(axis: @window_axes)
777
+ def count_not_masked (**kw)
778
+ sliding_view.count_not_masked(axis: @window_axes,
779
+ **CAIterator.reduce_keywords(:count_not_masked, kw))
619
780
  end
620
781
 
621
782
  # @overload count_masked
622
783
  # Rolling count of masked cells.
623
784
  # @return [CArray]
624
- def count_masked
625
- sliding_view.count_masked(axis: @window_axes)
785
+ def count_masked (**kw)
786
+ sliding_view.count_masked(axis: @window_axes,
787
+ **CAIterator.reduce_keywords(:count_masked, kw))
626
788
  end
627
789
 
628
790
  # @overload elements
@@ -694,40 +856,31 @@ class CAWindowIterator < CAIterator
694
856
 
695
857
  # ---- order statistics (median / percentile / quantile) ----------------
696
858
  #
697
- # Core per-axis order statistics take a single axis and do not accept a
698
- # masked input, so the window mode is dispatched:
699
- #
700
- # single window axis + unmasked margin -> `sliding_view.op(axis: window_axis)`
701
- # multi window axes + unmasked margin -> materialize the windows, flatten
702
- # the window axes into one, single-
703
- # axis core order-stat
704
- # :skip (UNDEF margin) -> raise (core has no masked per-axis
705
- # order-stat); guide to :nearest /
706
- # :truncate
707
- #
708
- # When core gains masked per-axis order statistics (a tracked refactor), the
709
- # :skip guard can be dropped and :skip served directly.
859
+ # Core per-axis order statistics take a single axis, so a single window
860
+ # axis goes straight to `sliding_view.op(axis: window_axis)`, and several
861
+ # are materialized with the window axes flattened into one. The UNDEF
862
+ # margin of :skip is left out of each window as any masked cell is.
710
863
 
711
- # @overload median
712
- # Rolling median. Requires an unmasked margin (`bounds: :nearest` or
713
- # `:truncate`); with the default `:skip` it raises.
864
+ # @overload median(min_count: nil, fill_value: nil)
865
+ # Rolling median.
714
866
  # @return [CArray]
715
- def median
716
- order_stat { |view, axis| view.median(axis: axis) }
867
+ def median (**kw)
868
+ kw = CAIterator.reduce_keywords(:median, kw)
869
+ order_stat { |view, axis| view.median(axis: axis, **kw) }
717
870
  end
718
871
 
719
- # @overload percentile(*pers)
872
+ # @overload percentile(*pers, min_count: nil, fill_value: nil)
720
873
  # Rolling percentile(s). One argument returns one CArray, several return
721
- # an array of CArrays (as `CArray#percentile`). Requires an unmasked
722
- # margin.
874
+ # an array of CArrays (as `CArray#percentile`).
723
875
  # @return [CArray, Array<CArray>]
724
- def percentile (*pers)
725
- order_stat { |view, axis| view.percentile(*pers, axis: axis) }
876
+ def percentile (*pers, **kw)
877
+ kw = CAIterator.reduce_keywords(:percentile, kw)
878
+ order_stat { |view, axis| view.percentile(*pers, axis: axis, **kw) }
726
879
  end
727
880
 
728
881
  # @overload quantile
729
882
  # Rolling five-number summary `[min, Q1, median, Q3, max]` (five CArrays),
730
- # as `CArray#quantile`. Requires an unmasked margin.
883
+ # as `CArray#quantile`.
731
884
  # @return [Array<CArray>]
732
885
  def quantile
733
886
  order_stat { |view, axis| view.quantile(axis: axis) }
@@ -736,14 +889,8 @@ class CAWindowIterator < CAIterator
736
889
  private
737
890
 
738
891
  # Drive an order statistic (yielded as `block.call(view, axis)`) through the
739
- # single-axis / multi-axis / :skip-reject dispatch above.
892
+ # single-axis / multi-axis dispatch above.
740
893
  def order_stat
741
- if @bounds == :skip
742
- raise ArgumentError,
743
- "windowed order statistics need an unmasked margin; " \
744
- "use bounds: :nearest (edge-extend) or bounds: :truncate (valid). " \
745
- "For an UNDEF-margin median use reduce { |w| w.median } (slower)."
746
- end
747
894
  sv = sliding_view
748
895
  if @window_axes.size == 1
749
896
  yield sv, @window_axes[0]
@@ -764,15 +911,17 @@ class CAWindowIterator < CAIterator
764
911
  # @overload wsum(weights)
765
912
  # Rolling weighted sum, `weights` shaped like a single window.
766
913
  # @return [CArray]
767
- def wsum (weights)
768
- weighted(weights) { |sv, w, axis| sv.wsum(w, axis: axis) }
914
+ def wsum (weights, **kw)
915
+ kw = CAIterator.reduce_keywords(:wsum, kw)
916
+ weighted(weights) { |sv, w, axis| sv.wsum(w, axis: axis, **kw) }
769
917
  end
770
918
 
771
919
  # @overload wmean(weights)
772
920
  # Rolling weighted mean, `weights` shaped like a single window.
773
921
  # @return [CArray]
774
- def wmean (weights)
775
- weighted(weights) { |sv, w, axis| sv.wmean(w, axis: axis) }
922
+ def wmean (weights, **kw)
923
+ kw = CAIterator.reduce_keywords(:wmean, kw)
924
+ weighted(weights) { |sv, w, axis| sv.wmean(w, axis: axis, **kw) }
776
925
  end
777
926
 
778
927
  private
@@ -873,13 +1022,41 @@ class CAWindowIterator < CAIterator
873
1022
  "sort of source addresses is ill-defined."
874
1023
  end
875
1024
 
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
1025
+ # @!method cumsum
1026
+ # Not supported for a window iterator. A segment scan writes a per-cell
1027
+ # running sum, which is single-valued only when each cell belongs to
1028
+ # exactly one piece. Overlapping windows put a cell in many windows, so
1029
+ # there is no single running value. Raises NotImplementedError, exactly as
1030
+ # {#map} / {#sort_addr} do (min / max reductions stay available: a single
1031
+ # winner is well-defined).
1032
+ # @raise [NotImplementedError]
1033
+ # @!method cumprod
1034
+ # Not supported for a window iterator. A segment scan writes a per-cell
1035
+ # running product, which is single-valued only when each cell belongs to
1036
+ # exactly one piece. Overlapping windows put a cell in many windows, so
1037
+ # there is no single running value. Raises NotImplementedError, exactly as
1038
+ # {#map} / {#sort_addr} do (min / max reductions stay available: a single
1039
+ # winner is well-defined).
1040
+ # @raise [NotImplementedError]
1041
+ # @!method cummax
1042
+ # Not supported for a window iterator. A segment scan writes a per-cell
1043
+ # running maximum, which is single-valued only when each cell belongs to
1044
+ # exactly one piece. Overlapping windows put a cell in many windows, so
1045
+ # there is no single running value. Raises NotImplementedError, exactly as
1046
+ # {#map} / {#sort_addr} do (min / max reductions stay available: a single
1047
+ # winner is well-defined).
1048
+ # @raise [NotImplementedError]
1049
+ # @!method cummin
1050
+ # Not supported for a window iterator. A segment scan writes a per-cell
1051
+ # running minimum, which is single-valued only when each cell belongs to
1052
+ # exactly one piece. Overlapping windows put a cell in many windows, so
1053
+ # there is no single running value. Raises NotImplementedError, exactly as
1054
+ # {#map} / {#sort_addr} do (min / max reductions stay available: a single
1055
+ # winner is well-defined).
1056
+ # @raise [NotImplementedError]
1057
+ # @!method cumcount
1058
+ # Not supported for a window iterator. A segment scan writes a per-cell
1059
+ # running count of present cells, which is single-valued only when each cell belongs to
883
1060
  # exactly one piece. Overlapping windows put a cell in many windows, so
884
1061
  # there is no single running value. Raises NotImplementedError, exactly as
885
1062
  # {#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.
@@ -23,19 +24,20 @@ require 'carray/runtime' # load-bearing Ruby support the core depends on
23
24
  require 'carray/basics' # frequently-used convenience methods kept eager
24
25
  require 'carray/conditional' # then_else / replace_where / conditional
25
26
  require 'carray/mask_gap_fill' # unmask/strip_mask method: keyword (hold / linear gap-fill)
26
- require 'carray/attribute' # per-instance metadata Hash (#attribute / #has_attribute?)
27
+ require 'carray/attribute' # per-instance metadata Hash (#attr / #set_attr / #attrs / #has_attr?)
27
28
  require 'carray/boolean_reduce' # all/any/none skip_masked: keyword (Kleene fold)
28
29
  require 'carray/meld_reduce' # CAMeld per-parent reduce fast path (sum/mean/min/max along meld_axis)
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)
35
37
  require 'carray/lazy' # the lazy elementwise view layer
36
38
  # carray/face.rb was deleted (the Phase 1 skeleton CArray::Face module
37
39
  # became dead weight, replaced by C-layer macro deploy +
38
- # copy_state/storage_to_scalar convention).
40
+ # copy_state/storage_to_element convention).
39
41
  require 'carray/time' # CATime / CATimedelta
40
42
  # carray/methods/* (bincount / broadcast / gather_nd+put_nd) are small
41
43
  # single-feature method files, loaded lazily via autoload_carray.
@@ -43,9 +43,9 @@ class CArray
43
43
  # `data_type`, shape, mask, and element data into `self`. Result
44
44
  # is an independent entity.
45
45
  #
46
- # Note that for views, `dup`/`clone` produce a new view sharing
47
- # the parent (Ruby shallow-copy semantics); use {#copy} when an
48
- # independent owned array is required.
46
+ # For views, `dup` / `clone` produce a new view sharing the parent
47
+ # (Ruby shallow-copy semantics), so they do not copy. Don't use
48
+ # them to copy a CArray; use {#copy}.
49
49
  # @param other [CArray]
50
50
  # @return [self]
51
51
  # @api private
@@ -66,7 +66,7 @@ class CArray
66
66
  # @return [Class]
67
67
  # @overload fixlen(*shape, bytes:) { ... }
68
68
  # Equivalent to `CArray.new(:fixlen, shape, bytes: bytes) { ... }`.
69
- # The `bytes:` keyword is required for `:fixlen`.
69
+ # The `bytes:` keyword is required for `:fixlen`, and is 1 or more.
70
70
  # @param shape [Array<Integer>]
71
71
  # @param bytes [Integer]
72
72
  # @return [CArray]
@@ -11,6 +11,11 @@
11
11
  # On big-endian hosts the bit axis of a non-fixlen parent reflects
12
12
  # network byte order (parent bytes are walked in reverse within each
13
13
  # element); single-byte parents are linear on either endian.
14
+ #
15
+ # A bit view has no mask. The bits of one byte would share that byte's
16
+ # one mask cell, so the view refuses a masked parent and refuses to be
17
+ # masked (`mask=`, storing `UNDEF`, storing a masked array). Read the
18
+ # bits of a masked array through `value.bitarray`.
14
19
  class CABitarray < CAView
15
20
  end
16
21
 
@@ -27,6 +32,8 @@ class CArray
27
32
  # @return [CABitarray]
28
33
  # @raise [CADataTypeError] when `self.data_type` is a complex or
29
34
  # object type (bit-level access is not defined for those).
35
+ # @raise [ArgumentError] when `self` has a mask; use
36
+ # `value.bitarray` to read the bits without it.
30
37
  def bitarray; end
31
38
 
32
39
  # Alias for {#bitarray}.
@@ -19,24 +19,35 @@ class CArray
19
19
  # of the returned array.
20
20
  #
21
21
  # `range` may be an integer (a single bit — the resulting view has
22
- # `data_type :boolean`) or a `Range` covering the bit positions.
23
- # The `data_type` of the view is chosen from the bit width:
24
- # 1 bit → `:boolean`, 2..8 → `:uint8`, 9..16 → `:uint16`,
25
- # 17..32 → `:uint32`, 33..64 → `:uint64`.
26
- #
27
- # `type` is accepted but currently ignored (the width-derived type
28
- # is always used).
22
+ # `data_type :boolean`) or a `Range` covering the bit positions. A
23
+ # negative bit or range end counts from the last bit of the cell.
24
+ # A field is read with one 8-byte load from the byte it starts in, so
25
+ # it may not reach more than 64 bits past the start of that byte.
26
+ # `type` is the integer type the field is read as. A signed type
27
+ # (`:int8` .. `:int64`) reads the field's top bit as its sign: the
28
+ # 3-bit field `0b101` is 5 as `:uint8` and -3 as `:int8`. A type
29
+ # wider than the field only widens the value. Without `type`, the
30
+ # narrowest unsigned type that holds the field is used: 1 bit →
31
+ # `:boolean`, 2..8 → `:uint8`, 9..16 → `:uint16`, 17..32 → `:uint32`,
32
+ # 33..64 → `:uint64`. A write keeps the low bits of the value that
33
+ # fit the field, signed or not (-3 into a 3-bit field is `0b101`).
29
34
  #
30
35
  # @overload bitfield(range, type = nil)
31
36
  # @param range [Integer, Range] bit position (single bit) or bit
32
37
  # range within one parent cell.
33
- # @param type [Symbol, nil] reserved, currently ignored.
38
+ # @param type [Symbol, Integer, nil] the integer type the field is
39
+ # read as, or `nil` for the narrowest unsigned type.
34
40
  # @return [CABitfield]
35
41
  # @raise [IndexError] when `range` extends past the parent's bit
36
- # width, when the range has a step != 1, or when the bit length
37
- # is outside `1..64`.
38
- # @raise [ArgumentError] when the derived bit length exceeds the
39
- # resolved data type.
42
+ # width, when the range has a step != 1, when the bit length
43
+ # is outside `1..64`, or when the field reaches more than 64 bits
44
+ # past the start of its first byte.
45
+ # @raise [CArray::DataTypeError] when `self` is an object or complex
46
+ # array.
47
+ # @raise [ArgumentError] when `type` is narrower than the field
48
+ # (or `:boolean` for a field of more than one bit).
49
+ # @raise [CArray::DataTypeError] when `type` is not an integer type
50
+ # or `:boolean`.
40
51
  def bitfield(range, type = nil); end
41
52
 
42
53
  # @!endgroup