Class: Decimal::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/decimal/decimal.rb

Overview

The context defines the arithmetic context: rounding mode, precision,… Decimal.context is the current (thread-local) 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(*options) ⇒ Context

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 : true or false (precision is ignored when true)

  • :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 exponents

  • :capitals : (true or false) to use capitals in text representations

  • :clamp : (true or false) enables clamping

See also the context constructor method Decimal.Context().



307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
# File 'lib/decimal/decimal.rb', line 307

def initialize(*options)

  if options.first.instance_of?(Context)
    base = options.shift
    copy_from base
  else
    @ignored_flags = Decimal::Flags()
    @traps = Decimal::Flags()
    @flags = Decimal::Flags()
    @coercible_type_handlers = Decimal.base_coercible_types.dup
    @conversions = Decimal.base_conversions.dup
  end
  assign options.first

end

Instance Attribute Details

#capitalsObject

Returns the value of attribute capitals.



323
324
325
# File 'lib/decimal/decimal.rb', line 323

def capitals
  @capitals
end

#clampObject

Returns the value of attribute clamp.



323
324
325
# File 'lib/decimal/decimal.rb', line 323

def clamp
  @clamp
end

#emaxObject

Returns the value of attribute emax.



323
324
325
# File 'lib/decimal/decimal.rb', line 323

def emax
  @emax
end

#eminObject

Returns the value of attribute emin.



323
324
325
# File 'lib/decimal/decimal.rb', line 323

def emin
  @emin
end

#flagsObject

Returns the value of attribute flags.



323
324
325
# File 'lib/decimal/decimal.rb', line 323

def flags
  @flags
end

#ignored_flagsObject

Returns the value of attribute ignored_flags.



323
324
325
# File 'lib/decimal/decimal.rb', line 323

def ignored_flags
  @ignored_flags
end

#roundingObject

Returns the value of attribute rounding.



323
324
325
# File 'lib/decimal/decimal.rb', line 323

def rounding
  @rounding
end

#trapsObject

Returns the value of attribute traps.



323
324
325
# File 'lib/decimal/decimal.rb', line 323

def traps
  @traps
end

Instance Method Details

#_coerce(x) ⇒ Object

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



769
770
771
772
773
774
775
776
777
778
779
# File 'lib/decimal/decimal.rb', line 769

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



493
494
495
# File 'lib/decimal/decimal.rb', line 493

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

#add(x, y) ⇒ Object

Addition of two decimal numbers



473
474
475
# File 'lib/decimal/decimal.rb', line 473

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

#assign(options) ⇒ Object

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



416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
# File 'lib/decimal/decimal.rb', line 416

def assign(options)
  if options
    @rounding = options[:rounding] unless options[:rounding].nil?
    @precision = options[:precision] unless options[:precision].nil?
    @traps = Decimal::Flags(options[:traps]) unless options[:traps].nil?
    @flags = Decimal::Flags(options[:flags]) unless options[:flags].nil?
    @ignored_flags = Decimal::Flags(options[:ignored_flags]) unless options[:ignored_flags].nil?
    @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?
    update_precision
  end
end

#clamp?Boolean

is clamping enabled?

Returns:

  • (Boolean)


380
381
382
# File 'lib/decimal/decimal.rb', line 380

def clamp?
  @clamp
end

#coercible_typesObject

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



759
760
761
# File 'lib/decimal/decimal.rb', line 759

def coercible_types
  @coercible_type_handlers.keys
end

#coercible_types_or_decimalObject

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



764
765
766
# File 'lib/decimal/decimal.rb', line 764

def coercible_types_or_decimal
  [Decimal] + coercible_types
end

#compare(x, y) ⇒ Object

Compares like <=> but returns a Decimal value.

  • -1 if x < y

  • 0 if x == b

  • +1 if x > y

  • NaN if x or y is NaN



652
653
654
# File 'lib/decimal/decimal.rb', line 652

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

#convert_to(type, x) ⇒ Object

Convert a Decimal x to other numerical type



794
795
796
797
798
799
800
801
802
803
# File 'lib/decimal/decimal.rb', line 794

def convert_to(type, x)
  converter = @conversions[type]
  if converter.nil?
    raise TypeError, "Undefined conversion from Decimal 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 +



657
658
659
# File 'lib/decimal/decimal.rb', line 657

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

#copy_from(other) ⇒ Object

Copy the state from other Context object.



436
437
438
439
440
441
442
443
444
445
446
447
448
449
# File 'lib/decimal/decimal.rb', line 436

def copy_from(other)
  @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
end

#copy_negate(x) ⇒ Object

Returns a copy of x with the sign inverted



662
663
664
# File 'lib/decimal/decimal.rb', line 662

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

#copy_sign(x, y) ⇒ Object

Returns a copy of x with the sign of y



667
668
669
# File 'lib/decimal/decimal.rb', line 667

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

#define_conversion_from(type, &blk) ⇒ Object

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



784
785
786
# File 'lib/decimal/decimal.rb', line 784

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

#define_conversion_to(type, &blk) ⇒ Object

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



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

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

#digitsObject

synonym for precision()



360
361
362
# File 'lib/decimal/decimal.rb', line 360

def digits
  self.precision
end

#digits=(n) ⇒ Object

synonym for precision=()



365
366
367
# File 'lib/decimal/decimal.rb', line 365

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

#div(x, y) ⇒ Object

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



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

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

#divide(x, y) ⇒ Object

Division of two decimal numbers



488
489
490
# File 'lib/decimal/decimal.rb', line 488

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

#divide_int(x, y) ⇒ Object

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



619
620
621
# File 'lib/decimal/decimal.rb', line 619

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



614
615
616
# File 'lib/decimal/decimal.rb', line 614

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


636
637
638
# File 'lib/decimal/decimal.rb', line 636

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

#dupObject



451
452
453
# File 'lib/decimal/decimal.rb', line 451

def dup
  Context.new(self)
end

#etinyObject

‘tiny’ exponet (emin - precision + 1)



350
351
352
# File 'lib/decimal/decimal.rb', line 350

def etiny
  emin - precision + 1
end

#etopObject

maximum exponent (emax - precision + 1)



355
356
357
# File 'lib/decimal/decimal.rb', line 355

def etop
  emax - precision + 1
end

#exactObject

Returns true if the precision is exact



406
407
408
# File 'lib/decimal/decimal.rb', line 406

def exact
  @exact
end

#exact=(v) ⇒ Object

Enables or disables the exact precision



399
400
401
402
403
# File 'lib/decimal/decimal.rb', line 399

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

#exact?Boolean

Returns true if the precision is exact

Returns:

  • (Boolean)


411
412
413
# File 'lib/decimal/decimal.rb', line 411

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


464
465
466
467
468
469
470
# File 'lib/decimal/decimal.rb', line 464

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



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

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

#fma(x, y, z) ⇒ Object

Fused multiply-add.

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



643
644
645
# File 'lib/decimal/decimal.rb', line 643

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

#ignore_all_flagsObject

Ignore all flags if they are raised



333
334
335
336
# File 'lib/decimal/decimal.rb', line 333

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



339
340
341
342
# File 'lib/decimal/decimal.rb', line 339

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

#inspectObject



733
734
735
736
737
# File 'lib/decimal/decimal.rb', line 733

def inspect
  "<#{self.class}:\n" +
  instance_variables.map { |v| "  #{v}: #{eval(v)}"}.join("\n") +
  ">\n"
end

#ln(x) ⇒ Object

Returns the natural (base e) logarithm



557
558
559
# File 'lib/decimal/decimal.rb', line 557

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

#log10(x) ⇒ Object

Returns the base 10 logarithm



547
548
549
# File 'lib/decimal/decimal.rb', line 547

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

#logb(x) ⇒ Object

Adjusted exponent of x returned as a Decimal value.



530
531
532
# File 'lib/decimal/decimal.rb', line 530

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

#maximum_nan_diagnostic_digitsObject

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



750
751
752
753
754
755
756
# File 'lib/decimal/decimal.rb', line 750

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

#maximum_significandObject

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



740
741
742
743
744
745
746
747
# File 'lib/decimal/decimal.rb', line 740

def maximum_significand
  if exact?
    exception(InvalidOperation, 'Exact maximum significand')
    nil
  else
    Decimal.int_radix_power(precision)-1
  end
end

#minus(x) ⇒ Object

Unary prefix minus operator



503
504
505
# File 'lib/decimal/decimal.rb', line 503

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

#modulo(x, y) ⇒ Object

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



609
610
611
# File 'lib/decimal/decimal.rb', line 609

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

#multiply(x, y) ⇒ Object

Multiplication of two decimal numbers



483
484
485
# File 'lib/decimal/decimal.rb', line 483

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

#next_minus(x) ⇒ Object

Returns the largest representable number smaller than x.



709
710
711
# File 'lib/decimal/decimal.rb', line 709

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

#next_plus(x) ⇒ Object

Returns the smallest representable number larger than x.



714
715
716
# File 'lib/decimal/decimal.rb', line 714

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.



725
726
727
# File 'lib/decimal/decimal.rb', line 725

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

#normal?(x) ⇒ Boolean

Is a normal number?

Returns:

  • (Boolean)


582
583
584
# File 'lib/decimal/decimal.rb', line 582

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

#normalized_integral_exponent(x) ⇒ Object

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



563
564
565
566
# File 'lib/decimal/decimal.rb', line 563

def normalized_integral_exponent(x)
  x = _convert(x)
  x.integral_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)



570
571
572
573
# File 'lib/decimal/decimal.rb', line 570

def normalized_integral_significand(x)
  x = _convert(x)
  x.integral_significand*(Decimal.int_radix_power(precision - x.number_of_digits))
end

#number_class(x) ⇒ Object

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

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


594
595
596
# File 'lib/decimal/decimal.rb', line 594

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

#plus(x) ⇒ Object

Unary prefix plus operator



498
499
500
# File 'lib/decimal/decimal.rb', line 498

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

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

Power. See Decimal#power()



542
543
544
# File 'lib/decimal/decimal.rb', line 542

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

#precObject

synonym for precision()



370
371
372
# File 'lib/decimal/decimal.rb', line 370

def prec
  self.precision
end

#prec=(n) ⇒ Object

synonym for precision=()



375
376
377
# File 'lib/decimal/decimal.rb', line 375

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

#precisionObject

Number of digits of precision



394
395
396
# File 'lib/decimal/decimal.rb', line 394

def precision
  @precision
end

#precision=(n) ⇒ Object

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



386
387
388
389
390
391
# File 'lib/decimal/decimal.rb', line 386

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.



678
679
680
# File 'lib/decimal/decimal.rb', line 678

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

#reduce(x) ⇒ Object

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



525
526
527
# File 'lib/decimal/decimal.rb', line 525

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

#regard_flags(*flags) ⇒ Object

Stop ignoring a set of flags, if they are raised



345
346
347
# File 'lib/decimal/decimal.rb', line 345

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

#remainder(x, y) ⇒ Object

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



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

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)


630
631
632
# File 'lib/decimal/decimal.rb', line 630

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.



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

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)


688
689
690
# File 'lib/decimal/decimal.rb', line 688

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



537
538
539
# File 'lib/decimal/decimal.rb', line 537

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

#sqrt(x) ⇒ Object

Square root of a decimal number



599
600
601
# File 'lib/decimal/decimal.rb', line 599

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

#subnormal?(x) ⇒ Boolean

Is a subnormal number?

Returns:

  • (Boolean)


587
588
589
# File 'lib/decimal/decimal.rb', line 587

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

#subtract(x, y) ⇒ Object

Subtraction of two decimal numbers



478
479
480
# File 'lib/decimal/decimal.rb', line 478

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

#to_eng_string(x) ⇒ Object

Converts a number to a string, using engineering notation



518
519
520
# File 'lib/decimal/decimal.rb', line 518

def to_eng_string(x)
  to_string x, true
end

#to_integral_exact(x) ⇒ Object

Rounds to a nearby integer.

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



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

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: Decimal#to_integral_exact(), which does exactly the same as this method except that it may raise Inexact or Rounded.



704
705
706
# File 'lib/decimal/decimal.rb', line 704

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



576
577
578
579
# File 'lib/decimal/decimal.rb', line 576

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

#to_sObject



729
730
731
# File 'lib/decimal/decimal.rb', line 729

def to_s
  inspect
end

#to_sci_string(x) ⇒ Object

Converts a number to a string, using scientific notation



513
514
515
# File 'lib/decimal/decimal.rb', line 513

def to_sci_string(x)
  to_string x, false
end

#to_string(x, eng = false) ⇒ Object

Converts a number to a string



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

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