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().
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 |
# File 'lib/flt/num.rb', line 424 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.
509 510 511 |
# File 'lib/flt/num.rb', line 509 def angle @angle end |
#capitals ⇒ Object
Returns the value of attribute capitals.
509 510 511 |
# File 'lib/flt/num.rb', line 509 def capitals @capitals end |
#clamp ⇒ Object
Returns the value of attribute clamp.
509 510 511 |
# File 'lib/flt/num.rb', line 509 def clamp @clamp end |
#emax ⇒ Object
Returns the value of attribute emax.
509 510 511 |
# File 'lib/flt/num.rb', line 509 def emax @emax end |
#emin ⇒ Object
Returns the value of attribute emin.
509 510 511 |
# File 'lib/flt/num.rb', line 509 def emin @emin end |
#flags ⇒ Object
Returns the value of attribute flags.
509 510 511 |
# File 'lib/flt/num.rb', line 509 def flags @flags end |
#ignored_flags ⇒ Object
Returns the value of attribute ignored_flags.
509 510 511 |
# File 'lib/flt/num.rb', line 509 def ignored_flags @ignored_flags end |
#rounding ⇒ Object
Returns the value of attribute rounding.
509 510 511 |
# File 'lib/flt/num.rb', line 509 def rounding @rounding end |
#traps ⇒ Object
Returns the value of attribute traps.
509 510 511 |
# File 'lib/flt/num.rb', line 509 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])
1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 |
# File 'lib/flt/num.rb', line 1081 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
695 696 697 |
# File 'lib/flt/num.rb', line 695 def abs(x) _convert(x).abs(self) end |
#add(x, y) ⇒ Object
Addition of two decimal numbers
675 676 677 |
# File 'lib/flt/num.rb', line 675 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.
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 |
# File 'lib/flt/num.rb', line 611 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?
575 576 577 |
# File 'lib/flt/num.rb', line 575 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
1131 1132 1133 |
# File 'lib/flt/num.rb', line 1131 def coefficient(x) _convert(x).coefficient end |
#coercible_types ⇒ Object
Internal use: array of numeric types that be coerced to DecNum.
1071 1072 1073 |
# File 'lib/flt/num.rb', line 1071 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
1076 1077 1078 |
# File 'lib/flt/num.rb', line 1076 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
876 877 878 |
# File 'lib/flt/num.rb', line 876 def compare(x,y) _convert(x).compare(y, self) end |
#convert_to(type, x) ⇒ Object
Convert a DecNum x to other numerical type
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 |
# File 'lib/flt/num.rb', line 1106 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 +
881 882 883 |
# File 'lib/flt/num.rb', line 881 def copy_abs(x) _convert(x).copy_abs end |
#copy_from(other) ⇒ Object
Copy the state from other Context object.
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 |
# File 'lib/flt/num.rb', line 636 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
886 887 888 |
# File 'lib/flt/num.rb', line 886 def copy_negate(x) _convert(x).copy_negate end |
#copy_sign(x, y) ⇒ Object
Returns a copy of x with the sign of y
891 892 893 |
# File 'lib/flt/num.rb', line 891 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]
1096 1097 1098 |
# File 'lib/flt/num.rb', line 1096 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
1101 1102 1103 |
# File 'lib/flt/num.rb', line 1101 def define_conversion_to(type, &blk) @conversions[type] = blk end |
#digits ⇒ Object
synonym for precision()
555 556 557 |
# File 'lib/flt/num.rb', line 555 def digits self.precision end |
#digits=(n) ⇒ Object
synonym for precision=()
560 561 562 |
# File 'lib/flt/num.rb', line 560 def digits=(n) self.precision=n end |
#div(x, y) ⇒ Object
Ruby-style integer division: (x/y).floor
828 829 830 |
# File 'lib/flt/num.rb', line 828 def div(x,y) _convert(x).div(y,self) end |
#divide(x, y) ⇒ Object
Division of two decimal numbers
690 691 692 |
# File 'lib/flt/num.rb', line 690 def divide(x,y) _convert(x).divide(y,self) end |
#divide_int(x, y) ⇒ Object
General Decimal Arithmetic Specification integer division: (x/y).truncate
843 844 845 |
# File 'lib/flt/num.rb', line 843 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
838 839 840 |
# File 'lib/flt/num.rb', line 838 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
860 861 862 |
# File 'lib/flt/num.rb', line 860 def divrem(x,y) _convert(x).divrem(y,self) end |
#dup ⇒ Object
653 654 655 |
# File 'lib/flt/num.rb', line 653 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
550 551 552 |
# File 'lib/flt/num.rb', line 550 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))
992 993 994 995 |
# File 'lib/flt/num.rb', line 992 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
537 538 539 |
# File 'lib/flt/num.rb', line 537 def etiny emin - precision + 1 end |
#etop ⇒ Object
top exponent (emax - precision + 1) is the maximum valid value for the (integral) exponent
543 544 545 |
# File 'lib/flt/num.rb', line 543 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 { ... }
456 457 458 459 |
# File 'lib/flt/num.rb', line 456 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
601 602 603 |
# File 'lib/flt/num.rb', line 601 def exact @exact end |
#exact=(v) ⇒ Object
Enables or disables the exact precision
594 595 596 597 598 |
# File 'lib/flt/num.rb', line 594 def exact=(v) @exact = v update_precision v end |
#exact? ⇒ Boolean
Returns true if the precision is exact
606 607 608 |
# File 'lib/flt/num.rb', line 606 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.
666 667 668 669 670 671 672 |
# File 'lib/flt/num.rb', line 666 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
725 726 727 |
# File 'lib/flt/num.rb', line 725 def exp(x) _convert(x).exp(self) end |
#exponent(x) ⇒ Object
1135 1136 1137 |
# File 'lib/flt/num.rb', line 1135 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.
867 868 869 |
# File 'lib/flt/num.rb', line 867 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…”
1026 1027 1028 |
# File 'lib/flt/num.rb', line 1026 def half_epsilon(sign=+1) Num(sign, num_class.radix/2, -precision) end |
#ignore_all_flags ⇒ Object
Ignore all flags if they are raised
519 520 521 522 |
# File 'lib/flt/num.rb', line 519 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
525 526 527 528 |
# File 'lib/flt/num.rb', line 525 def ignore_flags(*flags) #@ignored_flags << flags @ignored_flags.set(*flags) end |
#infinite?(x) ⇒ Boolean
1143 1144 1145 |
# File 'lib/flt/num.rb', line 1143 def infinite?(x) _convert(x).infinite? end |
#inspect ⇒ Object
1034 1035 1036 1037 1038 1039 |
# File 'lib/flt/num.rb', line 1034 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.
505 506 507 |
# File 'lib/flt/num.rb', line 505 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.
499 500 501 |
# File 'lib/flt/num.rb', line 499 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.
493 494 495 |
# File 'lib/flt/num.rb', line 493 def int_radix_power(n) @num_class.int_radix_power(n) end |
#ln(x) ⇒ Object
Returns the natural (base e) logarithm
730 731 732 |
# File 'lib/flt/num.rb', line 730 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
735 736 737 |
# File 'lib/flt/num.rb', line 735 def log(x, base=nil) _convert(x).log(base, self) end |
#log10(x) ⇒ Object
Returns the base 10 logarithm
715 716 717 |
# File 'lib/flt/num.rb', line 715 def log10(x) _convert(x).log10(self) end |
#log2(x) ⇒ Object
Returns the base 2 logarithm
720 721 722 |
# File 'lib/flt/num.rb', line 720 def log2(x) _convert(x).log10(self) end |
#logb(x) ⇒ Object
Adjusted exponent of x returned as a DecNum value.
774 775 776 |
# File 'lib/flt/num.rb', line 774 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
466 467 468 469 470 471 472 473 474 475 476 |
# File 'lib/flt/num.rb', line 466 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.
1042 1043 1044 1045 1046 1047 1048 1049 |
# File 'lib/flt/num.rb', line 1042 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
963 964 965 966 967 968 |
# File 'lib/flt/num.rb', line 963 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.
1062 1063 1064 1065 1066 1067 1068 |
# File 'lib/flt/num.rb', line 1062 def maximum_nan_diagnostic_digits if exact? nil # ? else precision - (clamp ? 1 : 0) end end |
#maximum_subnormal(sign = +1) ⇒ Object
Maximum subnormal number
978 979 980 981 982 |
# File 'lib/flt/num.rb', line 978 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)
985 986 987 988 |
# File 'lib/flt/num.rb', line 985 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
971 972 973 974 975 |
# File 'lib/flt/num.rb', line 971 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)
1052 1053 1054 1055 1056 1057 1058 1059 |
# File 'lib/flt/num.rb', line 1052 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
705 706 707 |
# File 'lib/flt/num.rb', line 705 def minus(x) _convert(x)._neg(self) end |
#modulo(x, y) ⇒ Object
Ruby-style modulo: x - y*div(x,y)
833 834 835 |
# File 'lib/flt/num.rb', line 833 def modulo(x,y) _convert(x).modulo(y,self) end |
#multiply(x, y) ⇒ Object
Multiplication of two decimal numbers
685 686 687 |
# File 'lib/flt/num.rb', line 685 def multiply(x,y) _convert(x).multiply(y,self) end |
#nan?(x) ⇒ Boolean
1139 1140 1141 |
# File 'lib/flt/num.rb', line 1139 def nan?(x) _convert(x).nan? end |
#next_minus(x) ⇒ Object
Returns the largest representable number smaller than x.
933 934 935 |
# File 'lib/flt/num.rb', line 933 def next_minus(x) _convert(x).next_minus(self) end |
#next_plus(x) ⇒ Object
Returns the smallest representable number larger than x.
938 939 940 |
# File 'lib/flt/num.rb', line 938 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.
949 950 951 |
# File 'lib/flt/num.rb', line 949 def next_toward(x, y) _convert(x).next_toward(y, self) end |
#normal?(x) ⇒ Boolean
Is a normal number?
806 807 808 |
# File 'lib/flt/num.rb', line 806 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.
769 770 771 |
# File 'lib/flt/num.rb', line 769 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)
787 788 789 790 |
# File 'lib/flt/num.rb', line 787 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)
794 795 796 797 |
# File 'lib/flt/num.rb', line 794 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
484 485 486 |
# File 'lib/flt/num.rb', line 484 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.
479 480 481 |
# File 'lib/flt/num.rb', line 479 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'
818 819 820 |
# File 'lib/flt/num.rb', line 818 def number_class(x) _convert(x).number_class(self) end |
#plus(x) ⇒ Object
Unary prefix plus operator
700 701 702 |
# File 'lib/flt/num.rb', line 700 def plus(x) _convert(x).plus(self) end |
#power(x, y, modulo = nil) ⇒ Object
Power. See DecNum#power()
710 711 712 |
# File 'lib/flt/num.rb', line 710 def power(x,y,modulo=nil) _convert(x).power(y,modulo,self) end |
#prec ⇒ Object
synonym for precision()
565 566 567 |
# File 'lib/flt/num.rb', line 565 def prec self.precision end |
#prec=(n) ⇒ Object
synonym for precision=()
570 571 572 |
# File 'lib/flt/num.rb', line 570 def prec=(n) self.precision = n end |
#precision ⇒ Object
Number of digits of precision
589 590 591 |
# File 'lib/flt/num.rb', line 589 def precision @precision end |
#precision=(n) ⇒ Object
Set the number of digits of precision. If 0 is set the precision turns to be exact.
581 582 583 584 585 586 |
# File 'lib/flt/num.rb', line 581 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.
902 903 904 |
# File 'lib/flt/num.rb', line 902 def quantize(x, y, watch_exp=true) _convert(x).quantize(y, self, watch_exp) end |
#radix ⇒ Object
488 489 490 |
# File 'lib/flt/num.rb', line 488 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)
757 758 759 |
# File 'lib/flt/num.rb', line 757 def reduce(x) _convert(x).reduce(self) end |
#regard_flags(*flags) ⇒ Object
Stop ignoring a set of flags, if they are raised
531 532 533 |
# File 'lib/flt/num.rb', line 531 def regard_flags(*flags) @ignored_flags.clear(*flags) end |
#remainder(x, y) ⇒ Object
General Decimal Arithmetic Specification remainder: x - y*divide_int(x,y)
848 849 850 |
# File 'lib/flt/num.rb', line 848 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)
854 855 856 |
# File 'lib/flt/num.rb', line 854 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.
897 898 899 |
# File 'lib/flt/num.rb', line 897 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.
912 913 914 |
# File 'lib/flt/num.rb', line 912 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
781 782 783 |
# File 'lib/flt/num.rb', line 781 def scaleb(x, y) _convert(x).scaleb(y,self) end |
#sign(x) ⇒ Object
1127 1128 1129 |
# File 'lib/flt/num.rb', line 1127 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.
1119 1120 1121 |
# File 'lib/flt/num.rb', line 1119 def split(x) _convert(x).split end |
#sqrt(x) ⇒ Object
Square root of a decimal number
823 824 825 |
# File 'lib/flt/num.rb', line 823 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.
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 |
# File 'lib/flt/num.rb', line 1000 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?
811 812 813 |
# File 'lib/flt/num.rb', line 811 def subnormal?(x) _convert(x).subnormal?(self) end |
#subtract(x, y) ⇒ Object
Subtraction of two decimal numbers
680 681 682 |
# File 'lib/flt/num.rb', line 680 def subtract(x,y) _convert(x).subtract(y,self) end |
#to_eng_string(x) ⇒ Object
Converts a number to a string, using engineering notation
750 751 752 |
# File 'lib/flt/num.rb', line 750 def to_eng_string(x) to_string x, true end |
#to_int_scale(x) ⇒ Object
1123 1124 1125 |
# File 'lib/flt/num.rb', line 1123 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.
920 921 922 |
# File 'lib/flt/num.rb', line 920 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.
928 929 930 |
# File 'lib/flt/num.rb', line 928 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
800 801 802 803 |
# File 'lib/flt/num.rb', line 800 def to_normalized_int_scale(x) x = _convert(x) [x.sign*normalized_integral_significand(x), normalized_integral_exponent(x)] end |
#to_s ⇒ Object
1030 1031 1032 |
# File 'lib/flt/num.rb', line 1030 def to_s inspect end |
#to_sci_string(x) ⇒ Object
Converts a number to a string, using scientific notation
745 746 747 |
# File 'lib/flt/num.rb', line 745 def to_sci_string(x) to_string x, false end |
#to_string(x, eng = false) ⇒ Object
Converts a number to a string
740 741 742 |
# File 'lib/flt/num.rb', line 740 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
955 956 957 958 |
# File 'lib/flt/num.rb', line 955 def ulp(x=nil, mode=:low) x ||= 1 _convert(x).ulp(self, mode) end |
#zero?(x) ⇒ Boolean
1147 1148 1149 |
# File 'lib/flt/num.rb', line 1147 def zero?(x) _convert(x).zero? end |