module Flt
Flt
contains constants for common floating point formats.
Constants
- APPLE
Sofware floating point implementatin for the Apple II (6502) the significand & sign are a single field in two's commplement
- HFP_DOUBLE
- HFP_EXTENDED
- HFP_SINGLE
- IEEE_128
- IEEE_128_BE
- IEEE_DEC128
- IEEE_DEC32
old names
- IEEE_DEC64
- IEEE_DOUBLE
- IEEE_D_BE
- IEEE_EXTENDED
- IEEE_HALF
- IEEE_H_BE
- IEEE_QUAD
- IEEE_Q_BE
- IEEE_SINGLE
- IEEE_S_BE
- IEEE_X_BE
- IEEE_binaryx
old names
- MBF_EXTENDEND
- RPL
- RPL_X
Public Instance Methods
# File lib/float-formats/classes.rb, line 1751 def *(v) # TODO: coercion if v.form_class==form_class form_class.arithmetic do |t| x = to(t,:exact) * v.to(t,:exact) form_class.from_number(x,:exact) end else # TODO end end
# File lib/float-formats/classes.rb, line 1718 def +(v) # TODO: coercion if v.form_class==form_class form_class.arithmetic do |t| x = to(t,:exact) + v.to(t,:exact) form_class.from_number(x,:exact) end else # TODO end end
# File lib/float-formats/classes.rb, line 1740 def -(v) # TODO: coercion if v.form_class==form_class form_class.arithmetic do |t| x = to(t,:exact) - v.to(t,:exact) form_class.from_number(x,:exact) end else # TODO end end
# File lib/float-formats/classes.rb, line 1715 def -@ minus end
# File lib/float-formats/classes.rb, line 1729 def /(v) # TODO: coercion if v.form_class==form_class form_class.arithmetic do |t| x = to(t,:exact) / v.to(t,:exact) form_class.from_number(x,:exact) end else # TODO end end
Compress BCD to Densely Packed Decimal
adapted from Mike Cowlishaw's Rexx program:
http://www2.hursley.ibm.com/decimal/DPDecimal.html
# File lib/float-formats/bytes.rb, line 338 def bcd2dpd(arg) # assign each bit to a variable, named as in the description a,b,c,d,e,f,g,h,i,j,k,m = ("%012B"%arg).split('').collect{|bit| bit.to_i} # derive the result bits, using boolean expressions only #-- [the operators are: '&'=AND, '|'=OR, '\'=NOT.] p=b | (a & j) | (a & f & i) q=c | (a & k) | (a & g & i) r=d s=(f & (bitnot(a) | bitnot(i))) | (bitnot(a) & e & j) | (e & i) t=g | (bitnot(a) & e &k) | (a & i) u=h v=a | e | i w=a | (e & i) | (bitnot(e) & j) x=e | (a & i) | (bitnot(a) & k) y=m # concatenate the bits and return # result = [p,q,r,s,t,u,v,w,x,y].collect{|bit| bit.to_s}.inject{|aa,bb|aa+bb}.to_i(2) result = 0 [p,q,r,s,t,u,v,w,x,y].each do |bit| result <<= 1 result |= bit end result end
Negate a bit. Auxiliar method for DPD conversions
# File lib/float-formats/bytes.rb, line 330 def bitnot(b) (~b)&1 end
# File lib/float-formats/classes.rb, line 1991 def convert_bytes(bytes,from_format,to_format) from_format.from_bytes(bytes).convert_to(to_format) end
generate a DBL value stored in a byte string given a Float value
# File lib/float-formats/native.rb, line 89 def dbl_from_float(val, little_endian=true) code = little_endian ? 'E':'G' [val].pack(code) end
generate a DBL value stored in a byte string given a decimal value formatted as text
# File lib/float-formats/native.rb, line 83 def dbl_from_text(txt, little_endian=true) code = little_endian ? 'E':'G' [txt].pack(code) end
convert a DBL value stored in a byte string to a Float value
# File lib/float-formats/native.rb, line 95 def dbl_to_float(sgl, little_endian=true) code = little_endian ? 'E':'G' sgl.unpack(code)[0] end
# File lib/float-formats/classes.rb, line 1971 def define(*arguments) raise "Invalid number of arguments for Flt definitions." if arguments.size<2 || arguments.size>3 if arguments.first.kind_of?(Class) base,name,parameters = arguments elsif arguments[1].kind_of?(Class) name,base,parameters = arguments else name,parameters = arguments base = parameters[:base] || FormatBase end Flt.const_set name, cls=Class.new(base) cls.define parameters constructor = lambda { |*args| cls.new(*args) } Flt.send :define_method,name,constructor Flt.send :module_function, name yield cls if block_given? end
Expand Densely Packed Decimal to BCD
adapted from Mike Cowlishaw's Rexx program:
http://www2.hursley.ibm.com/decimal/DPDecimal.html
# File lib/float-formats/bytes.rb, line 369 def dpd2bcd(arg) # assign each bit to a variable, named as in the description p,q,r,s,t,u,v,w,x,y = ("%010B"%arg).split('').collect{|bit| bit.to_i} # derive the result bits, using boolean expressions only a= (v & w) & (bitnot(s) | t | bitnot(x)) b=p & (bitnot(v) | bitnot(w) | (s & bitnot(t) & x)) c=q & (bitnot(v) | bitnot(w) | (s & bitnot(t) & x)) d=r e=v & ((bitnot(w) & x) | (bitnot(t) & x) | (s & x)) f=(s & (bitnot(v) | bitnot(x))) | (p & bitnot(s) & t & v & w & x) g=(t & (bitnot(v) | bitnot(x))) | (q & bitnot(s) & t & w) h=u i=v & ((bitnot(w) & bitnot(x)) | (w & x & (s | t))) j=(bitnot(v) & w) | (s & v & bitnot(w) & x) | (p & w & (bitnot(x) | (bitnot(s) & bitnot(t)))) k=(bitnot(v) & x) | (t & bitnot(w) & x) | (q & v & w & (bitnot(x) | (bitnot(s) & bitnot(t)))) m=y # concatenate the bits and return # result = [a,b,c,d,e,f,g,h,i,j,k,m].collect{|bit| bit.to_s}.inject{|aa,bb|aa+bb}.to_i(2) result = 0 [a,b,c,d,e,f,g,h,i,j,k,m].each do |bit| result <<= 1 result |= bit end result end
Unpack DPD digits
# File lib/float-formats/bytes.rb, line 430 def dpd_to_hexbcd(dpd, dpd_bits, endianness=:big_endian) bcd = "" while dpd_bits>=10 v = dpd2bcd(dpd & 0x3FF) dpd >>= 10 dpd_bits -= 10 bcd = ("%03X"%v)+bcd end if dpd_bits>0 case dpd_bits when 4 v = dpd & 0xF n = 1 when 7 v = dpd & 0x7F n = 2 else raise "Invalid DPD data" end v = dpd2bcd(v,true) bcd = ("%0#{n}X"%v)+bcd end bcd = bcd.reverse if endianness==:little_endian bcd end
binary representation
# File lib/float-formats/native.rb, line 27 def float_bin(x) Numerals::Format[:free, :exact_input, :scientific, base: 2].write(x) end
complete exact decimal representation
# File lib/float-formats/native.rb, line 22 def float_dec(x) Numerals::Format[:free, :exact_input].write(x) end
# File lib/float-formats/native.rb, line 45 def float_from_integral_sign_significand_exponent(sgn,s,e) Float.context.Num(sgn,s,e) end
compose float from significand and exponent
# File lib/float-formats/native.rb, line 37 def float_from_integral_significand_exponent(s,e) Float.context.Num(s,e) end
shortest decimal unambiguous reprentation
# File lib/float-formats/native.rb, line 12 def float_shortest_dec(x) Numerals::Format[:short].write(x) end
decimal representation showing all significant digits
# File lib/float-formats/native.rb, line 17 def float_significant_dec(x) Numerals::Format[:free].write(x) end
# File lib/float-formats/native.rb, line 41 def float_to_integral_sign_significand_exponent(x) Float.context.split(x) end
decompose a float into a signed integer significand and exponent (base Float::RADIX)
# File lib/float-formats/native.rb, line 32 def float_to_integral_significand_exponent(x) Float.context.to_int_scale(x) end
convert a float to C99's hexadecimal notation
# File lib/float-formats/native.rb, line 50 def hex_from_float(v) Numerals::Format[:hexbin].write(v) end
convert a string formatted in C99's hexadecimal notation to a float
# File lib/float-formats/native.rb, line 55 def hex_to_float(txt) # Numerals::Format[:hexbin].read(txt, type: Float) # txt.scanf("%A").first Float(txt) end
Pack a bcd digits string into DPD
# File lib/float-formats/bytes.rb, line 398 def hexbcd_to_dpd(bcd, endianness=:big_endian) n = bcd.size dpd = 0 dpd_bits = 0 i = 0 m = n%3 if m>0 v = bcd2dpd(bcd[0,m].to_i(16)) i += m n -= m bits = m==1 ? 4 : 7 dpd_bits += bits dpd <<= bits dpd |= v end while n>0 v = bcd2dpd(bcd[i,3].to_i(16)) i += 3 n -= 3 bits = 10 dpd_bits += bits dpd <<= bits dpd |= v end [dpd, dpd_bits] end
generate a SGL value stored in a byte string given a Float value
# File lib/float-formats/native.rb, line 70 def sgl_from_float(val, little_endian=true) code = little_endian ? 'e':'g' [val].pack(code) end
generate a SGL value stored in a byte string given a decimal value formatted as text
# File lib/float-formats/native.rb, line 64 def sgl_from_text(txt, little_endian=true) code = little_endian ? 'e':'g' [txt].pack(code) end
convert a SGL value stored in a byte string to a Float value
# File lib/float-formats/native.rb, line 76 def sgl_to_float(sgl, littel_endian=true) code = little_endian ? 'e':'g' sgl.unpack(code)[0] end