Class: Flt::Num::ContextBase
- Defined in:
- lib/flt/num.rb,
lib/flt/complex.rb
Overview
Base class for Context classes.
Derived classes will implement Floating-Point contexts for the specific floating-point types (DecNum, BinNum)
Direct Known Subclasses
Constant Summary collapse
- CONDITION_MAP =
{ #ConversionSyntax=>InvalidOperation, #DivisionImpossible=>InvalidOperation, DivisionUndefined=>InvalidOperation, InvalidContext=>InvalidOperation }
Instance Attribute Summary collapse
-
#angle ⇒ Object
Returns the value of attribute angle.
-
#capitals ⇒ Object
Returns the value of attribute capitals.
-
#clamp ⇒ Object
Returns the value of attribute clamp.
-
#emax ⇒ Object
Returns the value of attribute emax.
-
#emin ⇒ Object
Returns the value of attribute emin.
-
#flags ⇒ Object
Returns the value of attribute flags.
-
#ignored_flags ⇒ Object
Returns the value of attribute ignored_flags.
-
#rounding ⇒ Object
Returns the value of attribute rounding.
-
#traps ⇒ Object
Returns the value of attribute traps.
Instance Method Summary collapse
-
#_coerce(x) ⇒ Object
Internally used to convert numeric types to DecNum (or to an array [sign,coefficient,exponent]).
-
#abs(x) ⇒ Object
Absolute value of a decimal number.
-
#add(x, y) ⇒ Object
Addition of two decimal numbers.
-
#assign(options) ⇒ Object
Alters the contexts by assigning options from a Hash.
-
#clamp? ⇒ Boolean
is clamping enabled?.
- #cmath(*parameters, &blk) ⇒ Object
- #coefficient(x) ⇒ Object
-
#coercible_types ⇒ Object
Internal use: array of numeric types that be coerced to DecNum.
-
#coercible_types_or_num ⇒ Object
Internal use: array of numeric types that be coerced to DecNum, including DecNum.
-
#compare(x, y) ⇒ Object
Compares like <=> but returns a DecNum value.
-
#convert_to(type, x) ⇒ Object
Convert a DecNum x to other numerical type.
-
#copy_abs(x) ⇒ Object
Returns a copy of x with the sign set to +.
-
#copy_from(other) ⇒ Object
Copy the state from other Context object.
-
#copy_negate(x) ⇒ Object
Returns a copy of x with the sign inverted.
-
#copy_sign(x, y) ⇒ Object
Returns a copy of x with the sign of y.
-
#define_conversion_from(type, &blk) ⇒ Object
Define a numerical conversion from type to DecNum.
-
#define_conversion_to(type, &blk) ⇒ Object
Define a numerical conversion from DecNum to type as an instance method of DecNum.
-
#digits ⇒ Object
synonym for precision().
-
#digits=(n) ⇒ Object
synonym for precision=().
-
#div(x, y) ⇒ Object
Ruby-style integer division: (x/y).floor.
-
#divide(x, y) ⇒ Object
Division of two decimal numbers.
-
#divide_int(x, y) ⇒ Object
General Decimal Arithmetic Specification integer division: (x/y).truncate.
-
#divmod(x, y) ⇒ Object
Ruby-style integer division and modulo: (x/y).floor, x - y*(x/y).floor.
-
#divrem(x, y) ⇒ Object
General Decimal Arithmetic Specification integer division and remainder: (x/y).truncate, x - y*(x/y).truncate.
- #dup ⇒ Object
-
#elimit=(e) ⇒ Object
Set the exponent limits, according to IEEE 754-2008 if e > 0 it is taken as emax and emin=1-emax if e < 0 it is taken as emin and emax=1-emin.
-
#epsilon(sign = +1) ⇒ Object
This is the difference between 1 and the smallest DecNum value greater than 1: (DecNum(1).next_plus - DecNum(1)).
-
#etiny ⇒ Object
‘tiny’ exponent (emin - precision + 1) is the minimum valid value for the (integral) exponent.
-
#etop ⇒ Object
top exponent (emax - precision + 1) is the maximum valid value for the (integral) exponent.
-
#eval(&blk) ⇒ Object
Evaluate a block under a context (set up the context as a local context).
-
#exact ⇒ Object
Returns true if the precision is exact.
-
#exact=(v) ⇒ Object
Enables or disables the exact precision.
-
#exact? ⇒ Boolean
Returns true if the precision is exact.
-
#exception(cond, msg = '', *params) ⇒ Object
Raises a flag (unless it is being ignores) and raises and exceptioin if the trap for it is enabled.
-
#exp(x) ⇒ Object
Exponential function: e**x.
- #exponent(x) ⇒ Object
-
#fma(x, y, z) ⇒ Object
Fused multiply-add.
-
#half_epsilon(sign = +1) ⇒ Object
This is the maximum relative error corresponding to 1/2 ulp: (radix/2)radix*(-precision) == epsilon/2 This is called “machine epsilon” in Goldberg’s “What Every Computer Scientist…”.
-
#ignore_all_flags ⇒ Object
Ignore all flags if they are raised.
-
#ignore_flags(*flags) ⇒ Object
Ignore a specified set of flags if they are raised.
- #infinite?(x) ⇒ Boolean
-
#initialize(num_class, *options) ⇒ ContextBase
constructor
If an options hash is passed, the options are applied to the default context; if a Context is passed as the first argument, it is used as the base instead of the default context.
- #inspect ⇒ Object
-
#int_div_radix_power(x, n) ⇒ Object
Divide by an integral power of the base: x/(radix**n) for x,n integer; returns an integer.
-
#int_mult_radix_power(x, n) ⇒ Object
Multiply by an integral power of the base: x*(radix**n) for x,n integer; returns an integer.
-
#int_radix_power(n) ⇒ Object
Integral power of the base: radix**n for integer n; returns an integer.
-
#ln(x) ⇒ Object
Returns the natural (base e) logarithm.
-
#log(x, base = nil) ⇒ Object
Ruby-style log function: arbitrary base logarithm which defaults to natural logarithm.
-
#log10(x) ⇒ Object
Returns the base 10 logarithm.
-
#log2(x) ⇒ Object
Returns the base 2 logarithm.
-
#logb(x) ⇒ Object
Adjusted exponent of x returned as a DecNum value.
-
#math(*parameters, &blk) ⇒ Object
Evalute a block under a context (set up the context as a local context) and inject the context methods (math and otherwise) into the block scope.
-
#maximum_coefficient ⇒ Object
Maximum integral significand value for numbers using this context’s precision.
-
#maximum_finite(sign = +1) ⇒ Object
Maximum finite number.
-
#maximum_nan_diagnostic_digits ⇒ Object
Maximum number of diagnostic digits in NaNs for numbers using this context’s precision.
-
#maximum_subnormal(sign = +1) ⇒ Object
Maximum subnormal number.
-
#minimum_nonzero(sign = +1) ⇒ Object
Minimum nonzero positive number (minimum positive subnormal).
-
#minimum_normal(sign = +1) ⇒ Object
Minimum positive normal number.
-
#minimum_normalized_coefficient ⇒ Object
Minimum value of a normalized coefficient (normalized unit).
-
#minus(x) ⇒ Object
Unary prefix minus operator.
-
#modulo(x, y) ⇒ Object
Ruby-style modulo: x - y*div(x,y).
-
#multiply(x, y) ⇒ Object
Multiplication of two decimal numbers.
- #nan?(x) ⇒ Boolean
-
#next_minus(x) ⇒ Object
Returns the largest representable number smaller than x.
-
#next_plus(x) ⇒ Object
Returns the smallest representable number larger than x.
-
#next_toward(x, y) ⇒ Object
Returns the number closest to x, in the direction towards y.
-
#normal?(x) ⇒ Boolean
Is a normal number?.
-
#normalize(x) ⇒ Object
Normalizes (changes quantum) so that the coefficient has precision digits, unless it is subnormal.
-
#normalized_integral_exponent(x) ⇒ Object
Exponent in relation to the significand as an integer normalized to precision digits.
-
#normalized_integral_significand(x) ⇒ Object
Significand normalized to precision digits x == normalized_integral_significand(x) * radix**(normalized_integral_exponent).
-
#Num(*args) ⇒ Object
Constructor for the associated numeric class.
-
#num_class ⇒ Object
This gives access to the numeric class (Flt::Num-derived) this context is for.
-
#number_class(x) ⇒ Object
Classifies a number as one of ‘sNaN’, ‘NaN’, ‘-Infinity’, ‘-Normal’, ‘-Subnormal’, ‘-Zero’, ‘+Zero’, ‘+Subnormal’, ‘+Normal’, ‘+Infinity’.
-
#plus(x) ⇒ Object
Unary prefix plus operator.
-
#power(x, y, modulo = nil) ⇒ Object
Power.
-
#prec ⇒ Object
synonym for precision().
-
#prec=(n) ⇒ Object
synonym for precision=().
-
#precision ⇒ Object
Number of digits of precision.
-
#precision=(n) ⇒ Object
Set the number of digits of precision.
-
#quantize(x, y, watch_exp = true) ⇒ Object
Quantize x so its exponent is the same as that of y.
- #radix ⇒ Object
-
#reduce(x) ⇒ Object
Reduces an operand to its simplest form by removing trailing 0s and incrementing the exponent.
-
#regard_flags(*flags) ⇒ Object
Stop ignoring a set of flags, if they are raised.
-
#remainder(x, y) ⇒ Object
General Decimal Arithmetic Specification remainder: x - y*divide_int(x,y).
-
#remainder_near(x, y) ⇒ Object
General Decimal Arithmetic Specification remainder-near x - y*round_half_even(x/y).
-
#rescale(x, exp, watch_exp = true) ⇒ Object
Rescale x so that the exponent is exp, either by padding with zeros or by truncating digits.
-
#same_quantum?(x, y) ⇒ Boolean
Return true if x and y have the same exponent.
-
#scaleb(x, y) ⇒ Object
Adds the second value to the exponent of the first: x*(radix**y).
- #sign(x) ⇒ Object
-
#split(x) ⇒ Object
Simply calls x.split; implemented to ease handling Float and BigDecimal as Nums withoug having to add methods like split to those classes.
-
#sqrt(x) ⇒ Object
Square root of a decimal number.
-
#strict_epsilon(sign = +1) ⇒ Object
The strict epsilon is the smallest value that produces something different from 1 wehen added to 1.
-
#subnormal?(x) ⇒ Boolean
Is a subnormal number?.
-
#subtract(x, y) ⇒ Object
Subtraction of two decimal numbers.
-
#to_eng_string(x) ⇒ Object
Converts a number to a string, using engineering notation.
- #to_int_scale(x) ⇒ Object
-
#to_integral_exact(x) ⇒ Object
Rounds to a nearby integer.
-
#to_integral_value(x) ⇒ Object
Rounds to a nearby integerwithout raising inexact, rounded.
-
#to_normalized_int_scale(x) ⇒ Object
Returns both the (signed) normalized integral significand and the corresponding exponent.
- #to_s ⇒ Object
-
#to_sci_string(x) ⇒ Object
Converts a number to a string, using scientific notation.
-
#to_string(x, eng = false) ⇒ Object
Converts a number to a string.
-
#ulp(x = nil, mode = :low) ⇒ Object
ulp (unit in the last place) according to the definition proposed by J.M.
- #zero?(x) ⇒ Boolean
Constructor Details
#initialize(num_class, *options) ⇒ ContextBase
If an options hash is passed, the options are applied to the default context; if a Context is passed as the first argument, it is used as the base instead of the default context.
The valid options are:
-
:rounding : one of :half_even, :half_down, :half_up, :floor, :ceiling, :down, :up, :up05
-
:precision : number of digits (or 0 for exact precision)
-
:exact : if true precision is ignored and Inexact conditions are trapped,
if :quiet it set exact precision but no trapping;
-
:traps : a Flags object with the exceptions to be trapped
-
:flags : a Flags object with the raised flags
-
:ignored_flags : a Flags object with the exceptions to be ignored
-
:emin, :emax : minimum and maximum adjusted exponents
-
:elimit : the exponent limits can also be defined by a single value; if positive it is taken as emax and emin=1-emax; otherwiae it is taken as emin and emax=1-emin. Such limits comply with IEEE 754-2008
-
:capitals : (true or false) to use capitals in text representations
-
:clamp : (true or false) enables clamping
See also the context constructor method Flt::Num.Context().
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 |
# File 'lib/flt/num.rb', line 395 def initialize(num_class, *) @num_class = num_class if .first.kind_of?(ContextBase) base = .shift copy_from base else @exact = false @rounding = @emin = @emax = nil @capitals = false @clamp = false @ignored_flags = Num::Flags() @traps = Num::Flags() @flags = Num::Flags() @coercible_type_handlers = num_class.base_coercible_types.dup @conversions = num_class.base_conversions.dup @angle = :rad # angular units: :rad (radians) / :deg (degrees) / :grad (gradians) end assign .first end |
Instance Attribute Details
#angle ⇒ Object
Returns the value of attribute angle.
480 481 482 |
# File 'lib/flt/num.rb', line 480 def angle @angle end |
#capitals ⇒ Object
Returns the value of attribute capitals.
480 481 482 |
# File 'lib/flt/num.rb', line 480 def capitals @capitals end |
#clamp ⇒ Object
Returns the value of attribute clamp.
480 481 482 |
# File 'lib/flt/num.rb', line 480 def clamp @clamp end |
#emax ⇒ Object
Returns the value of attribute emax.
480 481 482 |
# File 'lib/flt/num.rb', line 480 def emax @emax end |
#emin ⇒ Object
Returns the value of attribute emin.
480 481 482 |
# File 'lib/flt/num.rb', line 480 def emin @emin end |
#flags ⇒ Object
Returns the value of attribute flags.
480 481 482 |
# File 'lib/flt/num.rb', line 480 def flags @flags end |
#ignored_flags ⇒ Object
Returns the value of attribute ignored_flags.
480 481 482 |
# File 'lib/flt/num.rb', line 480 def ignored_flags @ignored_flags end |
#rounding ⇒ Object
Returns the value of attribute rounding.
480 481 482 |
# File 'lib/flt/num.rb', line 480 def rounding @rounding end |
#traps ⇒ Object
Returns the value of attribute traps.
480 481 482 |
# File 'lib/flt/num.rb', line 480 def traps @traps end |
Instance Method Details
#_coerce(x) ⇒ Object
Internally used to convert numeric types to DecNum (or to an array [sign,coefficient,exponent])
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 |
# File 'lib/flt/num.rb', line 1052 def _coerce(x) c = x.class while c!=Object && (h=@coercible_type_handlers[c]).nil? c = c.superclass end if h h.call(x, self) else nil end end |
#abs(x) ⇒ Object
Absolute value of a decimal number
666 667 668 |
# File 'lib/flt/num.rb', line 666 def abs(x) _convert(x).abs(self) end |
#add(x, y) ⇒ Object
Addition of two decimal numbers
646 647 648 |
# File 'lib/flt/num.rb', line 646 def add(x,y) _convert(x).add(y,self) end |
#assign(options) ⇒ Object
Alters the contexts by assigning options from a Hash. See DecNum#new() for the valid options.
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 |
# File 'lib/flt/num.rb', line 582 def assign() if @rounding = [:rounding] unless [:rounding].nil? @precision = [:precision] unless [:precision].nil? @traps = DecNum::Flags([:traps]) unless [:traps].nil? @flags = DecNum::Flags([:flags]) unless [:flags].nil? @ignored_flags = DecNum::Flags([:ignored_flags]) unless [:ignored_flags].nil? if elimit=[:elimit] @emin, @emax = [elimit, 1-elimit].sort end @emin = [:emin] unless [:emin].nil? @emax = [:emax] unless [:emax].nil? @capitals = [:capitals ] unless [:capitals ].nil? @clamp = [:clamp ] unless [:clamp ].nil? @exact = [:exact ] unless [:exact ].nil? @angle = [:angle ] unless [:angle ].nil? @precision += [:extra_precision] unless [:extra_precision].nil? update_precision end end |
#clamp? ⇒ Boolean
is clamping enabled?
546 547 548 |
# File 'lib/flt/num.rb', line 546 def clamp? @clamp end |
#cmath(*parameters, &blk) ⇒ Object
279 280 281 282 283 284 285 286 287 288 |
# File 'lib/flt/complex.rb', line 279 def cmath(*parameters, &blk) # if ComplexContext is derived from ContextBase: return ComplexContext(self).math(*parameters, &blk) num_class.context(self) do if parameters.empty? Flt.ComplexContext(num_class.context).instance_eval &blk else Flt.xiComplexContext(num_class.context).instance_exec *parameters, &blk end end end |
#coefficient(x) ⇒ Object
1102 1103 1104 |
# File 'lib/flt/num.rb', line 1102 def coefficient(x) _convert(x).coefficient end |
#coercible_types ⇒ Object
Internal use: array of numeric types that be coerced to DecNum.
1042 1043 1044 |
# File 'lib/flt/num.rb', line 1042 def coercible_types @coercible_type_handlers.keys end |
#coercible_types_or_num ⇒ Object
Internal use: array of numeric types that be coerced to DecNum, including DecNum
1047 1048 1049 |
# File 'lib/flt/num.rb', line 1047 def coercible_types_or_num [num_class] + coercible_types end |
#compare(x, y) ⇒ Object
Compares like <=> but returns a DecNum value.
-
-1 if x < y
-
0 if x == b
-
+1 if x > y
-
NaN if x or y is NaN
847 848 849 |
# File 'lib/flt/num.rb', line 847 def compare(x,y) _convert(x).compare(y, self) end |
#convert_to(type, x) ⇒ Object
Convert a DecNum x to other numerical type
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 |
# File 'lib/flt/num.rb', line 1077 def convert_to(type, x) converter = @conversions[type] if converter.nil? raise TypeError, "Undefined conversion from DecNum to #{type}." elsif converter.is_a?(Symbol) x.send converter else converter.call(x) end end |
#copy_abs(x) ⇒ Object
Returns a copy of x with the sign set to +
852 853 854 |
# File 'lib/flt/num.rb', line 852 def copy_abs(x) _convert(x).copy_abs end |
#copy_from(other) ⇒ Object
Copy the state from other Context object.
607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 |
# File 'lib/flt/num.rb', line 607 def copy_from(other) raise TypeError, "Assign #{other.num_class} context to #{self.num_class} context" if other.num_class != self.num_class @rounding = other.rounding @precision = other.precision @traps = other.traps.dup @flags = other.flags.dup @ignored_flags = other.ignored_flags.dup @emin = other.emin @emax = other.emax @capitals = other.capitals @clamp = other.clamp @exact = other.exact @coercible_type_handlers = other.coercible_type_handlers.dup @conversions = other.conversions.dup @angle = other.angle end |
#copy_negate(x) ⇒ Object
Returns a copy of x with the sign inverted
857 858 859 |
# File 'lib/flt/num.rb', line 857 def copy_negate(x) _convert(x).copy_negate end |
#copy_sign(x, y) ⇒ Object
Returns a copy of x with the sign of y
862 863 864 |
# File 'lib/flt/num.rb', line 862 def copy_sign(x,y) _convert(x).copy_sign(y) end |
#define_conversion_from(type, &blk) ⇒ Object
Define a numerical conversion from type to DecNum. The block that defines the conversion has two parameters: the value to be converted and the context and must return either a DecNum or [sign,coefficient,exponent]
1067 1068 1069 |
# File 'lib/flt/num.rb', line 1067 def define_conversion_from(type, &blk) @coercible_type_handlers[type] = blk end |
#define_conversion_to(type, &blk) ⇒ Object
Define a numerical conversion from DecNum to type as an instance method of DecNum
1072 1073 1074 |
# File 'lib/flt/num.rb', line 1072 def define_conversion_to(type, &blk) @conversions[type] = blk end |
#digits ⇒ Object
synonym for precision()
526 527 528 |
# File 'lib/flt/num.rb', line 526 def digits self.precision end |
#digits=(n) ⇒ Object
synonym for precision=()
531 532 533 |
# File 'lib/flt/num.rb', line 531 def digits=(n) self.precision=n end |
#div(x, y) ⇒ Object
Ruby-style integer division: (x/y).floor
799 800 801 |
# File 'lib/flt/num.rb', line 799 def div(x,y) _convert(x).div(y,self) end |
#divide(x, y) ⇒ Object
Division of two decimal numbers
661 662 663 |
# File 'lib/flt/num.rb', line 661 def divide(x,y) _convert(x).divide(y,self) end |
#divide_int(x, y) ⇒ Object
General Decimal Arithmetic Specification integer division: (x/y).truncate
814 815 816 |
# File 'lib/flt/num.rb', line 814 def divide_int(x,y) _convert(x).divide_int(y,self) end |
#divmod(x, y) ⇒ Object
Ruby-style integer division and modulo: (x/y).floor, x - y*(x/y).floor
809 810 811 |
# File 'lib/flt/num.rb', line 809 def divmod(x,y) _convert(x).divmod(y,self) end |
#divrem(x, y) ⇒ Object
General Decimal Arithmetic Specification integer division and remainder:
(x/y).truncate, x - y*(x/y).truncate
831 832 833 |
# File 'lib/flt/num.rb', line 831 def divrem(x,y) _convert(x).divrem(y,self) end |
#dup ⇒ Object
624 625 626 |
# File 'lib/flt/num.rb', line 624 def dup self.class.new(self) end |
#elimit=(e) ⇒ Object
Set the exponent limits, according to IEEE 754-2008 if e > 0 it is taken as emax and emin=1-emax if e < 0 it is taken as emin and emax=1-emin
521 522 523 |
# File 'lib/flt/num.rb', line 521 def elimit=(e) @emin, @emax = [e, 1-e].sort end |
#epsilon(sign = +1) ⇒ Object
This is the difference between 1 and the smallest DecNum value greater than 1: (DecNum(1).next_plus - DecNum(1))
963 964 965 966 |
# File 'lib/flt/num.rb', line 963 def epsilon(sign=+1) return exception(InvalidOperation, "Exact context epsilon") if exact? Num(sign, 1, 1-precision) end |
#etiny ⇒ Object
‘tiny’ exponent (emin - precision + 1) is the minimum valid value for the (integral) exponent
508 509 510 |
# File 'lib/flt/num.rb', line 508 def etiny emin - precision + 1 end |
#etop ⇒ Object
top exponent (emax - precision + 1) is the maximum valid value for the (integral) exponent
514 515 516 |
# File 'lib/flt/num.rb', line 514 def etop emax - precision + 1 end |
#eval(&blk) ⇒ Object
Evaluate a block under a context (set up the context as a local context)
When we have a context object we can use this instead of using the context method of the numeric class, e.g.:
DecNum.context(context) { ... }
This saves verbosity, specially when numeric class is not fixed, in which case we would have to write:
context.num_class.context(context) { ... }
With this method, we simply write:
context.eval { ... }
427 428 429 430 |
# File 'lib/flt/num.rb', line 427 def eval(&blk) # TODO: consider other names for this method; use ? apply ? local ? with ? num_class.context(self, &blk) end |
#exact ⇒ Object
Returns true if the precision is exact
572 573 574 |
# File 'lib/flt/num.rb', line 572 def exact @exact end |
#exact=(v) ⇒ Object
Enables or disables the exact precision
565 566 567 568 569 |
# File 'lib/flt/num.rb', line 565 def exact=(v) @exact = v update_precision v end |
#exact? ⇒ Boolean
Returns true if the precision is exact
577 578 579 |
# File 'lib/flt/num.rb', line 577 def exact? @exact end |
#exception(cond, msg = '', *params) ⇒ Object
Raises a flag (unless it is being ignores) and raises and exceptioin if the trap for it is enabled.
637 638 639 640 641 642 643 |
# File 'lib/flt/num.rb', line 637 def exception(cond, msg='', *params) err = (CONDITION_MAP[cond] || cond) return err.handle(self, *params) if @ignored_flags[err] @flags << err # @flags[err] = true return cond.handle(self, *params) if !@traps[err] raise err.new(*params), msg end |
#exp(x) ⇒ Object
Exponential function: e**x
696 697 698 |
# File 'lib/flt/num.rb', line 696 def exp(x) _convert(x).exp(self) end |
#exponent(x) ⇒ Object
1106 1107 1108 |
# File 'lib/flt/num.rb', line 1106 def exponent(x) _convert(x).exponent end |
#fma(x, y, z) ⇒ Object
Fused multiply-add.
Computes (x*y+z) with no rounding of the intermediate product x*y.
838 839 840 |
# File 'lib/flt/num.rb', line 838 def fma(x,y,z) _convert(x).fma(y,z,self) end |
#half_epsilon(sign = +1) ⇒ Object
This is the maximum relative error corresponding to 1/2 ulp:
(radix/2)*radix**(-precision) == epsilon/2
This is called “machine epsilon” in Goldberg’s “What Every Computer Scientist…”
997 998 999 |
# File 'lib/flt/num.rb', line 997 def half_epsilon(sign=+1) Num(sign, num_class.radix/2, -precision) end |
#ignore_all_flags ⇒ Object
Ignore all flags if they are raised
490 491 492 493 |
# File 'lib/flt/num.rb', line 490 def ignore_all_flags #@ignored_flags << EXCEPTIONS @ignored_flags.set! end |
#ignore_flags(*flags) ⇒ Object
Ignore a specified set of flags if they are raised
496 497 498 499 |
# File 'lib/flt/num.rb', line 496 def ignore_flags(*flags) #@ignored_flags << flags @ignored_flags.set(*flags) end |
#infinite?(x) ⇒ Boolean
1114 1115 1116 |
# File 'lib/flt/num.rb', line 1114 def infinite?(x) _convert(x).infinite? end |
#inspect ⇒ Object
1005 1006 1007 1008 1009 1010 |
# File 'lib/flt/num.rb', line 1005 def inspect class_name = self.class.to_s.split('::').last "<#{class_name}:\n" + instance_variables.map { |v| " #{v}: #{instance_variable_get(v).inspect}"}.join("\n") + ">\n" end |
#int_div_radix_power(x, n) ⇒ Object
Divide by an integral power of the base: x/(radix**n) for x,n integer; returns an integer.
476 477 478 |
# File 'lib/flt/num.rb', line 476 def int_div_radix_power(x,n) @num_class.int_div_radix_power(x,n) end |
#int_mult_radix_power(x, n) ⇒ Object
Multiply by an integral power of the base: x*(radix**n) for x,n integer; returns an integer.
470 471 472 |
# File 'lib/flt/num.rb', line 470 def int_mult_radix_power(x,n) @num_class.int_mult_radix_power(x,n) end |
#int_radix_power(n) ⇒ Object
Integral power of the base: radix**n for integer n; returns an integer.
464 465 466 |
# File 'lib/flt/num.rb', line 464 def int_radix_power(n) @num_class.int_radix_power(n) end |
#ln(x) ⇒ Object
Returns the natural (base e) logarithm
701 702 703 |
# File 'lib/flt/num.rb', line 701 def ln(x) _convert(x).ln(self) end |
#log(x, base = nil) ⇒ Object
Ruby-style log function: arbitrary base logarithm which defaults to natural logarithm
706 707 708 |
# File 'lib/flt/num.rb', line 706 def log(x, base=nil) _convert(x).log(base, self) end |
#log10(x) ⇒ Object
Returns the base 10 logarithm
686 687 688 |
# File 'lib/flt/num.rb', line 686 def log10(x) _convert(x).log10(self) end |
#log2(x) ⇒ Object
Returns the base 2 logarithm
691 692 693 |
# File 'lib/flt/num.rb', line 691 def log2(x) _convert(x).log10(self) end |
#logb(x) ⇒ Object
Adjusted exponent of x returned as a DecNum value.
745 746 747 |
# File 'lib/flt/num.rb', line 745 def logb(x) _convert(x).logb(self) end |
#math(*parameters, &blk) ⇒ Object
Evalute a block under a context (set up the context as a local context) and inject the context methods (math and otherwise) into the block scope.
This allows the use of regular algebraic notations for math functions, e.g. exp(x) instead of x.exp
437 438 439 440 441 442 443 444 445 446 447 |
# File 'lib/flt/num.rb', line 437 def math(*parameters, &blk) # TODO: consider renaming this to eval num_class.context(self) do if parameters.empty? num_class.context.instance_eval &blk else # needs instance_exe (available in Ruby 1.9, ActiveRecord; TODO: include implementation here) num_class.context.instance_exec *parameters, &blk end end end |
#maximum_coefficient ⇒ Object
Maximum integral significand value for numbers using this context’s precision.
1013 1014 1015 1016 1017 1018 1019 1020 |
# File 'lib/flt/num.rb', line 1013 def maximum_coefficient if exact? exception(InvalidOperation, 'Exact maximum coefficient') nil else num_class.int_radix_power(precision)-1 end end |
#maximum_finite(sign = +1) ⇒ Object
Maximum finite number
934 935 936 937 938 939 |
# File 'lib/flt/num.rb', line 934 def maximum_finite(sign=+1) return exception(InvalidOperation, "Exact context maximum finite value") if exact? # equals +Num(+1, 1, emax) # equals Num.infinity.next_minus(self) Num(sign, num_class.int_radix_power(precision)-1, etop) end |
#maximum_nan_diagnostic_digits ⇒ Object
Maximum number of diagnostic digits in NaNs for numbers using this context’s precision.
1033 1034 1035 1036 1037 1038 1039 |
# File 'lib/flt/num.rb', line 1033 def maximum_nan_diagnostic_digits if exact? nil # ? else precision - (clamp ? 1 : 0) end end |
#maximum_subnormal(sign = +1) ⇒ Object
Maximum subnormal number
949 950 951 952 953 |
# File 'lib/flt/num.rb', line 949 def maximum_subnormal(sign=+1) return exception(InvalidOperation, "Exact context maximum subnormal value") if exact? # equals mininum_normal.next_minus(self) Num(sign, num_class.int_radix_power(precision-1)-1, etiny) end |
#minimum_nonzero(sign = +1) ⇒ Object
Minimum nonzero positive number (minimum positive subnormal)
956 957 958 959 |
# File 'lib/flt/num.rb', line 956 def minimum_nonzero(sign=+1) return exception(InvalidOperation, "Exact context minimum nonzero value") if exact? Num(sign, 1, etiny) end |
#minimum_normal(sign = +1) ⇒ Object
Minimum positive normal number
942 943 944 945 946 |
# File 'lib/flt/num.rb', line 942 def minimum_normal(sign=+1) return exception(InvalidOperation, "Exact context maximum normal value") if exact? #Num(sign, 1, emin).normalize(self) Num(sign, minimum_normalized_coefficient, etiny) end |
#minimum_normalized_coefficient ⇒ Object
Minimum value of a normalized coefficient (normalized unit)
1023 1024 1025 1026 1027 1028 1029 1030 |
# File 'lib/flt/num.rb', line 1023 def minimum_normalized_coefficient if exact? exception(InvalidOperation, 'Exact maximum coefficient') nil else num_class.int_radix_power(precision-1) end end |
#minus(x) ⇒ Object
Unary prefix minus operator
676 677 678 |
# File 'lib/flt/num.rb', line 676 def minus(x) _convert(x)._neg(self) end |
#modulo(x, y) ⇒ Object
Ruby-style modulo: x - y*div(x,y)
804 805 806 |
# File 'lib/flt/num.rb', line 804 def modulo(x,y) _convert(x).modulo(y,self) end |
#multiply(x, y) ⇒ Object
Multiplication of two decimal numbers
656 657 658 |
# File 'lib/flt/num.rb', line 656 def multiply(x,y) _convert(x).multiply(y,self) end |
#nan?(x) ⇒ Boolean
1110 1111 1112 |
# File 'lib/flt/num.rb', line 1110 def nan?(x) _convert(x).nan? end |
#next_minus(x) ⇒ Object
Returns the largest representable number smaller than x.
904 905 906 |
# File 'lib/flt/num.rb', line 904 def next_minus(x) _convert(x).next_minus(self) end |
#next_plus(x) ⇒ Object
Returns the smallest representable number larger than x.
909 910 911 |
# File 'lib/flt/num.rb', line 909 def next_plus(x) _convert(x).next_plus(self) end |
#next_toward(x, y) ⇒ Object
Returns the number closest to x, in the direction towards y.
The result is the closest representable number to x (excluding x) that is in the direction towards y, unless both have the same value. If the two operands are numerically equal, then the result is a copy of x with the sign set to be the same as the sign of y.
920 921 922 |
# File 'lib/flt/num.rb', line 920 def next_toward(x, y) _convert(x).next_toward(y, self) end |
#normal?(x) ⇒ Boolean
Is a normal number?
777 778 779 |
# File 'lib/flt/num.rb', line 777 def normal?(x) _convert(x).normal?(self) end |
#normalize(x) ⇒ Object
Normalizes (changes quantum) so that the coefficient has precision digits, unless it is subnormal. For surnormal numbers the Subnormal flag is raised an a subnormal is returned with the smallest possible exponent.
This is different from reduce GDAS function which was formerly called normalize, and corresponds to the classic meaning of floating-point normalization.
Note that the number is also rounded (precision is reduced) if it had more precision than the context.
740 741 742 |
# File 'lib/flt/num.rb', line 740 def normalize(x) _convert(x).normalize(self) end |
#normalized_integral_exponent(x) ⇒ Object
Exponent in relation to the significand as an integer normalized to precision digits. (minimum exponent)
758 759 760 761 |
# File 'lib/flt/num.rb', line 758 def normalized_integral_exponent(x) x = _convert(x) x.exponent - (precision - x.number_of_digits) end |
#normalized_integral_significand(x) ⇒ Object
Significand normalized to precision digits x == normalized_integral_significand(x) * radix**(normalized_integral_exponent)
765 766 767 768 |
# File 'lib/flt/num.rb', line 765 def normalized_integral_significand(x) x = _convert(x) x.coefficient*(num_class.int_radix_power(precision - x.number_of_digits)) end |
#Num(*args) ⇒ Object
Constructor for the associated numeric class
455 456 457 |
# File 'lib/flt/num.rb', line 455 def Num(*args) num_class.Num(*args) end |
#num_class ⇒ Object
This gives access to the numeric class (Flt::Num-derived) this context is for.
450 451 452 |
# File 'lib/flt/num.rb', line 450 def num_class @num_class end |
#number_class(x) ⇒ Object
Classifies a number as one of ‘sNaN’, ‘NaN’, ‘-Infinity’, ‘-Normal’, ‘-Subnormal’, ‘-Zero’,
'+Zero', '+Subnormal', '+Normal', '+Infinity'
789 790 791 |
# File 'lib/flt/num.rb', line 789 def number_class(x) _convert(x).number_class(self) end |
#plus(x) ⇒ Object
Unary prefix plus operator
671 672 673 |
# File 'lib/flt/num.rb', line 671 def plus(x) _convert(x).plus(self) end |
#power(x, y, modulo = nil) ⇒ Object
Power. See DecNum#power()
681 682 683 |
# File 'lib/flt/num.rb', line 681 def power(x,y,modulo=nil) _convert(x).power(y,modulo,self) end |
#prec ⇒ Object
synonym for precision()
536 537 538 |
# File 'lib/flt/num.rb', line 536 def prec self.precision end |
#prec=(n) ⇒ Object
synonym for precision=()
541 542 543 |
# File 'lib/flt/num.rb', line 541 def prec=(n) self.precision = n end |
#precision ⇒ Object
Number of digits of precision
560 561 562 |
# File 'lib/flt/num.rb', line 560 def precision @precision end |
#precision=(n) ⇒ Object
Set the number of digits of precision. If 0 is set the precision turns to be exact.
552 553 554 555 556 557 |
# File 'lib/flt/num.rb', line 552 def precision=(n) @precision = n @exact = false unless n==0 update_precision n end |
#quantize(x, y, watch_exp = true) ⇒ Object
Quantize x so its exponent is the same as that of y.
873 874 875 |
# File 'lib/flt/num.rb', line 873 def quantize(x, y, watch_exp=true) _convert(x).quantize(y, self, watch_exp) end |
#radix ⇒ Object
459 460 461 |
# File 'lib/flt/num.rb', line 459 def radix @num_class.radix end |
#reduce(x) ⇒ Object
Reduces an operand to its simplest form by removing trailing 0s and incrementing the exponent. (formerly called normalize in GDAS)
728 729 730 |
# File 'lib/flt/num.rb', line 728 def reduce(x) _convert(x).reduce(self) end |
#regard_flags(*flags) ⇒ Object
Stop ignoring a set of flags, if they are raised
502 503 504 |
# File 'lib/flt/num.rb', line 502 def regard_flags(*flags) @ignored_flags.clear(*flags) end |
#remainder(x, y) ⇒ Object
General Decimal Arithmetic Specification remainder: x - y*divide_int(x,y)
819 820 821 |
# File 'lib/flt/num.rb', line 819 def remainder(x,y) _convert(x).remainder(y,self) end |
#remainder_near(x, y) ⇒ Object
General Decimal Arithmetic Specification remainder-near
x - y*round_half_even(x/y)
825 826 827 |
# File 'lib/flt/num.rb', line 825 def remainder_near(x,y) _convert(x).remainder_near(y,self) end |
#rescale(x, exp, watch_exp = true) ⇒ Object
Rescale x so that the exponent is exp, either by padding with zeros or by truncating digits.
868 869 870 |
# File 'lib/flt/num.rb', line 868 def rescale(x, exp, watch_exp=true) _convert(x).rescale(exp, self, watch_exp) end |
#same_quantum?(x, y) ⇒ Boolean
Return true if x and y have the same exponent.
If either operand is a special value, the following rules are used:
-
return true if both operands are infinities
-
return true if both operands are NaNs
-
otherwise, return false.
883 884 885 |
# File 'lib/flt/num.rb', line 883 def same_quantum?(x,y) _convert(x).same_quantum?(y) end |
#scaleb(x, y) ⇒ Object
Adds the second value to the exponent of the first: x*(radix**y)
y must be an integer
752 753 754 |
# File 'lib/flt/num.rb', line 752 def scaleb(x, y) _convert(x).scaleb(y,self) end |
#sign(x) ⇒ Object
1098 1099 1100 |
# File 'lib/flt/num.rb', line 1098 def sign(x) _convert(x).sign end |
#split(x) ⇒ Object
Simply calls x.split; implemented to ease handling Float and BigDecimal as Nums withoug having to add methods like split to those classes.
1090 1091 1092 |
# File 'lib/flt/num.rb', line 1090 def split(x) _convert(x).split end |
#sqrt(x) ⇒ Object
Square root of a decimal number
794 795 796 |
# File 'lib/flt/num.rb', line 794 def sqrt(x) _convert(x).sqrt(self) end |
#strict_epsilon(sign = +1) ⇒ Object
The strict epsilon is the smallest value that produces something different from 1 wehen added to 1. It may be smaller than the general epsilon, because of the particular rounding rules used.
971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 |
# File 'lib/flt/num.rb', line 971 def strict_epsilon(sign=+1) return exception(InvalidOperation, "Exact context strict epsilon") if exact? # assume radix is even (num_class.radix%2 == 0) case rounding when :down, :floor # largest epsilon: 0.0...10 (precision digits shown to the right of the decimal point) exp = 1-precision coeff = 1 when :half_even, :half_down # next largest: 0.0...050...1 (+precision-1 additional digits here) exp = 1-2*precision coeff = 1 + num_class.int_radix_power(precision)/2 when :half_up # next largest: 0.0...05 (precision digits shown to the right of the decimal point) exp = 1-2*precision coeff = num_class.int_radix_power(precision)/2 when :up, :ceiling, :up05 # smallest epsilon return minimum_nonzero(sign) end return Num(sign, coeff, exp) end |
#subnormal?(x) ⇒ Boolean
Is a subnormal number?
782 783 784 |
# File 'lib/flt/num.rb', line 782 def subnormal?(x) _convert(x).subnormal?(self) end |
#subtract(x, y) ⇒ Object
Subtraction of two decimal numbers
651 652 653 |
# File 'lib/flt/num.rb', line 651 def subtract(x,y) _convert(x).subtract(y,self) end |
#to_eng_string(x) ⇒ Object
Converts a number to a string, using engineering notation
721 722 723 |
# File 'lib/flt/num.rb', line 721 def to_eng_string(x) to_string x, true end |
#to_int_scale(x) ⇒ Object
1094 1095 1096 |
# File 'lib/flt/num.rb', line 1094 def to_int_scale(x) _convert(x).to_int_scale end |
#to_integral_exact(x) ⇒ Object
Rounds to a nearby integer.
See also: DecNum#to_integral_value(), which does exactly the same as this method except that it doesn’t raise Inexact or Rounded.
891 892 893 |
# File 'lib/flt/num.rb', line 891 def to_integral_exact(x) _convert(x).to_integral_exact(self) end |
#to_integral_value(x) ⇒ Object
Rounds to a nearby integerwithout raising inexact, rounded.
See also: DecNum#to_integral_exact(), which does exactly the same as this method except that it may raise Inexact or Rounded.
899 900 901 |
# File 'lib/flt/num.rb', line 899 def to_integral_value(x) _convert(x).to_integral_value(self) end |
#to_normalized_int_scale(x) ⇒ Object
Returns both the (signed) normalized integral significand and the corresponding exponent
771 772 773 774 |
# File 'lib/flt/num.rb', line 771 def to_normalized_int_scale(x) x = _convert(x) [x.sign*normalized_integral_significand(x), normalized_integral_exponent(x)] end |
#to_s ⇒ Object
1001 1002 1003 |
# File 'lib/flt/num.rb', line 1001 def to_s inspect end |
#to_sci_string(x) ⇒ Object
Converts a number to a string, using scientific notation
716 717 718 |
# File 'lib/flt/num.rb', line 716 def to_sci_string(x) to_string x, false end |
#to_string(x, eng = false) ⇒ Object
Converts a number to a string
711 712 713 |
# File 'lib/flt/num.rb', line 711 def to_string(x, eng=false) _convert(x)._fix(self).to_s(eng, self) end |
#ulp(x = nil, mode = :low) ⇒ Object
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
926 927 928 929 |
# File 'lib/flt/num.rb', line 926 def ulp(x=nil, mode=:low) x ||= 1 _convert(x).ulp(self, mode) end |
#zero?(x) ⇒ Boolean
1118 1119 1120 |
# File 'lib/flt/num.rb', line 1118 def zero?(x) _convert(x).zero? end |