Flt contains constants for common floating point formats.
old names
old names
Sofware floating point implementatin for the Apple II (6502) the significand & sign are a single field in two’s commplement
# File lib/float-formats/classes.rb, line 1702 1702: def *(v) 1703: # TODO: coercion 1704: if v.form_class==form_class 1705: form_class.arithmetic do |t| 1706: x = to(t,:exact) * v.to(t,:exact) 1707: form_class.from_number(x,:exact) 1708: end 1709: else 1710: # TODO 1711: end 1712: end
# File lib/float-formats/classes.rb, line 1669 1669: def +(v) 1670: # TODO: coercion 1671: if v.form_class==form_class 1672: form_class.arithmetic do |t| 1673: x = to(t,:exact) + v.to(t,:exact) 1674: form_class.from_number(x,:exact) 1675: end 1676: else 1677: # TODO 1678: end 1679: end
# File lib/float-formats/classes.rb, line 1691 1691: def -(v) 1692: # TODO: coercion 1693: if v.form_class==form_class 1694: form_class.arithmetic do |t| 1695: x = to(t,:exact) - v.to(t,:exact) 1696: form_class.from_number(x,:exact) 1697: end 1698: else 1699: # TODO 1700: end 1701: end
# File lib/float-formats/classes.rb, line 1666 1666: def -@ 1667: minus 1668: end
# File lib/float-formats/classes.rb, line 1680 1680: def /(v) 1681: # TODO: coercion 1682: if v.form_class==form_class 1683: form_class.arithmetic do |t| 1684: x = to(t,:exact) / v.to(t,:exact) 1685: form_class.from_number(x,:exact) 1686: end 1687: else 1688: # TODO 1689: end 1690: 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 338: def bcd2dpd(arg) 339: # assign each bit to a variable, named as in the description 340: a,b,c,d,e,f,g,h,i,j,k,m = ("%012B"%arg).split('').collect{|bit| bit.to_i} 341: 342: # derive the result bits, using boolean expressions only 343: #-- [the operators are: '&'=AND, '|'=OR, '\'=NOT.] 344: p=b | (a & j) | (a & f & i) 345: q=c | (a & k) | (a & g & i) 346: r=d 347: s=(f & (bitnot(a) | bitnot(i))) | (bitnot(a) & e & j) | (e & i) 348: t=g | (bitnot(a) & e &k) | (a & i) 349: u=h 350: v=a | e | i 351: w=a | (e & i) | (bitnot(e) & j) 352: x=e | (a & i) | (bitnot(a) & k) 353: y=m 354: 355: # concatenate the bits and return 356: # result = [p,q,r,s,t,u,v,w,x,y].collect{|bit| bit.to_s}.inject{|aa,bb|aa+bb}.to_i(2) 357: result = 0 358: [p,q,r,s,t,u,v,w,x,y].each do |bit| 359: result <<= 1 360: result |= bit 361: end 362: result 363: end
Negate a bit. Auxiliar method for DPD conversions
# File lib/float-formats/bytes.rb, line 330 330: def bitnot(b) 331: (~b)&1 332: end
# File lib/float-formats/classes.rb, line 1942 1942: def convert_bytes(bytes,from_format,to_format) 1943: from_format.from_bytes(bytes).convert_to(to_format) 1944: end
generate a DBL value stored in a byte string given a Float value
# File lib/float-formats/native.rb, line 134 134: def dbl_from_float(val, little_endian=true) 135: code = little_endian ? 'E':'G' 136: [val].pack(code) 137: end
generate a DBL value stored in a byte string given a decimal value formatted as text
# File lib/float-formats/native.rb, line 128 128: def dbl_from_text(txt, little_endian=true) 129: code = little_endian ? 'E':'G' 130: [txt].pack(code) 131: end
convert a DBL value stored in a byte string to a Float value
# File lib/float-formats/native.rb, line 140 140: def dbl_to_float(sgl, little_endian=true) 141: code = little_endian ? 'E':'G' 142: sgl.unpack(code)[0] 143: end
# File lib/float-formats/classes.rb, line 1922 1922: def define(*arguments) 1923: raise "Invalid number of arguments for Flt definitions." if arguments.size<2 || arguments.size>3 1924: if arguments.first.kind_of?(Class) 1925: base,name,parameters = arguments 1926: elsif arguments[1].kind_of?(Class) 1927: name,base,parameters = arguments 1928: else 1929: name,parameters = arguments 1930: base = parameters[:base] || FormatBase 1931: end 1932: Flt.const_set name, cls=Class.new(base) 1933: cls.define parameters 1934: constructor = lambda { |*args| cls.new(*args) } 1935: Flt.send :define_method,name,constructor 1936: Flt.send :module_function, name 1937: yield cls if block_given? 1938: 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 369: def dpd2bcd(arg) 370: 371: # assign each bit to a variable, named as in the description 372: p,q,r,s,t,u,v,w,x,y = ("%010B"%arg).split('').collect{|bit| bit.to_i} 373: 374: # derive the result bits, using boolean expressions only 375: a= (v & w) & (bitnot(s) | t | bitnot(x)) 376: b=p & (bitnot(v) | bitnot(w) | (s & bitnot(t) & x)) 377: c=q & (bitnot(v) | bitnot(w) | (s & bitnot(t) & x)) 378: d=r 379: e=v & ((bitnot(w) & x) | (bitnot(t) & x) | (s & x)) 380: f=(s & (bitnot(v) | bitnot(x))) | (p & bitnot(s) & t & v & w & x) 381: g=(t & (bitnot(v) | bitnot(x))) | (q & bitnot(s) & t & w) 382: h=u 383: i=v & ((bitnot(w) & bitnot(x)) | (w & x & (s | t))) 384: j=(bitnot(v) & w) | (s & v & bitnot(w) & x) | (p & w & (bitnot(x) | (bitnot(s) & bitnot(t)))) 385: k=(bitnot(v) & x) | (t & bitnot(w) & x) | (q & v & w & (bitnot(x) | (bitnot(s) & bitnot(t)))) 386: m=y 387: # concatenate the bits and return 388: # 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) 389: result = 0 390: [a,b,c,d,e,f,g,h,i,j,k,m].each do |bit| 391: result <<= 1 392: result |= bit 393: end 394: result 395: end
Unpack DPD digits
# File lib/float-formats/bytes.rb, line 430 430: def dpd_to_hexbcd(dpd, dpd_bits, endianness=:big_endian) 431: 432: bcd = "" 433: 434: while dpd_bits>=10 435: v = dpd2bcd(dpd & 0x3FF) 436: dpd >>= 10 437: dpd_bits -= 10 438: bcd = ("%03X"%v)+bcd 439: end 440: 441: if dpd_bits>0 442: case dpd_bits 443: when 4 444: v = dpd & 0xF 445: n = 1 446: when 7 447: v = dpd & 0x7F 448: n = 2 449: else 450: raise "Invalid DPD data" 451: end 452: v = dpd2bcd(v,true) 453: bcd = ("%0#{n}X"%v)+bcd 454: end 455: 456: bcd = bcd.reverse if endianness==:little_endian 457: 458: bcd 459: 460: end
binary representation
# File lib/float-formats/native.rb, line 29 29: def float_bin(x) 30: x.nio_write(Nio::Fmt.mode(:sci,:exact).base(2)) 31: end
complete exact decimal representation
# File lib/float-formats/native.rb, line 24 24: def float_dec(x) 25: x.nio_write(Nio::Fmt.prec(:exact).approx_mode(:exact)) 26: end
# File lib/float-formats/native.rb, line 47 47: def float_from_integral_sign_significand_exponent(sgn,s,e) 48: Float.context.Num(sgn,s,e) 49: end
compose float from significand and exponent
# File lib/float-formats/native.rb, line 39 39: def float_from_integral_significand_exponent(s,e) 40: Float.context.Num(s,e) 41: end
shortest decimal unambiguous reprentation
# File lib/float-formats/native.rb, line 14 14: def float_shortest_dec(x) 15: x.nio_write(Nio::Fmt.prec(:exact)) 16: end
decimal representation showing all significant digits
# File lib/float-formats/native.rb, line 19 19: def float_significant_dec(x) 20: x.nio_write(Nio::Fmt.prec(:exact).show_all_digits(true)) 21: end
# File lib/float-formats/native.rb, line 43 43: def float_to_integral_sign_significand_exponent(x) 44: Float.context.split(x) 45: end
decompose a float into a signed integer significand and exponent (base Float::RADIX)
# File lib/float-formats/native.rb, line 34 34: def float_to_integral_significand_exponent(x) 35: Float.context.to_int_scale(x) 36: end
convert a float to C99’s hexadecimal notation
# File lib/float-formats/native.rb, line 52 52: def hex_from_float(v) 53: if Float::RADIX==2 54: sgn,s,e = float_to_integral_sign_significand_exponent(v) 55: else 56: txt = v.nio_write(Fmt.base(2).sep('.')).upcase 57: p = txt.index('E') 58: exp = 0 59: if p 60: exp = rep[p+1..1].to_i 61: txt = rep[0...p] 62: end 63: p = txt.index('.') 64: if p 65: exp -= (txt.size-p-1) 66: txt.tr!('.','') 67: end 68: s = txt.to_i(2) 69: e = exp 70: end 71: "0x#{sgn<0 ? '-' : ''}#{s.to_s(16)}p#{e}" 72: end
convert a string formatted in C99’s hexadecimal notation to a float
# File lib/float-formats/native.rb, line 75 75: def hex_to_float(txt) 76: txt = txt.strip.upcase 77: txt = txt[2..1] if txt[0,2]=='0X' 78: p = txt.index('P') 79: if p 80: exp = txt[p+1..1].to_i 81: txt = txt[0...p] 82: else 83: exp = 0 84: end 85: p = txt.index('.') 86: if p 87: exp -= (txt.size-p-1)*4 88: txt.tr!('.','') 89: end 90: if Float::RADIX==2 91: v = txt.to_i(16) 92: if v==0 && txt.include?('-') 93: sign = 1 94: elsif v<0 95: sign = 1 96: v = -v 97: else 98: sign = 1 99: end 100: float_from_integral_sign_significand_exponent(sign,v,exp) 101: else 102: (txt.to_i(16)*(2**exp)).to_f 103: end 104: end
Pack a bcd digits string into DPD
# File lib/float-formats/bytes.rb, line 398 398: def hexbcd_to_dpd(bcd, endianness=:big_endian) 399: 400: n = bcd.size 401: dpd = 0 402: dpd_bits = 0 403: 404: i = 0 405: m = n%3 406: if m>0 407: v = bcd2dpd(bcd[0,m].to_i(16)) 408: i += m 409: n -= m 410: bits = m==1 ? 4 : 7 411: dpd_bits += bits 412: dpd <<= bits 413: dpd |= v 414: end 415: 416: while n>0 417: v = bcd2dpd(bcd[i,3].to_i(16)) 418: i += 3 419: n -= 3 420: bits = 10 421: dpd_bits += bits 422: dpd <<= bits 423: dpd |= v 424: end 425: 426: [dpd, dpd_bits] 427: end
generate a SGL value stored in a byte string given a Float value
# File lib/float-formats/native.rb, line 115 115: def sgl_from_float(val, little_endian=true) 116: code = little_endian ? 'e':'g' 117: [val].pack(code) 118: end
generate a SGL value stored in a byte string given a decimal value formatted as text
# File lib/float-formats/native.rb, line 109 109: def sgl_from_text(txt, little_endian=true) 110: code = little_endian ? 'e':'g' 111: [txt].pack(code) 112: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.