class Flt::FormatBase
General Floating Point Format Base class
Attributes
define format properties:
radix
-
Numeric base
significand_digits
-
Number of digits in the significand (precision)
hidden_bit
-
Has the format a hidden bit?
parameters
-
Parameters used to define the class
define format properties:
radix
-
Numeric base
significand_digits
-
Number of digits in the significand (precision)
hidden_bit
-
Has the format a hidden bit?
parameters
-
Parameters used to define the class
define format properties:
radix
-
Numeric base
significand_digits
-
Number of digits in the significand (precision)
hidden_bit
-
Has the format a hidden bit?
parameters
-
Parameters used to define the class
Public Class Methods
Exponent bias for excess notation exponent encoding The argument defines the interpretation of the significand and so determines the actual bias value.
# File lib/float-formats/classes.rb, line 647 def self.bias(significand_mode = :scientific_significand) case significand_mode when :integral_significand @integral_bias when :fractional_significand @fractional_bias when :scientific_significand @scientific_bias end end
# File lib/float-formats/classes.rb, line 658 def self.canonicalized(s,m,e,normalize=nil) #puts "s=#{s} m=#{m} e=#{e}" #return [s,m,e] normalize = @normalized if normalize.nil? min_exp = radix_min_exp(:integral_significand) e = min_exp if e==:denormal if m.kind_of?(Integer) && m>0 && e.kind_of?(Integer) while e<min_exp e += 1 m /= radix # TODO: round end end s,m,e = normalized(s,m,e) if normalize if m==0 && e.kind_of?(Integer) e=:zero end #puts " -> s=#{s} m=#{m} e=#{e}" [s,m,e] end
# File lib/float-formats/classes.rb, line 581 def self.context num_class::Context.new( precision: significand_digits, emin: radix_min_exp(:scientific_significand), emax: radix_max_exp(:scientific_significand), rounding: @round || :half_even, normalized: @normalized ) end
number of decimal digits necessary to unambiguosly define any floating point value
# File lib/float-formats/classes.rb, line 502 def self.decimal_digits_necessary (significand_digits*radix_log10).ceil+1 end
number of decimal digits that can be stored in a floating point value and restored unaltered
# File lib/float-formats/classes.rb, line 498 def self.decimal_digits_stored ((significand_digits-1)*radix_log10).floor end
Maximum integer such that 10 raised to that power is in the range of the normalised floating point numbers
# File lib/float-formats/classes.rb, line 508 def self.decimal_max_exp (radix_max_exp(:fractional_significand)*radix_log10+(1-radix_power(-significand_digits))*radix_log10).floor #(Math.log((1-radix**(significand_digits))*radix**radix_max_exp(:fractional_significand))/Math.log(10)).floor end
Minimum negative integer such that 10 raised to that power is in the range of the normalised floating point numbers
# File lib/float-formats/classes.rb, line 514 def self.decimal_min_exp (radix_min_exp(:fractional_significand)*radix_log10).ceil end
Common parameters for all floating-point formats:
:bias_mode
-
This defines how the significand is interpreted:
-
:fractional_significand
The radix point is before the most significant digit of the significand (including a hidden bit if there's one). -
:scientific_significand
The radix point is after the most significant digit of the significand (including a hidden bit if there's one). -
:integral_significand
The significand is assumed to be an integer, i.e. the radix point is after the least significant digit.
:bias
-
Defines the exponent encoding method to be excess notation and defines the bias.
:endianness
-
Defines the byte endianness. One of:
-
:little_endian
Least significant bytes come first. (Intel etc.) -
:big_endian
(Network order): most significant bytes come first. (Motorola, SPARC,…) -
:little_big_endian
(Middle endian) Each pair of bytes (16-bit word) has the bytes in little endian order, but the words are stored in big endian order (we assume the number of bytes is even). (PDP-11).
# File lib/float-formats/classes.rb, line 357 def self.define(params={}) @parameters = params @normalized = params[:normalized] @normalized = true if @normalized.nil? @fields_handler = params[:fields_handler] @exponent_radix = params[:exponent_radix] || radix @zero_encoded_exp = params[:zero_encoded_exp] || 0 @min_encoded_exp = params[:min_encoded_exp] || 0 @denormal_encoded_exp = params[:denormal_encoded_exp] @gradual_underflow = params[:gradual_underflow] || (@denormal_encoded_exp ? true : false) if @gradual_underflow @denormal_encoded_exp = 0 if !@denormal_encoded_exp if @denormal_encoded_exp>=@min_encoded_exp @min_encoded_exp = @denormal_encoded_exp # originally, we incremented min_encoded_exp here unconditionally, but # now we don't if there's no hidden bit # (we assume the minimum exponent can be used for normalized and denormalized numbers) # because of this, IEEE_EXTENDED & 128 formats now specify min_encoded_exp: 1 in it's definitions @min_encoded_exp += 1 if @hidden_bit end end # Note that if there's a hidden bit and no gradual underflow, the minimum encoded exponent will only # be used for zero unless a parameter :min_encoded_exp (=0) is passed. In this case all numbers with # minimun exponent and nonzero encoded significand will have a 1-valued hidden bit. Otherwise # the only valid encoded significand with minimun encoded exponent is 0. # In case of gradual underflow, the minimum exponent implies a hidden bit value of 0 @min_encoded_exp += 1 if @min_encoded_exp==@zero_encoded_exp && (@hidden_bit && params[:min_encoded_exp].nil?) @infinite_encoded_exp = params[:infinite_encoded_exp] @nan_encoded_exp = params[:nan_encoded_exp] @infinity = params[:infinity] || (@infinite_encoded_exp ? true : false) @max_encoded_exp = params[:max_encoded_exp] || @exponent_radix**@fields[:exponent]-1 # maximum regular exponent, encoded if @infinity @infinite_encoded_exp = @nan_encoded_exp || @max_encoded_exp if !@infinite_encoded_exp @max_encoded_exp = @infinite_encoded_exp - 1 if @infinite_encoded_exp.kind_of?(Integer) && @infinite_encoded_exp<=@max_encoded_exp end @nan = params[:nan] || (@nan_encoded_exp ? true : false) if @nan @nan_encoded_exp = @infinite_encoded_exp || @max_encoded_exp if !@nan_encoded_exp @max_encoded_exp = @nan_encoded_exp - 1 if @nan_encoded_exp.kind_of?(Integer) && @nan_encoded_exp<=@max_encoded_exp end @exponent_mode = params[:exponent_mode] if @exponent_mode.nil? if params[:bias] @exponent_mode = :excess else @exponent_mode = :radix_complement end end @exponent_digits = @fields[:exponent] if @exponent_mode==:excess @bias = params[:bias] || (@exponent_radix**(@fields[:exponent]-1)-1) @bias_mode = params[:bias_mode] || :scientific_significand @min_exp = params[:min_exp] @max_exp = params[:max_exp] case @bias_mode when :integral_significand @integral_bias = @bias @fractional_bias = @integral_bias-@significand_digits @scientific_bias = @fractional_bias+1 when :fractional_significand @fractional_bias = @bias @integral_bias = @fractional_bias+@significand_digits @scientific_bias = @fractional_bias+1 @min_exp -= @significand_digits if @min_exp @max_exp -= @significand_digits if @max_exp when :scientific_significand @scientific_bias = @bias @fractional_bias = @scientific_bias-1 @integral_bias = @fractional_bias+@significand_digits @min_exp -= @significand_digits-1 if @min_exp @max_exp -= @significand_digits-1 if @max_exp end else #@bias_mode = :scientific_significand @min_exp = params[:min_exp] || (-(@exponent_radix**@exponent_digits)/2 + 1) @max_exp = params[:max_exp] || ((@exponent_radix**@exponent_digits)/2 - 1) end @endianness = params[:endianness] || :little_endian @min_exp = @min_encoded_exp - @integral_bias if @min_exp.nil? @max_exp = @max_encoded_exp - @integral_bias if @max_exp.nil? if @exponent_mode==:excess @integral_max_exp = @max_exp @integral_min_exp = @min_exp @fractional_max_exp = @max_exp+@significand_digits @fractional_min_exp = @min_exp+@significand_digits @scientific_max_exp = @max_exp+@significand_digits-1 @scientific_min_exp = @min_exp+@significand_digits-1 else @integral_max_exp = @max_exp - (@significand_digits-1) @integral_min_exp = @min_exp - (@significand_digits-1) @fractional_max_exp = @max_exp+1 @fractional_min_exp = @min_exp+1 @scientific_max_exp = @max_exp @scientific_min_exp = @min_exp end @round = params[:round] # || :half_even @neg_mode = params[:neg_mode] || :sign_magnitude yield self if block_given? end
Endianness of the format (:little_endian, :big_endian or :little_big_endian)
# File lib/float-formats/classes.rb, line 635 def self.endianness @endianness end
This is the difference between 1.0 and the smallest floating-point value greater than 1.0, radix_power
(1-significand_precision)
# File lib/float-formats/classes.rb, line 751 def self.epsilon(sign=+1) s = sign #m = 1 #e = 1-significand_digits m = minimum_normalized_integral_significand e = 2*(1-significand_digits) return_value s,m,e, false end
from methods
# File lib/float-formats/classes.rb, line 827 def self.from(*args) new(*args) end
Defines a floating-point number from the encoded integral value.
# File lib/float-formats/classes.rb, line 867 def self.from_bits(i) v = Bytes.from_i(i) if v.size<total_bytes fill = (0.chr*(total_bytes-v.size)) if @endianness==:little_endian v << fill else v = Bytes.new(fill) + bytes end elsif v.size>total_bytes raise "Invalid floating point value" end from_bytes v end
Defines a floating-point number from a text representation of the encoded integral value in a given base. Returns a Value.
# File lib/float-formats/classes.rb, line 885 def self.from_bits_text(txt, base) i = Numerals::Format[].read(txt, type: Integer, base: base) from_bits i end
# File lib/float-formats/classes.rb, line 831 def self.from_bytes(b) return_value(*unpack(b)) end
# File lib/float-formats/classes.rb, line 835 def self.from_hex(hex) from_bytes Bytes.from_hex(hex) end
# File lib/float-formats/classes.rb, line 839 def self.from_number(v, mode = :approx) if v.is_a?(Flt::Num) && v.num_class.radix==self.radix self.num(v) else options = { type: self, exact_input: (mode != :approx), output_mode: @normalized ? :fixed : :short } Numerals::Conversions.convert(v, options) end end
# File lib/float-formats/classes.rb, line 852 def self.from_text(txt, *args) if @normalized fmt = Numerals::Format[exact_input: true] else fmt = Numerals::Format[:short, exact_input: false] end fmt = fmt[*args] fmt.read(txt, type: self) end
Does the format support gradual underflow? (denormalized numbers)
# File lib/float-formats/classes.rb, line 640 def self.gradual_underflow? @gradual_underflow end
This is the maximum relative error corresponding to 1/2 ulp:
(radix/2)*radix_power(-significand_precision) == epsilon/2
This is called “machine epsilon” in [Goldberg] TODO: use Flt::Num
# File lib/float-formats/classes.rb, line 794 def self.half_epsilon(sign=+1) s = sign m = radix/2 e = -significand_digits # normalize: m *= minimum_normalized_integral_significand e -= significand_digits-1 return_value s,m,e, false end
Floating point representation of infinity.
# File lib/float-formats/classes.rb, line 809 def self.infinity(sign=+1) if @infinite_encoded_exp return_value sign, 0, :infinity else nil end end
# File lib/float-formats/classes.rb, line 862 def self.join(sign,significand,exponent) self.new sign,significand,exponent end
Greatest finite normalized floating point number in the representation. It can be made negative by passing the sign (a so this would be the smallest finite number).
# File lib/float-formats/classes.rb, line 721 def self.max_value(sign=+1) s = sign m = maximum_integral_significand e = radix_max_exp(:integral_significand) return_value s,m,e, false end
# File lib/float-formats/classes.rb, line 546 def self.maximum_integral_significand radix_power(significand_digits)-1 end
Smallest normalized floating point number greater than zero in the representation. It can be made negative by passing the sign.
# File lib/float-formats/classes.rb, line 729 def self.min_normalized_value(sign=+1) s = sign m = minimum_normalized_integral_significand e = radix_min_exp(:integral_significand) m += 1 if @hidden_bit && (@min_encoded_exp==@zero_encoded_exp) return_value s,m,e, true end
Smallest floating point number greater than zero in the representation, including denormalized values if the representation supports it. It can be made negative by passing the sign.
# File lib/float-formats/classes.rb, line 739 def self.min_value(sign=+1) if @denormal_encoded_exp s = sign m = 1 e = :denormal return_value s,m,e, false else min_normalized_value(sign) end end
# File lib/float-formats/classes.rb, line 543 def self.minimum_normalized_integral_significand radix_power(significand_digits-1) end
Stored (integral) value for the minus sign
# File lib/float-formats/classes.rb, line 518 def self.minus_sign_value (-1) % radix end
Floating point representation of Not-a-Number.
# File lib/float-formats/classes.rb, line 817 def self.nan if @nan_encoded_exp return_value(+1, 0, :nan) else nil end end
# File lib/float-formats/classes.rb, line 50 def initialize(*args) if (args.size == 3 || args.size==4 || args.size==2) && (args.first.kind_of?(Integer) && args[1].kind_of?(Integer)) sign,significand,exponent,normalize = args if normalize.nil? if [nil,true,false].include?(exponent) normalize = exponent exponent = significand significand = sign.abs sign = sign<0 ? -1 : +1 end end @sign,@significand,@exponent = self.class.canonicalized(sign,significand,exponent,normalize) else v = form_class.nan case args.first when form_class v = args.first raise "Too many arguments for FormatBase constructor" if args.size>1 when Array v = args.first raise "Too many arguments for FormatBase constructor" if args.size>1 when FormatBase v = args.first.convert_to(form_class) raise "Too many arguments for FormatBase constructor" if args.size>1 when String v = form_class.from_text(*args) when Bytes v = form_class.from_bytes(*args) when Bits v = form_class.from_bits(*args) when Numeric v = form_class.from_number(args.first) raise "Too many arguments for FormatBase constructor" if args.size>1 when Symbol if args.first.to_s[0..3]!='from' args = ["from_#{args.first}".to_sym] + args[1..-1] end v = form_class.send(*args) end @sign,@significand,@exponent = v.to_a end end
# File lib/float-formats/classes.rb, line 480 def self.normalized? @normalized end
def to_num
# num_class = Flt::Num[form_class.radix] num_class = self.class.num_class case @exponent when :zero num_class.zero(@sign) when :infinity num_class.infinity(@sign) when :nan num_class.nan else num_class.new(@sign, @significand, @exponent) end
end
# File lib/float-formats/classes.rb, line 619 def self.num(x) s, c, e = x.split if x.zero? e = :zero else case e when :inf e = :infinity when :nan e = :nan end end new([s, c, e]) end
# File lib/float-formats/classes.rb, line 573 def self.num_class Num[self.radix] end
# File lib/float-formats/classes.rb, line 577 def self.numerals_conversion(options = {}) FltFmtConversion.new(self, options) end
Produce an encoded floating point value using hash of the internal field values. Returns a Value.
# File lib/float-formats/classes.rb, line 922 def self.pack_fields_hash(h) if @splitted_fields.nil? pack_fields @field_meaning.collect{|f| h[f]} else flds = [nil]*@field_meaning.size @fields.each_key do |f| splits = @splitted_fields[f] if splits v = h[f] splits.each do |i| k = fields_radix**(@field_lengths[i]) flds[i] = v % k v /= k end else flds[@field_meaning.index(f)] = h[f] end end pack_fields flds end end
radix-base logarithm
# File lib/float-formats/classes.rb, line 494 def self.radix_log(x) Math.log(x)/Math.log(radix) end
base-10 logarithm of the radix
# File lib/float-formats/classes.rb, line 490 def self.radix_log10 Math.log(radix)/Math.log(10) end
Maximum exponent
# File lib/float-formats/classes.rb, line 551 def self.radix_max_exp(significand_mode = :scientific_significand) case significand_mode when :integral_significand @integral_max_exp when :fractional_significand @fractional_max_exp when :scientific_significand @scientific_max_exp end end
Mminimum exponent
# File lib/float-formats/classes.rb, line 562 def self.radix_min_exp(significand_mode = :scientific_significand) case significand_mode when :integral_significand @integral_min_exp when :fractional_significand @fractional_min_exp when :scientific_significand @scientific_min_exp end end
compute a power of the radix (base)
# File lib/float-formats/classes.rb, line 485 def self.radix_power(n) radix**n end
Rounding mode use for this floating-point format; can be one of:
:half_even
-
round to nearest with ties toward an even digits
:half_up
-
round to nearest with ties toward infinity (away from zero)
:half_down
-
round to nearest with ties toward zero
nil
-
rounding mode not specified
# File lib/float-formats/classes.rb, line 539 def self.rounding_mode @round end
# File lib/float-formats/classes.rb, line 530 def self.sign_from_unit(u) u<0 ? minus_sign_value : 0 end
# File lib/float-formats/classes.rb, line 526 def self.sign_to_unit(s) s==0 ? +1 : -1 # ((-1)**s) end
The strict epsilon is the smallest value that produces something different from 1.0 wehen added to 1.0. It may be smaller than the general epsilon, because of the particular rounding rules used with the floating point format. This is only meaningful when well-defined rules are used for rounding the result of floating-point addition. Note that (in pseudo-code):
((1.0+strict_epsilon)-1.0)==epsilon
TODO: use Flt::Num
# File lib/float-formats/classes.rb, line 767 def self.strict_epsilon(sign=+1, round=nil) round ||= @round s = sign m = minimum_normalized_integral_significand e = 2*(1-significand_digits) # assume radix is even case @round when :down, :floor, :any_rounding, nil e = 2*(1-significand_digits) m = minimum_normalized_integral_significand when :half_even, :half_down e = 1-2*significand_digits m = 1 + radix_power(significand_digits)/2 when :half_up e = 1-2*significand_digits m = radix_power(significand_digits)/2 when :ceiling, :up, :up05 return min_value end return_value sign,m,e end
switch between the encodings of minus and plus
# File lib/float-formats/classes.rb, line 522 def self.switch_sign_value(v) (v==0) ? minus_sign_value : 0 end
Converts en ancoded floating point number to hash containing the internal fields that define the number. Accepts either a Value or a byte String.
# File lib/float-formats/classes.rb, line 893 def self.unpack_fields_hash(v) a = unpack_fields(v) h = {} if @splitted_fields.nil? (0...a.size).each do |i| h[@field_meaning[i]] = a[i] end else @fields.each_key do |f| splits = @splitted_fields[f] if splits v = 0 k = 1 splits.each do |i| v += k*a[i] k *= fields_radix**(@field_lengths[i]) end h[f] = v else h[f] = a[@field_meaning.index(f)] end end end h end
Floating point representation of zero.
# File lib/float-formats/classes.rb, line 805 def self.zero(sign=+1) return_value sign, 0, :zero end
Protected Class Methods
# File lib/float-formats/classes.rb, line 705 def self.input_bytes(v) if v.kind_of?(FormatBase) raise "Invalid f.p. format" if v.fp_format!=self v = v.to_bytes elsif !v.kind_of?(Bytes) v = Bytes.new(v) end v end
# File lib/float-formats/classes.rb, line 683 def self.normalized(s,m,e) if m.kind_of?(Integer) && e.kind_of?(Integer) min_exp = radix_min_exp(:integral_significand) if m>0 while m<minimum_normalized_integral_significand && e>min_exp e -= 1 m *= radix end if @normalized && !@gradual_underflow if e<=min_exp && m<minimum_normalized_integral_significand m = 0 e = :zero end end end end [s,m,e] end
# File lib/float-formats/classes.rb, line 702 def self.return_value(s,m,e,normalize=nil) self.new s,m,e,normalize end
Public Instance Methods
# File lib/float-formats/classes.rb, line 284 def <=>(other) return 1 if nan? || other.nan? return 0 if zero? && other.zero? this_sign,this_significand,this_exponent = split other_sign, other_significand, other_exponent = other.split return -1 if other_sign < this_sign return 1 if other_sign > this_sign return 0 if infinite? && other.infinite? if this_sign<0 this_significand,other_significand = other_significand,this_significand this_exponent,other_exponent = other_exponent,this_exponent end if this_exponent==other_exponent return this_significand <=> other_significand else mns = form_class.minimum_normalized_integral_significand this_normal = this_significand >= mns other_normal = other_significand >= mns if this_normal && other_normal return this_exponent <=> other_exponent else min_exp = form_class.radix_min_exp(:integral_significand) max_exp = form_class.radix_max_exp(:integral_significand) while this_significand<mns && this_exponent>min_exp this_exponent -= 1 this_significand *= form_class.radix end while other_significand<mns && other_exponent>min_exp other_exponent -= 1 other_significand *= form_class.radix end if this_exponent==other_exponent return this_significand <=> other_significand else return this_exponent <=> other_exponent end end end end
Converts a floating point value to another format
# File lib/float-formats/classes.rb, line 192 def convert_to(fpclass, options = {}) Numerals::Conversions.convert(self, options.merge(type: fpclass)) end
# File lib/float-formats/classes.rb, line 336 def form_class self.class end
todo hash cononicalizing first
# File lib/float-formats/classes.rb, line 333 def fp_format form_class end
# File lib/float-formats/classes.rb, line 112 def infinite? return @exponent==:infinity end
Computes the negation of a floating point value (unary minus)
# File lib/float-formats/classes.rb, line 187 def minus form_class.new(-@sign,@significand,@exponent) end
# File lib/float-formats/classes.rb, line 104 def nan? @exponent == :nan end
Computes the previous adjacent floating point value. Accepts either a Value or a byte String. Returns a Value.
# File lib/float-formats/classes.rb, line 236 def next_minus s,f,e = self.class.canonicalized(@sign,@significand,@exponent,true) return minus.next_plus.minus if s<0 return self.next_plus.minus if e==:zero if e!=:nan if e == :infinity f = form_class.maximum_integral_significand e = form_class.radix_max_exp(:integral_significand) else f -= 1 if f<form_class.minimum_normalized_integral_significand if e!=:denormal && e>form_class.radix_min_exp(:integral_significand) e -= 1 f *= form_class.radix else if form_class.gradual_underflow? e = :denormal else e = :zero end end end end end form_class.new s, f, e end
Computes the next adjacent floating point value. Accepts either a Value or a byte String. Returns a Value. TODO: use Flt
# File lib/float-formats/classes.rb, line 200 def next_plus s,f,e = self.class.canonicalized(@sign,@significand,@exponent,true) return minus.next_minus.minus if s<0 && e!=:zero s = -s if e==:zero && s<0 if e!=:nan && e!=:infinity if f==0 if form_class.gradual_underflow? e = form_class.radix_min_exp(:integral_significand) f = 1 else e = form_class.radix_min_exp(:integral_significand) f = form_class.minimum_normalized_integral_significand end else f += 1 end if f>=form_class.radix_power(form_class.significand_digits) f /= form_class.radix if e==:denormal e = form_class.radix_min_exp(:integral_significand) else e += 1 end if e>form_class.radix_max_exp(:integral_significand) e = :infinity f = 0 end end form_class.new s, f, e end end
# File lib/float-formats/classes.rb, line 120 def normal? @exponend.kind_of?(Integer) && @significand>=self.class.minimum_normalized_integral_significand end
# File lib/float-formats/classes.rb, line 100 def split return [@sign,@significand,@exponent] end
# File lib/float-formats/classes.rb, line 116 def subnormal? return @exponent==:denormal || (@significand.kind_of?(Integer) && @significand<self.class.minimum_normalized_integral_significand) end
# File lib/float-formats/classes.rb, line 143 def to(number_class, mode = :approx) if number_class == Bytes to_bytes elsif number_class == String mode = Numerals::Format[] if mode == :approx to_text(mode) elsif Numerals::Format === number_class to_text(number_class) elsif number_class == Array split elsif Symbol === number_class send "to_#{number_class}" elsif number_class.is_a?(Flt::Num) && number_class.radix == form_class.radix self.to_num elsif number_class.is_a?(FormatBase) number_class.from_number(self, mode) else # assume number_class.ancestors.include?(Numeric) (number_class < Numeric) options = { type: number_class, exact_input: (mode != :approx), output_mode: :fixed } Numerals::Conversions.convert(self, options) end end
# File lib/float-formats/classes.rb, line 96 def to_a split end
# File lib/float-formats/classes.rb, line 168 def to_bits to_bytes.to_bits(form_class.endianness,false,form_class.total_bits) end
Returns the encoded integral value of a floating point number as a text representation in a given base. Accepts either a Value or a byte String.
# File lib/float-formats/classes.rb, line 174 def to_bits_text(base) to_bits.to_s(base) #i = to_bits #fmt = Numerals::Format[base: base] #if [2,4,8,16].include?(base) # n = (Math.log(base)/Math.log(2)).round.to_i # digits = (form_class.total_bits+n-1)/n # fmt.set_trailing_zeros!(digits) #end #fmt.writ(i.to_i) end
# File lib/float-formats/classes.rb, line 133 def to_bytes form_class.pack(@sign,@significand,@exponent) end
# File lib/float-formats/classes.rb, line 136 def to_hex(sep_bytes=false) if (form_class.total_bits % 8)==0 to_bytes.to_hex(sep_bytes) else to_bits.to_hex end end
# File lib/float-formats/classes.rb, line 591 def to_num s, c, e = split case e when :zero e = 0 when :infinity e = :inf when :nan e = :nan end form_class.num_class.Num(s, c, e) end
from/to integral_sign_significand_exponent
# File lib/float-formats/classes.rb, line 126 def to_text(fmt = Numerals::Format[]) if infinite? fmt = fmt[symbols: [show_plus: true]] end fmt.write(self) end
ulp (unit in the last place) according to the definition proposed by J.M. Muller in “On the definition of ulp(x)” INRIA No. 5504
# File lib/float-formats/classes.rb, line 265 def ulp sign,sig,exp = @sign,@significand,@exponent mnexp = form_class.radix_min_exp(:integral_significand) mxexp = form_class.radix_max_exp(:integral_significand) prec = form_class.significand_digits if exp==:nan elsif exp==:infinity sign,sig,exp = 1,1,mxexp elsif exp==:zero || exp <= mnexp return form_class.min_value else exp -= 1 if sig==form_class.minimum_normalized_integral_significand sign,sig,exp = 1,1,exp end form_class.new sign, sig, exp end
# File lib/float-formats/classes.rb, line 108 def zero? return @exponent==:zero || @significand==0 end