class Flt::DoubleFormat
Class to define formats such as “double double” by pairing two floating-point values which define a higher precision value by its sum. The :half parameter is a format class that defines the type of each part of the numbers. The formats defined here have a fixed precision, although these formats can actually have a variable precision. For binary formats there's an option to gain one bit of precision by adjusting the sign of the second number. This is enabled by the :extra_prec option. For example, the “double double” format used in PowerPC is this
Flt.define :DoubleDouble, DoubleFormat, half: IEEE_binary64, extra_prec: true
Although this has a fixed 107 bits precision, the format as used in the PowerPC can have greater precision for specific values (by having greater separation between the exponents of both halves)
Public Class Methods
define(params)
click to toggle source
Calls superclass method
Flt::FormatBase::define
# File lib/float-formats/classes.rb, line 1799 def self.define(params) @half = params[:half] params = @half.parameters.merge(params) if @half.radix==2 @extra_prec = params[:extra_prec] else @extra_prec = false end params[:significand_digits] = 2*@half.significand_digits params[:significand_digits] += 1 if @extra_prec @significand_digits = params[:significand_digits] @hidden_bit = params[:hidden_bit] = @half.hidden_bit fields1 = [] fields2 = [] params[:fields].each_slice(2) do |s,v| fields1 << s # (s.to_s+"_1").to_sym fields1 << v fields2 << (s.to_s+"_2").to_sym fields2 << v end params[:fields] = fields1 + fields2 define_fields params[:fields] super params end
half()
click to toggle source
# File lib/float-formats/classes.rb, line 1832 def self.half @half end
join_halfs(h1,h2)
click to toggle source
# File lib/float-formats/classes.rb, line 1871 def self.join_halfs(h1,h2) self.from_bytes(h1.to_bytes+h2.to_bytes) end
pack(s,m,e)
click to toggle source
# File lib/float-formats/classes.rb, line 1851 def self.pack(s,m,e) if e.kind_of?(Symbol) f1 = @half.pack(s,m,e) f2 = @half.pack(+1,0,:zero) else s1,m1,e1,s2,m2,e2 = split_fp(s,m,e) f1 = @half.pack(s1,m1,e1) f2 = @half.pack(s2,m2,e2) end f1+f2 end
radix()
click to toggle source
# File lib/float-formats/classes.rb, line 1828 def self.radix @half.radix end
total_bits()
click to toggle source
# File lib/float-formats/classes.rb, line 1881 def self.total_bits 8*total_bytes end
total_bytes()
click to toggle source
# File lib/float-formats/classes.rb, line 1878 def self.total_bytes 2*@half.total_bytes end
total_nibbles()
click to toggle source
# File lib/float-formats/classes.rb, line 1875 def self.total_nibbles 2*total_bytes end
unpack(v)
click to toggle source
# File lib/float-formats/classes.rb, line 1836 def self.unpack(v) sz = @half.total_bytes v1 = @half.unpack(v[0...sz]) v2 = @half.unpack(v[sz..-1]) if v1.last == :nan nan elsif v1.last == :infinity infinity(v1.sign) else v2 = @half.zero.split if @half.new(*v1).subnormal? params = v1 + v2 join_fp(*params) end end
Private Class Methods
split_fp(s,m,e)
click to toggle source
# File lib/float-formats/classes.rb, line 1886 def self.split_fp(s,m,e) n = @half.significand_digits if @half.radix==2 if @extra_prec if (m & (1<<n))==0 # m.to_bits[n] == 0 m1 = m >> (n+1) # m/2**(n+1) e1 = e + n + 1 s1 = s m2 = m & ((1<<n) - 1) # m%2**n e2 = e s2 = s else m1 = (m >> (n+1)) + 1 # m/2**(n+1) + 1 e1 = e + n + 1 s1 = s if m1>=(1<<n) # 2**n m1 >>= 1 e1 += 1 end if m2==0 m2 = (1<<(n-1)) # 2**(n-1) e2 = e+1 s2 = -s else m2 = -((m & ((1<<n) - 1)) - (1<<n)) # m%2**n - 2**n e2 = e s2 = -s end end else # m has 2*n bits m1 = m >> n e1 = e + n s1 = s m2 = m & ((1<<n) - 1) # m%2**n e2 = e s2 = s end else m1 = m / @half.radix_power(n) e1 = e + n s1 = s m2 = m % @half.radix_power(n) e2 = e s2 = s end [s1,m1,e1,s2,m2,e2] end
Public Instance Methods
split_halfs()
click to toggle source
# File lib/float-formats/classes.rb, line 1863 def split_halfs b = to_bytes sz = form_class.half.total_bytes b1 = b[0...sz] b2 = b[sz..-1] [form_class.half.from_bytes(b1), form_class.half.from_bytes(b2)] end