Files

Flt

Flt contains constants for common floating point formats.

Constants

IEEE_binaryx

old names

IEEE_HALF
IEEE_SINGLE
IEEE_DOUBLE
IEEE_EXTENDED
IEEE_QUAD
IEEE_128
IEEE_H_BE
IEEE_S_BE
IEEE_D_BE
IEEE_X_BE
IEEE_128_BE
IEEE_Q_BE
IEEE_DEC32

old names

IEEE_DEC64
IEEE_DEC128
RPL
RPL_X
APPLE

Sofware floating point implementatin for the Apple II (6502) the significand & sign are a single field in two’s commplement

Public Instance Methods

*(v) click to toggle source
      # 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
+(v) click to toggle source
      # 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
-(v) click to toggle source
      # 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
-@() click to toggle source
      # File lib/float-formats/classes.rb, line 1666
1666:   def -@
1667:     minus
1668:   end
/(v) click to toggle source
      # 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
bcd2dpd(arg) click to toggle source

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
bitnot(b) click to toggle source

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
convert_bytes(bytes,from_format,to_format) click to toggle source
      # 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
dbl_from_float(val, little_endian=true) click to toggle source

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
dbl_from_text(txt, little_endian=true) click to toggle source

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
dbl_to_float(sgl, little_endian=true) click to toggle source

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
define(*arguments) click to toggle source
      # 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
dpd2bcd(arg) click to toggle source

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
dpd_to_hexbcd(dpd, dpd_bits, endianness=:big_endian) click to toggle source

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
float_bin(x) click to toggle source

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
float_dec(x) click to toggle source

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
float_from_integral_sign_significand_exponent(sgn,s,e) click to toggle source
    # 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
float_from_integral_significand_exponent(s,e) click to toggle source

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
float_shortest_dec(x) click to toggle source

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
float_significant_dec(x) click to toggle source

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
float_to_integral_sign_significand_exponent(x) click to toggle source
    # File lib/float-formats/native.rb, line 43
43: def float_to_integral_sign_significand_exponent(x)
44:   Float.context.split(x)
45: end
float_to_integral_significand_exponent(x) click to toggle source

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
hex_from_float(v) click to toggle source

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
hex_to_float(txt) click to toggle source

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
hexbcd_to_dpd(bcd, endianness=:big_endian) click to toggle source

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
sgl_from_float(val, little_endian=true) click to toggle source

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
sgl_from_text(txt, little_endian=true) click to toggle source

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
sgl_to_float(sgl, littel_endian=true) click to toggle source

convert a SGL value stored in a byte string to a Float value

     # File lib/float-formats/native.rb, line 121
121: def sgl_to_float(sgl, littel_endian=true)
122:   code = little_endian ? 'e':'g'
123:   sgl.unpack(code)[0]
124: end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.