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

See also the context constructor method Flt::Num.Context().



395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
# File 'lib/flt/num.rb', line 395

def initialize(num_class, *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)
  end
  assign options.first

end

Instance Attribute Details

#angleObject

Returns the value of attribute angle.



480
481
482
# File 'lib/flt/num.rb', line 480

def angle
  @angle
end

#capitalsObject

Returns the value of attribute capitals.



480
481
482
# File 'lib/flt/num.rb', line 480

def capitals
  @capitals
end

#clampObject

Returns the value of attribute clamp.



480
481
482
# File 'lib/flt/num.rb', line 480

def clamp
  @clamp
end

#emaxObject

Returns the value of attribute emax.



480
481
482
# File 'lib/flt/num.rb', line 480

def emax
  @emax
end

#eminObject

Returns the value of attribute emin.



480
481
482
# File 'lib/flt/num.rb', line 480

def emin
  @emin
end

#flagsObject

Returns the value of attribute flags.



480
481
482
# File 'lib/flt/num.rb', line 480

def flags
  @flags
end

#ignored_flagsObject

Returns the value of attribute ignored_flags.



480
481
482
# File 'lib/flt/num.rb', line 480

def ignored_flags
  @ignored_flags
end

#roundingObject

Returns the value of attribute rounding.



480
481
482
# File 'lib/flt/num.rb', line 480

def rounding
  @rounding
end

#trapsObject

Returns the value of attribute traps.



480
481
482
# File 'lib/flt/num.rb', line 480

def traps
  @traps
end

Instance Method Details

#_coerce(x) ⇒ Object

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



1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
# File 'lib/flt/num.rb', line 1052

def _coerce(x)
  c = x.class
  while c!=Object && (h=@coercible_type_handlers[c]).nil?
    c = c.superclass
  end
  if h
    h.call(x, self)
  else
    nil
  end
end

#abs(x) ⇒ Object

Absolute value of a decimal number



666
667
668
# File 'lib/flt/num.rb', line 666

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

#add(x, y) ⇒ Object

Addition of two decimal numbers



646
647
648
# File 'lib/flt/num.rb', line 646

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

#assign(options) ⇒ Object

Alters the contexts by assigning options from a Hash. See DecNum#new() for the valid options.



582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
# File 'lib/flt/num.rb', line 582

def assign(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?
    @precision += options[:extra_precision] unless options[:extra_precision].nil?
    update_precision
  end
end

#clamp?Boolean

is clamping enabled?

Returns:

  • (Boolean)


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

def clamp?
  @clamp
end

#cmath(*parameters, &blk) ⇒ Object



279
280
281
282
283
284
285
286
287
288
# File 'lib/flt/complex.rb', line 279

def cmath(*parameters, &blk)
  # if ComplexContext is derived from ContextBase: return ComplexContext(self).math(*parameters, &blk)
  num_class.context(self) do
    if parameters.empty?
      Flt.ComplexContext(num_class.context).instance_eval &blk
    else
      Flt.xiComplexContext(num_class.context).instance_exec *parameters, &blk
    end
  end
end

#coefficient(x) ⇒ Object



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

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

#coercible_typesObject

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



1042
1043
1044
# File 'lib/flt/num.rb', line 1042

def coercible_types
  @coercible_type_handlers.keys
end

#coercible_types_or_numObject

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



1047
1048
1049
# File 'lib/flt/num.rb', line 1047

def coercible_types_or_num
  [num_class] + coercible_types
end

#compare(x, y) ⇒ Object

Compares like <=> but returns a DecNum value.

  • -1 if x < y

  • 0 if x == b

  • +1 if x > y

  • NaN if x or y is NaN



847
848
849
# File 'lib/flt/num.rb', line 847

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

#convert_to(type, x) ⇒ Object

Convert a DecNum x to other numerical type



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

def convert_to(type, x)
  converter = @conversions[type]
  if converter.nil?
    raise TypeError, "Undefined conversion from DecNum to #{type}."
  elsif converter.is_a?(Symbol)
    x.send converter
  else
    converter.call(x)
  end
end

#copy_abs(x) ⇒ Object

Returns a copy of x with the sign set to +



852
853
854
# File 'lib/flt/num.rb', line 852

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

#copy_from(other) ⇒ Object

Copy the state from other Context object.

Raises:

  • (TypeError)


607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
# File 'lib/flt/num.rb', line 607

def copy_from(other)
  raise TypeError, "Assign #{other.num_class} context to #{self.num_class} context" if other.num_class != self.num_class
  @rounding = other.rounding
  @precision = other.precision
  @traps = other.traps.dup
  @flags = other.flags.dup
  @ignored_flags = other.ignored_flags.dup
  @emin = other.emin
  @emax = other.emax
  @capitals = other.capitals
  @clamp = other.clamp
  @exact = other.exact
  @coercible_type_handlers = other.coercible_type_handlers.dup
  @conversions = other.conversions.dup
  @angle = other.angle
end

#copy_negate(x) ⇒ Object

Returns a copy of x with the sign inverted



857
858
859
# File 'lib/flt/num.rb', line 857

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

#copy_sign(x, y) ⇒ Object

Returns a copy of x with the sign of y



862
863
864
# File 'lib/flt/num.rb', line 862

def copy_sign(x,y)
  _convert(x).copy_sign(y)
end

#define_conversion_from(type, &blk) ⇒ Object

Define a numerical conversion from type to DecNum. The block that defines the conversion has two parameters: the value to be converted and the context and must return either a DecNum or [sign,coefficient,exponent]



1067
1068
1069
# File 'lib/flt/num.rb', line 1067

def define_conversion_from(type, &blk)
  @coercible_type_handlers[type] = blk
end

#define_conversion_to(type, &blk) ⇒ Object

Define a numerical conversion from DecNum to type as an instance method of DecNum



1072
1073
1074
# File 'lib/flt/num.rb', line 1072

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

#digitsObject

synonym for precision()



526
527
528
# File 'lib/flt/num.rb', line 526

def digits
  self.precision
end

#digits=(n) ⇒ Object

synonym for precision=()



531
532
533
# File 'lib/flt/num.rb', line 531

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

#div(x, y) ⇒ Object

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



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

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

#divide(x, y) ⇒ Object

Division of two decimal numbers



661
662
663
# File 'lib/flt/num.rb', line 661

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

#divide_int(x, y) ⇒ Object

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



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

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

#divmod(x, y) ⇒ Object

Ruby-style integer division and modulo: (x/y).floor, x - y*(x/y).floor



809
810
811
# File 'lib/flt/num.rb', line 809

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

#divrem(x, y) ⇒ Object

General Decimal Arithmetic Specification integer division and remainder:

(x/y).truncate, x - y*(x/y).truncate


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

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

#dupObject



624
625
626
# File 'lib/flt/num.rb', line 624

def dup
  self.class.new(self)
end

#elimit=(e) ⇒ Object

Set the exponent limits, according to IEEE 754-2008 if e > 0 it is taken as emax and emin=1-emax if e < 0 it is taken as emin and emax=1-emin



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

def elimit=(e)
  @emin, @emax = [e, 1-e].sort
end

#epsilon(sign = +1) ⇒ Object

This is the difference between 1 and the smallest DecNum value greater than 1: (DecNum(1).next_plus - DecNum(1))



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

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

#etinyObject

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



508
509
510
# File 'lib/flt/num.rb', line 508

def etiny
  emin - precision + 1
end

#etopObject

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



514
515
516
# File 'lib/flt/num.rb', line 514

def etop
  emax - precision + 1
end

#eval(&blk) ⇒ Object

Evaluate a block under a context (set up the context as a local context)

When we have a context object we can use this instead of using the context method of the numeric class, e.g.:

DecNum.context(context) { ... }

This saves verbosity, specially when numeric class is not fixed, in which case we would have to write:

context.num_class.context(context) { ... }

With this method, we simply write:

context.eval { ... }


427
428
429
430
# File 'lib/flt/num.rb', line 427

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

#exactObject

Returns true if the precision is exact



572
573
574
# File 'lib/flt/num.rb', line 572

def exact
  @exact
end

#exact=(v) ⇒ Object

Enables or disables the exact precision



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

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

#exact?Boolean

Returns true if the precision is exact

Returns:

  • (Boolean)


577
578
579
# File 'lib/flt/num.rb', line 577

def exact?
  @exact
end

#exception(cond, msg = '', *params) ⇒ Object

Raises a flag (unless it is being ignores) and raises and exceptioin if the trap for it is enabled.

Raises:

  • (err.new(*params))


637
638
639
640
641
642
643
# File 'lib/flt/num.rb', line 637

def exception(cond, msg='', *params)
  err = (CONDITION_MAP[cond] || cond)
  return err.handle(self, *params) if @ignored_flags[err]
  @flags << err # @flags[err] = true
  return cond.handle(self, *params) if !@traps[err]
  raise err.new(*params), msg
end

#exp(x) ⇒ Object

Exponential function: e**x



696
697
698
# File 'lib/flt/num.rb', line 696

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

#exponent(x) ⇒ Object



1106
1107
1108
# File 'lib/flt/num.rb', line 1106

def exponent(x)
  _convert(x).exponent
end

#fma(x, y, z) ⇒ Object

Fused multiply-add.

Computes (x*y+z) with no rounding of the intermediate product x*y.



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

def fma(x,y,z)
  _convert(x).fma(y,z,self)
end

#half_epsilon(sign = +1) ⇒ Object

This is the maximum relative error corresponding to 1/2 ulp:

(radix/2)*radix**(-precision) == epsilon/2

This is called “machine epsilon” in Goldberg’s “What Every Computer Scientist…”



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

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

#ignore_all_flagsObject

Ignore all flags if they are raised



490
491
492
493
# File 'lib/flt/num.rb', line 490

def ignore_all_flags
  #@ignored_flags << EXCEPTIONS
  @ignored_flags.set!
end

#ignore_flags(*flags) ⇒ Object

Ignore a specified set of flags if they are raised



496
497
498
499
# File 'lib/flt/num.rb', line 496

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

#infinite?(x) ⇒ Boolean

Returns:

  • (Boolean)


1114
1115
1116
# File 'lib/flt/num.rb', line 1114

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

#inspectObject



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

def inspect
  class_name = self.class.to_s.split('::').last
  "<#{class_name}:\n" +
  instance_variables.map { |v| "  #{v}: #{instance_variable_get(v).inspect}"}.join("\n") +
  ">\n"
end

#int_div_radix_power(x, n) ⇒ Object

Divide by an integral power of the base: x/(radix**n) for x,n integer; returns an integer.



476
477
478
# File 'lib/flt/num.rb', line 476

def int_div_radix_power(x,n)
  @num_class.int_div_radix_power(x,n)
end

#int_mult_radix_power(x, n) ⇒ Object

Multiply by an integral power of the base: x*(radix**n) for x,n integer; returns an integer.



470
471
472
# File 'lib/flt/num.rb', line 470

def int_mult_radix_power(x,n)
  @num_class.int_mult_radix_power(x,n)
end

#int_radix_power(n) ⇒ Object

Integral power of the base: radix**n for integer n; returns an integer.



464
465
466
# File 'lib/flt/num.rb', line 464

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

#ln(x) ⇒ Object

Returns the natural (base e) logarithm



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

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

#log(x, base = nil) ⇒ Object

Ruby-style log function: arbitrary base logarithm which defaults to natural logarithm



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

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

#log10(x) ⇒ Object

Returns the base 10 logarithm



686
687
688
# File 'lib/flt/num.rb', line 686

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

#log2(x) ⇒ Object

Returns the base 2 logarithm



691
692
693
# File 'lib/flt/num.rb', line 691

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

#logb(x) ⇒ Object

Adjusted exponent of x returned as a DecNum value.



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

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

#math(*parameters, &blk) ⇒ Object

Evalute a block under a context (set up the context as a local context) and inject the context methods (math and otherwise) into the block scope.

This allows the use of regular algebraic notations for math functions, e.g. exp(x) instead of x.exp



437
438
439
440
441
442
443
444
445
446
447
# File 'lib/flt/num.rb', line 437

def math(*parameters, &blk)
  # TODO: consider renaming this to eval
  num_class.context(self) do
    if parameters.empty?
      num_class.context.instance_eval &blk
    else
      # needs instance_exe (available in Ruby 1.9, ActiveRecord; TODO: include implementation here)
      num_class.context.instance_exec *parameters, &blk
    end
  end
end

#maximum_coefficientObject

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



1013
1014
1015
1016
1017
1018
1019
1020
# File 'lib/flt/num.rb', line 1013

def maximum_coefficient
  if exact?
    exception(InvalidOperation, 'Exact maximum coefficient')
    nil
  else
    num_class.int_radix_power(precision)-1
  end
end

#maximum_finite(sign = +1) ⇒ Object

Maximum finite number



934
935
936
937
938
939
# File 'lib/flt/num.rb', line 934

def maximum_finite(sign=+1)
  return exception(InvalidOperation, "Exact context maximum finite value") if exact?
  # equals +Num(+1, 1, emax)
  # equals Num.infinity.next_minus(self)
  Num(sign, num_class.int_radix_power(precision)-1, etop)
end

#maximum_nan_diagnostic_digitsObject

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



1033
1034
1035
1036
1037
1038
1039
# File 'lib/flt/num.rb', line 1033

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

#maximum_subnormal(sign = +1) ⇒ Object

Maximum subnormal number



949
950
951
952
953
# File 'lib/flt/num.rb', line 949

def maximum_subnormal(sign=+1)
  return exception(InvalidOperation, "Exact context maximum subnormal value") if exact?
  # equals mininum_normal.next_minus(self)
  Num(sign, num_class.int_radix_power(precision-1)-1, etiny)
end

#minimum_nonzero(sign = +1) ⇒ Object

Minimum nonzero positive number (minimum positive subnormal)



956
957
958
959
# File 'lib/flt/num.rb', line 956

def minimum_nonzero(sign=+1)
  return exception(InvalidOperation, "Exact context minimum nonzero value") if exact?
  Num(sign, 1, etiny)
end

#minimum_normal(sign = +1) ⇒ Object

Minimum positive normal number



942
943
944
945
946
# File 'lib/flt/num.rb', line 942

def minimum_normal(sign=+1)
  return exception(InvalidOperation, "Exact context maximum normal value") if exact?
  #Num(sign, 1, emin).normalize(self)
  Num(sign, minimum_normalized_coefficient, etiny)
end

#minimum_normalized_coefficientObject

Minimum value of a normalized coefficient (normalized unit)



1023
1024
1025
1026
1027
1028
1029
1030
# File 'lib/flt/num.rb', line 1023

def minimum_normalized_coefficient
  if exact?
    exception(InvalidOperation, 'Exact maximum coefficient')
    nil
  else
    num_class.int_radix_power(precision-1)
  end
end

#minus(x) ⇒ Object

Unary prefix minus operator



676
677
678
# File 'lib/flt/num.rb', line 676

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

#modulo(x, y) ⇒ Object

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



804
805
806
# File 'lib/flt/num.rb', line 804

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

#multiply(x, y) ⇒ Object

Multiplication of two decimal numbers



656
657
658
# File 'lib/flt/num.rb', line 656

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

#nan?(x) ⇒ Boolean

Returns:

  • (Boolean)


1110
1111
1112
# File 'lib/flt/num.rb', line 1110

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

#next_minus(x) ⇒ Object

Returns the largest representable number smaller than x.



904
905
906
# File 'lib/flt/num.rb', line 904

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

#next_plus(x) ⇒ Object

Returns the smallest representable number larger than x.



909
910
911
# File 'lib/flt/num.rb', line 909

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

#next_toward(x, y) ⇒ Object

Returns the number closest to x, in the direction towards y.

The result is the closest representable number to x (excluding x) that is in the direction towards y, unless both have the same value. If the two operands are numerically equal, then the result is a copy of x with the sign set to be the same as the sign of y.



920
921
922
# File 'lib/flt/num.rb', line 920

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

#normal?(x) ⇒ Boolean

Is a normal number?

Returns:

  • (Boolean)


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

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

#normalize(x) ⇒ Object

Normalizes (changes quantum) so that the coefficient has precision digits, unless it is subnormal. For surnormal numbers the Subnormal flag is raised an a subnormal is returned with the smallest possible exponent.

This is different from reduce GDAS function which was formerly called normalize, and corresponds to the classic meaning of floating-point normalization.

Note that the number is also rounded (precision is reduced) if it had more precision than the context.



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

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

#normalized_integral_exponent(x) ⇒ Object

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



758
759
760
761
# File 'lib/flt/num.rb', line 758

def normalized_integral_exponent(x)
  x = _convert(x)
  x.exponent - (precision - x.number_of_digits)
end

#normalized_integral_significand(x) ⇒ Object

Significand normalized to precision digits x == normalized_integral_significand(x) * radix**(normalized_integral_exponent)



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

def normalized_integral_significand(x)
  x = _convert(x)
  x.coefficient*(num_class.int_radix_power(precision - x.number_of_digits))
end

#Num(*args) ⇒ Object

Constructor for the associated numeric class



455
456
457
# File 'lib/flt/num.rb', line 455

def Num(*args)
  num_class.Num(*args)
end

#num_classObject

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



450
451
452
# File 'lib/flt/num.rb', line 450

def num_class
  @num_class
end

#number_class(x) ⇒ Object

Classifies a number as one of ‘sNaN’, ‘NaN’, ‘-Infinity’, ‘-Normal’, ‘-Subnormal’, ‘-Zero’,

'+Zero', '+Subnormal', '+Normal', '+Infinity'


789
790
791
# File 'lib/flt/num.rb', line 789

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

#plus(x) ⇒ Object

Unary prefix plus operator



671
672
673
# File 'lib/flt/num.rb', line 671

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

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

Power. See DecNum#power()



681
682
683
# File 'lib/flt/num.rb', line 681

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

#precObject

synonym for precision()



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

def prec
  self.precision
end

#prec=(n) ⇒ Object

synonym for precision=()



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

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

#precisionObject

Number of digits of precision



560
561
562
# File 'lib/flt/num.rb', line 560

def precision
  @precision
end

#precision=(n) ⇒ Object

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



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

def precision=(n)
  @precision = n
  @exact = false unless n==0
  update_precision
  n
end

#quantize(x, y, watch_exp = true) ⇒ Object

Quantize x so its exponent is the same as that of y.



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

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

#radixObject



459
460
461
# File 'lib/flt/num.rb', line 459

def radix
  @num_class.radix
end

#reduce(x) ⇒ Object

Reduces an operand to its simplest form by removing trailing 0s and incrementing the exponent. (formerly called normalize in GDAS)



728
729
730
# File 'lib/flt/num.rb', line 728

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

#regard_flags(*flags) ⇒ Object

Stop ignoring a set of flags, if they are raised



502
503
504
# File 'lib/flt/num.rb', line 502

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

#remainder(x, y) ⇒ Object

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



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

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

#remainder_near(x, y) ⇒ Object

General Decimal Arithmetic Specification remainder-near

x - y*round_half_even(x/y)


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

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

#rescale(x, exp, watch_exp = true) ⇒ Object

Rescale x so that the exponent is exp, either by padding with zeros or by truncating digits.



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

def rescale(x, exp, watch_exp=true)
  _convert(x).rescale(exp, self, watch_exp)
end

#same_quantum?(x, y) ⇒ Boolean

Return true if x and y have the same exponent.

If either operand is a special value, the following rules are used:

  • return true if both operands are infinities

  • return true if both operands are NaNs

  • otherwise, return false.

Returns:

  • (Boolean)


883
884
885
# File 'lib/flt/num.rb', line 883

def same_quantum?(x,y)
  _convert(x).same_quantum?(y)
end

#scaleb(x, y) ⇒ Object

Adds the second value to the exponent of the first: x*(radix**y)

y must be an integer



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

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

#sign(x) ⇒ Object



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

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

#split(x) ⇒ Object

Simply calls x.split; implemented to ease handling Float and BigDecimal as Nums withoug having to add methods like split to those classes.



1090
1091
1092
# File 'lib/flt/num.rb', line 1090

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

#sqrt(x) ⇒ Object

Square root of a decimal number



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

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

#strict_epsilon(sign = +1) ⇒ Object

The strict epsilon is the smallest value that produces something different from 1 wehen added to 1. It may be smaller than the general epsilon, because of the particular rounding rules used.



971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
# File 'lib/flt/num.rb', line 971

def strict_epsilon(sign=+1)
  return exception(InvalidOperation, "Exact context strict epsilon") if exact?
  # assume radix is even (num_class.radix%2 == 0)
  case rounding
  when :down, :floor
    # largest epsilon: 0.0...10 (precision digits shown to the right of the decimal point)
    exp = 1-precision
    coeff = 1
  when :half_even, :half_down
    # next largest:    0.0...050...1 (+precision-1 additional digits here)
    exp = 1-2*precision
    coeff = 1 + num_class.int_radix_power(precision)/2
  when :half_up
    # next largest:    0.0...05 (precision digits shown to the right of the decimal point)
    exp = 1-2*precision
    coeff = num_class.int_radix_power(precision)/2
  when :up, :ceiling, :up05
    # smallest epsilon
    return minimum_nonzero(sign)
  end
  return Num(sign, coeff, exp)
end

#subnormal?(x) ⇒ Boolean

Is a subnormal number?

Returns:

  • (Boolean)


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

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

#subtract(x, y) ⇒ Object

Subtraction of two decimal numbers



651
652
653
# File 'lib/flt/num.rb', line 651

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

#to_eng_string(x) ⇒ Object

Converts a number to a string, using engineering notation



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

def to_eng_string(x)
  to_string x, true
end

#to_int_scale(x) ⇒ Object



1094
1095
1096
# File 'lib/flt/num.rb', line 1094

def to_int_scale(x)
  _convert(x).to_int_scale
end

#to_integral_exact(x) ⇒ Object

Rounds to a nearby integer.

See also: DecNum#to_integral_value(), which does exactly the same as this method except that it doesn’t raise Inexact or Rounded.



891
892
893
# File 'lib/flt/num.rb', line 891

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

#to_integral_value(x) ⇒ Object

Rounds to a nearby integerwithout raising inexact, rounded.

See also: DecNum#to_integral_exact(), which does exactly the same as this method except that it may raise Inexact or Rounded.



899
900
901
# File 'lib/flt/num.rb', line 899

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

#to_normalized_int_scale(x) ⇒ Object

Returns both the (signed) normalized integral significand and the corresponding exponent



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

def to_normalized_int_scale(x)
  x = _convert(x)
  [x.sign*normalized_integral_significand(x), normalized_integral_exponent(x)]
end

#to_sObject



1001
1002
1003
# File 'lib/flt/num.rb', line 1001

def to_s
  inspect
end

#to_sci_string(x) ⇒ Object

Converts a number to a string, using scientific notation



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

def to_sci_string(x)
  to_string x, false
end

#to_string(x, eng = false) ⇒ Object

Converts a number to a string



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

def to_string(x, eng=false)
  _convert(x)._fix(self).to_s(eng, self)
end

#ulp(x = nil, mode = :low) ⇒ Object

ulp (unit in the last place) according to the definition proposed by J.M. Muller in “On the definition of ulp(x)” INRIA No. 5504



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

def ulp(x=nil, mode=:low)
  x ||= 1
  _convert(x).ulp(self, mode)
end

#zero?(x) ⇒ Boolean

Returns:

  • (Boolean)


1118
1119
1120
# File 'lib/flt/num.rb', line 1118

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