Module: Half

Defined in:
lib/half.rb

Constant Summary collapse

NAN_BYTES =
"\x7e\x00"

Class Method Summary collapse

Class Method Details

.decode(b16) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/half.rb', line 25

def self.decode(b16)
  exp = b16 >> 10 & 0x1f
  mant = b16 & 0x3ff
  val =
    if exp == 0
      Math.ldexp(mant, -24)
    elsif exp == 31
      mant == 0 ? Float::INFINITY : Math.ldexp(0x400 + mant, -10).cbor_nan_toggle
    else
      Math.ldexp(0x400 + mant, exp-25)
    end
  if b16[15] != 0
    -val
  else
    val
  end
end

.decode_from_bytes(hs) ⇒ Object



21
22
23
24
# File 'lib/half.rb', line 21

def self.decode_from_bytes(hs)
  b16, = hs.unpack("n")
  self.decode(b16)
end

.encode(fv) ⇒ Object



68
69
70
# File 'lib/half.rb', line 68

def self.encode(fv)
  self.encode_from_single(fv, [fv].pack("g"))
end

.encode_from_single(fv, ss) ⇒ Object



60
61
62
63
64
65
66
# File 'lib/half.rb', line 60

def self.encode_from_single(fv, ss)
  if e = self.encode_from_single_bytes(ss)
    # p e.to_s(16)
    hs = [e].pack("n")
    hs if self.decode_from_bytes(hs) == fv
  end
end

.encode_from_single_bytes(ss) ⇒ Object

single-precision string



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/half.rb', line 43

def self.encode_from_single_bytes(ss)        # single-precision string
  b32, = ss.unpack("N")
  s16 = b32 >> 16 & 0x8000
  mant = b32 & 0x7fffff
  exp = b32 >> 23 & 0xff
  # puts "#{fv} #{s16} #{mant.to_s(16)} #{exp}"
  if exp == 0
    s16 if mant == 0            # 0.0, -0.0
  elsif exp >= 103 && exp < 113 # denorm, exp16 = 0
    s16 + ((mant + 0x800000) >> (126 - exp))
  elsif exp >= 113 && exp <= 142 # normalized
    s16 + ((exp - 112) << 10) + (mant >> 13)
  elsif exp == 255              # Inf (handle NaN elsewhere!)
    s16 + 0x7c00 if mant == 0   # +Inf/-Inf
  end
end