carray 3.0.3 → 3.0.4

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 (212) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +264 -0
  3. data/README.md +3 -2
  4. data/carray.gemspec +1 -1
  5. data/ext/ca_axis_descriptor.h +27 -24
  6. data/ext/ca_axis_dispatch.c +1 -6
  7. data/ext/ca_axis_group.c +27 -27
  8. data/ext/ca_binop_dispatch.c +1 -29
  9. data/ext/ca_binop_dispatch.h +0 -1
  10. data/ext/ca_categorical_iterator.c +205 -134
  11. data/ext/ca_compare.c +7 -18
  12. data/ext/ca_group_iter.c +16 -17
  13. data/ext/ca_kernel_iterator.c +1234 -1994
  14. data/ext/ca_kernel_iterator.h +391 -437
  15. data/ext/ca_monop_dispatch.c +82 -59
  16. data/ext/ca_monop_dispatch.h +1 -0
  17. data/ext/ca_obj_array.c +96 -39
  18. data/ext/ca_obj_bincmp.c +24 -21
  19. data/ext/ca_obj_binop.c +15 -26
  20. data/ext/ca_obj_bitarray.c +3 -2
  21. data/ext/ca_obj_bitfield.c +5 -6
  22. data/ext/ca_obj_block.c +18 -9
  23. data/ext/ca_obj_byte_swap.c +5 -6
  24. data/ext/ca_obj_const_string.c +173 -19
  25. data/ext/ca_obj_face.c +238 -57
  26. data/ext/ca_obj_face.h +19 -0
  27. data/ext/ca_obj_fake.c +15 -29
  28. data/ext/ca_obj_farray.c +6 -3
  29. data/ext/ca_obj_field.c +17 -5
  30. data/ext/ca_obj_fixlen_string.c +2 -3
  31. data/ext/ca_obj_grid.c +406 -132
  32. data/ext/ca_obj_meld.c +172 -34
  33. data/ext/ca_obj_moncmp.c +23 -8
  34. data/ext/ca_obj_monop.c +67 -57
  35. data/ext/ca_obj_object.c +157 -51
  36. data/ext/ca_obj_record.c +12 -7
  37. data/ext/ca_obj_reduce.c +13 -8
  38. data/ext/ca_obj_refer.c +25 -27
  39. data/ext/ca_obj_remap.c +30 -9
  40. data/ext/ca_obj_repeat.c +9 -10
  41. data/ext/ca_obj_roll.c +6 -5
  42. data/ext/ca_obj_select.c +14 -9
  43. data/ext/ca_obj_select_axis.c +15 -47
  44. data/ext/ca_obj_shift.c +11 -1
  45. data/ext/ca_obj_stack.c +179 -34
  46. data/ext/ca_obj_stride.c +162 -115
  47. data/ext/ca_obj_string.c +71 -4
  48. data/ext/ca_obj_tile.c +6 -5
  49. data/ext/ca_obj_time.c +22 -6
  50. data/ext/ca_obj_timedelta.c +22 -6
  51. data/ext/ca_obj_transpose.c +5 -3
  52. data/ext/ca_obj_triop.c +23 -32
  53. data/ext/ca_obj_window.c +190 -26
  54. data/ext/ca_sweep_engine.c +2 -2
  55. data/ext/caframe_csv_reader.c +80 -1
  56. data/ext/carray.h +181 -75
  57. data/ext/carray_access.c +184 -96
  58. data/ext/carray_address_basis.c +343 -87
  59. data/ext/carray_attribute.c +89 -6
  60. data/ext/carray_bincount.c +10 -8
  61. data/ext/carray_broadcast.c +13 -8
  62. data/ext/carray_build_flags.h +3 -0
  63. data/ext/carray_call_cfunc.c +108 -0
  64. data/ext/carray_cast.c +142 -24
  65. data/ext/carray_cast_func.rb +46 -6
  66. data/ext/carray_class.c +4 -3
  67. data/ext/carray_config.h +28 -0
  68. data/ext/carray_conversion.c +16 -7
  69. data/ext/carray_copy.c +51 -14
  70. data/ext/carray_core.c +147 -55
  71. data/ext/carray_count.c +50 -20
  72. data/ext/carray_element.c +76 -33
  73. data/ext/carray_factorize.c +118 -64
  74. data/ext/carray_generate.c +191 -50
  75. data/ext/carray_histogram.c +62 -17
  76. data/ext/carray_hold.c +12 -15
  77. data/ext/carray_index_classifier.c +388 -176
  78. data/ext/carray_internal.h +336 -29
  79. data/ext/carray_kernels_bincmp.c +4453 -0
  80. data/ext/carray_kernels_binop.c +11368 -0
  81. data/ext/carray_kernels_init.c +1734 -0
  82. data/ext/carray_kernels_moncmp.c +2104 -0
  83. data/ext/carray_kernels_monop.c +18369 -0
  84. data/ext/carray_kernels_reduce_aggregate.c +23818 -0
  85. data/ext/carray_kernels_reduce_boolean.c +406 -0
  86. data/ext/carray_kernels_reduce_cumulative.c +10086 -0
  87. data/ext/carray_kernels_reduce_extreme.c +17634 -0
  88. data/ext/carray_kernels_reduce_variance.c +3849 -0
  89. data/ext/carray_kernels_scan.c +4302 -0
  90. data/ext/carray_kernels_search.c +33829 -0
  91. data/ext/carray_kernels_sort.c +10906 -0
  92. data/ext/carray_kernels_triop.c +1864 -0
  93. data/ext/carray_key_windows.c +216 -0
  94. data/ext/carray_lazy.c +170 -111
  95. data/ext/carray_mask.c +292 -72
  96. data/ext/carray_median_percentile.c +82 -28
  97. data/ext/carray_memory_view.c +669 -561
  98. data/ext/carray_operator.c +124 -47
  99. data/ext/carray_order.c +384 -76
  100. data/ext/carray_partition.c +28 -27
  101. data/ext/carray_random.c +67 -13
  102. data/ext/carray_round.c +273 -0
  103. data/ext/carray_scatter.c +63 -38
  104. data/ext/carray_segment.c +3 -3
  105. data/ext/carray_slab.c +91 -28
  106. data/ext/carray_sort.c +35 -35
  107. data/ext/carray_struct.c +19 -18
  108. data/ext/carray_test.c +26 -5
  109. data/ext/carray_undef.c +4 -0
  110. data/ext/carray_utils.c +246 -45
  111. data/ext/mk_call_cfunc.rb +19 -2
  112. data/ext/mkkernel.rb +198 -240
  113. data/ext/ruby_carray.c +10 -4
  114. data/ext/version.h +4 -4
  115. data/lib/carray/attribute.rb +126 -22
  116. data/lib/carray/autoload_carray.rb +8 -31
  117. data/lib/carray/autoload_method_extension.rb +14 -5
  118. data/lib/carray/axis_group.rb +255 -106
  119. data/lib/carray/basics.rb +78 -10
  120. data/lib/carray/bincount_nd.rb +12 -2
  121. data/lib/carray/block_iterator.rb +126 -23
  122. data/lib/carray/boolean_reduce.rb +17 -17
  123. data/lib/carray/categorical.rb +165 -43
  124. data/lib/carray/categorical_iterator.rb +130 -27
  125. data/lib/carray/complex.rb +5 -5
  126. data/lib/carray/conditional.rb +67 -18
  127. data/lib/carray/const_string.rb +14 -5
  128. data/lib/carray/construct.rb +15 -11
  129. data/lib/carray/data_type_extension.rb +1 -0
  130. data/lib/carray/distance_limit.rb +77 -0
  131. data/lib/carray/fixlen_string.rb +7 -1
  132. data/lib/carray/frame/column_verbs.rb +70 -0
  133. data/lib/carray/frame/convert.rb +69 -0
  134. data/lib/carray/frame/csv_parser.rb +111 -17
  135. data/lib/carray/frame/describe.rb +3 -2
  136. data/lib/carray/frame/frame.rb +246 -21
  137. data/lib/carray/frame/group.rb +510 -95
  138. data/lib/carray/frame/io.rb +115 -28
  139. data/lib/carray/frame/join.rb +312 -51
  140. data/lib/carray/frame/records.rb +83 -7
  141. data/lib/carray/frame/reshape.rb +42 -35
  142. data/lib/carray/frame/sort.rb +7 -19
  143. data/lib/carray/frame/verbs.rb +188 -48
  144. data/lib/carray/frame/windows.rb +117 -0
  145. data/lib/carray/frame.rb +2 -0
  146. data/lib/carray/fuse_source.rb +11 -4
  147. data/lib/carray/fusion.rb +40 -16
  148. data/lib/carray/histogram.rb +6 -1
  149. data/lib/carray/inspect.rb +31 -8
  150. data/lib/carray/iterator.rb +85 -7
  151. data/lib/carray/key_windows.rb +620 -0
  152. data/lib/carray/lazy.rb +182 -183
  153. data/lib/carray/mask_gap_fill.rb +63 -57
  154. data/lib/carray/meld_reduce.rb +12 -14
  155. data/lib/carray/methods/bin.rb +26 -18
  156. data/lib/carray/methods/bincount.rb +16 -0
  157. data/lib/carray/methods/bit_string.rb +1 -1
  158. data/lib/carray/methods/choose.rb +16 -3
  159. data/lib/carray/methods/composition.rb +3 -1
  160. data/lib/carray/methods/gather_nd.rb +14 -5
  161. data/lib/carray/methods/insert_block.rb +2 -2
  162. data/lib/carray/methods/is_between.rb +59 -0
  163. data/lib/carray/methods/is_in.rb +53 -36
  164. data/lib/carray/methods/join.rb +1 -6
  165. data/lib/carray/methods/lag.rb +49 -0
  166. data/lib/carray/methods/locate_addr.rb +47 -51
  167. data/lib/carray/methods/mode.rb +1 -1
  168. data/lib/carray/methods/nunique.rb +11 -6
  169. data/lib/carray/methods/resize.rb +3 -3
  170. data/lib/carray/methods/value_counts.rb +4 -11
  171. data/lib/carray/record_order.rb +3 -3
  172. data/lib/carray/rng.rb +3 -0
  173. data/lib/carray/runtime.rb +53 -8
  174. data/lib/carray/segment_iterator.rb +313 -82
  175. data/lib/carray/serialize.rb +24 -10
  176. data/lib/carray/slab_iterator.rb +50 -0
  177. data/lib/carray/string.rb +105 -5
  178. data/lib/carray/string_operation_extension.rb +8 -1
  179. data/lib/carray/struct.rb +9 -21
  180. data/lib/carray/struct_builder.rb +19 -8
  181. data/lib/carray/time.rb +726 -104
  182. data/lib/carray/window_iterator.rb +122 -16
  183. data/lib/carray.rb +7 -0
  184. data/yard-stubs/ca_obj_bitfield.rb +1 -1
  185. data/yard-stubs/ca_obj_field.rb +4 -0
  186. data/yard-stubs/ca_obj_grid.rb +21 -10
  187. data/yard-stubs/ca_obj_refer.rb +2 -1
  188. data/yard-stubs/ca_obj_roll.rb +2 -2
  189. data/yard-stubs/ca_obj_shift.rb +5 -1
  190. data/yard-stubs/ca_obj_tile.rb +1 -1
  191. data/yard-stubs/ca_obj_window.rb +8 -3
  192. data/yard-stubs/carray_access.rb +6 -1
  193. data/yard-stubs/carray_attribute.rb +0 -5
  194. data/yard-stubs/carray_cast.rb +10 -0
  195. data/yard-stubs/carray_conversion.rb +2 -1
  196. data/yard-stubs/carray_copy.rb +4 -2
  197. data/yard-stubs/carray_count.rb +4 -4
  198. data/yard-stubs/carray_element.rb +10 -4
  199. data/yard-stubs/carray_generate.rb +21 -1
  200. data/yard-stubs/carray_mask.rb +26 -2
  201. data/yard-stubs/carray_math.rb +27 -1
  202. data/yard-stubs/carray_median_percentile.rb +5 -2
  203. data/yard-stubs/carray_memory_view.rb +40 -23
  204. data/yard-stubs/carray_order.rb +29 -18
  205. data/yard-stubs/carray_random.rb +13 -4
  206. data/yard-stubs/carray_scatter.rb +14 -9
  207. data/yard-stubs/carray_slab.rb +9 -2
  208. data/yard-stubs/carray_sort.rb +6 -5
  209. data/yard-stubs/carray_test.rb +5 -3
  210. metadata +25 -3
  211. data/lib/carray/arrow_tensor.rb +0 -401
  212. data/lib/carray/table.rb +0 -108
@@ -1,401 +0,0 @@
1
- # Apache Arrow "tensor IPC" reader / writer for CArray. [experimental]
2
- #
3
- # This surface is experimental: the method names, the module namespace, and
4
- # the packaging (it may later be extracted into a standalone, array-library-
5
- # neutral gem) are not yet frozen and may change in a future release.
6
- #
7
- # This is an interoperability layer, not an archival format: it exchanges
8
- # a dense numeric array with the Arrow ecosystem (pyarrow.ipc.write_tensor /
9
- # read_tensor and equivalents) using Arrow's encapsulated tensor message.
10
- # For faithful, reproducible persistence of a CArray -- mask, attributes,
11
- # data_class and all -- use CArray.save / CArray.load (the _CARRAY3 format).
12
- #
13
- # The on-disk shape is: a 0xFFFFFFFF continuation marker, an int32 metadata
14
- # length, a FlatBuffers Message whose header is a Tensor (element type, shape,
15
- # byte strides, and a Buffer descriptor), padding to an 8-byte boundary, then
16
- # the raw contiguous element bytes. Only the numeric types Arrow tensors
17
- # admit are supported (int8..int64, uint8..uint64, float32, float64); boolean,
18
- # complex, fixlen and object arrays have no Arrow tensor representation and are
19
- # rejected. A masked CArray is rejected too, mirroring the MemoryView policy:
20
- # Arrow tensors carry no validity concept, so the caller must be explicit
21
- # (ca.value to drop the mask, ca.unmask_copy(fill) to bake it in, or persist
22
- # the mask separately through CArray.save).
23
-
24
- require "stringio"
25
-
26
- class CArray
27
- # Reader / writer for Arrow's encapsulated tensor IPC message, for
28
- # exchanging a dense numeric array with the Arrow ecosystem
29
- # (`pyarrow.ipc.write_tensor` / `read_tensor` and equivalents).
30
- #
31
- # Experimental: the method names, this namespace and the packaging are not
32
- # frozen, and the layer may later move to a standalone, array-library-neutral
33
- # gem. It is an interoperability format, not an archival one — an Arrow
34
- # tensor carries no mask, attributes or data_class, so `CArray.save` /
35
- # `CArray.load` remain the way to persist a CArray faithfully.
36
- #
37
- # Only the numeric types an Arrow tensor admits are supported (int8..int64,
38
- # uint8..uint64, float32, float64). Boolean, complex, fixlen and object
39
- # arrays are rejected, as is a masked array — Arrow tensors have no validity
40
- # concept, so the caller must be explicit (`ca.value` to drop the mask,
41
- # `ca.unmask_copy(fill)` to bake it in, or save the mask separately).
42
- module ArrowTensor
43
-
44
- # CArray data_type symbol -> Arrow element-type descriptor.
45
- # [:float, precision] precision: 1 = single, 2 = double
46
- # [:int, bit_width, signed?]
47
- DTYPE_TO_ARROW = {
48
- float32: [:float, 1], float64: [:float, 2],
49
- int8: [:int, 8, true], int16: [:int, 16, true],
50
- int32: [:int, 32, true], int64: [:int, 64, true],
51
- uint8: [:int, 8, false], uint16:[:int, 16, false],
52
- uint32:[:int, 32, false], uint64:[:int, 64, false],
53
- }.freeze
54
-
55
- module_function
56
-
57
- # Write +ca+ to +io+ as an Arrow tensor IPC message.
58
- def write (ca, io)
59
- if ca.has_mask?
60
- raise ArgumentError,
61
- "cannot write a masked CArray as an Arrow tensor " \
62
- "(Arrow tensors have no validity concept); pass ca.value to " \
63
- "drop the mask, ca.unmask_copy(fill) to fill it, or use " \
64
- "CArray.save for a mask-preserving round-trip"
65
- end
66
- arrow = DTYPE_TO_ARROW[ca.data_type]
67
- unless arrow
68
- raise ArgumentError,
69
- "cannot write a #{ca.data_type} CArray as an Arrow tensor " \
70
- "(Arrow tensors are numeric only: int8..int64, uint8..uint64, " \
71
- "float32, float64)"
72
- end
73
- raise ArgumentError, "cannot write a 0-dimensional array" if ca.ndim < 1
74
-
75
- shape = ca.shape
76
- elt = ca.bytes
77
- strides = row_major_strides(shape, elt)
78
-
79
- body = StringIO.new("".b)
80
- ca.dump_binary(body) # raw contiguous element bytes, row-major
81
- body = body.string
82
-
83
- meta = build_metadata(arrow, shape, strides, body.bytesize)
84
- pad = (8 - ((8 + meta.bytesize) % 8)) % 8
85
- meta += "\0".b * pad
86
-
87
- io.write([0xFFFFFFFF].pack("V"))
88
- io.write([meta.bytesize].pack("l<"))
89
- io.write(meta)
90
- io.write(body)
91
- ca
92
- end
93
-
94
- # Read an Arrow tensor IPC message from +io+ and return a new CArray.
95
- def read (io)
96
- b = io.respond_to?(:read) ? io.read : io.to_s
97
- b = b.b
98
- meta = parse_metadata(b)
99
- type = meta[:data_type]
100
- unless CArray.respond_to?(:data_type_code) && DTYPE_TO_ARROW.key?(type)
101
- raise ArgumentError,
102
- "Arrow tensor element type #{type.inspect} has no CArray " \
103
- "counterpart"
104
- end
105
- build_carray(type, meta[:shape], meta[:strides], meta[:body])
106
- end
107
-
108
- # ---- helpers ----------------------------------------------------------
109
-
110
- def row_major_strides (shape, elt)
111
- s = Array.new(shape.length)
112
- acc = elt
113
- (shape.length - 1).downto(0) do |i|
114
- s[i] = acc
115
- acc *= shape[i]
116
- end
117
- s
118
- end
119
- private_class_method :row_major_strides
120
-
121
- def build_carray (type, shape, strides, body)
122
- elt = CArray.new(type, [1]).bytes
123
- rmaj = row_major_strides(shape, elt)
124
- if strides == rmaj
125
- ca = CArray.new(type, shape)
126
- ca.load_binary(StringIO.new(body))
127
- return ca
128
- end
129
- cmaj = row_major_strides(shape.reverse, elt).reverse
130
- if strides == cmaj
131
- t = CArray.new(type, shape.reverse)
132
- t.load_binary(StringIO.new(body))
133
- return t.transpose(*(0...shape.length).to_a.reverse).to_ca
134
- end
135
- # General strided layout (rare): gather element by element.
136
- gather_strided(type, shape, strides, body)
137
- end
138
- private_class_method :build_carray
139
-
140
- def gather_strided (type, shape, strides, body)
141
- elt = CArray.new(type, [1]).bytes
142
- code = UNPACK[type]
143
- ca = CArray.new(type, shape)
144
- elements = shape.inject(1, :*)
145
- idx = Array.new(shape.length, 0)
146
- elements.times do
147
- off = 0
148
- idx.each_with_index { |v, k| off += v * strides[k] }
149
- ca[*idx] = body[off, elt].unpack1(code)
150
- k = shape.length - 1
151
- while k >= 0
152
- idx[k] += 1
153
- break if idx[k] < shape[k]
154
- idx[k] = 0
155
- k -= 1
156
- end
157
- end
158
- ca
159
- end
160
- private_class_method :gather_strided
161
-
162
- # @!visibility private
163
- UNPACK = {
164
- float32:"e", float64:"E",
165
- int8:"c", int16:"s<", int32:"l<", int64:"q<",
166
- uint8:"C", uint16:"v", uint32:"V", uint64:"Q<",
167
- }.freeze
168
-
169
- # ---- FlatBuffers Message encoder (header = Tensor) --------------------
170
-
171
- # Minimal back-to-front FlatBuffers builder, specialised to the fields the
172
- # Tensor message uses (scalars, tables, vectors, one inline struct).
173
- #
174
- # @!visibility private
175
- class Builder
176
- def initialize
177
- @buf = "".b
178
- @minalign = 1
179
- @vt = nil
180
- @obj_start = nil
181
- end
182
-
183
- # @!visibility private
184
- def offset; @buf.bytesize; end
185
-
186
- # @!visibility private
187
- def prep (size, additional)
188
- @minalign = size if size > @minalign
189
- align = ((~(@buf.bytesize + additional)) + 1) & (size - 1)
190
- @buf.prepend("\0".b * align) if align > 0
191
- end
192
-
193
- # @!visibility private
194
- def u8 (x); @buf.prepend([x].pack("C")); end
195
- # @!visibility private
196
- def i16 (x); @buf.prepend([x].pack("s<")); end
197
- # @!visibility private
198
- def u16 (x); @buf.prepend([x].pack("v")); end
199
- # @!visibility private
200
- def u32 (x); @buf.prepend([x].pack("V")); end
201
- # @!visibility private
202
- def i32 (x); @buf.prepend([x].pack("l<")); end
203
- # @!visibility private
204
- def i64 (x); @buf.prepend([x].pack("q<")); end
205
-
206
- # @!visibility private
207
- def uoffset (off)
208
- prep(4, 0)
209
- u32(offset() - off + 4)
210
- end
211
-
212
- # @!visibility private
213
- def slot (v); @vt[v] = offset(); end
214
-
215
- # @!visibility private
216
- def slot_i16 (v, x); prep(2,0); i16(x); slot(v); end
217
- # @!visibility private
218
- def slot_u8 (v, x); prep(1,0); u8(x); slot(v); end
219
- # @!visibility private
220
- def slot_i32 (v, x); prep(4,0); i32(x); slot(v); end
221
- # @!visibility private
222
- def slot_i64 (v, x); prep(8,0); i64(x); slot(v); end
223
- # @!visibility private
224
- def slot_bool(v, x); prep(1,0); u8(x ? 1 : 0); slot(v); end
225
- # @!visibility private
226
- def slot_uoffset (v, off); uoffset(off); slot(v); end
227
-
228
- # @!visibility private
229
- def start_object (n); @vt = Array.new(n, 0); @obj_start = offset(); end
230
-
231
- # @!visibility private
232
- def end_object
233
- prep(4, 0)
234
- i32(0) # soffset placeholder
235
- obj = offset()
236
- n = @vt.length
237
- n -= 1 while n > 0 && @vt[n-1] == 0
238
- (n-1).downto(0) do |i|
239
- u16(@vt[i] == 0 ? 0 : (obj - @vt[i]))
240
- end
241
- u16(obj - @obj_start) # referenced table size
242
- u16((n + 2) * 2) # vtable size
243
- soff = offset() - obj
244
- @buf[@buf.bytesize - obj, 4] = [soff].pack("l<")
245
- obj
246
- end
247
-
248
- # @!visibility private
249
- def start_vector (elem, count, align); prep(4, elem*count); prep(align, elem*count); end
250
- # @!visibility private
251
- def end_vector (count); u32(count); offset(); end
252
-
253
- # @!visibility private
254
- def finish (root)
255
- prep(@minalign, 4)
256
- uoffset(root)
257
- @buf
258
- end
259
- end
260
-
261
- def build_metadata (arrow, shape, strides, body_len)
262
- fb = Builder.new
263
- tag = arrow[0] == :float ? 3 : 2
264
-
265
- type_off =
266
- if arrow[0] == :float
267
- fb.start_object(1)
268
- fb.slot_i16(0, arrow[1]) # precision
269
- fb.end_object
270
- else
271
- fb.start_object(2)
272
- fb.slot_i32(0, arrow[1]) # bitWidth
273
- fb.slot_bool(1, arrow[2]) # is_signed
274
- fb.end_object
275
- end
276
-
277
- dim_offs = shape.map do |sz|
278
- fb.start_object(2)
279
- fb.slot_i64(0, sz) # TensorDim.size (name omitted)
280
- fb.end_object
281
- end
282
- fb.start_vector(4, dim_offs.length, 4)
283
- dim_offs.reverse_each { |o| fb.uoffset(o) }
284
- shape_vec = fb.end_vector(dim_offs.length)
285
-
286
- fb.start_vector(8, strides.length, 8)
287
- strides.reverse_each { |s| fb.i64(s) }
288
- strides_vec = fb.end_vector(strides.length)
289
-
290
- fb.start_object(5) # Tensor: type_type,type,shape,strides,data
291
- fb.prep(8, 16) # data: inline Buffer struct
292
- fb.i64(body_len) # length
293
- fb.i64(0) # offset
294
- fb.slot(4)
295
- fb.slot_uoffset(3, strides_vec)
296
- fb.slot_uoffset(2, shape_vec)
297
- fb.slot_uoffset(1, type_off)
298
- fb.slot_u8(0, tag) # type_type
299
- tensor_off = fb.end_object
300
-
301
- fb.start_object(5) # Message: version,header_type,header,bodyLength,custom
302
- fb.slot_i64(3, body_len)
303
- fb.slot_uoffset(2, tensor_off)
304
- fb.slot_u8(1, 4) # header_type = Tensor
305
- fb.slot_i16(0, 4) # metadata version V5
306
- msg_off = fb.end_object
307
-
308
- fb.finish(msg_off)
309
- end
310
- private_class_method :build_metadata
311
-
312
- # ---- FlatBuffers Message decoder --------------------------------------
313
-
314
- def parse_metadata (b)
315
- u16 = ->(o){ b[o,2].unpack1("v") }
316
- i32 = ->(o){ b[o,4].unpack1("l<") }
317
- u32 = ->(o){ b[o,4].unpack1("V") }
318
- i64 = ->(o){ b[o,8].unpack1("q<") }
319
- field = ->(t,f){ vt = t - i32.(t); vts = u16.(vt); slot = 4 + f*2
320
- next 0 if slot >= vts; vo = u16.(vt+slot); vo==0 ? 0 : t+vo }
321
- deref = ->(pos){ pos + u32.(pos) }
322
-
323
- raise ArgumentError, "not an Arrow IPC message" unless u32.(0) == 0xffffffff
324
- meta_len = i32.(4)
325
- fb = 8
326
- body_off = 8 + meta_len
327
-
328
- msg = fb + i32.(fb)
329
- htag = (p = field.(msg,1); p == 0 ? 0 : b.getbyte(p))
330
- raise ArgumentError, "not a tensor message" unless htag == 4
331
- hpos = deref.(field.(msg,2))
332
-
333
- type_tag = b.getbyte(field.(hpos,0))
334
- type_tbl = deref.(field.(hpos,1))
335
- shp_vec = deref.(field.(hpos,2)); n = u32.(shp_vec)
336
- shape = (0...n).map { |i| dp = deref.(shp_vec + 4 + i*4); i64.(field.(dp,0)) }
337
- sv_slot = field.(hpos,3)
338
- strides =
339
- if sv_slot == 0
340
- row_major_strides(shape, CArray.new(arrow_symbol(type_tag, type_tbl, u16, i32, b), [1]).bytes)
341
- else
342
- sv = deref.(sv_slot); m = u32.(sv); (0...m).map { |i| i64.(sv + 4 + i*8) }
343
- end
344
- dpos = field.(hpos,4)
345
- data_off = i64.(dpos); data_len = i64.(dpos+8)
346
-
347
- { data_type: arrow_symbol(type_tag, type_tbl, u16, i32, b),
348
- shape: shape, strides: strides,
349
- body: b[body_off + data_off, data_len] }
350
- end
351
- private_class_method :parse_metadata
352
-
353
- def arrow_symbol (tag, tbl, u16, i32, b)
354
- case tag
355
- when 3
356
- { 0=>:float16, 1=>:float32, 2=>:float64 }[u16.(tbl_field(tbl, 0, i32, u16))] ||
357
- (raise ArgumentError, "unsupported Arrow float precision")
358
- when 2
359
- bw = i32.(tbl_field(tbl, 0, i32, u16))
360
- sf = tbl_field(tbl, 1, i32, u16)
361
- signed = sf == 0 ? false : (b.getbyte(sf) != 0) # is_signed FlatBuffers default = false
362
- (signed ? "int#{bw}" : "uint#{bw}").to_sym
363
- else
364
- raise ArgumentError, "unsupported Arrow tensor element type (tag=#{tag})"
365
- end
366
- end
367
- private_class_method :arrow_symbol
368
-
369
- def tbl_field (t, f, i32, u16)
370
- vt = t - i32.(t); vts = u16.(vt); slot = 4 + f*2
371
- return 0 if slot >= vts
372
- vo = u16.(vt + slot); vo == 0 ? 0 : t + vo
373
- end
374
- private_class_method :tbl_field
375
-
376
- end
377
-
378
- # Reads an Arrow tensor IPC file and returns it as a new CArray.
379
- #
380
- # Experimental, and the name is provisional.
381
- #
382
- # @param filename [String] path to the message.
383
- # @return [CArray]
384
- # @see ArrowTensor
385
- def self.load_arrow_tensor (filename)
386
- File.open(filename, "rb") { |io| ArrowTensor.read(io) }
387
- end
388
-
389
- # Writes `self` to `filename` as an Arrow tensor IPC message.
390
- #
391
- # Experimental, and the name is provisional. Rejects a masked or
392
- # non-numeric array; see {ArrowTensor} for the type policy.
393
- #
394
- # @param filename [String] path to write.
395
- # @return [self]
396
- # @see ArrowTensor
397
- def save_arrow_tensor (filename)
398
- File.open(filename, "wb") { |io| ArrowTensor.write(self, io) }
399
- self
400
- end
401
- end
data/lib/carray/table.rb DELETED
@@ -1,108 +0,0 @@
1
-
2
- class CArray
3
-
4
- # Column-name support for a 2-D CArray used as a table: an ordered name
5
- # list alongside the data, plus name-based column access.
6
- module TableMethods
7
-
8
- # @!attribute [r] column_names
9
- # @return [Array<Symbol, String>, nil] the assigned column
10
- # names, or `nil` when none have been set.
11
- attr_reader :column_names
12
-
13
- # @overload column_names=(list)
14
- # Sets the column-name list for `self`. `list` must have length
15
- # equal to `dim1` (the second axis size); `nil` and empty lists
16
- # are silently ignored.
17
- # @param list [Array<Symbol, String>, nil] column names.
18
- # @return [Array<Symbol, String>, nil] the assigned list.
19
- # @raise [ArgumentError] when `list.size != dim1`.
20
- def column_names= (list)
21
- if self.empty?
22
- return
23
- elsif list.nil?
24
- return
25
- elsif list.empty?
26
- return
27
- elsif list and list.size != dim1
28
- raise ArgumentError, "column_names list size is invalid (#{list.size} <=> #{dim1} )"
29
- else
30
- @column_names = list
31
- end
32
- end
33
-
34
- # @overload column(name)
35
- # Returns the column view identified by `name`. Integer names
36
- # index the second axis directly; Symbol and String names look
37
- # up the position in {#column_names}. Returns `nil` when the
38
- # name is unknown.
39
- # @param name [Integer, Symbol, String] column identifier.
40
- # @return [CArray, nil] column view or `nil` when unknown.
41
- def column (name)
42
- if name.is_a?(Integer)
43
- return self[false, name]
44
- elsif @column_names
45
- case name
46
- when Symbol
47
- if i = @column_names.index(name) or i = @column_names.index(name.to_s)
48
- return self[false, i]
49
- end
50
- when String
51
- if i = @column_names.index(name) or i = @column_names.index(name.intern)
52
- return self[false, i]
53
- end
54
- end
55
- end
56
- return nil
57
- end
58
-
59
- # @overload row(i)
60
- # Returns the `i`-th row as a Hash keyed by {#column_names}
61
- # (falling back to 0-based Integer keys when none are set).
62
- # @param i [Integer] row index.
63
- # @return [Hash]
64
- def row (i)
65
- keys = @column_names || (0...dim0).to_a
66
- output = {}
67
- data = self[i, nil]
68
- keys.each_with_index do |key, j|
69
- output[key] = data[j]
70
- end
71
- return output
72
- end
73
-
74
- # @overload rows(arg)
75
- # Returns a fresh table copy holding the rows selected by `arg`,
76
- # extended with {TableMethods} and carrying `self`'s
77
- # {#column_names}.
78
- # @param arg [Object] row selector accepted by `self[arg, nil]`
79
- # (Integer, Range, boolean CArray, ...).
80
- # @return [CArray] new table copy.
81
- def rows (arg)
82
- table = self[arg, nil].copy
83
- table.extend(CArray::TableMethods)
84
- table.column_names = @column_names
85
- return table
86
- end
87
-
88
- # @overload select { |table| ... }
89
- # Yields `self` and returns a new table restricted to the rows
90
- # selected by the block's return value. The block may return
91
- # an Integer index array or a boolean mask (which is converted
92
- # via `#where`).
93
- # @yieldparam table [CArray] `self`.
94
- # @yieldreturn [CArray] row selector.
95
- # @return [CArray] filtered table copy.
96
- def select
97
- idx = yield(self)
98
- case idx.data_type
99
- when CA_BOOLEAN
100
- idx = idx.where
101
- end
102
- return rows(+idx)
103
- end
104
-
105
- end
106
-
107
- end
108
-