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
-
#infinity(sign = +1) ⇒ Object
A floating-point infinite number with the specified sign.
-
#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 ⇒ Object
A floating-point NaN (not a number).
- #nan?(x) ⇒ Boolean
-
#necessary_digits(b) ⇒ Object
Mininum number of base b digits necessary to store any context floating point number while being able to convert the digits back to the same exact context floating point number.
-
#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’.
-
#one_half ⇒ Object
One half: 1/2.
-
#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
-
#rationalize(x, tol = nil) ⇒ Object
Approximate conversion to Rational within given tolerance.
-
#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).
-
#representable_digits(b) ⇒ Object
Maximum number of base b digits that can be stored in a context floating point number and then preserved when converted back to base b.
-
#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_r(x) ⇒ Object
Exact conversion to Rational.
- #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(sign = +1) ⇒ Object
A floating-point number with value zero and the specified sign.
- #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().
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 |
# File 'lib/flt/num.rb', line 428 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.
513 514 515 |
# File 'lib/flt/num.rb', line 513 def angle @angle end |
#capitals ⇒ Object
Returns the value of attribute capitals.
513 514 515 |
# File 'lib/flt/num.rb', line 513 def capitals @capitals end |
#clamp ⇒ Object
Returns the value of attribute clamp.
513 514 515 |
# File 'lib/flt/num.rb', line 513 def clamp @clamp end |
#emax ⇒ Object
Returns the value of attribute emax.
513 514 515 |
# File 'lib/flt/num.rb', line 513 def emax @emax end |
#emin ⇒ Object
Returns the value of attribute emin.
513 514 515 |
# File 'lib/flt/num.rb', line 513 def emin @emin end |
#flags ⇒ Object
Returns the value of attribute flags.
513 514 515 |
# File 'lib/flt/num.rb', line 513 def flags @flags end |
#ignored_flags ⇒ Object
Returns the value of attribute ignored_flags.
513 514 515 |
# File 'lib/flt/num.rb', line 513 def ignored_flags @ignored_flags end |
#rounding ⇒ Object
Returns the value of attribute rounding.
513 514 515 |
# File 'lib/flt/num.rb', line 513 def rounding @rounding end |
#traps ⇒ Object
Returns the value of attribute traps.
513 514 515 |
# File 'lib/flt/num.rb', line 513 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])
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 |
# File 'lib/flt/num.rb', line 1088 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
702 703 704 |
# File 'lib/flt/num.rb', line 702 def abs(x) _convert(x).abs(self) end |
#add(x, y) ⇒ Object
Addition of two decimal numbers
682 683 684 |
# File 'lib/flt/num.rb', line 682 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.
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 |
# File 'lib/flt/num.rb', line 615 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? update_precision if [:extra_precision] && !@exact @precision += [:extra_precision] end end self end |
#clamp? ⇒ Boolean
is clamping enabled?
579 580 581 |
# File 'lib/flt/num.rb', line 579 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
1138 1139 1140 |
# File 'lib/flt/num.rb', line 1138 def coefficient(x) _convert(x).coefficient end |
#coercible_types ⇒ Object
Internal use: array of numeric types that be coerced to DecNum.
1078 1079 1080 |
# File 'lib/flt/num.rb', line 1078 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
1083 1084 1085 |
# File 'lib/flt/num.rb', line 1083 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
883 884 885 |
# File 'lib/flt/num.rb', line 883 def compare(x,y) _convert(x).compare(y, self) end |
#convert_to(type, x) ⇒ Object
Convert a DecNum x to other numerical type
1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 |
# File 'lib/flt/num.rb', line 1113 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 +
888 889 890 |
# File 'lib/flt/num.rb', line 888 def copy_abs(x) _convert(x).copy_abs end |
#copy_from(other) ⇒ Object
Copy the state from other Context object.
643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 |
# File 'lib/flt/num.rb', line 643 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
893 894 895 |
# File 'lib/flt/num.rb', line 893 def copy_negate(x) _convert(x).copy_negate end |
#copy_sign(x, y) ⇒ Object
Returns a copy of x with the sign of y
898 899 900 |
# File 'lib/flt/num.rb', line 898 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]
1103 1104 1105 |
# File 'lib/flt/num.rb', line 1103 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
1108 1109 1110 |
# File 'lib/flt/num.rb', line 1108 def define_conversion_to(type, &blk) @conversions[type] = blk end |
#digits ⇒ Object
synonym for precision()
559 560 561 |
# File 'lib/flt/num.rb', line 559 def digits self.precision end |
#digits=(n) ⇒ Object
synonym for precision=()
564 565 566 |
# File 'lib/flt/num.rb', line 564 def digits=(n) self.precision=n end |
#div(x, y) ⇒ Object
Ruby-style integer division: (x/y).floor
835 836 837 |
# File 'lib/flt/num.rb', line 835 def div(x,y) _convert(x).div(y,self) end |
#divide(x, y) ⇒ Object
Division of two decimal numbers
697 698 699 |
# File 'lib/flt/num.rb', line 697 def divide(x,y) _convert(x).divide(y,self) end |
#divide_int(x, y) ⇒ Object
General Decimal Arithmetic Specification integer division: (x/y).truncate
850 851 852 |
# File 'lib/flt/num.rb', line 850 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
845 846 847 |
# File 'lib/flt/num.rb', line 845 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
867 868 869 |
# File 'lib/flt/num.rb', line 867 def divrem(x,y) _convert(x).divrem(y,self) end |
#dup ⇒ Object
660 661 662 |
# File 'lib/flt/num.rb', line 660 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
554 555 556 |
# File 'lib/flt/num.rb', line 554 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))
999 1000 1001 1002 |
# File 'lib/flt/num.rb', line 999 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
541 542 543 |
# File 'lib/flt/num.rb', line 541 def etiny emin - precision + 1 end |
#etop ⇒ Object
top exponent (emax - precision + 1) is the maximum valid value for the (integral) exponent
547 548 549 |
# File 'lib/flt/num.rb', line 547 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 { ... }
460 461 462 463 |
# File 'lib/flt/num.rb', line 460 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
605 606 607 |
# File 'lib/flt/num.rb', line 605 def exact @exact end |
#exact=(v) ⇒ Object
Enables or disables the exact precision
598 599 600 601 602 |
# File 'lib/flt/num.rb', line 598 def exact=(v) @exact = v update_precision v end |
#exact? ⇒ Boolean
Returns true if the precision is exact
610 611 612 |
# File 'lib/flt/num.rb', line 610 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.
673 674 675 676 677 678 679 |
# File 'lib/flt/num.rb', line 673 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
732 733 734 |
# File 'lib/flt/num.rb', line 732 def exp(x) _convert(x).exp(self) end |
#exponent(x) ⇒ Object
1142 1143 1144 |
# File 'lib/flt/num.rb', line 1142 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.
874 875 876 |
# File 'lib/flt/num.rb', line 874 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…”
1033 1034 1035 |
# File 'lib/flt/num.rb', line 1033 def half_epsilon(sign=+1) Num(sign, num_class.radix/2, -precision) end |
#ignore_all_flags ⇒ Object
Ignore all flags if they are raised
523 524 525 526 |
# File 'lib/flt/num.rb', line 523 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
529 530 531 532 |
# File 'lib/flt/num.rb', line 529 def ignore_flags(*flags) #@ignored_flags << flags @ignored_flags.set(*flags) end |
#infinite?(x) ⇒ Boolean
1150 1151 1152 |
# File 'lib/flt/num.rb', line 1150 def infinite?(x) _convert(x).infinite? end |
#infinity(sign = +1) ⇒ Object
A floating-point infinite number with the specified sign
1194 1195 1196 |
# File 'lib/flt/num.rb', line 1194 def infinity(sign = +1) num_class.infinity(sign) end |
#inspect ⇒ Object
1041 1042 1043 1044 1045 1046 |
# File 'lib/flt/num.rb', line 1041 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.
509 510 511 |
# File 'lib/flt/num.rb', line 509 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.
503 504 505 |
# File 'lib/flt/num.rb', line 503 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.
497 498 499 |
# File 'lib/flt/num.rb', line 497 def int_radix_power(n) @num_class.int_radix_power(n) end |
#ln(x) ⇒ Object
Returns the natural (base e) logarithm
737 738 739 |
# File 'lib/flt/num.rb', line 737 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
742 743 744 |
# File 'lib/flt/num.rb', line 742 def log(x, base=nil) _convert(x).log(base, self) end |
#log10(x) ⇒ Object
Returns the base 10 logarithm
722 723 724 |
# File 'lib/flt/num.rb', line 722 def log10(x) _convert(x).log10(self) end |
#log2(x) ⇒ Object
Returns the base 2 logarithm
727 728 729 |
# File 'lib/flt/num.rb', line 727 def log2(x) _convert(x).log10(self) end |
#logb(x) ⇒ Object
Adjusted exponent of x returned as a DecNum value.
781 782 783 |
# File 'lib/flt/num.rb', line 781 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
470 471 472 473 474 475 476 477 478 479 480 |
# File 'lib/flt/num.rb', line 470 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.
1049 1050 1051 1052 1053 1054 1055 1056 |
# File 'lib/flt/num.rb', line 1049 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
970 971 972 973 974 975 |
# File 'lib/flt/num.rb', line 970 def maximum_finite(sign=+1) return exception(InvalidOperation, "Exact context maximum finite value") if exact? # equals Num(+1, 1, emax+1) - Num(+1, 1, etop) # 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.
1069 1070 1071 1072 1073 1074 1075 |
# File 'lib/flt/num.rb', line 1069 def maximum_nan_diagnostic_digits if exact? nil # ? else precision - (clamp ? 1 : 0) end end |
#maximum_subnormal(sign = +1) ⇒ Object
Maximum subnormal number
985 986 987 988 989 |
# File 'lib/flt/num.rb', line 985 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)
992 993 994 995 |
# File 'lib/flt/num.rb', line 992 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
978 979 980 981 982 |
# File 'lib/flt/num.rb', line 978 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)
1059 1060 1061 1062 1063 1064 1065 1066 |
# File 'lib/flt/num.rb', line 1059 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
712 713 714 |
# File 'lib/flt/num.rb', line 712 def minus(x) _convert(x)._neg(self) end |
#modulo(x, y) ⇒ Object
Ruby-style modulo: x - y*div(x,y)
840 841 842 |
# File 'lib/flt/num.rb', line 840 def modulo(x,y) _convert(x).modulo(y,self) end |
#multiply(x, y) ⇒ Object
Multiplication of two decimal numbers
692 693 694 |
# File 'lib/flt/num.rb', line 692 def multiply(x,y) _convert(x).multiply(y,self) end |
#nan ⇒ Object
A floating-point NaN (not a number)
1199 1200 1201 |
# File 'lib/flt/num.rb', line 1199 def nan num_class.nan end |
#nan?(x) ⇒ Boolean
1146 1147 1148 |
# File 'lib/flt/num.rb', line 1146 def nan?(x) _convert(x).nan? end |
#necessary_digits(b) ⇒ Object
Mininum number of base b digits necessary to store any context floating point number while being able to convert the digits back to the same exact context floating point number
To convert any floating point number to base b and be able to round the result back to the same floating point number, at least this many base b digits are needed.
1178 1179 1180 1181 1182 1183 1184 1185 1186 |
# File 'lib/flt/num.rb', line 1178 def necessary_digits(b) unless exact? if b == radix precision else (precision*log(radix, b)).ceil + 1 end end end |
#next_minus(x) ⇒ Object
Returns the largest representable number smaller than x.
940 941 942 |
# File 'lib/flt/num.rb', line 940 def next_minus(x) _convert(x).next_minus(self) end |
#next_plus(x) ⇒ Object
Returns the smallest representable number larger than x.
945 946 947 |
# File 'lib/flt/num.rb', line 945 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.
956 957 958 |
# File 'lib/flt/num.rb', line 956 def next_toward(x, y) _convert(x).next_toward(y, self) end |
#normal?(x) ⇒ Boolean
Is a normal number?
813 814 815 |
# File 'lib/flt/num.rb', line 813 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.
776 777 778 |
# File 'lib/flt/num.rb', line 776 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)
794 795 796 797 |
# File 'lib/flt/num.rb', line 794 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)
801 802 803 804 |
# File 'lib/flt/num.rb', line 801 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
488 489 490 |
# File 'lib/flt/num.rb', line 488 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.
483 484 485 |
# File 'lib/flt/num.rb', line 483 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'
825 826 827 |
# File 'lib/flt/num.rb', line 825 def number_class(x) _convert(x).number_class(self) end |
#one_half ⇒ Object
One half: 1/2
1204 1205 1206 |
# File 'lib/flt/num.rb', line 1204 def one_half num_class.one_half end |
#plus(x) ⇒ Object
Unary prefix plus operator
707 708 709 |
# File 'lib/flt/num.rb', line 707 def plus(x) _convert(x).plus(self) end |
#power(x, y, modulo = nil) ⇒ Object
Power. See DecNum#power()
717 718 719 |
# File 'lib/flt/num.rb', line 717 def power(x,y,modulo=nil) _convert(x).power(y,modulo,self) end |
#prec ⇒ Object
synonym for precision()
569 570 571 |
# File 'lib/flt/num.rb', line 569 def prec self.precision end |
#prec=(n) ⇒ Object
synonym for precision=()
574 575 576 |
# File 'lib/flt/num.rb', line 574 def prec=(n) self.precision = n end |
#precision ⇒ Object
Number of digits of precision
593 594 595 |
# File 'lib/flt/num.rb', line 593 def precision @precision end |
#precision=(n) ⇒ Object
Set the number of digits of precision. If 0 is set the precision turns to be exact.
585 586 587 588 589 590 |
# File 'lib/flt/num.rb', line 585 def precision=(n) @precision = n @exact = false update_precision n end |
#quantize(x, y, watch_exp = true) ⇒ Object
Quantize x so its exponent is the same as that of y.
909 910 911 |
# File 'lib/flt/num.rb', line 909 def quantize(x, y, watch_exp=true) _convert(x).quantize(y, self, watch_exp) end |
#radix ⇒ Object
492 493 494 |
# File 'lib/flt/num.rb', line 492 def radix @num_class.radix end |
#rationalize(x, tol = nil) ⇒ Object
Approximate conversion to Rational within given tolerance
1214 1215 1216 |
# File 'lib/flt/num.rb', line 1214 def rationalize(x, tol = nil) x.rationalize(tol) end |
#reduce(x) ⇒ Object
Reduces an operand to its simplest form by removing trailing 0s and incrementing the exponent. (formerly called normalize in GDAS)
764 765 766 |
# File 'lib/flt/num.rb', line 764 def reduce(x) _convert(x).reduce(self) end |
#regard_flags(*flags) ⇒ Object
Stop ignoring a set of flags, if they are raised
535 536 537 |
# File 'lib/flt/num.rb', line 535 def regard_flags(*flags) @ignored_flags.clear(*flags) end |
#remainder(x, y) ⇒ Object
General Decimal Arithmetic Specification remainder: x - y*divide_int(x,y)
855 856 857 |
# File 'lib/flt/num.rb', line 855 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)
861 862 863 |
# File 'lib/flt/num.rb', line 861 def remainder_near(x,y) _convert(x).remainder_near(y,self) end |
#representable_digits(b) ⇒ Object
Maximum number of base b digits that can be stored in a context floating point number and then preserved when converted back to base b.
To store a base b number in a floating point number and be able to get then back exactly the number cannot have more than these significant digits.
1163 1164 1165 1166 1167 1168 1169 1170 1171 |
# File 'lib/flt/num.rb', line 1163 def representable_digits(b) unless exact? if b == radix precision else ((precision-1)*log(radix, b)).floor end end 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.
904 905 906 |
# File 'lib/flt/num.rb', line 904 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.
919 920 921 |
# File 'lib/flt/num.rb', line 919 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
788 789 790 |
# File 'lib/flt/num.rb', line 788 def scaleb(x, y) _convert(x).scaleb(y,self) end |
#sign(x) ⇒ Object
1134 1135 1136 |
# File 'lib/flt/num.rb', line 1134 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.
1126 1127 1128 |
# File 'lib/flt/num.rb', line 1126 def split(x) _convert(x).split end |
#sqrt(x) ⇒ Object
Square root of a decimal number
830 831 832 |
# File 'lib/flt/num.rb', line 830 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.
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 |
# File 'lib/flt/num.rb', line 1007 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?
818 819 820 |
# File 'lib/flt/num.rb', line 818 def subnormal?(x) _convert(x).subnormal?(self) end |
#subtract(x, y) ⇒ Object
Subtraction of two decimal numbers
687 688 689 |
# File 'lib/flt/num.rb', line 687 def subtract(x,y) _convert(x).subtract(y,self) end |
#to_eng_string(x) ⇒ Object
Converts a number to a string, using engineering notation
757 758 759 |
# File 'lib/flt/num.rb', line 757 def to_eng_string(x) to_string x, true end |
#to_int_scale(x) ⇒ Object
1130 1131 1132 |
# File 'lib/flt/num.rb', line 1130 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.
927 928 929 |
# File 'lib/flt/num.rb', line 927 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.
935 936 937 |
# File 'lib/flt/num.rb', line 935 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
807 808 809 810 |
# File 'lib/flt/num.rb', line 807 def to_normalized_int_scale(x) x = _convert(x) [x.sign*normalized_integral_significand(x), normalized_integral_exponent(x)] end |
#to_r(x) ⇒ Object
Exact conversion to Rational
1209 1210 1211 |
# File 'lib/flt/num.rb', line 1209 def to_r(x) x.to_r end |
#to_s ⇒ Object
1037 1038 1039 |
# File 'lib/flt/num.rb', line 1037 def to_s inspect end |
#to_sci_string(x) ⇒ Object
Converts a number to a string, using scientific notation
752 753 754 |
# File 'lib/flt/num.rb', line 752 def to_sci_string(x) to_string x, false end |
#to_string(x, eng = false) ⇒ Object
Converts a number to a string
747 748 749 |
# File 'lib/flt/num.rb', line 747 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
962 963 964 965 |
# File 'lib/flt/num.rb', line 962 def ulp(x=nil, mode=:low) x ||= 1 _convert(x).ulp(self, mode) end |
#zero(sign = +1) ⇒ Object
A floating-point number with value zero and the specified sign
1189 1190 1191 |
# File 'lib/flt/num.rb', line 1189 def zero(sign = +1) num_class.zero(sign) end |
#zero?(x) ⇒ Boolean
1154 1155 1156 |
# File 'lib/flt/num.rb', line 1154 def zero?(x) _convert(x).zero? end |