Module: Flt
- Included in:
- FormatBase, FormatBase
- Defined in:
- lib/float-formats.rb,
lib/float-formats/bytes.rb,
lib/float-formats/native.rb,
lib/float-formats/classes.rb,
lib/float-formats/formats.rb,
lib/float-formats/version.rb
Overview
Flt contains constants for common floating point formats.
Defined Under Namespace
Modules: Frmts, IEEE Classes: BCDFormat, BinaryFormat, Bits, Bytes, C51BCDFormat, CDCFormat, DPDFormat, DecimalFormatBase, DoubleFormat, FieldsInBitsFormatBase, FormatBase, HexadecimalFormat
Constant Summary collapse
- IEEE_binaryx =
old names
IEEE_binary80
- IEEE_HALF =
IEEE_binary16
- IEEE_SINGLE =
IEEE_binary32
- IEEE_DOUBLE =
IEEE_binary64
- IEEE_EXTENDED =
IEEE_binary80
- IEEE_QUAD =
IEEE_binary128
- IEEE_128 =
IEEE_binary128
- IEEE_H_BE =
IEEE_binary16_BE
- IEEE_S_BE =
IEEE_binary32_BE
- IEEE_D_BE =
IEEE_binary64_BE
- IEEE_X_BE =
IEEE_binary80_BE
- IEEE_128_BE =
IEEE_binary128_BE
- IEEE_Q_BE =
IEEE_binary128_BE
- IEEE_DEC32 =
old names
IEEE_decimal32
- IEEE_DEC64 =
IEEE_decimal64
- IEEE_DEC128 =
IEEE_decimal128
- RPL =
SATURN
- RPL_X =
SATURN_X
- APPLE =
Sofware floating point implementatin for the Apple II (6502) the significand & sign are a single field in two’s commplement
APPLE_INSANE
Class Method Summary collapse
-
.bcd2dpd(arg) ⇒ Object
Compress BCD to Densely Packed Decimal.
-
.bitnot(b) ⇒ Object
Negate a bit.
- .convert_bytes(bytes, from_format, to_format) ⇒ Object
-
.dbl_from_float(val, little_endian = true) ⇒ Object
generate a DBL value stored in a byte string given a Float value.
-
.dbl_from_text(txt, little_endian = true) ⇒ Object
generate a DBL value stored in a byte string given a decimal value formatted as text.
-
.dbl_to_float(sgl, little_endian = true) ⇒ Object
convert a DBL value stored in a byte string to a Float value.
- .define(*arguments) {|cls| ... } ⇒ Object
-
.dpd2bcd(arg) ⇒ Object
Expand Densely Packed Decimal to BCD.
-
.dpd_to_hexbcd(dpd, dpd_bits, endianness = :big_endian) ⇒ Object
Unpack DPD digits.
-
.float_bin(x) ⇒ Object
binary representation.
-
.float_dec(x) ⇒ Object
complete exact decimal representation.
- .float_from_integral_sign_significand_exponent(sgn, s, e) ⇒ Object
-
.float_from_integral_significand_exponent(s, e) ⇒ Object
compose float from significand and exponent.
-
.float_shortest_dec(x) ⇒ Object
shortest decimal unambiguous reprentation.
-
.float_significant_dec(x) ⇒ Object
decimal representation showing all significant digits.
- .float_to_integral_sign_significand_exponent(x) ⇒ Object
-
.float_to_integral_significand_exponent(x) ⇒ Object
decompose a float into a signed integer significand and exponent (base Float::RADIX).
-
.hex_from_float(v) ⇒ Object
convert a float to C99’s hexadecimal notation.
-
.hex_to_float(txt) ⇒ Object
convert a string formatted in C99’s hexadecimal notation to a float.
-
.hexbcd_to_dpd(bcd, endianness = :big_endian) ⇒ Object
Pack a bcd digits string into DPD.
-
.sgl_from_float(val, little_endian = true) ⇒ Object
generate a SGL value stored in a byte string given a Float value.
-
.sgl_from_text(txt, little_endian = true) ⇒ Object
generate a SGL value stored in a byte string given a decimal value formatted as text.
-
.sgl_to_float(sgl, littel_endian = true) ⇒ Object
convert a SGL value stored in a byte string to a Float value.
Instance Method Summary collapse
Class Method Details
.bcd2dpd(arg) ⇒ Object
Compress BCD to Densely Packed Decimal
adapted from Mike Cowlishaw’s Rexx program:
http://www2.hursley.ibm.com/decimal/DPDecimal.html
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 |
# 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 |
.bitnot(b) ⇒ Object
Negate a bit. Auxiliar method for DPD conversions
330 331 332 |
# File 'lib/float-formats/bytes.rb', line 330 def bitnot(b) (~b)&1 end |
.convert_bytes(bytes, from_format, to_format) ⇒ Object
1986 1987 1988 |
# File 'lib/float-formats/classes.rb', line 1986 def convert_bytes(bytes,from_format,to_format) from_format.from_bytes(bytes).convert_to(to_format) end |
.dbl_from_float(val, little_endian = true) ⇒ Object
generate a DBL value stored in a byte string given a Float value
89 90 91 92 |
# 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 |
.dbl_from_text(txt, little_endian = true) ⇒ Object
generate a DBL value stored in a byte string given a decimal value formatted as text
83 84 85 86 |
# 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 |
.dbl_to_float(sgl, little_endian = true) ⇒ Object
convert a DBL value stored in a byte string to a Float value
95 96 97 98 |
# 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 |
.define(*arguments) {|cls| ... } ⇒ Object
1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 |
# File 'lib/float-formats/classes.rb', line 1966 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 |
.dpd2bcd(arg) ⇒ Object
Expand Densely Packed Decimal to BCD
adapted from Mike Cowlishaw’s Rexx program:
http://www2.hursley.ibm.com/decimal/DPDecimal.html
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 |
# 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 |
.dpd_to_hexbcd(dpd, dpd_bits, endianness = :big_endian) ⇒ Object
Unpack DPD digits
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 |
# 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 |
.float_bin(x) ⇒ Object
binary representation
27 28 29 |
# File 'lib/float-formats/native.rb', line 27 def float_bin(x) Numerals::Format[:free, :exact_input, :scientific, base: 2].write(x) end |
.float_dec(x) ⇒ Object
complete exact decimal representation
22 23 24 |
# File 'lib/float-formats/native.rb', line 22 def float_dec(x) Numerals::Format[:free, :exact_input].write(x) end |
.float_from_integral_sign_significand_exponent(sgn, s, e) ⇒ Object
45 46 47 |
# 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 |
.float_from_integral_significand_exponent(s, e) ⇒ Object
compose float from significand and exponent
37 38 39 |
# File 'lib/float-formats/native.rb', line 37 def float_from_integral_significand_exponent(s,e) Float.context.Num(s,e) end |
.float_shortest_dec(x) ⇒ Object
shortest decimal unambiguous reprentation
12 13 14 |
# File 'lib/float-formats/native.rb', line 12 def float_shortest_dec(x) Numerals::Format[:short].write(x) end |
.float_significant_dec(x) ⇒ Object
decimal representation showing all significant digits
17 18 19 |
# File 'lib/float-formats/native.rb', line 17 def float_significant_dec(x) Numerals::Format[:free].write(x) end |
.float_to_integral_sign_significand_exponent(x) ⇒ Object
41 42 43 |
# File 'lib/float-formats/native.rb', line 41 def float_to_integral_sign_significand_exponent(x) Float.context.split(x) end |
.float_to_integral_significand_exponent(x) ⇒ Object
decompose a float into a signed integer significand and exponent (base Float::RADIX)
32 33 34 |
# File 'lib/float-formats/native.rb', line 32 def float_to_integral_significand_exponent(x) Float.context.to_int_scale(x) end |
.hex_from_float(v) ⇒ Object
convert a float to C99’s hexadecimal notation
50 51 52 |
# File 'lib/float-formats/native.rb', line 50 def hex_from_float(v) Numerals::Format[:hexbin].write(v) end |
.hex_to_float(txt) ⇒ Object
convert a string formatted in C99’s hexadecimal notation to a float
55 56 57 58 59 |
# 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 |
.hexbcd_to_dpd(bcd, endianness = :big_endian) ⇒ Object
Pack a bcd digits string into DPD
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 |
# 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 |
.sgl_from_float(val, little_endian = true) ⇒ Object
generate a SGL value stored in a byte string given a Float value
70 71 72 73 |
# 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 |
.sgl_from_text(txt, little_endian = true) ⇒ Object
generate a SGL value stored in a byte string given a decimal value formatted as text
64 65 66 67 |
# 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 |
.sgl_to_float(sgl, littel_endian = true) ⇒ Object
convert a SGL value stored in a byte string to a Float value
76 77 78 79 |
# 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 |
Instance Method Details
#*(v) ⇒ Object
1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 |
# File 'lib/float-formats/classes.rb', line 1746 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 |
#+(v) ⇒ Object
1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 |
# File 'lib/float-formats/classes.rb', line 1713 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 |
#-(v) ⇒ Object
1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 |
# File 'lib/float-formats/classes.rb', line 1735 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 |
#-@ ⇒ Object
1710 1711 1712 |
# File 'lib/float-formats/classes.rb', line 1710 def -@ minus end |
#/(v) ⇒ Object
1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 |
# File 'lib/float-formats/classes.rb', line 1724 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 |