carray 3.0.5 → 3.0.6

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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +233 -0
  3. data/README.md +1 -1
  4. data/carray.gemspec +3 -2
  5. data/ext/ca_axis_dispatch.c +6 -0
  6. data/ext/ca_axis_group.c +1 -1
  7. data/ext/ca_categorical_iterator.c +7 -7
  8. data/ext/ca_kernel_iterator.c +116 -231
  9. data/ext/ca_kernel_iterator.h +410 -254
  10. data/ext/ca_obj_bincmp.c +9 -1
  11. data/ext/ca_obj_binop.c +10 -1
  12. data/ext/ca_obj_bitfield.c +2 -0
  13. data/ext/ca_obj_byte_swap.c +2 -0
  14. data/ext/ca_obj_face.c +2 -0
  15. data/ext/ca_obj_fake.c +3 -1
  16. data/ext/ca_obj_grid.c +167 -12
  17. data/ext/ca_obj_meld.c +69 -113
  18. data/ext/ca_obj_moncmp.c +9 -1
  19. data/ext/ca_obj_monop.c +40 -2
  20. data/ext/ca_obj_object.c +54 -20
  21. data/ext/ca_obj_reduce.c +15 -1
  22. data/ext/ca_obj_refer.c +65 -20
  23. data/ext/ca_obj_remap.c +69 -10
  24. data/ext/ca_obj_roll.c +1 -0
  25. data/ext/ca_obj_select.c +4 -1
  26. data/ext/ca_obj_select_axis.c +1 -0
  27. data/ext/ca_obj_shift.c +1 -0
  28. data/ext/ca_obj_stack.c +310 -111
  29. data/ext/ca_obj_stride.c +131 -45
  30. data/ext/ca_obj_string.c +18 -2
  31. data/ext/ca_obj_tile.c +1 -0
  32. data/ext/ca_obj_triop.c +9 -1
  33. data/ext/ca_obj_window.c +1 -0
  34. data/ext/ca_op_ipower.c +8 -8
  35. data/ext/caframe_csv_reader.c +1 -1
  36. data/ext/carray.h +2 -1
  37. data/ext/carray_access.c +27 -64
  38. data/ext/carray_address_basis.c +134 -0
  39. data/ext/carray_attribute.c +8 -0
  40. data/ext/carray_broadcast.c +3 -4
  41. data/ext/carray_build_flags.h +1 -1
  42. data/ext/carray_cast.c +8 -11
  43. data/ext/carray_conversion.c +9 -5
  44. data/ext/carray_core.c +811 -72
  45. data/ext/carray_element.c +13 -9
  46. data/ext/carray_histogram.c +25 -3
  47. data/ext/carray_internal.h +147 -12
  48. data/ext/carray_kernels_bincmp.c +2007 -3
  49. data/ext/carray_kernels_binop.c +25365 -5199
  50. data/ext/carray_kernels_init.c +8 -8
  51. data/ext/carray_kernels_monop.c +10696 -3678
  52. data/ext/carray_kernels_reduce_aggregate.c +4429 -702
  53. data/ext/carray_kernels_reduce_boolean.c +1533 -15
  54. data/ext/carray_kernels_reduce_cumulative.c +1808 -248
  55. data/ext/carray_kernels_reduce_extreme.c +4508 -511
  56. data/ext/carray_kernels_reduce_variance.c +2284 -152
  57. data/ext/carray_kernels_scan.c +240 -240
  58. data/ext/carray_kernels_search.c +4211 -264
  59. data/ext/carray_kernels_sort.c +367 -450
  60. data/ext/carray_lazy.c +47 -0
  61. data/ext/carray_loop.c +1 -1
  62. data/ext/carray_mask.c +130 -139
  63. data/ext/carray_median_percentile.c +4 -4
  64. data/ext/carray_memory_view.c +13 -7
  65. data/ext/carray_operator.c +147 -44
  66. data/ext/carray_order.c +3 -2
  67. data/ext/carray_random.c +4 -1
  68. data/ext/carray_slab.c +97 -21
  69. data/ext/carray_sort.c +1 -1
  70. data/ext/carray_test.c +74 -19
  71. data/ext/carray_time_text.c +2 -2
  72. data/ext/extconf.rb +11 -0
  73. data/ext/mkkernel.rb +346 -94
  74. data/ext/ruby_carray.c +4 -1
  75. data/ext/version.h +4 -4
  76. data/lib/carray/attribute.rb +25 -1
  77. data/lib/carray/autoload_carray.rb +3 -3
  78. data/lib/carray/autoload_method_extension.rb +5 -3
  79. data/lib/carray/axis_group.rb +13 -7
  80. data/lib/carray/basics.rb +1 -1
  81. data/lib/carray/block_iterator.rb +17 -3
  82. data/lib/carray/categorical.rb +6 -8
  83. data/lib/carray/categorical_iterator.rb +2 -2
  84. data/lib/carray/complex.rb +2 -2
  85. data/lib/carray/conditional.rb +3 -2
  86. data/lib/carray/frame/column_verbs.rb +45 -14
  87. data/lib/carray/frame/convert.rb +19 -0
  88. data/lib/carray/frame/csv_parser.rb +32 -32
  89. data/lib/carray/frame/describe.rb +4 -2
  90. data/lib/carray/frame/frame.rb +399 -78
  91. data/lib/carray/frame/group.rb +679 -53
  92. data/lib/carray/frame/io.rb +209 -71
  93. data/lib/carray/frame/join.rb +146 -37
  94. data/lib/carray/frame/records.rb +3 -3
  95. data/lib/carray/frame/reshape.rb +89 -11
  96. data/lib/carray/frame/sort.rb +57 -9
  97. data/lib/carray/frame/verbs.rb +384 -49
  98. data/lib/carray/frame/windows.rb +44 -6
  99. data/lib/carray/inspect.rb +7 -2
  100. data/lib/carray/iterator.rb +32 -0
  101. data/lib/carray/lazy.rb +17 -8
  102. data/lib/carray/mask_gap_fill.rb +37 -17
  103. data/lib/carray/meld_reduce.rb +1 -1
  104. data/lib/carray/methods/choose.rb +3 -2
  105. data/lib/carray/methods/meshgrid.rb +3 -1
  106. data/lib/carray/runtime.rb +47 -8
  107. data/lib/carray/segment_iterator.rb +23 -8
  108. data/lib/carray/serialize.rb +34 -17
  109. data/lib/carray/stack.rb +18 -6
  110. data/lib/carray/time.rb +5 -0
  111. data/lib/carray/window_iterator.rb +16 -4
  112. data/yard-stubs/ca_obj_array.rb +26 -1
  113. data/yard-stubs/carray_cast.rb +8 -5
  114. data/yard-stubs/carray_conversion.rb +8 -2
  115. data/yard-stubs/carray_mask.rb +20 -1
  116. data/yard-stubs/carray_math.rb +31 -16
  117. data/yard-stubs/carray_memory_view.rb +7 -0
  118. data/yard-stubs/carray_test.rb +7 -4
  119. metadata +18 -4
@@ -106,6 +106,14 @@ class CAWindowIterator < CAIterator
106
106
  "windows: expected #{@source.ndim} ranges (one per axis), " \
107
107
  "got #{@ranges.size}"
108
108
  end
109
+ # Each window is read through a view with one axis per anchor and one
110
+ # per cell in the window, twice the source's rank.
111
+ if 2 * @source.ndim > CA_RANK_MAX
112
+ raise ArgumentError,
113
+ "windows: a rank #{@source.ndim} array would need #{2 * @source.ndim} " \
114
+ "axes for its windows, beyond the limit of #{CA_RANK_MAX}; " \
115
+ "windows works up to rank #{CA_RANK_MAX / 2}"
116
+ end
109
117
  @ranges = @ranges.each_with_index.map { |r, k| window_offsets(r, k) }
110
118
 
111
119
  @sndim = @source.ndim
@@ -151,14 +159,15 @@ class CAWindowIterator < CAIterator
151
159
 
152
160
  # ---- padded entity + sliding_windows view -----------------------------
153
161
  #
154
- # The engine: pad the source once (:skip -> UNDEF, :nearest -> edge, :constant
162
+ # The engine: pad the source (:skip -> UNDEF, :nearest -> edge, :constant
155
163
  # -> value; :truncate does not pad), then take a sliding_windows view. Both
156
- # are memoised: every named reduction reuses the one pad + one view.
164
+ # are kept for one call, so the helpers a reduction runs share one pad and
165
+ # one view, and the next call pads the source as it is then.
157
166
 
158
167
  # @overload sliding_view
159
168
  # Returns the sliding_windows view feeding the reductions. For :truncate
160
169
  # this is the source's own view (zero-copy); otherwise it is the view over
161
- # the padded entity.
170
+ # a padded copy made from the source as it is at this call.
162
171
  # @return [CArray]
163
172
  def sliding_view
164
173
  @sliding_view ||= @shape.include?(0) ? no_windows : anchored_buffer.sliding_windows(*@widths)
@@ -553,7 +562,7 @@ class CAWindowIterator < CAIterator
553
562
  # Runs the fold by offset, or returns nil when this window is not one it can
554
563
  # answer for -- in which case the caller delegates as before.
555
564
  def fold_by_offset (op, min_count, fill_value = nil)
556
- return nil unless CArray.__fast_paths_enabled__
565
+ return nil unless CArray.__fast_paths_enabled__(:window_fold_by_offset)
557
566
  need = CArray.__present_cells_needed_per_result_cell__(op, min_count, 0)
558
567
  return nil unless op == :mean || OFFSET_FOLD.key?(op)
559
568
  # The elementwise kernels act on a Face's storage; its reductions are its own.
@@ -1150,6 +1159,9 @@ class CAWindowIterator < CAIterator
1150
1159
  yield idx
1151
1160
  end
1152
1161
  end
1162
+
1163
+ read_source_per_call :@sliding_view, :@padded_entity, :@neutral_value,
1164
+ :@offset_fold_base, :@window_cell_counts
1153
1165
  end
1154
1166
 
1155
1167
 
@@ -244,7 +244,8 @@ class CScalar
244
244
  # @!group Construction
245
245
 
246
246
  # @overload initialize(data_type)
247
- # Allocates a CScalar (0-D CArray) of the given `data_type`.
247
+ # Allocates a CScalar of the given `data_type`: one cell on one axis
248
+ # (`ndim` 1, `shape` `[1]`).
248
249
  # @param data_type [Symbol, Integer, Class, String]
249
250
  # @return [self]
250
251
  # @overload initialize(data_type, bytes:)
@@ -269,6 +270,30 @@ class CScalar
269
270
 
270
271
  # @!endgroup
271
272
 
273
+ # @!group Indexing and slicing
274
+
275
+ # @overload []
276
+ # @overload [](0)
277
+ # Reads the scalar's value. A CScalar is one cell and takes no index:
278
+ # `s[]` and `s[0]` both name that cell, and any other index (another
279
+ # integer, a range, `nil`, an index array, a symbol) is refused. A view
280
+ # of the scalar, such as `s.refer(s.data_type, [1])`, takes the usual
281
+ # indexes.
282
+ # @return [Object] the value, or `UNDEF` if it is masked.
283
+ # @raise [ArgumentError] when any other index is given.
284
+ def [](*index); end
285
+
286
+ # @overload []=(value)
287
+ # @overload []=(0, value)
288
+ # Writes the scalar's value. `s[] = v` and `s[0] = v` both write it;
289
+ # any other index is refused.
290
+ # @param value [Object] the value, or `UNDEF` to mask the cell.
291
+ # @return [Object] value
292
+ # @raise [ArgumentError] when any other index is given.
293
+ def []=(*index_and_value); end
294
+
295
+ # @!endgroup
296
+
272
297
  class << self
273
298
  # @!group Construction (typed shorthands)
274
299
 
@@ -202,10 +202,13 @@ class CArray
202
202
  # -- as_type: reinterpreting view (no copy) ---------------------------
203
203
 
204
204
  # @overload as_type(data_type, bytes: nil)
205
- # Returns a {CAFake} view of `self` reinterpreted as `data_type`
206
- # (with `bytes:` for `:fixlen`). Reads and writes cast on the fly
207
- # through the shared parent storage; no copy is made. For an eager
208
- # copy use `arr.as_type(...).to_ca` or {#to_type}.
205
+ # Returns a view of `self` reinterpreted as `data_type` (with
206
+ # `bytes:` for `:fixlen`): a {CAMonOp} for a numeric type, a {CAFake}
207
+ # otherwise. Reads and writes cast on the fly through the shared
208
+ # parent storage; no copy is made. The view is a new array also when
209
+ # `data_type` is `self`'s own, so an attribute set on it or a freeze
210
+ # of it does not reach `self`. For an eager copy use
211
+ # `arr.as_type(...).copy` or {#to_type}.
209
212
  #
210
213
  # Note: for an `:object` source the on-the-fly cast to a numeric type
211
214
  # uses the lenient path and does NOT mask parse failures — a
@@ -225,7 +228,7 @@ class CArray
225
228
  # @param data_type [Symbol, Integer, Class, String] target element type.
226
229
  # @param bytes [Integer, nil] element width in bytes, required for
227
230
  # `:fixlen`.
228
- # @return [CAFake]
231
+ # @return [CAMonOp, CAFake]
229
232
  # @raise [TypeError] when `self` is a Face and the request would read its
230
233
  # storage under another type.
231
234
  # @raise [FloatDomainError] when a NaN cell that is not masked is read
@@ -81,10 +81,16 @@ class CArray
81
81
  # `String` of the exact size, or any object responding to
82
82
  # `read(n, buf = nil)`. Into a boolean array, a non-zero byte is
83
83
  # read as 1 (true).
84
+ # From an IO into an array that owns its memory, the bytes are written
85
+ # as they are read, so that no second copy of the data is held; when the
86
+ # IO runs out before the array is full, what the array holds afterwards
87
+ # is not defined (the part read so far may already be in it). Into a
88
+ # view the whole data is read first and nothing is written on a short
89
+ # read.
84
90
  # @param io [String, IO, #read]
85
91
  # @return [self]
86
- # @raise [RuntimeError] on a short read.
87
- # @raise [ArgumentError] when a String source is not the array's size.
92
+ # @raise [ArgumentError] on a short read, and when a String source is
93
+ # not the array's size.
88
94
  # @raise [CArray::DataTypeError] if `self.data_type` is
89
95
  # `:object`.
90
96
  def load_binary(io); end
@@ -26,7 +26,20 @@ class CArray
26
26
  # bypassing the mask. The returned view itself cannot carry a
27
27
  # mask (`value_array? == true`).
28
28
  #
29
- # Use this to read or write the data slot of masked elements.
29
+ # This is a method for peeking at the internal state of an array, and
30
+ # nothing more. What a masked cell holds is not defined: a computation
31
+ # leaves there whatever it happens to. Use it on the spot, as in
32
+ # `a.value.copy`, `a.value[nil, 1].copy` or `a.value[nil, 1] = 2`; do
33
+ # not keep the view to carry around (`b = a.value`,
34
+ # `b = a.value[nil, 1]`), do not compute with it, and do not mix it
35
+ # with other arrays (as an operand, or as a part of {CArray.stack} or
36
+ # {CArray.meld}). To take the mask off, use {#unmask} or
37
+ # {#strip_mask} and give the masked cells a value.
38
+ #
39
+ # A library that handles the mask itself may use `value` on the spot
40
+ # to hand the stored cells on together with {#mask}, as long as it
41
+ # reads nothing from the masked ones.
42
+ #
30
43
  # Nothing in a value array is masked, so `unmask` on it does nothing,
31
44
  # while a write that would mask a cell (`UNDEF`, `mask=`,
32
45
  # `invert_mask`) raises TypeError.
@@ -84,6 +97,12 @@ class CArray
84
97
  # that derives values from neighbouring valid cells (mask gap-fill).
85
98
  # The two are mutually exclusive: passing both raises `ArgumentError`.
86
99
  #
100
+ # On a view, the values are written through to the cells it views. A
101
+ # position with no cell behind it -- the place of a masked cell of an
102
+ # index array (`a[i]`), as a join with `view: :full` gives for an
103
+ # unmatched row -- takes no write and stays masked, without an error.
104
+ # `strip_mask` gives a new array, where every masked cell takes a value.
105
+ #
87
106
  # @overload unmask
88
107
  # Clears the mask state of every element of `self`, leaving the
89
108
  # stored data values untouched. Mutates `self`.
@@ -231,6 +231,13 @@ class CArray
231
231
  # integer base with a negative integer exponent truncates toward
232
232
  # zero rather than producing a fraction (`2 ** -1` is `0`). Cast to
233
233
  # a float `data_type` first when a fractional power is wanted.
234
+ # A float or complex array raised to an Integer is computed by
235
+ # repeated multiplication rather than by `pow`. Its rounding error
236
+ # grows roughly in proportion to the exponent (tens of ulps at 100,
237
+ # hundreds of thousands at a million), where `Float#**` and the same
238
+ # exponent given as a Float are within an ulp or so; give the exponent
239
+ # as a Float when a large one needs full precision. The exponent can
240
+ # be any Integer that fits 64 bits.
234
241
  # Masked elements stay masked.
235
242
  # @param other [CArray, Numeric] exponent, broadcast to `self.shape`.
236
243
  # @return [CArray] result of the promoted `data_type` of the two
@@ -949,13 +956,15 @@ class CArray
949
956
  # @overload &(other)
950
957
  # Returns the element-wise conjunction of `self` and `other`: a
951
958
  # bitwise `AND` on integer arrays, a logical `AND` on boolean ones.
959
+ # **On boolean arrays it is three-valued (Kleene); {#and} is the
960
+ # two-valued form.** The two give different answers where one side
961
+ # is masked.
952
962
  #
953
- # On boolean arrays the masked elements follow three-valued
954
- # (Kleene) logic rather than propagating blindly: an unknown
955
- # element `AND` `false` is `false`, because the answer does not
956
- # depend on the unknown. Only where the result genuinely depends on
957
- # a masked element is the result masked. {#and} is the two-valued
958
- # form that always propagates.
963
+ # An unknown (masked) element `AND` `false` is `false`, because the
964
+ # answer does not depend on the unknown; only where the result
965
+ # genuinely depends on a masked element is the result masked. So
966
+ # `(a & b).not` is `true` where `a` is `false`, whatever `b` is,
967
+ # while `a.and(b).not` stays masked where `b` is.
959
968
  # @param other [CArray, Integer, true, false] the other operand,
960
969
  # broadcast to `self.shape`.
961
970
  # @return [CArray] `:boolean` for boolean operands, otherwise the
@@ -972,8 +981,9 @@ class CArray
972
981
  # @overload |(other)
973
982
  # Returns the element-wise disjunction of `self` and `other`: a
974
983
  # bitwise `OR` on integer arrays, a logical `OR` on boolean ones.
975
- # Boolean operands follow Kleene logic as in {#&}, so an unknown
976
- # element `OR` `true` is `true`.
984
+ # **On boolean arrays it is three-valued (Kleene) as {#&} is; {#or}
985
+ # is the two-valued form.** An unknown element `OR` `true` is
986
+ # `true`.
977
987
  # @param other [CArray, Integer, true, false] the other operand,
978
988
  # broadcast to `self.shape`.
979
989
  # @return [CArray] `:boolean` for boolean operands, otherwise the
@@ -1055,13 +1065,16 @@ class CArray
1055
1065
  def not; end
1056
1066
 
1057
1067
  # @overload and(other)
1058
- # Returns the two-valued logical `AND` of two boolean arrays.
1068
+ # Returns the logical `AND` of two boolean arrays, **two-valued: a
1069
+ # masked element on either side makes the result masked**, even
1070
+ # where the other side alone would settle the answer. {#&} is the
1071
+ # three-valued form, and the two differ exactly there: `false & U`
1072
+ # is `false`, `false.and(U)` is `U`.
1059
1073
  #
1060
- # Where {#&} applies Kleene logic, this form propagates the mask
1061
- # unconditionally: if either element is masked the result is
1062
- # masked, even when the unmasked element alone would settle the
1063
- # answer. Use it when an unknown operand should make the result
1064
- # unknown regardless.
1074
+ # Use it when the answer should be given only where both inputs are
1075
+ # known -- the element-wise counterpart of keeping only complete
1076
+ # records -- and {#&} when an answer the known side settles should
1077
+ # stand.
1065
1078
  # @param other [CArray, true, false] the other operand, broadcast
1066
1079
  # to `self.shape`.
1067
1080
  # @return [CArray] `:boolean`.
@@ -1070,8 +1083,10 @@ class CArray
1070
1083
  def and(other); end
1071
1084
 
1072
1085
  # @overload or(other)
1073
- # Returns the two-valued logical `OR` of two boolean arrays,
1074
- # propagating the mask unconditionally as {#and} does.
1086
+ # Returns the logical `OR` of two boolean arrays, **two-valued: a
1087
+ # masked element on either side makes the result masked**, as
1088
+ # {#and} does. {#|} is the three-valued form: `true | U` is `true`,
1089
+ # `true.or(U)` is `U`.
1075
1090
  # @param other [CArray, true, false] the other operand.
1076
1091
  # @return [CArray] `:boolean`.
1077
1092
  # @raise [CArray::DataTypeError] for any `data_type` other than
@@ -102,6 +102,13 @@ class CArray
102
102
  # returned object via internal ivars; the source is released
103
103
  # when the wrap is garbage-collected.
104
104
  #
105
+ # Views made from the wrap keep it reachable too, so the view is
106
+ # given back only once all of them are collected. A producer that
107
+ # locks while it is borrowed (`IO::Buffer` refuses `resize` and
108
+ # `free`) stays locked until then; import with
109
+ # {.from_memory_view} to hold no view at all. See
110
+ # {file:docs/interop/MemoryView.md MemoryView} §9.
111
+ #
105
112
  # Contiguous typed producers return a `CAWrap`. Strided typed
106
113
  # producers return a `CAStride` over a byte `CAWrap` of the
107
114
  # bytes its elements reach, preserving the full stride pattern
@@ -36,8 +36,11 @@ class CArray
36
36
  # @overload ==(other)
37
37
  # Returns `true` if `other` is a CArray with the same shape,
38
38
  # `data_class`, `data_type`, mask state, and elementwise values as
39
- # `self`. NaN values compare unequal (IEEE semantics), so two
40
- # arrays with NaN at the same position are not `==`.
39
+ # `self`. It asks whether the contents are the same, so a NaN equals
40
+ # a NaN at the same position (whatever its payload, in a float, a
41
+ # complex part or an object cell) and -0.0 equals 0.0: an array with
42
+ # NaN is `==` to its copy. The IEEE comparison, where NaN equals
43
+ # nothing, is {#eq}, cell by cell.
41
44
  #
42
45
  # A Face (a time, string or categorical array) equals only a Face of
43
46
  # its own class, and is compared by its values: two time arrays of
@@ -53,8 +56,8 @@ class CArray
53
56
  # Returns `true` under Hash-invariant semantics: `data_class`,
54
57
  # `data_type`, shape, and mask state must all match, and elements
55
58
  # are compared bitwise (for numeric types) or via `Object#eql?`
56
- # (for `:object` arrays). Unlike `==`, `NaN.eql?(NaN)` holds, so
57
- # two mask-free arrays with NaN at the same positions are `eql?`.
59
+ # (for `:object` arrays), so -0.0 and 0.0 differ and two NaNs are
60
+ # `eql?` only with the same bits.
58
61
  # Two Faces are `eql?` only when they are of the same class, share
59
62
  # their state (a time array's unit, a categorical's labels) and hold
60
63
  # the same storage.
metadata CHANGED
@@ -1,14 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carray
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.5
4
+ version: 3.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - himotoyoshi
8
8
  bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
- dependencies: []
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: prism
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '1.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '1.0'
12
26
  description: |2
13
27
  Ruby/CArray adds multi-dimensional numerical arrays to Ruby. Elements are held
14
28
  in a single flat memory block, so whole-array work -- element-wise arithmetic,
@@ -318,14 +332,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
318
332
  requirements:
319
333
  - - ">="
320
334
  - !ruby/object:Gem::Version
321
- version: '3.0'
335
+ version: '3.2'
322
336
  required_rubygems_version: !ruby/object:Gem::Requirement
323
337
  requirements:
324
338
  - - ">="
325
339
  - !ruby/object:Gem::Version
326
340
  version: '0'
327
341
  requirements: []
328
- rubygems_version: 4.0.17
342
+ rubygems_version: 4.0.8
329
343
  specification_version: 4
330
344
  summary: Multi-dimensional numerical array class for Ruby
331
345
  test_files: []