Class: Flt::Num::ContextBase

Inherits:
Object
  • Object
show all
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

BinNum::Context, DecNum::Context

Constant Summary collapse

CONDITION_MAP =
{
  #ConversionSyntax=>InvalidOperation,
  #DivisionImpossible=>InvalidOperation,
  DivisionUndefined=>InvalidOperation,
  InvalidContext=>InvalidOperation
}

Instance Attribute Summary collapse

Instance Method Summary collapse

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

  • :normalized : (true or false) normalizes all results

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
449
# File 'lib/flt/num.rb', line 428

def initialize(num_class, *options)
  @num_class = num_class

  if options.first.kind_of?(ContextBase)
    base = options.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 options.first

end

Instance Attribute Details

#angleObject

Returns the value of attribute angle


520
521
522
# File 'lib/flt/num.rb', line 520

def angle
  @angle
end

#capitalsObject

Returns the value of attribute capitals


520
521
522
# File 'lib/flt/num.rb', line 520

def capitals
  @capitals
end

#clampObject

Returns the value of attribute clamp


520
521
522
# File 'lib/flt/num.rb', line 520

def clamp
  @clamp
end

#emaxObject

Returns the value of attribute emax


520
521
522
# File 'lib/flt/num.rb', line 520

def emax
  @emax
end

#eminObject

Returns the value of attribute emin


520
521
522
# File 'lib/flt/num.rb', line 520

def emin
  @emin
end

#flagsObject

Returns the value of attribute flags


520
521
522
# File 'lib/flt/num.rb', line 520

def flags
  @flags
end

#ignored_flagsObject

Returns the value of attribute ignored_flags


520
521
522
# File 'lib/flt/num.rb', line 520

def ignored_flags
  @ignored_flags
end

#normalizedObject

Returns the value of attribute normalized


520
521
522
# File 'lib/flt/num.rb', line 520

def normalized
  @normalized
end

#roundingObject

Returns the value of attribute rounding


520
521
522
# File 'lib/flt/num.rb', line 520

def rounding
  @rounding
end

#trapsObject

Returns the value of attribute traps


520
521
522
# File 'lib/flt/num.rb', line 520

def traps
  @traps
end

Instance Method Details

#[](options = {}) ⇒ Object

Create a context as a copy of the current one with some options changed.


679
680
681
# File 'lib/flt/num.rb', line 679

def [](options={})
  self.class.new self, options
end

#_coerce(x) ⇒ Object

Internally used to convert numeric types to DecNum (or to an array [sign,coefficient,exponent])


1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
# File 'lib/flt/num.rb', line 1107

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


721
722
723
# File 'lib/flt/num.rb', line 721

def abs(x)
  _convert(x).abs(self)
end

#add(x, y) ⇒ Object

Addition of two decimal numbers


701
702
703
# File 'lib/flt/num.rb', line 701

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.


626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
# File 'lib/flt/num.rb', line 626

def assign(options)
  if options
    @rounding = options[:rounding] unless options[:rounding].nil?
    @precision = options[:precision] unless options[:precision].nil?
    @traps = DecNum::Flags(options[:traps]) unless options[:traps].nil?
    @flags = DecNum::Flags(options[:flags]) unless options[:flags].nil?
    @ignored_flags = DecNum::Flags(options[:ignored_flags]) unless options[:ignored_flags].nil?
    if elimit=options[:elimit]
      @emin, @emax = [elimit, 1-elimit].sort
    end
    @emin = options[:emin] unless options[:emin].nil?
    @emax = options[:emax] unless options[:emax].nil?
    @capitals = options[:capitals ] unless options[:capitals ].nil?
    @clamp = options[:clamp] unless options[:clamp].nil?
    @exact = options[:exact] unless options[:exact].nil?
    @angle = options[:angle] unless options[:angle].nil?
    @normalized = options[:normalized] unless options[:normalized].nil?
    update_precision
    if options[:extra_precision] && !@exact
      @precision += options[:extra_precision]
    end
  end
  self
end

#clamp?Boolean

is clamping enabled?


590
591
592
# File 'lib/flt/num.rb', line 590

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


1157
1158
1159
# File 'lib/flt/num.rb', line 1157

def coefficient(x)
  _convert(x).coefficient
end

#coercible_typesObject

Internal use: array of numeric types that be coerced to DecNum.


1097
1098
1099
# File 'lib/flt/num.rb', line 1097

def coercible_types
  @coercible_type_handlers.keys
end

#coercible_types_or_numObject

Internal use: array of numeric types that be coerced to DecNum, including DecNum


1102
1103
1104
# File 'lib/flt/num.rb', line 1102

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


902
903
904
# File 'lib/flt/num.rb', line 902

def compare(x,y)
  _convert(x).compare(y, self)
end

#convert_to(type, x) ⇒ Object

Convert a DecNum x to other numerical type


1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
# File 'lib/flt/num.rb', line 1132

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 +


907
908
909
# File 'lib/flt/num.rb', line 907

def copy_abs(x)
  _convert(x).copy_abs
end

#copy_from(other) ⇒ Object

Copy the state from other Context object.

Raises:

  • (TypeError)

655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
# File 'lib/flt/num.rb', line 655

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


912
913
914
# File 'lib/flt/num.rb', line 912

def copy_negate(x)
  _convert(x).copy_negate
end

#copy_sign(x, y) ⇒ Object

Returns a copy of x with the sign of y


917
918
919
# File 'lib/flt/num.rb', line 917

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]


1122
1123
1124
# File 'lib/flt/num.rb', line 1122

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


1127
1128
1129
# File 'lib/flt/num.rb', line 1127

def define_conversion_to(type, &blk)
  @conversions[type] = blk
end

#digitsObject

synonym for precision()


570
571
572
# File 'lib/flt/num.rb', line 570

def digits
  self.precision
end

#digits=(n) ⇒ Object

synonym for precision=()


575
576
577
# File 'lib/flt/num.rb', line 575

def digits=(n)
  self.precision=n
end

#div(x, y) ⇒ Object

Ruby-style integer division: (x/y).floor


854
855
856
# File 'lib/flt/num.rb', line 854

def div(x,y)
  _convert(x).div(y,self)
end

#divide(x, y) ⇒ Object

Division of two decimal numbers


716
717
718
# File 'lib/flt/num.rb', line 716

def divide(x,y)
  _convert(x).divide(y,self)
end

#divide_int(x, y) ⇒ Object

General Decimal Arithmetic Specification integer division: (x/y).truncate


869
870
871
# File 'lib/flt/num.rb', line 869

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


864
865
866
# File 'lib/flt/num.rb', line 864

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

886
887
888
# File 'lib/flt/num.rb', line 886

def divrem(x,y)
  _convert(x).divrem(y,self)
end

#dupObject


673
674
675
# File 'lib/flt/num.rb', line 673

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


565
566
567
# File 'lib/flt/num.rb', line 565

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))


1018
1019
1020
1021
# File 'lib/flt/num.rb', line 1018

def epsilon(sign=+1)
  return exception(InvalidOperation, "Exact context epsilon") if exact?
  Num(sign, 1, 1-precision)
end

#etinyObject

'tiny' exponent (emin - precision + 1) is the minimum valid value for the (integral) exponent


552
553
554
# File 'lib/flt/num.rb', line 552

def etiny
  emin - precision + 1
end

#etopObject

top exponent (emax - precision + 1) is the maximum valid value for the (integral) exponent


558
559
560
# File 'lib/flt/num.rb', line 558

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 { ... }

461
462
463
464
# File 'lib/flt/num.rb', line 461

def eval(&blk)
  # TODO: consider other names for this method; use ? apply ? local ? with ?
  num_class.context(self, &blk)
end

#exactObject

Returns true if the precision is exact


616
617
618
# File 'lib/flt/num.rb', line 616

def exact
  @exact
end

#exact=(v) ⇒ Object

Enables or disables the exact precision


609
610
611
612
613
# File 'lib/flt/num.rb', line 609

def exact=(v)
  @exact = v
  update_precision
  v
end

#exact?Boolean

Returns true if the precision is exact


621
622
623
# File 'lib/flt/num.rb', line 621

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.

Raises:

  • (err.new(*params))

692
693
694
695
696
697
698
# File 'lib/flt/num.rb', line 692

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


751
752
753
# File 'lib/flt/num.rb', line 751

def exp(x)
  _convert(x).exp(self)
end

#exponent(x) ⇒ Object


1161
1162
1163
# File 'lib/flt/num.rb', line 1161

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.


893
894
895
# File 'lib/flt/num.rb', line 893

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…”


1052
1053
1054
# File 'lib/flt/num.rb', line 1052

def half_epsilon(sign=+1)
  Num(sign, num_class.radix/2, -precision)
end

#ignore_all_flagsObject

Ignore all flags if they are raised


534
535
536
537
# File 'lib/flt/num.rb', line 534

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


540
541
542
543
# File 'lib/flt/num.rb', line 540

def ignore_flags(*flags)
  #@ignored_flags << flags
  @ignored_flags.set(*flags)
end

#infinite?(x) ⇒ Boolean


1169
1170
1171
# File 'lib/flt/num.rb', line 1169

def infinite?(x)
  _convert(x).infinite?
end

#infinity(sign = +1) ⇒ Object

A floating-point infinite number with the specified sign


1217
1218
1219
# File 'lib/flt/num.rb', line 1217

def infinity(sign = +1)
  num_class.infinity(sign)
end

#inspectObject


1060
1061
1062
1063
1064
1065
# File 'lib/flt/num.rb', line 1060

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.


516
517
518
# File 'lib/flt/num.rb', line 516

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.


510
511
512
# File 'lib/flt/num.rb', line 510

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.


504
505
506
# File 'lib/flt/num.rb', line 504

def int_radix_power(n)
  @num_class.int_radix_power(n)
end

#ln(x) ⇒ Object

Returns the natural (base e) logarithm


756
757
758
# File 'lib/flt/num.rb', line 756

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


761
762
763
# File 'lib/flt/num.rb', line 761

def log(x, base=nil)
  _convert(x).log(base, self)
end

#log10(x) ⇒ Object

Returns the base 10 logarithm


741
742
743
# File 'lib/flt/num.rb', line 741

def log10(x)
  _convert(x).log10(self)
end

#log2(x) ⇒ Object

Returns the base 2 logarithm


746
747
748
# File 'lib/flt/num.rb', line 746

def log2(x)
  _convert(x).log10(self)
end

#logb(x) ⇒ Object

Adjusted exponent of x returned as a DecNum value.


800
801
802
# File 'lib/flt/num.rb', line 800

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


471
472
473
474
475
476
477
478
479
480
481
# File 'lib/flt/num.rb', line 471

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_coefficientObject

Maximum integral significand value for numbers using this context's precision.


1068
1069
1070
1071
1072
1073
1074
1075
# File 'lib/flt/num.rb', line 1068

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


989
990
991
992
993
994
# File 'lib/flt/num.rb', line 989

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_digitsObject

Maximum number of diagnostic digits in NaNs for numbers using this context's precision.


1088
1089
1090
1091
1092
1093
1094
# File 'lib/flt/num.rb', line 1088

def maximum_nan_diagnostic_digits
  if exact?
    nil # ?
  else
    precision - (clamp ? 1 : 0)
  end
end

#maximum_subnormal(sign = +1) ⇒ Object

Maximum subnormal number


1004
1005
1006
1007
1008
# File 'lib/flt/num.rb', line 1004

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)


1011
1012
1013
1014
# File 'lib/flt/num.rb', line 1011

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


997
998
999
1000
1001
# File 'lib/flt/num.rb', line 997

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_coefficientObject

Minimum value of a normalized coefficient (normalized unit)


1078
1079
1080
1081
1082
1083
1084
1085
# File 'lib/flt/num.rb', line 1078

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


731
732
733
# File 'lib/flt/num.rb', line 731

def minus(x)
  _convert(x)._neg(self)
end

#modulo(x, y) ⇒ Object

Ruby-style modulo: x - y*div(x,y)


859
860
861
# File 'lib/flt/num.rb', line 859

def modulo(x,y)
  _convert(x).modulo(y,self)
end

#multiply(x, y) ⇒ Object

Multiplication of two decimal numbers


711
712
713
# File 'lib/flt/num.rb', line 711

def multiply(x,y)
  _convert(x).multiply(y,self)
end

#nanObject

A floating-point NaN (not a number)


1222
1223
1224
# File 'lib/flt/num.rb', line 1222

def nan
  num_class.nan
end

#nan?(x) ⇒ Boolean


1165
1166
1167
# File 'lib/flt/num.rb', line 1165

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.


1201
1202
1203
1204
1205
1206
1207
1208
1209
# File 'lib/flt/num.rb', line 1201

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.


959
960
961
# File 'lib/flt/num.rb', line 959

def next_minus(x)
  _convert(x).next_minus(self)
end

#next_plus(x) ⇒ Object

Returns the smallest representable number larger than x.


964
965
966
# File 'lib/flt/num.rb', line 964

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.


975
976
977
# File 'lib/flt/num.rb', line 975

def next_toward(x, y)
  _convert(x).next_toward(y, self)
end

#normal?(x) ⇒ Boolean

Is a normal number?


832
833
834
# File 'lib/flt/num.rb', line 832

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.


795
796
797
# File 'lib/flt/num.rb', line 795

def normalize(x)
  _convert(x).normalize(self)
end

#normalized?Boolean


522
523
524
# File 'lib/flt/num.rb', line 522

def normalized?
  normalized
end

#normalized_integral_exponent(x) ⇒ Object

Exponent in relation to the significand as an integer normalized to precision digits. (minimum exponent)


813
814
815
816
# File 'lib/flt/num.rb', line 813

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)


820
821
822
823
# File 'lib/flt/num.rb', line 820

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


489
490
491
492
493
494
495
496
497
# File 'lib/flt/num.rb', line 489

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_classObject

This gives access to the numeric class (Flt::Num-derived) this context is for.


484
485
486
# File 'lib/flt/num.rb', line 484

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'

844
845
846
# File 'lib/flt/num.rb', line 844

def number_class(x)
  _convert(x).number_class(self)
end

#one_halfObject

One half: 1/2


1227
1228
1229
# File 'lib/flt/num.rb', line 1227

def one_half
  num_class.one_half
end

#plus(x) ⇒ Object

Unary prefix plus operator


726
727
728
# File 'lib/flt/num.rb', line 726

def plus(x)
  _convert(x).plus(self)
end

#power(x, y, modulo = nil) ⇒ Object

Power. See DecNum#power()


736
737
738
# File 'lib/flt/num.rb', line 736

def power(x,y,modulo=nil)
  _convert(x).power(y,modulo,self)
end

#precObject

synonym for precision()


580
581
582
# File 'lib/flt/num.rb', line 580

def prec
  self.precision
end

#prec=(n) ⇒ Object

synonym for precision=()


585
586
587
# File 'lib/flt/num.rb', line 585

def prec=(n)
  self.precision = n
end

#precisionObject

Number of digits of precision


604
605
606
# File 'lib/flt/num.rb', line 604

def precision
  @precision
end

#precision=(n) ⇒ Object

Set the number of digits of precision. If 0 is set the precision turns to be exact.


596
597
598
599
600
601
# File 'lib/flt/num.rb', line 596

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.


928
929
930
# File 'lib/flt/num.rb', line 928

def quantize(x, y, watch_exp=true)
  _convert(x).quantize(y, self, watch_exp)
end

#radixObject


499
500
501
# File 'lib/flt/num.rb', line 499

def radix
  @num_class.radix
end

#rationalize(x, tol = nil) ⇒ Object

Approximate conversion to Rational within given tolerance


1237
1238
1239
# File 'lib/flt/num.rb', line 1237

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)


783
784
785
# File 'lib/flt/num.rb', line 783

def reduce(x)
  _convert(x).reduce(self)
end

#regard_flags(*flags) ⇒ Object

Stop ignoring a set of flags, if they are raised


546
547
548
# File 'lib/flt/num.rb', line 546

def regard_flags(*flags)
  @ignored_flags.clear(*flags)
end

#remainder(x, y) ⇒ Object

General Decimal Arithmetic Specification remainder: x - y*divide_int(x,y)


874
875
876
# File 'lib/flt/num.rb', line 874

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)

880
881
882
# File 'lib/flt/num.rb', line 880

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.


1186
1187
1188
1189
1190
1191
1192
1193
1194
# File 'lib/flt/num.rb', line 1186

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.


923
924
925
# File 'lib/flt/num.rb', line 923

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.


938
939
940
# File 'lib/flt/num.rb', line 938

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


807
808
809
# File 'lib/flt/num.rb', line 807

def scaleb(x, y)
  _convert(x).scaleb(y,self)
end

#sign(x) ⇒ Object


1153
1154
1155
# File 'lib/flt/num.rb', line 1153

def sign(x)
  _convert(x).sign
end

#special?(x) ⇒ Boolean


1173
1174
1175
# File 'lib/flt/num.rb', line 1173

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.


1145
1146
1147
# File 'lib/flt/num.rb', line 1145

def split(x)
  _convert(x).split
end

#sqrt(x) ⇒ Object

Square root of a decimal number


849
850
851
# File 'lib/flt/num.rb', line 849

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.


1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
# File 'lib/flt/num.rb', line 1026

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?


837
838
839
# File 'lib/flt/num.rb', line 837

def subnormal?(x)
  _convert(x).subnormal?(self)
end

#subtract(x, y) ⇒ Object

Subtraction of two decimal numbers


706
707
708
# File 'lib/flt/num.rb', line 706

def subtract(x,y)
  _convert(x).subtract(y,self)
end

#to_eng_string(x) ⇒ Object

Converts a number to a string, using engineering notation


776
777
778
# File 'lib/flt/num.rb', line 776

def to_eng_string(x)
  to_string x, true
end

#to_int_scale(x) ⇒ Object


1149
1150
1151
# File 'lib/flt/num.rb', line 1149

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.


946
947
948
# File 'lib/flt/num.rb', line 946

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.


954
955
956
# File 'lib/flt/num.rb', line 954

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


826
827
828
829
# File 'lib/flt/num.rb', line 826

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


1232
1233
1234
# File 'lib/flt/num.rb', line 1232

def to_r(x)
  x.to_r
end

#to_sObject


1056
1057
1058
# File 'lib/flt/num.rb', line 1056

def to_s
  inspect
end

#to_sci_string(x) ⇒ Object

Converts a number to a string, using scientific notation


771
772
773
# File 'lib/flt/num.rb', line 771

def to_sci_string(x)
  to_string x, false
end

#to_string(x, eng = false) ⇒ Object

Converts a number to a string


766
767
768
# File 'lib/flt/num.rb', line 766

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


981
982
983
984
# File 'lib/flt/num.rb', line 981

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


1212
1213
1214
# File 'lib/flt/num.rb', line 1212

def zero(sign = +1)
  num_class.zero(sign)
end

#zero?(x) ⇒ Boolean


1177
1178
1179
# File 'lib/flt/num.rb', line 1177

def zero?(x)
  _convert(x).zero?
end