Module: HDF5::DataHelpers

Defined in:
lib/hdf5/data_helpers.rb

Class Method Summary collapse

Class Method Details

.buffer_for(narray) ⇒ Object

Raises:



26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/hdf5/data_helpers.rb', line 26

def buffer_for(narray)
  dtype = DType.for_numo(narray)
  binary = if dtype.kind == :bool
             narray.to_a.flatten.map { |value| value.zero? ? 0 : 1 }.pack('C*')
           else
             narray.to_binary
           end
  expected_bytes = narray.size * dtype.itemsize
  raise HDF5::Error, 'Numo binary representation has an unexpected size' unless binary.bytesize == expected_bytes

  ::FFI::MemoryPointer.new(:char, expected_bytes).tap { |buffer| buffer.put_bytes(0, binary) }
end

.from_binary(dtype, binary, shape) ⇒ Object



39
40
41
42
43
44
45
46
# File 'lib/hdf5/data_helpers.rb', line 39

def from_binary(dtype, binary, shape)
  return dtype.numo_class.from_binary(binary, shape) unless dtype.kind == :bool

  bytes = binary.unpack('C*')
  return Numo::Bit.new.store(bytes.first) if shape.empty?

  Numo::UInt8.cast(bytes).reshape(*shape).ne(0)
end

.normalize_booleans(value) ⇒ Object



48
49
50
51
52
# File 'lib/hdf5/data_helpers.rb', line 48

def normalize_booleans(value)
  return value.map { |item| normalize_booleans(item) } if value.is_a?(Array)

  value ? 1 : 0
end

.normalize_data(data, label: 'Data') ⇒ Object

Raises:



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/hdf5/data_helpers.rb', line 5

def normalize_data(data, label: 'Data')
  return data if data.is_a?(Numo::NArray) && DType.for_numo(data)

  values = data.is_a?(Array) ? data.flatten : [data]
  raise HDF5::Error, "#{label} must not be empty" if values.empty?

  dtype = if values.all? { |value| value.is_a?(Integer) }
            DType.for_symbol(:int64)
          elsif values.all? { |value| [true, false].include?(value) }
            DType.for_symbol(:bool)
          elsif values.all? { |value| value.is_a?(Numeric) } && values.any? { |value| value.is_a?(Complex) }
            DType.for_symbol(:complex128)
          elsif values.all? { |value| value.is_a?(Numeric) }
            DType.for_symbol(:float64)
          else
            raise HDF5::Error, "Only numeric #{label.downcase} is supported"
          end
  normalized = dtype.kind == :bool ? normalize_booleans(data) : data
  dtype.numo_class.cast(normalized)
end