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.
-
#normalized ⇒ Object
Returns the value of attribute normalized.
-
#rounding ⇒ Object
Returns the value of attribute rounding.
-
#traps ⇒ Object
Returns the value of attribute traps.
Instance Method Summary collapse
-
#[](options = {}) ⇒ Object
Create a context as a copy of the current one with some options changed.
-
#_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? ⇒ Boolean
-
#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
- #special?(x) ⇒ Boolean
-
#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; otherwise 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
-
:normalized : (true or false) normalizes all results
See also the context constructor method Flt::Num.Context().
427 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 427 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) @normalized = false end assign .first end |
Instance Attribute Details
#angle ⇒ Object
Returns the value of attribute angle.
519 520 521 |
# File 'lib/flt/num.rb', line 519 def angle @angle end |
#capitals ⇒ Object
Returns the value of attribute capitals.
519 520 521 |
# File 'lib/flt/num.rb', line 519 def capitals @capitals end |
#clamp ⇒ Object
Returns the value of attribute clamp.
519 520 521 |
# File 'lib/flt/num.rb', line 519 def clamp @clamp end |
#emax ⇒ Object
Returns the value of attribute emax.
519 520 521 |
# File 'lib/flt/num.rb', line 519 def emax @emax end |
#emin ⇒ Object
Returns the value of attribute emin.
519 520 521 |
# File 'lib/flt/num.rb', line 519 def emin @emin end |
#flags ⇒ Object
Returns the value of attribute flags.
519 520 521 |
# File 'lib/flt/num.rb', line 519 def flags @flags end |
#ignored_flags ⇒ Object
Returns the value of attribute ignored_flags.
519 520 521 |
# File 'lib/flt/num.rb', line 519 def ignored_flags @ignored_flags end |
#normalized ⇒ Object
Returns the value of attribute normalized.
519 520 521 |
# File 'lib/flt/num.rb', line 519 def normalized @normalized end |
#rounding ⇒ Object
Returns the value of attribute rounding.
519 520 521 |
# File 'lib/flt/num.rb', line 519 def rounding @rounding end |
#traps ⇒ Object
Returns the value of attribute traps.
519 520 521 |
# File 'lib/flt/num.rb', line 519 def traps @traps end |
Instance Method Details
#[](options = {}) ⇒ Object
Create a context as a copy of the current one with some options changed.
678 679 680 |
# File 'lib/flt/num.rb', line 678 def [](={}) self.class.new self, end |
#_coerce(x) ⇒ Object
Internally used to convert numeric types to DecNum (or to an array [sign,coefficient,exponent])
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 |
# File 'lib/flt/num.rb', line 1106 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
720 721 722 |
# File 'lib/flt/num.rb', line 720 def abs(x) _convert(x).abs(self) end |
#add(x, y) ⇒ Object
Addition of two decimal numbers
700 701 702 |
# File 'lib/flt/num.rb', line 700 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.
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 |
# File 'lib/flt/num.rb', line 625 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? @normalized = [:normalized] unless [:normalized].nil? update_precision if [:extra_precision] && !@exact @precision += [:extra_precision] end end self end |
#clamp? ⇒ Boolean
is clamping enabled?
589 590 591 |
# File 'lib/flt/num.rb', line 589 def clamp? @clamp end |
#cmath(*parameters, &blk) ⇒ Object
280 281 282 283 284 285 286 287 288 289 |
# File 'lib/flt/complex.rb', line 280 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
1156 1157 1158 |
# File 'lib/flt/num.rb', line 1156 def coefficient(x) _convert(x).coefficient end |
#coercible_types ⇒ Object
Internal use: array of numeric types that be coerced to DecNum.
1096 1097 1098 |
# File 'lib/flt/num.rb', line 1096 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
1101 1102 1103 |
# File 'lib/flt/num.rb', line 1101 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
901 902 903 |
# File 'lib/flt/num.rb', line 901 def compare(x,y) _convert(x).compare(y, self) end |
#convert_to(type, x) ⇒ Object
Convert a DecNum x to other numerical type
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 |
# File 'lib/flt/num.rb', line 1131 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 +
906 907 908 |
# File 'lib/flt/num.rb', line 906 def copy_abs(x) _convert(x).copy_abs end |
#copy_from(other) ⇒ Object
Copy the state from other Context object.
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 |
# File 'lib/flt/num.rb', line 654 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 @normalized = other.normalized end |
#copy_negate(x) ⇒ Object
Returns a copy of x with the sign inverted
911 912 913 |
# File 'lib/flt/num.rb', line 911 def copy_negate(x) _convert(x).copy_negate end |
#copy_sign(x, y) ⇒ Object
Returns a copy of x with the sign of y
916 917 918 |
# File 'lib/flt/num.rb', line 916 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]
1121 1122 1123 |
# File 'lib/flt/num.rb', line 1121 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
1126 1127 1128 |
# File 'lib/flt/num.rb', line 1126 def define_conversion_to(type, &blk) @conversions[type] = blk end |
#digits ⇒ Object
synonym for precision()
569 570 571 |
# File 'lib/flt/num.rb', line 569 def digits self.precision end |
#digits=(n) ⇒ Object
synonym for precision=()
574 575 576 |
# File 'lib/flt/num.rb', line 574 def digits=(n) self.precision=n end |
#div(x, y) ⇒ Object
Ruby-style integer division: (x/y).floor
853 854 855 |
# File 'lib/flt/num.rb', line 853 def div(x,y) _convert(x).div(y,self) end |
#divide(x, y) ⇒ Object
Division of two decimal numbers
715 716 717 |
# File 'lib/flt/num.rb', line 715 def divide(x,y) _convert(x).divide(y,self) end |
#divide_int(x, y) ⇒ Object
General Decimal Arithmetic Specification integer division: (x/y).truncate
868 869 870 |
# File 'lib/flt/num.rb', line 868 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
863 864 865 |
# File 'lib/flt/num.rb', line 863 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
885 886 887 |
# File 'lib/flt/num.rb', line 885 def divrem(x,y) _convert(x).divrem(y,self) end |
#dup ⇒ Object
672 673 674 |
# File 'lib/flt/num.rb', line 672 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
564 565 566 |
# File 'lib/flt/num.rb', line 564 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))
1017 1018 1019 1020 |
# File 'lib/flt/num.rb', line 1017 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
551 552 553 |
# File 'lib/flt/num.rb', line 551 def etiny emin - precision + 1 end |
#etop ⇒ Object
top exponent (emax - precision + 1) is the maximum valid value for the (integral) exponent
557 558 559 |
# File 'lib/flt/num.rb', line 557 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
615 616 617 |
# File 'lib/flt/num.rb', line 615 def exact @exact end |
#exact=(v) ⇒ Object
Enables or disables the exact precision
608 609 610 611 612 |
# File 'lib/flt/num.rb', line 608 def exact=(v) @exact = v update_precision v end |
#exact? ⇒ Boolean
Returns true if the precision is exact
620 621 622 |
# File 'lib/flt/num.rb', line 620 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.
691 692 693 694 695 696 697 |
# File 'lib/flt/num.rb', line 691 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
750 751 752 |
# File 'lib/flt/num.rb', line 750 def exp(x) _convert(x).exp(self) end |
#exponent(x) ⇒ Object
1160 1161 1162 |
# File 'lib/flt/num.rb', line 1160 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.
892 893 894 |
# File 'lib/flt/num.rb', line 892 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…”
1051 1052 1053 |
# File 'lib/flt/num.rb', line 1051 def half_epsilon(sign=+1) Num(sign, num_class.radix/2, -precision) end |
#ignore_all_flags ⇒ Object
Ignore all flags if they are raised
533 534 535 536 |
# File 'lib/flt/num.rb', line 533 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
539 540 541 542 |
# File 'lib/flt/num.rb', line 539 def ignore_flags(*flags) #@ignored_flags << flags @ignored_flags.set(*flags) end |
#infinite?(x) ⇒ Boolean
1168 1169 1170 |
# File 'lib/flt/num.rb', line 1168 def infinite?(x) _convert(x).infinite? end |
#infinity(sign = +1) ⇒ Object
A floating-point infinite number with the specified sign
1216 1217 1218 |
# File 'lib/flt/num.rb', line 1216 def infinity(sign = +1) num_class.infinity(sign) end |
#inspect ⇒ Object
1059 1060 1061 1062 1063 1064 |
# File 'lib/flt/num.rb', line 1059 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.
515 516 517 |
# File 'lib/flt/num.rb', line 515 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.
509 510 511 |
# File 'lib/flt/num.rb', line 509 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.
503 504 505 |
# File 'lib/flt/num.rb', line 503 def int_radix_power(n) @num_class.int_radix_power(n) end |
#ln(x) ⇒ Object
Returns the natural (base e) logarithm
755 756 757 |
# File 'lib/flt/num.rb', line 755 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
760 761 762 |
# File 'lib/flt/num.rb', line 760 def log(x, base=nil) _convert(x).log(base, self) end |
#log10(x) ⇒ Object
Returns the base 10 logarithm
740 741 742 |
# File 'lib/flt/num.rb', line 740 def log10(x) _convert(x).log10(self) end |
#log2(x) ⇒ Object
Returns the base 2 logarithm
745 746 747 |
# File 'lib/flt/num.rb', line 745 def log2(x) _convert(x).log10(self) end |
#logb(x) ⇒ Object
Adjusted exponent of x returned as a DecNum value.
799 800 801 |
# File 'lib/flt/num.rb', line 799 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.
1067 1068 1069 1070 1071 1072 1073 1074 |
# File 'lib/flt/num.rb', line 1067 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
988 989 990 991 992 993 |
# File 'lib/flt/num.rb', line 988 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.
1087 1088 1089 1090 1091 1092 1093 |
# File 'lib/flt/num.rb', line 1087 def maximum_nan_diagnostic_digits if exact? nil # ? else precision - (clamp ? 1 : 0) end end |
#maximum_subnormal(sign = +1) ⇒ Object
Maximum subnormal number
1003 1004 1005 1006 1007 |
# File 'lib/flt/num.rb', line 1003 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)
1010 1011 1012 1013 |
# File 'lib/flt/num.rb', line 1010 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
996 997 998 999 1000 |
# File 'lib/flt/num.rb', line 996 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)
1077 1078 1079 1080 1081 1082 1083 1084 |
# File 'lib/flt/num.rb', line 1077 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
730 731 732 |
# File 'lib/flt/num.rb', line 730 def minus(x) _convert(x)._neg(self) end |
#modulo(x, y) ⇒ Object
Ruby-style modulo: x - y*div(x,y)
858 859 860 |
# File 'lib/flt/num.rb', line 858 def modulo(x,y) _convert(x).modulo(y,self) end |
#multiply(x, y) ⇒ Object
Multiplication of two decimal numbers
710 711 712 |
# File 'lib/flt/num.rb', line 710 def multiply(x,y) _convert(x).multiply(y,self) end |
#nan ⇒ Object
A floating-point NaN (not a number)
1221 1222 1223 |
# File 'lib/flt/num.rb', line 1221 def nan num_class.nan end |
#nan?(x) ⇒ Boolean
1164 1165 1166 |
# File 'lib/flt/num.rb', line 1164 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.
1200 1201 1202 1203 1204 1205 1206 1207 1208 |
# File 'lib/flt/num.rb', line 1200 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.
958 959 960 |
# File 'lib/flt/num.rb', line 958 def next_minus(x) _convert(x).next_minus(self) end |
#next_plus(x) ⇒ Object
Returns the smallest representable number larger than x.
963 964 965 |
# File 'lib/flt/num.rb', line 963 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.
974 975 976 |
# File 'lib/flt/num.rb', line 974 def next_toward(x, y) _convert(x).next_toward(y, self) end |
#normal?(x) ⇒ Boolean
Is a normal number?
831 832 833 |
# File 'lib/flt/num.rb', line 831 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.
794 795 796 |
# File 'lib/flt/num.rb', line 794 def normalize(x) _convert(x).normalize(self) end |
#normalized? ⇒ Boolean
521 522 523 |
# File 'lib/flt/num.rb', line 521 def normalized? normalized end |
#normalized_integral_exponent(x) ⇒ Object
Exponent in relation to the significand as an integer normalized to precision digits. (minimum exponent)
812 813 814 815 |
# File 'lib/flt/num.rb', line 812 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)
819 820 821 822 |
# File 'lib/flt/num.rb', line 819 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 491 492 493 494 495 496 |
# File 'lib/flt/num.rb', line 488 def Num(*args) context = { context: self } if args.last.kind_of?(Hash) args = args[0...-1] + [ context.merge(args.last) ] else args << context end 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'
843 844 845 |
# File 'lib/flt/num.rb', line 843 def number_class(x) _convert(x).number_class(self) end |
#one_half ⇒ Object
One half: 1/2
1226 1227 1228 |
# File 'lib/flt/num.rb', line 1226 def one_half num_class.one_half end |
#plus(x) ⇒ Object
Unary prefix plus operator
725 726 727 |
# File 'lib/flt/num.rb', line 725 def plus(x) _convert(x).plus(self) end |
#power(x, y, modulo = nil) ⇒ Object
Power. See DecNum#power()
735 736 737 |
# File 'lib/flt/num.rb', line 735 def power(x,y,modulo=nil) _convert(x).power(y,modulo,self) end |
#prec ⇒ Object
synonym for precision()
579 580 581 |
# File 'lib/flt/num.rb', line 579 def prec self.precision end |
#prec=(n) ⇒ Object
synonym for precision=()
584 585 586 |
# File 'lib/flt/num.rb', line 584 def prec=(n) self.precision = n end |
#precision ⇒ Object
Number of digits of precision
603 604 605 |
# File 'lib/flt/num.rb', line 603 def precision @precision end |
#precision=(n) ⇒ Object
Set the number of digits of precision. If 0 is set the precision turns to be exact.
595 596 597 598 599 600 |
# File 'lib/flt/num.rb', line 595 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.
927 928 929 |
# File 'lib/flt/num.rb', line 927 def quantize(x, y, watch_exp=true) _convert(x).quantize(y, self, watch_exp) end |
#radix ⇒ Object
498 499 500 |
# File 'lib/flt/num.rb', line 498 def radix @num_class.radix end |
#rationalize(x, tol = nil) ⇒ Object
Approximate conversion to Rational within given tolerance
1236 1237 1238 |
# File 'lib/flt/num.rb', line 1236 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)
782 783 784 |
# File 'lib/flt/num.rb', line 782 def reduce(x) _convert(x).reduce(self) end |
#regard_flags(*flags) ⇒ Object
Stop ignoring a set of flags, if they are raised
545 546 547 |
# File 'lib/flt/num.rb', line 545 def regard_flags(*flags) @ignored_flags.clear(*flags) end |
#remainder(x, y) ⇒ Object
General Decimal Arithmetic Specification remainder: x - y*divide_int(x,y)
873 874 875 |
# File 'lib/flt/num.rb', line 873 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)
879 880 881 |
# File 'lib/flt/num.rb', line 879 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.
1185 1186 1187 1188 1189 1190 1191 1192 1193 |
# File 'lib/flt/num.rb', line 1185 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.
922 923 924 |
# File 'lib/flt/num.rb', line 922 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.
937 938 939 |
# File 'lib/flt/num.rb', line 937 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
806 807 808 |
# File 'lib/flt/num.rb', line 806 def scaleb(x, y) _convert(x).scaleb(y,self) end |
#sign(x) ⇒ Object
1152 1153 1154 |
# File 'lib/flt/num.rb', line 1152 def sign(x) _convert(x).sign end |
#special?(x) ⇒ Boolean
1172 1173 1174 |
# File 'lib/flt/num.rb', line 1172 def special?(x) _convert(x).special? 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.
1144 1145 1146 |
# File 'lib/flt/num.rb', line 1144 def split(x) _convert(x).split end |
#sqrt(x) ⇒ Object
Square root of a decimal number
848 849 850 |
# File 'lib/flt/num.rb', line 848 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.
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 |
# File 'lib/flt/num.rb', line 1025 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?
836 837 838 |
# File 'lib/flt/num.rb', line 836 def subnormal?(x) _convert(x).subnormal?(self) end |
#subtract(x, y) ⇒ Object
Subtraction of two decimal numbers
705 706 707 |
# File 'lib/flt/num.rb', line 705 def subtract(x,y) _convert(x).subtract(y,self) end |
#to_eng_string(x) ⇒ Object
Converts a number to a string, using engineering notation
775 776 777 |
# File 'lib/flt/num.rb', line 775 def to_eng_string(x) to_string x, true end |
#to_int_scale(x) ⇒ Object
1148 1149 1150 |
# File 'lib/flt/num.rb', line 1148 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.
945 946 947 |
# File 'lib/flt/num.rb', line 945 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.
953 954 955 |
# File 'lib/flt/num.rb', line 953 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
825 826 827 828 |
# File 'lib/flt/num.rb', line 825 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
1231 1232 1233 |
# File 'lib/flt/num.rb', line 1231 def to_r(x) x.to_r end |
#to_s ⇒ Object
1055 1056 1057 |
# File 'lib/flt/num.rb', line 1055 def to_s inspect end |
#to_sci_string(x) ⇒ Object
Converts a number to a string, using scientific notation
770 771 772 |
# File 'lib/flt/num.rb', line 770 def to_sci_string(x) to_string x, false end |
#to_string(x, eng = false) ⇒ Object
Converts a number to a string
765 766 767 |
# File 'lib/flt/num.rb', line 765 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
980 981 982 983 |
# File 'lib/flt/num.rb', line 980 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
1211 1212 1213 |
# File 'lib/flt/num.rb', line 1211 def zero(sign = +1) num_class.zero(sign) end |
#zero?(x) ⇒ Boolean
1176 1177 1178 |
# File 'lib/flt/num.rb', line 1176 def zero?(x) _convert(x).zero? end |