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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +264 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +1 -6
- data/ext/ca_axis_group.c +27 -27
- data/ext/ca_binop_dispatch.c +1 -29
- data/ext/ca_binop_dispatch.h +0 -1
- data/ext/ca_categorical_iterator.c +205 -134
- data/ext/ca_compare.c +7 -18
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1234 -1994
- data/ext/ca_kernel_iterator.h +391 -437
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +96 -39
- data/ext/ca_obj_bincmp.c +24 -21
- data/ext/ca_obj_binop.c +15 -26
- data/ext/ca_obj_bitarray.c +3 -2
- data/ext/ca_obj_bitfield.c +5 -6
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +5 -6
- data/ext/ca_obj_const_string.c +173 -19
- data/ext/ca_obj_face.c +238 -57
- data/ext/ca_obj_face.h +19 -0
- data/ext/ca_obj_fake.c +15 -29
- data/ext/ca_obj_farray.c +6 -3
- data/ext/ca_obj_field.c +17 -5
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +406 -132
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +67 -57
- data/ext/ca_obj_object.c +157 -51
- data/ext/ca_obj_record.c +12 -7
- data/ext/ca_obj_reduce.c +13 -8
- data/ext/ca_obj_refer.c +25 -27
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +6 -5
- data/ext/ca_obj_select.c +14 -9
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +11 -1
- data/ext/ca_obj_stack.c +179 -34
- data/ext/ca_obj_stride.c +162 -115
- data/ext/ca_obj_string.c +71 -4
- data/ext/ca_obj_tile.c +6 -5
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +5 -3
- data/ext/ca_obj_triop.c +23 -32
- data/ext/ca_obj_window.c +190 -26
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +181 -75
- data/ext/carray_access.c +184 -96
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +89 -6
- data/ext/carray_bincount.c +10 -8
- data/ext/carray_broadcast.c +13 -8
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +108 -0
- data/ext/carray_cast.c +142 -24
- data/ext/carray_cast_func.rb +46 -6
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +16 -7
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +147 -55
- data/ext/carray_count.c +50 -20
- data/ext/carray_element.c +76 -33
- data/ext/carray_factorize.c +118 -64
- data/ext/carray_generate.c +191 -50
- data/ext/carray_histogram.c +62 -17
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +336 -29
- data/ext/carray_kernels_bincmp.c +4453 -0
- data/ext/carray_kernels_binop.c +11368 -0
- data/ext/carray_kernels_init.c +1734 -0
- data/ext/carray_kernels_moncmp.c +2104 -0
- data/ext/carray_kernels_monop.c +18369 -0
- data/ext/carray_kernels_reduce_aggregate.c +23818 -0
- data/ext/carray_kernels_reduce_boolean.c +406 -0
- data/ext/carray_kernels_reduce_cumulative.c +10086 -0
- data/ext/carray_kernels_reduce_extreme.c +17634 -0
- data/ext/carray_kernels_reduce_variance.c +3849 -0
- data/ext/carray_kernels_scan.c +4302 -0
- data/ext/carray_kernels_search.c +33829 -0
- data/ext/carray_kernels_sort.c +10906 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +292 -72
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +124 -47
- data/ext/carray_order.c +384 -76
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +67 -13
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +63 -38
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +91 -28
- data/ext/carray_sort.c +35 -35
- data/ext/carray_struct.c +19 -18
- data/ext/carray_test.c +26 -5
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +246 -45
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +198 -240
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +126 -22
- data/lib/carray/autoload_carray.rb +8 -31
- data/lib/carray/autoload_method_extension.rb +14 -5
- data/lib/carray/axis_group.rb +255 -106
- data/lib/carray/basics.rb +78 -10
- data/lib/carray/bincount_nd.rb +12 -2
- data/lib/carray/block_iterator.rb +126 -23
- data/lib/carray/boolean_reduce.rb +17 -17
- data/lib/carray/categorical.rb +165 -43
- data/lib/carray/categorical_iterator.rb +130 -27
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +14 -5
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +7 -1
- data/lib/carray/frame/column_verbs.rb +70 -0
- data/lib/carray/frame/convert.rb +69 -0
- data/lib/carray/frame/csv_parser.rb +111 -17
- data/lib/carray/frame/describe.rb +3 -2
- data/lib/carray/frame/frame.rb +246 -21
- data/lib/carray/frame/group.rb +510 -95
- data/lib/carray/frame/io.rb +115 -28
- data/lib/carray/frame/join.rb +312 -51
- data/lib/carray/frame/records.rb +83 -7
- data/lib/carray/frame/reshape.rb +42 -35
- data/lib/carray/frame/sort.rb +7 -19
- data/lib/carray/frame/verbs.rb +188 -48
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +11 -4
- data/lib/carray/fusion.rb +40 -16
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +31 -8
- data/lib/carray/iterator.rb +85 -7
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +182 -183
- data/lib/carray/mask_gap_fill.rb +63 -57
- data/lib/carray/meld_reduce.rb +12 -14
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +16 -0
- data/lib/carray/methods/bit_string.rb +1 -1
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +3 -1
- data/lib/carray/methods/gather_nd.rb +14 -5
- data/lib/carray/methods/insert_block.rb +2 -2
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +53 -36
- data/lib/carray/methods/join.rb +1 -6
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +47 -51
- data/lib/carray/methods/mode.rb +1 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/resize.rb +3 -3
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +3 -3
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +53 -8
- data/lib/carray/segment_iterator.rb +313 -82
- data/lib/carray/serialize.rb +24 -10
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +8 -1
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +19 -8
- data/lib/carray/time.rb +726 -104
- data/lib/carray/window_iterator.rb +122 -16
- data/lib/carray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +4 -0
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +2 -1
- data/yard-stubs/ca_obj_roll.rb +2 -2
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_cast.rb +10 -0
- data/yard-stubs/carray_conversion.rb +2 -1
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +26 -2
- data/yard-stubs/carray_math.rb +27 -1
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +29 -18
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +14 -9
- data/yard-stubs/carray_slab.rb +9 -2
- data/yard-stubs/carray_sort.rb +6 -5
- data/yard-stubs/carray_test.rb +5 -3
- metadata +25 -3
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/lib/carray/arrow_tensor.rb
DELETED
|
@@ -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
|
-
|