ruby-decimal 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,9 @@
1
1
  == 0.1.0 2009-06-19
2
2
 
3
- * Initial release
3
+ * Initial release 0.1.0
4
+
5
+ == 0.2.0 2009-06-21
6
+
7
+ * Release 0.2.0
8
+ New functions implemented: exp(), ln(), log10(), power().
9
+
data/README.txt CHANGED
@@ -9,6 +9,10 @@ define a nice feature-set and API for Decimal and have a good test suite for its
9
9
  specification. Then an efficient implementation could be written, for example
10
10
  by using a C extension wrapper around the decNumber library.
11
11
 
12
+ The documentation for this package is available at http://ruby-decimal.rubyforge.org/
13
+
14
+ The code is at http://github.com/jgoizueta/ruby-decimal/
15
+
12
16
  == Standars compliance.
13
17
 
14
18
  Decimal pretends to be conformant to the General Decimal Arithmetic Specification
@@ -248,7 +252,7 @@ Note that the conversion we've defined depends on the context precision:
248
252
 
249
253
  Decimal.local_context(:precision=>12) { puts Decimal(0.1) } -> 0.100000000000
250
254
 
251
- == Available functionality
255
+ == More Information
252
256
 
253
257
  Consult the documentation for the classes Decimal and Decimal::Context.
254
258
 
@@ -301,6 +305,5 @@ EXPAND+
301
305
 
302
306
  = Roadmap
303
307
 
308
+ * Version 0.3.0: Implement the remaining of GDA functions
304
309
  * Complete documentation (README sections on special values & exceptions, etc. and method descriptions.)
305
- * Version 0.2.0: Implement GDAS exp(), power(), ln() log10() and also the Ruby-style operator **.
306
- * Version 0.3.0:
@@ -37,6 +37,16 @@ class Decimal
37
37
  attr_reader :base_conversions
38
38
  end
39
39
 
40
+ #--
41
+ # Some functions use the next methods instead of 10, 10**x, etc.
42
+ # This has been done for two reasons:
43
+ # * Much of the code of Decimal is generic enough to work for non-decimal floating-point numbers.
44
+ # In the future a binary (or arbitrary radix) class could be derived from Decimal.
45
+ # * The radix power operations could be optimized (specinally for binary)
46
+ # But note that some code (e.g. powers & logarithms, auxiliar funtions) use algorithms
47
+ # that assume radix=10.
48
+ #++
49
+
40
50
  # Numerical base of Decimal.
41
51
  def self.radix
42
52
  10
@@ -146,8 +156,12 @@ class Decimal
146
156
  # This occurs and signals inexact whenever the result of an operation is
147
157
  # not exact (that is, it needed to be rounded and any discarded digits
148
158
  # were non-zero), or if an overflow or underflow condition occurs. The
149
- # result in all cases is unchanged.
159
+ # result in all cases is unchanged unless the context has exact precision,
160
+ # in which case the result is Nan
150
161
  class Inexact < Exception
162
+ def self.handle(context, *args)
163
+ Decimal.nan if context.exact?
164
+ end
151
165
  end
152
166
 
153
167
  # Overflow Exception.
@@ -308,6 +322,13 @@ class Decimal
308
322
 
309
323
  attr_accessor :rounding, :emin, :emax, :flags, :traps, :ignored_flags, :capitals, :clamp
310
324
 
325
+ # TODO: consider the convenience of adding accessors of this kind:
326
+ # def rounding(new_rounding=nil)
327
+ # old_rounding = @rounding
328
+ # @rounding = new_rounding unless new_rounding.nil?
329
+ # old_rounding
330
+ # end
331
+
311
332
  # Ignore all flags if they are raised
312
333
  def ignore_all_flags
313
334
  #@ignored_flags << EXCEPTIONS
@@ -450,42 +471,42 @@ class Decimal
450
471
 
451
472
  # Addition of two decimal numbers
452
473
  def add(x,y)
453
- Decimal._convert(x).add(y,self)
474
+ _convert(x).add(y,self)
454
475
  end
455
476
 
456
477
  # Subtraction of two decimal numbers
457
478
  def subtract(x,y)
458
- Decimal._convert(x).subtract(y,self)
479
+ _convert(x).subtract(y,self)
459
480
  end
460
481
 
461
482
  # Multiplication of two decimal numbers
462
483
  def multiply(x,y)
463
- Decimal._convert(x).multiply(y,self)
484
+ _convert(x).multiply(y,self)
464
485
  end
465
486
 
466
487
  # Division of two decimal numbers
467
488
  def divide(x,y)
468
- Decimal._convert(x).divide(y,self)
489
+ _convert(x).divide(y,self)
469
490
  end
470
491
 
471
492
  # Absolute value of a decimal number
472
493
  def abs(x)
473
- Decimal._convert(x).abs(self)
494
+ _convert(x).abs(self)
474
495
  end
475
496
 
476
497
  # Unary prefix plus operator
477
498
  def plus(x)
478
- Decimal._convert(x).plus(self)
499
+ _convert(x).plus(self)
479
500
  end
480
501
 
481
502
  # Unary prefix minus operator
482
503
  def minus(x)
483
- Decimal._convert(x)._neg(self)
504
+ _convert(x)._neg(self)
484
505
  end
485
506
 
486
507
  # Converts a number to a string
487
508
  def to_string(x, eng=false)
488
- Decimal._convert(x)._fix(self).to_s(eng, self)
509
+ _convert(x)._fix(self).to_s(eng, self)
489
510
  end
490
511
 
491
512
  # Converts a number to a string, using scientific notation
@@ -502,106 +523,125 @@ class Decimal
502
523
  # by removing trailing 0s and incrementing the exponent.
503
524
  # (formerly called normalize in GDAS)
504
525
  def reduce(x)
505
- Decimal._convert(x).reduce(self)
526
+ _convert(x).reduce(self)
506
527
  end
507
528
 
508
529
  # Adjusted exponent of x returned as a Decimal value.
509
530
  def logb(x)
510
- Decimal._convert(x).logb(self)
531
+ _convert(x).logb(self)
511
532
  end
512
533
 
513
534
  # Adds the second value to the exponent of the first: x*(radix**y)
514
535
  #
515
536
  # y must be an integer
516
537
  def scaleb(x, y)
517
- Decimal._convert(x).scaleb(y,self)
538
+ _convert(x).scaleb(y,self)
539
+ end
540
+
541
+ # Power. See Decimal#power()
542
+ def power(x,y,modulo=nil)
543
+ _convert(x).power(y,modulo,self)
544
+ end
545
+
546
+ # Returns the base 10 logarithm
547
+ def log10(x)
548
+ _convert(x).log10(self)
549
+ end
550
+
551
+ # Exponential function: e**x
552
+ def exp(x)
553
+ _convert(x).exp(self)
518
554
  end
519
555
 
556
+ # Returns the natural (base e) logarithm
557
+ def ln(x)
558
+ _convert(x).ln(self)
559
+ end
520
560
 
521
561
  # Exponent in relation to the significand as an integer
522
562
  # normalized to precision digits. (minimum exponent)
523
563
  def normalized_integral_exponent(x)
524
- x = Decimal._convert(x)
564
+ x = _convert(x)
525
565
  x.integral_exponent - (precision - x.number_of_digits)
526
566
  end
527
567
 
528
568
  # Significand normalized to precision digits
529
569
  # x == normalized_integral_significand(x) * radix**(normalized_integral_exponent)
530
570
  def normalized_integral_significand(x)
531
- x = Decimal._convert(x)
571
+ x = _convert(x)
532
572
  x.integral_significand*(Decimal.int_radix_power(precision - x.number_of_digits))
533
573
  end
534
574
 
535
575
  # Returns both the (signed) normalized integral significand and the corresponding exponent
536
576
  def to_normalized_int_scale(x)
537
- x = Decimal._convert(x)
577
+ x = _convert(x)
538
578
  [x.sign*normalized_integral_significand(x), normalized_integral_exponent(x)]
539
579
  end
540
580
 
541
581
  # Is a normal number?
542
582
  def normal?(x)
543
- Decimal._convert(x).normal?(self)
583
+ _convert(x).normal?(self)
544
584
  end
545
585
 
546
586
  # Is a subnormal number?
547
587
  def subnormal?(x)
548
- Decimal._convert(x).subnormal?(self)
588
+ _convert(x).subnormal?(self)
549
589
  end
550
590
 
551
591
  # Classifies a number as one of
552
592
  # 'sNaN', 'NaN', '-Infinity', '-Normal', '-Subnormal', '-Zero',
553
593
  # '+Zero', '+Subnormal', '+Normal', '+Infinity'
554
594
  def number_class(x)
555
- Decimal._convert(x).number_class(self)
595
+ _convert(x).number_class(self)
556
596
  end
557
597
 
558
598
  # Square root of a decimal number
559
599
  def sqrt(x)
560
- Decimal._convert(x).sqrt(self)
600
+ _convert(x).sqrt(self)
561
601
  end
562
602
 
563
603
  # Ruby-style integer division: (x/y).floor
564
604
  def div(x,y)
565
- Decimal._convert(x).div(y,self)
605
+ _convert(x).div(y,self)
566
606
  end
567
607
 
568
608
  # Ruby-style modulo: x - y*div(x,y)
569
609
  def modulo(x,y)
570
- Decimal._convert(x).modulo(y,self)
610
+ _convert(x).modulo(y,self)
571
611
  end
572
612
 
573
613
  # Ruby-style integer division and modulo: (x/y).floor, x - y*(x/y).floor
574
614
  def divmod(x,y)
575
- Decimal._convert(x).divmod(y,self)
615
+ _convert(x).divmod(y,self)
576
616
  end
577
617
 
578
618
  # General Decimal Arithmetic Specification integer division: (x/y).truncate
579
619
  def divide_int(x,y)
580
- Decimal._convert(x).divide_int(y,self)
620
+ _convert(x).divide_int(y,self)
581
621
  end
582
622
 
583
623
  # General Decimal Arithmetic Specification remainder: x - y*divide_int(x,y)
584
624
  def remainder(x,y)
585
- Decimal._convert(x).remainder(y,self)
625
+ _convert(x).remainder(y,self)
586
626
  end
587
627
 
588
628
  # General Decimal Arithmetic Specification remainder-near
589
629
  # x - y*round_half_even(x/y)
590
630
  def remainder_near(x,y)
591
- Decimal._convert(x).remainder_near(y,self)
631
+ _convert(x).remainder_near(y,self)
592
632
  end
593
633
 
594
634
  # General Decimal Arithmetic Specification integer division and remainder:
595
635
  # (x/y).truncate, x - y*(x/y).truncate
596
636
  def divrem(x,y)
597
- Decimal._convert(x).divrem(y,self)
637
+ _convert(x).divrem(y,self)
598
638
  end
599
639
 
600
640
  # Fused multiply-add.
601
641
  #
602
642
  # Computes (x*y+z) with no rounding of the intermediate product x*y.
603
643
  def fma(x,y,z)
604
- Decimal._convert(x).fma(y,z,self)
644
+ _convert(x).fma(y,z,self)
605
645
  end
606
646
 
607
647
  # Compares like <=> but returns a Decimal value.
@@ -610,33 +650,33 @@ class Decimal
610
650
  # * +1 if x > y
611
651
  # * NaN if x or y is NaN
612
652
  def compare(x,y)
613
- Decimal._convert(x).compare(y, self)
653
+ _convert(x).compare(y, self)
614
654
  end
615
655
 
616
656
  # Returns a copy of x with the sign set to +
617
657
  def copy_abs(x)
618
- Decimal._convert(x).copy_abs
658
+ _convert(x).copy_abs
619
659
  end
620
660
 
621
661
  # Returns a copy of x with the sign inverted
622
662
  def copy_negate(x)
623
- Decimal._convert(x).copy_negate
663
+ _convert(x).copy_negate
624
664
  end
625
665
 
626
666
  # Returns a copy of x with the sign of y
627
667
  def copy_sign(x,y)
628
- Decimal._convert(x).copy_sign(y)
668
+ _convert(x).copy_sign(y)
629
669
  end
630
670
 
631
671
  # Rescale x so that the exponent is exp, either by padding with zeros
632
672
  # or by truncating digits.
633
673
  def rescale(x, exp, watch_exp=true)
634
- Decimal._convert(x).rescale(exp, self, watch_exp)
674
+ _convert(x).rescale(exp, self, watch_exp)
635
675
  end
636
676
 
637
677
  # Quantize x so its exponent is the same as that of y.
638
678
  def quantize(x, y, watch_exp=true)
639
- Decimal._convert(x).quantize(y, self, watch_exp)
679
+ _convert(x).quantize(y, self, watch_exp)
640
680
  end
641
681
 
642
682
  # Return true if x and y have the same exponent.
@@ -646,7 +686,7 @@ class Decimal
646
686
  # * return true if both operands are NaNs
647
687
  # * otherwise, return false.
648
688
  def same_quantum?(x,y)
649
- Decimal._convert(x).same_quantum?(y)
689
+ _convert(x).same_quantum?(y)
650
690
  end
651
691
 
652
692
  # Rounds to a nearby integer.
@@ -654,7 +694,7 @@ class Decimal
654
694
  # See also: Decimal#to_integral_value(), which does exactly the same as
655
695
  # this method except that it doesn't raise Inexact or Rounded.
656
696
  def to_integral_exact(x)
657
- Decimal._convert(x).to_integral_exact(self)
697
+ _convert(x).to_integral_exact(self)
658
698
  end
659
699
 
660
700
  # Rounds to a nearby integerwithout raising inexact, rounded.
@@ -662,17 +702,17 @@ class Decimal
662
702
  # See also: Decimal#to_integral_exact(), which does exactly the same as
663
703
  # this method except that it may raise Inexact or Rounded.
664
704
  def to_integral_value(x)
665
- Decimal._convert(x).to_integral_value(self)
705
+ _convert(x).to_integral_value(self)
666
706
  end
667
707
 
668
708
  # Returns the largest representable number smaller than x.
669
709
  def next_minus(x)
670
- Decimal._convert(x).next_minus(self)
710
+ _convert(x).next_minus(self)
671
711
  end
672
712
 
673
713
  # Returns the smallest representable number larger than x.
674
714
  def next_plus(x)
675
- Decimal._convert(x).next_plus(self)
715
+ _convert(x).next_plus(self)
676
716
  end
677
717
 
678
718
  # Returns the number closest to x, in the direction towards y.
@@ -683,7 +723,7 @@ class Decimal
683
723
  # numerically equal, then the result is a copy of x with the
684
724
  # sign set to be the same as the sign of y.
685
725
  def next_toward(x, y)
686
- Decimal._convert(x).next_toward(y, self)
726
+ _convert(x).next_toward(y, self)
687
727
  end
688
728
 
689
729
  def to_s
@@ -763,6 +803,11 @@ class Decimal
763
803
  end
764
804
 
765
805
  private
806
+
807
+ def _convert(x)
808
+ AuxiliarFunctions._convert(x)
809
+ end
810
+
766
811
  def update_precision
767
812
  if @exact || @precision==0
768
813
  @exact = true
@@ -874,6 +919,13 @@ class Decimal
874
919
  keep = context.dup
875
920
  Decimal.context = define_context(*args)
876
921
  result = yield Decimal.context
922
+ # TODO: consider the convenience of copying the flags from Decimal.context to keep
923
+ # This way a local context does not affect the settings of the previous context,
924
+ # but flags are transferred.
925
+ # (this could be done always or be controlled by some option)
926
+ # keep.flags = Decimal.context.flags
927
+ # Another alternative to consider: logically or the flags:
928
+ # keep.flags ||= Decimal.context.flags # (this requires implementing || in Flags)
877
929
  Decimal.context = keep
878
930
  result
879
931
  end
@@ -958,7 +1010,7 @@ class Decimal
958
1010
  # and the left hand is another numeric type
959
1011
  # * Decimal#_bin_op() used internally to define binary operators and use the Ruby coerce protocol:
960
1012
  # if the right-hand operand is of known type it is converted with Decimal; otherwise use coerce
961
- # * Decimal._convert() converts known types to Decimal with Decimal() or raises an exception.
1013
+ # * _convert() converts known types to Decimal with Decimal() or raises an exception.
962
1014
  # * Decimal() casts known types and text representations of numbers to Decimal using the constructor.
963
1015
  # * Decimal#initialize performs the actual type conversion
964
1016
  #
@@ -1212,11 +1264,16 @@ class Decimal
1212
1264
  _bin_op :%, :modulo, other, context
1213
1265
  end
1214
1266
 
1267
+ # Power
1268
+ def **(other, context=nil)
1269
+ _bin_op :**, :power, other, context
1270
+ end
1271
+
1215
1272
  # Addition
1216
1273
  def add(other, context=nil)
1217
1274
 
1218
1275
  context = Decimal.define_context(context)
1219
- other = Decimal._convert(other)
1276
+ other = _convert(other)
1220
1277
 
1221
1278
  if self.special? || other.special?
1222
1279
  ans = _check_nans(context,other)
@@ -1252,7 +1309,7 @@ class Decimal
1252
1309
  return self._rescale(exp, context.rounding)._fix(context)
1253
1310
  end
1254
1311
 
1255
- op1, op2 = Decimal._normalize(self, other, context.precision)
1312
+ op1, op2 = _normalize(self, other, context.precision)
1256
1313
 
1257
1314
  result_sign = result_coeff = result_exp = nil
1258
1315
  if op1.sign != op2.sign
@@ -1267,9 +1324,6 @@ class Decimal
1267
1324
  result_sign = +1
1268
1325
  end
1269
1326
 
1270
- #puts "op1=#{op1.inspect} op2=#{op2.inspect}"
1271
-
1272
-
1273
1327
  if op2.sign == +1
1274
1328
  result_coeff = op1.integral_significand + op2.integral_significand
1275
1329
  else
@@ -1278,8 +1332,6 @@ class Decimal
1278
1332
 
1279
1333
  result_exp = op1.integral_exponent
1280
1334
 
1281
- #puts "->#{Decimal([result_sign, result_coeff, result_exp]).inspect}"
1282
-
1283
1335
  return Decimal([result_sign, result_coeff, result_exp])._fix(context)
1284
1336
 
1285
1337
  end
@@ -1289,7 +1341,7 @@ class Decimal
1289
1341
  def subtract(other, context=nil)
1290
1342
 
1291
1343
  context = Decimal.define_context(context)
1292
- other = Decimal._convert(other)
1344
+ other = _convert(other)
1293
1345
 
1294
1346
  if self.special? || other.special?
1295
1347
  ans = _check_nans(context,other)
@@ -1301,7 +1353,7 @@ class Decimal
1301
1353
  # Multiplication
1302
1354
  def multiply(other, context=nil)
1303
1355
  context = Decimal.define_context(context)
1304
- other = Decimal._convert(other)
1356
+ other = _convert(other)
1305
1357
  resultsign = self.sign * other.sign
1306
1358
  if self.special? || other.special?
1307
1359
  ans = _check_nans(context,other)
@@ -1330,7 +1382,7 @@ class Decimal
1330
1382
  # Division
1331
1383
  def divide(other, context=nil)
1332
1384
  context = Decimal.define_context(context)
1333
- other = Decimal._convert(other)
1385
+ other = _convert(other)
1334
1386
  resultsign = self.sign * other.sign
1335
1387
  if self.special? || other.special?
1336
1388
  ans = _check_nans(context,other)
@@ -1414,6 +1466,8 @@ class Decimal
1414
1466
  end
1415
1467
  end
1416
1468
 
1469
+ return context.exception(InvalidOperation, 'Exact next minus') if context.exact?
1470
+
1417
1471
  result = nil
1418
1472
  Decimal.local_context(context) do |local|
1419
1473
  local.rounding = :floor
@@ -1429,6 +1483,7 @@ class Decimal
1429
1483
  # Smallest representable number larger than itself
1430
1484
  def next_plus(context=nil)
1431
1485
  context = Decimal.define_context(context)
1486
+
1432
1487
  if special?
1433
1488
  ans = _check_nans(context)
1434
1489
  return ans if ans
@@ -1443,6 +1498,8 @@ class Decimal
1443
1498
  end
1444
1499
  end
1445
1500
 
1501
+ return context.exception(InvalidOperation, 'Exact next plus') if context.exact?
1502
+
1446
1503
  result = nil
1447
1504
  Decimal.local_context(context) do |local|
1448
1505
  local.rounding = :ceiling
@@ -1459,10 +1516,12 @@ class Decimal
1459
1516
  # Returns the number closest to self, in the direction towards other.
1460
1517
  def next_toward(other, context=nil)
1461
1518
  context = Decimal.define_context(context)
1462
- other = Decimal._convert(other)
1519
+ other = _convert(other)
1463
1520
  ans = _check_nans(context,other)
1464
1521
  return ans if ans
1465
1522
 
1523
+ return context.exception(InvalidOperation, 'Exact next_toward') if context.exact?
1524
+
1466
1525
  comparison = self <=> other
1467
1526
  return self.copy_sign(other) if comparison == 0
1468
1527
 
@@ -1549,7 +1608,7 @@ class Decimal
1549
1608
  # (x/y).truncate, x - y*(x/y).truncate
1550
1609
  def divrem(other, context=nil)
1551
1610
  context = Decimal.define_context(context)
1552
- other = Decimal._convert(other)
1611
+ other = _convert(other)
1553
1612
 
1554
1613
  ans = _check_nans(context,other)
1555
1614
  return [ans,ans] if ans
@@ -1582,7 +1641,7 @@ class Decimal
1582
1641
  # Ruby-style integer division and modulo: (x/y).floor, x - y*(x/y).floor
1583
1642
  def divmod(other, context=nil)
1584
1643
  context = Decimal.define_context(context)
1585
- other = Decimal._convert(other)
1644
+ other = _convert(other)
1586
1645
 
1587
1646
  ans = _check_nans(context,other)
1588
1647
  return [ans,ans] if ans
@@ -1616,7 +1675,7 @@ class Decimal
1616
1675
  # General Decimal Arithmetic Specification integer division: (x/y).truncate
1617
1676
  def divide_int(other, context=nil)
1618
1677
  context = Decimal.define_context(context)
1619
- other = Decimal._convert(other)
1678
+ other = _convert(other)
1620
1679
 
1621
1680
  ans = _check_nans(context,other)
1622
1681
  return ans if ans
@@ -1641,7 +1700,7 @@ class Decimal
1641
1700
  # Ruby-style integer division: (x/y).floor
1642
1701
  def div(other, context=nil)
1643
1702
  context = Decimal.define_context(context)
1644
- other = Decimal._convert(other)
1703
+ other = _convert(other)
1645
1704
 
1646
1705
  ans = _check_nans(context,other)
1647
1706
  return [ans,ans] if ans
@@ -1667,7 +1726,7 @@ class Decimal
1667
1726
  # Ruby-style modulo: x - y*div(x,y)
1668
1727
  def modulo(other, context=nil)
1669
1728
  context = Decimal.define_context(context)
1670
- other = Decimal._convert(other)
1729
+ other = _convert(other)
1671
1730
 
1672
1731
  ans = _check_nans(context,other)
1673
1732
  return ans if ans
@@ -1690,7 +1749,7 @@ class Decimal
1690
1749
  # General Decimal Arithmetic Specification remainder: x - y*divide_int(x,y)
1691
1750
  def remainder(other, context=nil)
1692
1751
  context = Decimal.define_context(context)
1693
- other = Decimal._convert(other)
1752
+ other = _convert(other)
1694
1753
 
1695
1754
  ans = _check_nans(context,other)
1696
1755
  return ans if ans
@@ -1714,7 +1773,7 @@ class Decimal
1714
1773
  # x - y*round_half_even(x/y)
1715
1774
  def remainder_near(other, context=nil)
1716
1775
  context = Decimal.define_context(context)
1717
- other = Decimal._convert(other)
1776
+ other = _convert(other)
1718
1777
 
1719
1778
  ans = _check_nans(context,other)
1720
1779
  return ans if ans
@@ -1819,7 +1878,7 @@ class Decimal
1819
1878
  def scaleb(other, context=nil)
1820
1879
 
1821
1880
  context = Decimal.define_context(context)
1822
- other = Decimal._convert(other)
1881
+ other = _convert(other)
1823
1882
  ans = _check_nans(context, other)
1824
1883
  return ans if ans
1825
1884
  return context.exception(InvalidOperation) if other.infinite? || other.integral_exponent != 0
@@ -1843,7 +1902,11 @@ class Decimal
1843
1902
  # Ruby-style to integer conversion.
1844
1903
  def to_i
1845
1904
  if special?
1846
- return nil if nan?
1905
+ if nan?
1906
+ #return Decimal.context.exception(InvalidContext)
1907
+ Decimal.context.exception InvalidContext
1908
+ return nil
1909
+ end
1847
1910
  raise Error, "Cannot convert infinity to Integer"
1848
1911
  end
1849
1912
  if @exp >= 0
@@ -2011,7 +2074,7 @@ class Decimal
2011
2074
  # Compares like <=> but returns a Decimal value.
2012
2075
  def compare(other, context=nil)
2013
2076
 
2014
- other = Decimal._convert(other)
2077
+ other = _convert(other)
2015
2078
 
2016
2079
  if self.special? || other.special?
2017
2080
  ans = _check_nans(context, other)
@@ -2052,14 +2115,15 @@ class Decimal
2052
2115
  @coeff.to_s.size
2053
2116
  end
2054
2117
 
2055
- # Significand as an integer
2118
+ # Significand as an integer, unsigned
2056
2119
  def integral_significand
2057
2120
  @coeff
2058
2121
  end
2059
2122
 
2060
2123
  # Exponent of the significand as an integer
2061
2124
  def integral_exponent
2062
- fractional_exponent - number_of_digits
2125
+ # fractional_exponent - number_of_digits
2126
+ @exp
2063
2127
  end
2064
2128
 
2065
2129
  # Sign of the number: +1 for plus / -1 for minus.
@@ -2076,262 +2140,635 @@ class Decimal
2076
2140
  end
2077
2141
  end
2078
2142
 
2079
- # Returns copy with sign inverted
2080
- def _neg(context=nil)
2081
- if special?
2082
- ans = _check_nans(context)
2083
- return ans if ans
2084
- end
2085
- if zero?
2086
- ans = copy_abs
2087
- else
2088
- ans = copy_negate
2089
- end
2090
- context = Decimal.define_context(context)
2091
- ans._fix(context)
2143
+ # Returns a copy of with the sign set to +
2144
+ def copy_abs
2145
+ Decimal.new([+1,@coeff,@exp])
2092
2146
  end
2093
2147
 
2094
- # Returns a copy with precision adjusted
2095
- def _pos(context=nil)
2096
- if special?
2097
- ans = _check_nans(context)
2098
- return ans if ans
2099
- end
2100
- if zero?
2101
- ans = copy_abs
2102
- else
2103
- ans = Decimal.new(self)
2104
- end
2105
- context = Decimal.define_context(context)
2106
- ans._fix(context)
2148
+ # Returns a copy of with the sign inverted
2149
+ def copy_negate
2150
+ Decimal.new([-@sign,@coeff,@exp])
2107
2151
  end
2108
2152
 
2109
- # Returns a copy with positive sign
2110
- def _abs(round=true, context=nil)
2111
- return copy_abs if not round
2112
-
2113
- if special?
2114
- ans = _check_nans(context)
2115
- return ans if ans
2116
- end
2117
- if sign>0
2118
- ans = _neg(context)
2119
- else
2120
- ans = _pos(context)
2121
- end
2122
- ans
2153
+ # Returns a copy of with the sign of other
2154
+ def copy_sign(other)
2155
+ Decimal.new([other.sign, @coeff, @exp])
2123
2156
  end
2124
2157
 
2125
- # Round if it is necessary to keep within precision.
2126
- def _fix(context)
2127
- return self if context.exact?
2128
-
2129
- if special?
2130
- if nan?
2131
- return _fix_nan(context)
2158
+ # Returns true if the value is an integer
2159
+ def integral?
2160
+ if finite?
2161
+ if @exp>=0 || @coeff==0
2162
+ true
2132
2163
  else
2133
- return Decimal.new(self)
2164
+ if @exp <= -number_of_digits
2165
+ false
2166
+ else
2167
+ m = Decimal.int_radix_power(-@exp)
2168
+ (@coeff % m) == 0
2169
+ end
2134
2170
  end
2171
+ else
2172
+ false
2135
2173
  end
2174
+ end
2136
2175
 
2137
- etiny = context.etiny
2138
- etop = context.etop
2139
- if zero?
2140
- exp_max = context.clamp? ? etop : context.emax
2141
- new_exp = [[@exp, etiny].max, exp_max].min
2142
- if new_exp!=@exp
2143
- context.exception Clamped
2144
- return Decimal.new([sign,0,new_exp])
2176
+ # returns true if is an even integer
2177
+ def even?
2178
+ # integral? && ((to_i%2)==0)
2179
+ if finite?
2180
+ if @exp>0 || @coeff==0
2181
+ true
2145
2182
  else
2146
- return Decimal.new(self)
2183
+ if @exp <= -number_of_digits
2184
+ false
2185
+ else
2186
+ m = Decimal.int_radix_power(-@exp)
2187
+ if (@coeff % m) == 0
2188
+ # ((@coeff / m) % 2) == 0
2189
+ ((@coeff / m) & 1) == 0
2190
+ else
2191
+ false
2192
+ end
2193
+ end
2147
2194
  end
2195
+ else
2196
+ false
2148
2197
  end
2198
+ end
2149
2199
 
2150
- nd = number_of_digits
2151
- exp_min = nd + @exp - context.precision
2152
- if exp_min > etop
2153
- context.exception Inexact
2154
- context.exception Rounded
2155
- return context.exception(Overflow, 'above Emax', sign)
2156
- end
2157
-
2158
- self_is_subnormal = exp_min < etiny
2159
-
2160
- if self_is_subnormal
2161
- context.exception Subnormal
2162
- exp_min = etiny
2163
- end
2164
-
2165
- if @exp < exp_min
2166
- #puts "_fix(#{self}) rounded; e=#{@exp} em=#{exp_min}"
2167
- context.exception Rounded
2168
- # dig is the digits number from 0 (MS) to number_of_digits-1 (LS)
2169
- # dg = numberof_digits-dig is from 1 (LS) to number_of_digits (MS)
2170
- dg = exp_min - @exp # dig = number_of_digits + exp - exp_min
2171
- if dg > number_of_digits # dig<0
2172
- d = Decimal.new([sign,1,exp_min-1])
2173
- dg = number_of_digits # dig = 0
2200
+ # returns true if is an odd integer
2201
+ def odd?
2202
+ # integral? && ((to_i%2)==1)
2203
+ # integral? && !even?
2204
+ if finite?
2205
+ if @exp>0 || @coeff==0
2206
+ false
2174
2207
  else
2175
- d = Decimal.new(self)
2176
- end
2177
- changed = d._round(context.rounding, dg)
2178
- coeff = Decimal.int_div_radix_power(d.integral_significand, dg)
2179
- coeff += 1 if changed==1
2180
- ans = Decimal.new([sign, coeff, exp_min])
2181
- if changed!=0
2182
- context.exception Inexact
2183
- if self_is_subnormal
2184
- context.exception Underflow
2185
- if ans.zero?
2186
- context.exception Clamped
2187
- end
2188
- elsif ans.number_of_digits == context.precision+1
2189
- if ans.integral_exponent< etop
2190
- ans = Decimal.new([ans.sign, Decimal.int_div_radix_power(ans.integral_significand,1), ans.integral_exponent+1])
2208
+ if @exp <= -number_of_digits
2209
+ false
2210
+ else
2211
+ m = Decimal.int_radix_power(-@exp)
2212
+ if (@coeff % m) == 0
2213
+ # ((@coeff / m) % 2) == 1
2214
+ ((@coeff / m) & 1) == 1
2191
2215
  else
2192
- ans = context.exception(Overflow, 'above Emax', d.sign)
2216
+ false
2193
2217
  end
2194
2218
  end
2195
2219
  end
2196
- return ans
2220
+ else
2221
+ false
2197
2222
  end
2223
+ end
2198
2224
 
2199
- if context.clamp? && @exp>etop
2200
- context.exception Clamped
2201
- self_padded = Decimal.int_mult_radix_power(@coeff, @exp-etop)
2202
- return Decimal.new([sign,self_padded,etop])
2225
+ # Rescale so that the exponent is exp, either by padding with zeros
2226
+ # or by truncating digits.
2227
+ def rescale(exp, context=nil, watch_exp=true)
2228
+ context = Decimal.define_context(context)
2229
+ exp = _convert(exp)
2230
+ if self.special? || exp.special?
2231
+ ans = _check_nans(context, exp)
2232
+ return ans if ans
2233
+ if exp.infinite? || self.infinite?
2234
+ return Decimal.new(self) if exp.infinite? && self.infinite?
2235
+ return context.exception(InvalidOperation, 'rescale with one INF')
2236
+ end
2203
2237
  end
2204
-
2205
- return Decimal.new(self)
2206
-
2238
+ return context.exception(InvalidOperation,"exponent of rescale is not integral") unless exp.integral?
2239
+ exp = exp.to_i
2240
+ _watched_rescale(exp, context, watch_exp)
2207
2241
  end
2208
2242
 
2243
+ # Quantize so its exponent is the same as that of y.
2244
+ def quantize(exp, context=nil, watch_exp=true)
2245
+ exp = _convert(exp)
2246
+ context = Decimal.define_context(context)
2247
+ if self.special? || exp.special?
2248
+ ans = _check_nans(context, exp)
2249
+ return ans if ans
2250
+ if exp.infinite? || self.infinite?
2251
+ return Decimal.new(self) if exp.infinite? && self.infinite?
2252
+ return context.exception(InvalidOperation, 'quantize with one INF')
2253
+ end
2254
+ end
2255
+ exp = exp.integral_exponent
2256
+ _watched_rescale(exp, context, watch_exp)
2257
+ end
2209
2258
 
2210
- ROUND_ARITHMETIC = true
2211
-
2212
- # Round to i digits using the specified method
2213
- def _round(rounding, i)
2214
- send("_round_#{rounding}", i)
2259
+ # Return true if has the same exponent as other.
2260
+ #
2261
+ # If either operand is a special value, the following rules are used:
2262
+ # * return true if both operands are infinities
2263
+ # * return true if both operands are NaNs
2264
+ # * otherwise, return false.
2265
+ def same_quantum?(other)
2266
+ other = _convert(other)
2267
+ if self.special? || other.special?
2268
+ return (self.nan? && other.nan?) || (self.infinite? && other.infinite?)
2269
+ end
2270
+ return self.integral_exponent == other.integral_exponent
2215
2271
  end
2216
2272
 
2217
- # Round down (toward 0, truncate) to i digits
2218
- def _round_down(i)
2219
- if ROUND_ARITHMETIC
2220
- (@coeff % Decimal.int_radix_power(i))==0 ? 0 : -1
2221
- else
2222
- d = @coeff.to_s
2223
- p = d.size - i
2224
- d[p..-1].match(/\A0+\Z/) ? 0 : -1
2273
+ # Rounds to a nearby integer. May raise Inexact or Rounded.
2274
+ def to_integral_exact(context=nil)
2275
+ context = Decimal.define_context(context)
2276
+ if special?
2277
+ ans = _check_nans(context)
2278
+ return ans if ans
2279
+ return Decimal.new(self)
2225
2280
  end
2281
+ return Decimal.new(self) if @exp >= 0
2282
+ return Decimal.new([@sign, 0, 0]) if zero?
2283
+ context.exception Rounded
2284
+ ans = _rescale(0, context.rounding)
2285
+ context.exception Inexact if ans != self
2286
+ return ans
2226
2287
  end
2227
2288
 
2228
- # Round up (away from 0) to i digits
2229
- def _round_up(i)
2230
- -_round_down(i)
2289
+ # Rounds to a nearby integer. Doesn't raise Inexact or Rounded.
2290
+ def to_integral_value(context=nil)
2291
+ context = Decimal.define_context(context)
2292
+ if special?
2293
+ ans = _check_nans(context)
2294
+ return ans if ans
2295
+ return Decimal.new(self)
2296
+ end
2297
+ return Decimal.new(self) if @exp >= 0
2298
+ return _rescale(0, context.rounding)
2231
2299
  end
2232
2300
 
2233
- # Round to closest i-digit number with ties down (rounds 5 toward 0)
2234
- def _round_half_down(i)
2235
- if ROUND_ARITHMETIC
2236
- m = Decimal.int_radix_power(i)
2237
- if (m>1) && ((@coeff%m) == m/2)
2238
- -1
2239
- else
2240
- _round_half_up(i)
2241
- end
2301
+ # General rounding.
2302
+ #
2303
+ # With an integer argument this acts like Float#round: the parameter specifies the number
2304
+ # of fractional digits (or digits to the left of the decimal point if negative).
2305
+ #
2306
+ # Options can be passed as a Hash instead; valid options are:
2307
+ # * :rounding method for rounding (see Context#new())
2308
+ # The precision can be specified as:
2309
+ # * :places number of fractional digits as above.
2310
+ # * :exponent specifies the exponent corresponding to the
2311
+ # digit to be rounded (exponent == -places)
2312
+ # * :precision or :significan_digits is the number of digits
2313
+ # * :power 10^exponent, value of the digit to be rounded,
2314
+ # should be passed as a type convertible to Decimal.
2315
+ # * :index 0-based index of the digit to be rounded
2316
+ # * :rindex right 0-based index of the digit to be rounded
2317
+ #
2318
+ # The default is :places=>0 (round to integer).
2319
+ #
2320
+ # Example: ways of specifiying the rounding position
2321
+ # number: 1 2 3 4 . 5 6 7 8
2322
+ # :places -3 -2 -1 0 1 2 3 4
2323
+ # :exponent 3 2 1 0 -1 -2 -3 -4
2324
+ # :precision 1 2 3 4 5 6 7 8
2325
+ # :power 1E3 1E2 10 1 0.1 1E-2 1E-3 1E-4
2326
+ # :index 0 1 2 3 4 5 6 7
2327
+ # :index 7 6 5 4 3 2 1 0
2328
+ def round(opt={})
2329
+ opt = { :places=>opt } if opt.kind_of?(Integer)
2330
+ r = opt[:rounding] || :half_up
2331
+ as_int = false
2332
+ if v=(opt[:precision] || opt[:significant_digits])
2333
+ prec = v
2334
+ elsif v=(opt[:places])
2335
+ prec = adjusted_exponent + 1 + v
2336
+ elsif v=(opt[:exponent])
2337
+ prec = adjusted_exponent + 1 - v
2338
+ elsif v=(opt[:power])
2339
+ prec = adjusted_exponent + 1 - Decimal(v).adjusted_exponent
2340
+ elsif v=(opt[:index])
2341
+ prec = i+1
2342
+ elsif v=(opt[:rindex])
2343
+ prec = number_of_digits - v
2242
2344
  else
2243
- d = @coeff.to_s
2244
- p = d.size - i
2245
- d[p..-1].match(/^5d*$/) ? -1 : _round_half_up(i)
2345
+ prec = adjusted_exponent + 1
2346
+ as_int = true
2246
2347
  end
2348
+ result = plus(:rounding=>r, :precision=>prec)
2349
+ return as_int ? result.to_i : result
2350
+ end
2247
2351
 
2352
+ # General ceiling operation (as for Float) with same options for precision
2353
+ # as Decimal#round()
2354
+ def ceil(opt={})
2355
+ opt[:rounding] = :ceiling
2356
+ round opt
2248
2357
  end
2249
2358
 
2250
- # Round to closest i-digit number with ties up (rounds 5 away from 0)
2251
- def _round_half_up(i)
2252
- if ROUND_ARITHMETIC
2253
- m = Decimal.int_radix_power(i)
2254
- if (m>1) && ((@coeff%m) >= m/2)
2255
- 1
2256
- else
2257
- (@coeff % m)==0 ? 0 : -1
2359
+ # General floor operation (as for Float) with same options for precision
2360
+ # as Decimal#round()
2361
+ def floor(opt={})
2362
+ opt[:rounding] = :floor
2363
+ round opt
2364
+ end
2365
+
2366
+ # General truncate operation (as for Float) with same options for precision
2367
+ # as Decimal#round()
2368
+ def truncate(opt={})
2369
+ opt[:rounding] = :down
2370
+ round opt
2371
+ end
2372
+
2373
+ # Fused multiply-add.
2374
+ #
2375
+ # Computes (self*other+third) with no rounding of the intermediate product self*other.
2376
+ def fma(other, third, context=nil)
2377
+ context = Decimal.define_context(context)
2378
+ other = _convert(other)
2379
+ third = _convert(third)
2380
+ if self.special? || other.special?
2381
+ return context.exception(InvalidOperation, 'sNaN', self) if self.snan?
2382
+ return context.exception(InvalidOperation, 'sNaN', other) if other.snan?
2383
+ if self.nan?
2384
+ product = self
2385
+ elsif other.nan?
2386
+ product = other
2387
+ elsif self.infinite?
2388
+ return context.exception(InvalidOperation, 'INF * 0 in fma') if other.zero?
2389
+ product = Decimal.infinity(self.sign*other.sign)
2390
+ elsif other.infinite?
2391
+ return context.exception(InvalidOperation, '0 * INF in fma') if self.zero?
2392
+ product = Decimal.infinity(self.sign*other.sign)
2258
2393
  end
2259
2394
  else
2260
- d = @coeff.to_s
2261
- p = d.size - i
2262
- if '56789'.include?(d[p,1])
2263
- 1
2395
+ product = Decimal.new([self.sign*other.sign,self.integral_significand*other.integral_significand, self.integral_exponent+other.integral_exponent])
2396
+ end
2397
+ return product.add(third, context)
2398
+ end
2399
+
2400
+ # Raises to the power of x, to modulo if given.
2401
+ #
2402
+ # With two arguments, compute self**other. If self is negative then other
2403
+ # must be integral. The result will be inexact unless other is
2404
+ # integral and the result is finite and can be expressed exactly
2405
+ # in 'precision' digits.
2406
+ #
2407
+ # With three arguments, compute (self**other) % modulo. For the
2408
+ # three argument form, the following restrictions on the
2409
+ # arguments hold:
2410
+ #
2411
+ # - all three arguments must be integral
2412
+ # - other must be nonnegative
2413
+ # - at least one of self or other must be nonzero
2414
+ # - modulo must be nonzero and have at most 'precision' digits
2415
+ #
2416
+ # The result of a.power(b, modulo) is identical to the result
2417
+ # that would be obtained by computing (a**b) % modulo with
2418
+ # unbounded precision, but is computed more efficiently. It is
2419
+ # always exact.
2420
+ def power(other, modulo=nil, context=nil)
2421
+
2422
+ if context.nil? && (modulo.is_a?(Context) || modulo.is_a?(Hash))
2423
+ context = modulo
2424
+ modulo = nil
2425
+ end
2426
+
2427
+ return self.power_modulo(other, modulo, context) if modulo
2428
+
2429
+ context = Decimal.define_context(context)
2430
+ other = _convert(other)
2431
+
2432
+ ans = _check_nans(context, other)
2433
+ return ans if ans
2434
+
2435
+ # 0**0 = NaN (!), x**0 = 1 for nonzero x (including +/-Infinity)
2436
+ if other.zero?
2437
+ if self.zero?
2438
+ return context.exception(InvalidOperation, '0 ** 0')
2264
2439
  else
2265
- d[p..-1].match(/^0+$/) ? 0 : -1
2440
+ return Decimal(1)
2266
2441
  end
2267
2442
  end
2268
2443
 
2269
- end
2444
+ # result has sign -1 iff self.sign is -1 and other is an odd integer
2445
+ result_sign = +1
2446
+ _self = self
2447
+ if _self.sign == -1
2448
+ if other.integral?
2449
+ result_sign = -1 if !other.even?
2450
+ else
2451
+ # -ve**noninteger = NaN
2452
+ # (-0)**noninteger = 0**noninteger
2453
+ unless self.zero?
2454
+ return context.exception(InvalidOperation, 'x ** y with x negative and y not an integer')
2455
+ end
2456
+ end
2457
+ # negate self, without doing any unwanted rounding
2458
+ _self = self.copy_negate
2459
+ end
2460
+
2461
+ # 0**(+ve or Inf)= 0; 0**(-ve or -Inf) = Infinity
2462
+ if _self.zero?
2463
+ return (other.sign == +1) ? Decimal(result_sign, 0, 0) : Decimal.infinity(result_sign)
2464
+ end
2465
+
2466
+ # Inf**(+ve or Inf) = Inf; Inf**(-ve or -Inf) = 0
2467
+ if _self.infinite?
2468
+ return (other.sign == +1) ? Decimal.infinity(result_sign) : Decimal(result_sign, 0, 0)
2469
+ end
2470
+
2471
+ # 1**other = 1, but the choice of exponent and the flags
2472
+ # depend on the exponent of self, and on whether other is a
2473
+ # positive integer, a negative integer, or neither
2474
+ if _self == Decimal(1)
2475
+ return _self if context.exact?
2476
+ if other.integral?
2477
+ # exp = max(self._exp*max(int(other), 0),
2478
+ # 1-context.prec) but evaluating int(other) directly
2479
+ # is dangerous until we know other is small (other
2480
+ # could be 1e999999999)
2481
+ if other.sign == -1
2482
+ multiplier = 0
2483
+ elsif other > context.precision
2484
+ multiplier = context.precision
2485
+ else
2486
+ multiplier = other.to_i
2487
+ end
2270
2488
 
2271
- # Round to closest i-digit number with ties (5) to an even digit
2272
- def _round_half_even(i)
2273
- if ROUND_ARITHMETIC
2274
- m = Decimal.int_radix_power(i)
2275
- if (m>1) && ((@coeff%m) == m/2 && ((@coeff/m)%2)==0)
2276
- -1
2489
+ exp = _self.integral_exponent * multiplier
2490
+ if exp < 1-context.precision
2491
+ exp = 1-context.precision
2492
+ context.exception Rounded
2493
+ end
2277
2494
  else
2278
- _round_half_up(i)
2495
+ context.exception Rounded
2496
+ context.exception Inexact
2497
+ exp = 1-context.precision
2498
+ end
2499
+
2500
+ return Decimal(result_sign, Decimal.int_radix_power(-exp), exp)
2501
+ end
2502
+
2503
+ # compute adjusted exponent of self
2504
+ self_adj = _self.adjusted_exponent
2505
+
2506
+ # self ** infinity is infinity if self > 1, 0 if self < 1
2507
+ # self ** -infinity is infinity if self < 1, 0 if self > 1
2508
+ if other.infinite?
2509
+ if (other.sign == +1) == (self_adj < 0)
2510
+ return Decimal(result_sign, 0, 0)
2511
+ else
2512
+ return Decimal.infinity(result_sign)
2513
+ end
2514
+ end
2515
+
2516
+ # from here on, the result always goes through the call
2517
+ # to _fix at the end of this function.
2518
+ ans = nil
2519
+
2520
+ # crude test to catch cases of extreme overflow/underflow. If
2521
+ # log10(self)*other >= 10**bound and bound >= len(str(Emax))
2522
+ # then 10**bound >= 10**len(str(Emax)) >= Emax+1 and hence
2523
+ # self**other >= 10**(Emax+1), so overflow occurs. The test
2524
+ # for underflow is similar.
2525
+ bound = _self._log10_exp_bound + other.adjusted_exponent
2526
+ if (self_adj >= 0) == (other.sign == +1)
2527
+ # self > 1 and other +ve, or self < 1 and other -ve
2528
+ # possibility of overflow
2529
+ if bound >= context.emax.to_s.length
2530
+ ans = Decimal(result_sign, 1, context.emax+1)
2279
2531
  end
2280
2532
  else
2281
- d = @coeff.to_s
2282
- p = d.size - i
2533
+ # self > 1 and other -ve, or self < 1 and other +ve
2534
+ # possibility of underflow to 0
2535
+ etiny = context.etiny
2536
+ if bound >= (-etiny).to_s.length
2537
+ ans = Decimal(result_sign, 1, etiny-1)
2538
+ end
2539
+ end
2283
2540
 
2284
- if d[p..-1].match(/\A#{radix/2}0*\Z/) && (p==0 || ((d[p-1,1].to_i%2)==0))
2285
- -1
2541
+ # try for an exact result with precision +1
2542
+ if ans.nil?
2543
+ if context.exact?
2544
+ if other.adjusted_exponent < 100
2545
+ test_precision = _self.number_of_digits*other.to_i+1
2546
+ else
2547
+ test_precision = _self.number_of_digits+1
2548
+ end
2286
2549
  else
2287
- _round_half_up(i)
2550
+ test_precision = context.precision + 1
2288
2551
  end
2552
+ ans = _self._power_exact(other, test_precision)
2553
+ if !ans.nil? && (result_sign == -1)
2554
+ ans = Decimal(-1, ans.integral_significand, ans.integral_exponent)
2555
+ end
2556
+ end
2289
2557
 
2558
+ # usual case: inexact result, x**y computed directly as exp(y*log(x))
2559
+ if !ans.nil?
2560
+ return ans if context.exact?
2561
+ else
2562
+ return context.exception(Inexact, "Inexact power") if context.exact?
2563
+
2564
+ p = context.precision
2565
+ xc = _self.integral_significand
2566
+ xe = _self.integral_exponent
2567
+ yc = other.integral_significand
2568
+ ye = other.integral_exponent
2569
+ yc = -yc if other.sign == -1
2570
+
2571
+ # compute correctly rounded result: start with precision +3,
2572
+ # then increase precision until result is unambiguously roundable
2573
+ extra = 3
2574
+ coeff, exp = nil, nil
2575
+ loop do
2576
+ coeff, exp = _dpower(xc, xe, yc, ye, p+extra)
2577
+ #break if (coeff % Decimal.int_mult_radix_power(5,coeff.to_s.length-p-1)) != 0
2578
+ break if (coeff % (5*10**(coeff.to_s.length-p-1))) != 0
2579
+ extra += 3
2580
+ end
2581
+ ans = Decimal(result_sign, coeff, exp)
2290
2582
  end
2291
- end
2292
2583
 
2293
- # Round up (not away from 0 if negative) to i digits
2294
- def _round_ceiling(i)
2295
- sign<0 ? _round_down(i) : -_round_down(i)
2584
+ # the specification says that for non-integer other we need to
2585
+ # raise Inexact, even when the result is actually exact. In
2586
+ # the same way, we need to raise Underflow here if the result
2587
+ # is subnormal. (The call to _fix will take care of raising
2588
+ # Rounded and Subnormal, as usual.)
2589
+ if !other.integral?
2590
+ context.exception Inexact
2591
+ # pad with zeros up to length context.precision+1 if necessary
2592
+ if ans.number_of_digits <= context.precision
2593
+ expdiff = context.precision+1 - ans.number_of_digits
2594
+ ans = Decimal(ans.sign, Decimal.int_mult_radix_power(ans.integral_significand, expdiff), ans.integral_exponent-expdiff)
2595
+ end
2596
+ context.exception Underflow if ans.adjusted_exponent < context.emin
2597
+ end
2598
+ # unlike exp, ln and log10, the power function respects the
2599
+ # rounding mode; no need to use ROUND_HALF_EVEN here
2600
+ ans._fix(context)
2296
2601
  end
2297
2602
 
2298
- # Round down (not toward 0 if negative) to i digits
2299
- def _round_floor(i)
2300
- sign>0 ? _round_down(i) : -_round_down(i)
2301
- end
2603
+ # Returns the base 10 logarithm
2604
+ def log10(context=nil)
2605
+ context = Decimal.define_context(context)
2302
2606
 
2303
- # Round down unless digit i-1 is 0 or 5
2304
- def _round_up05(i)
2305
- if ROUND_ARITHMETIC
2306
- dg = (@coeff%Decimal.int_radix_power(i+1))/Decimal.int_radix_power(i)
2607
+ # log10(NaN) = NaN
2608
+ ans = _check_nans(context)
2609
+ return ans if ans
2610
+
2611
+ # log10(0.0) == -Infinity
2612
+ return Decimal.infinity(-1) if self.zero?
2613
+
2614
+ # log10(Infinity) = Infinity
2615
+ return Decimal.infinity if self.infinite? && self.sign == +1
2616
+
2617
+ # log10(negative or -Infinity) raises InvalidOperation
2618
+ return context.exception(InvalidOperation, 'log10 of a negative value') if self.sign == -1
2619
+
2620
+ digits = self.digits
2621
+ # log10(10**n) = n
2622
+ if digits.first == 1 && digits[1..-1].all?{|d| d==0}
2623
+ # answer may need rounding
2624
+ ans = Decimal(self.integral_exponent + digits.size - 1)
2625
+ return ans if context.exact?
2307
2626
  else
2308
- d = @coeff.to_s
2309
- p = d.size - i
2310
- dg = (p>0) ? d[p-1,1].to_i : 0
2627
+ # result is irrational, so necessarily inexact
2628
+ return context.exception(Inexact, "Inexact power") if context.exact?
2629
+ c = self.integral_significand
2630
+ e = self.integral_exponent
2631
+ p = context.precision
2632
+
2633
+ # correctly rounded result: repeatedly increase precision
2634
+ # until result is unambiguously roundable
2635
+ places = p-self._log10_exp_bound+2
2636
+ coeff = nil
2637
+ loop do
2638
+ coeff = _dlog10(c, e, places)
2639
+ # assert coeff.abs.to_s.length-p >= 1
2640
+ break if (coeff % (5*10**(coeff.abs.to_s.length-p-1)))!=0
2641
+ places += 3
2642
+ end
2643
+ ans = Decimal(coeff<0 ? -1 : +1, coeff.abs, -places)
2311
2644
  end
2312
- if [0,Decimal.radix/2].include?(dg)
2313
- -_round_down(i)
2314
- else
2315
- _round_down(i)
2645
+
2646
+ Decimal.context(context, :rounding=>:half_even) do |local_context|
2647
+ ans = ans._fix(local_context)
2648
+ context.flags = local_context.flags
2316
2649
  end
2650
+ return ans
2317
2651
  end
2318
2652
 
2319
- # adjust payload of a NaN to the context
2320
- def _fix_nan(context)
2321
- if !context.exact?
2322
- payload = @coeff
2323
- payload = nil if payload==0
2653
+ # Exponential function
2654
+ def exp(context=nil)
2655
+ context = Decimal.define_context(context)
2324
2656
 
2325
- max_payload_len = context.maximum_nan_diagnostic_digits
2657
+ # exp(NaN) = NaN
2658
+ ans = _check_nans(context)
2659
+ return ans if ans
2326
2660
 
2327
- if number_of_digits > max_payload_len
2328
- payload = payload.to_s[-max_payload_len..-1].to_i
2329
- return Decimal([@sign, payload, @exp])
2661
+ # exp(-Infinity) = 0
2662
+ return Decimal.zero if self.infinite? && (self.sign == -1)
2663
+
2664
+ # exp(0) = 1
2665
+ return Decimal(1) if self.zero?
2666
+
2667
+ # exp(Infinity) = Infinity
2668
+ return Decimal(self) if self.infinite?
2669
+
2670
+ # the result is now guaranteed to be inexact (the true
2671
+ # mathematical result is transcendental). There's no need to
2672
+ # raise Rounded and Inexact here---they'll always be raised as
2673
+ # a result of the call to _fix.
2674
+ return context.exception(Inexact, 'Inexact exp') if context.exact?
2675
+ p = context.precision
2676
+ adj = self.adjusted_exponent
2677
+
2678
+ # we only need to do any computation for quite a small range
2679
+ # of adjusted exponents---for example, -29 <= adj <= 10 for
2680
+ # the default context. For smaller exponent the result is
2681
+ # indistinguishable from 1 at the given precision, while for
2682
+ # larger exponent the result either overflows or underflows.
2683
+ if self.sign == +1 and adj > ((context.emax+1)*3).to_s.length
2684
+ # overflow
2685
+ ans = Decimal(+1, 1, context.emax+1)
2686
+ elsif self.sign == -1 and adj > ((-context.etiny+1)*3).to_s.length
2687
+ # underflow to 0
2688
+ ans = Decimal(+1, 1, context.etiny-1)
2689
+ elsif self.sign == +1 and adj < -p
2690
+ # p+1 digits; final round will raise correct flags
2691
+ ans = Decimal(+1, Decimal.int_radix_power(p)+1, -p)
2692
+ elsif self.sign == -1 and adj < -p-1
2693
+ # p+1 digits; final round will raise correct flags
2694
+ ans = Decimal(+1, Decimal.int_radix_power(p+1)-1, -p-1)
2695
+ else
2696
+ # general case
2697
+ c = self.integral_significand
2698
+ e = self.integral_exponent
2699
+ c = -c if self.sign == -1
2700
+
2701
+ # compute correctly rounded result: increase precision by
2702
+ # 3 digits at a time until we get an unambiguously
2703
+ # roundable result
2704
+ extra = 3
2705
+ coeff = exp = nil
2706
+ loop do
2707
+ coeff, exp = _dexp(c, e, p+extra)
2708
+ break if (coeff % (5*10**(coeff.to_s.length-p-1)))!=0
2709
+ extra += 3
2330
2710
  end
2711
+ ans = Decimal(+1, coeff, exp)
2331
2712
  end
2332
- Decimal(self)
2713
+
2714
+ # at this stage, ans should round correctly with *any*
2715
+ # rounding mode, not just with ROUND_HALF_EVEN
2716
+ Decimal.context(context, :rounding=>:half_even) do |local_context|
2717
+ ans = ans._fix(local_context)
2718
+ context.flags = local_context.flags
2719
+ end
2720
+
2721
+ return ans
2722
+ end
2723
+
2724
+ # Returns the natural (base e) logarithm
2725
+ def ln(context=nil)
2726
+ context = Decimal.define_context(context)
2727
+
2728
+ # ln(NaN) = NaN
2729
+ ans = _check_nans(context)
2730
+ return ans if ans
2731
+
2732
+ # ln(0.0) == -Infinity
2733
+ return Decimal.infinity(-1) if self.zero?
2734
+
2735
+ # ln(Infinity) = Infinity
2736
+ return Decimal.infinity if self.infinite? && self.sign == +1
2737
+
2738
+ # ln(1.0) == 0.0
2739
+ return Decimal.zero if self == Decimal(1)
2740
+
2741
+ # ln(negative) raises InvalidOperation
2742
+ return context.exception(InvalidOperation, 'ln of a negative value') if self.sign==-1
2743
+
2744
+ # result is irrational, so necessarily inexact
2745
+ return context.exception(Inexact, 'Inexact exp') if context.exact?
2746
+
2747
+ c = self.integral_significand
2748
+ e = self.integral_exponent
2749
+ p = context.precision
2750
+
2751
+ # correctly rounded result: repeatedly increase precision by 3
2752
+ # until we get an unambiguously roundable result
2753
+ places = p - self._ln_exp_bound + 2 # at least p+3 places
2754
+ coeff = nil
2755
+ loop do
2756
+ coeff = _dlog(c, e, places)
2757
+ # assert coeff.to_s.length-p >= 1
2758
+ break if (coeff % (5*10**(coeff.abs.to_s.length-p-1))) != 0
2759
+ places += 3
2760
+ end
2761
+ ans = Decimal((coeff<0) ? -1 : +1, coeff.abs, -places)
2762
+
2763
+ Decimal.context(context, :rounding=>:half_even) do |local_context|
2764
+ ans = ans._fix(local_context)
2765
+ context.flags = local_context.flags
2766
+ end
2767
+ return ans
2333
2768
  end
2334
2769
 
2770
+ # Auxiliar Methods
2771
+
2335
2772
  # Check if the number or other is NaN, signal if sNaN or return NaN;
2336
2773
  # return nil if none is NaN.
2337
2774
  def _check_nans(context=nil, other=nil)
@@ -2377,113 +2814,23 @@ class Decimal
2377
2814
 
2378
2815
  end
2379
2816
 
2380
- # Normalizes op1, op2 to have the same exp and length of coefficient. Used for addition.
2381
- def Decimal._normalize(op1, op2, prec=0)
2382
- #puts "N: #{op1.inspect} #{op2.inspect} p=#{prec}"
2383
- if op1.integral_exponent < op2.integral_exponent
2384
- swap = true
2385
- tmp,other = op2,op1
2386
- else
2387
- swap = false
2388
- tmp,other = op1,op2
2817
+ def _watched_rescale(exp, context, watch_exp)
2818
+ if !watch_exp
2819
+ ans = _rescale(exp, context.rounding)
2820
+ context.exception(Rounded) if ans.integral_exponent > self.integral_exponent
2821
+ context.exception(Inexact) if ans != self
2822
+ return ans
2389
2823
  end
2390
- tmp_len = tmp.number_of_digits
2391
- other_len = other.number_of_digits
2392
- exp = tmp.integral_exponent + [-1, tmp_len - prec - 2].min
2393
- #puts "exp=#{exp}"
2394
- if (other_len+other.integral_exponent-1 < exp) && prec>0
2395
- other = Decimal.new([other.sign, 1, exp])
2396
- #puts "other = #{other.inspect}"
2824
+
2825
+ if exp < context.etiny || exp > context.emax
2826
+ return context.exception(InvalidOperation, "target operation out of bounds in quantize/rescale")
2397
2827
  end
2398
- tmp = Decimal.new([tmp.sign, int_mult_radix_power(tmp.integral_significand, tmp.integral_exponent-other.integral_exponent), other.integral_exponent])
2399
- #puts "tmp=#{tmp.inspect}"
2400
- return swap ? [other, tmp] : [tmp, other]
2401
- end
2402
2828
 
2403
- # Returns a copy of with the sign set to +
2404
- def copy_abs
2405
- Decimal.new([+1,@coeff,@exp])
2406
- end
2829
+ return Decimal.new([@sign, 0, exp])._fix(context) if zero?
2407
2830
 
2408
- # Returns a copy of with the sign inverted
2409
- def copy_negate
2410
- Decimal.new([-@sign,@coeff,@exp])
2411
- end
2412
-
2413
- # Returns a copy of with the sign of other
2414
- def copy_sign(other)
2415
- Decimal.new([other.sign, @coeff, @exp])
2416
- end
2417
-
2418
- # Returns true if the value is an integer
2419
- def integral?
2420
- if finite?
2421
- if @exp>=0 || @coeff==0
2422
- true
2423
- else
2424
- if @exp <= -number_of_digits
2425
- false
2426
- else
2427
- m = Decimal.int_radix_power(-@exp)
2428
- (@coeff % m) == 0
2429
- end
2430
- end
2431
- else
2432
- false
2433
- end
2434
- end
2435
-
2436
- # Rescale so that the exponent is exp, either by padding with zeros
2437
- # or by truncating digits.
2438
- def rescale(exp, context=nil, watch_exp=true)
2439
- context = Decimal.define_context(context)
2440
- exp = Decimal._convert(exp)
2441
- if self.special? || exp.special?
2442
- ans = _check_nans(context, exp)
2443
- return ans if ans
2444
- if exp.infinite? || self.infinite?
2445
- return Decimal.new(self) if exp.infinite? && self.infinite?
2446
- return context.exception(InvalidOperation, 'rescale with one INF')
2447
- end
2448
- end
2449
- return context.exception(InvalidOperation,"exponent of rescale is not integral") unless exp.integral?
2450
- exp = exp.to_i
2451
- _watched_rescale(exp, context, watch_exp)
2452
- end
2453
-
2454
- # Quantize so its exponent is the same as that of y.
2455
- def quantize(exp, context=nil, watch_exp=true)
2456
- exp = Decimal._convert(exp)
2457
- context = Decimal.define_context(context)
2458
- if self.special? || exp.special?
2459
- ans = _check_nans(context, exp)
2460
- return ans if ans
2461
- if exp.infinite? || self.infinite?
2462
- return Decimal.new(self) if exp.infinite? && self.infinite?
2463
- return context.exception(InvalidOperation, 'quantize with one INF')
2464
- end
2465
- end
2466
- exp = exp.integral_exponent
2467
- _watched_rescale(exp, context, watch_exp)
2468
- end
2469
-
2470
- def _watched_rescale(exp, context, watch_exp)
2471
- if !watch_exp
2472
- ans = _rescale(exp, context.rounding)
2473
- context.exception(Rounded) if ans.integral_exponent > self.integral_exponent
2474
- context.exception(Inexact) if ans != self
2475
- return ans
2476
- end
2477
-
2478
- if exp < context.etiny || exp > context.emax
2479
- return context.exception(InvalidOperation, "target operation out of bounds in quantize/rescale")
2480
- end
2481
-
2482
- return Decimal.new([@sign, 0, exp])._fix(context) if zero?
2483
-
2484
- self_adjusted = adjusted_exponent
2485
- return context.exception(InvalidOperation,"exponent of quantize/rescale result too large for current context") if self_adjusted > context.emax
2486
- return context.exception(InvalidOperation,"quantize/rescale has too many digits for current context") if (self_adjusted - exp + 1 > context.precision) && !context.exact?
2831
+ self_adjusted = adjusted_exponent
2832
+ return context.exception(InvalidOperation,"exponent of quantize/rescale result too large for current context") if self_adjusted > context.emax
2833
+ return context.exception(InvalidOperation,"quantize/rescale has too many digits for current context") if (self_adjusted - exp + 1 > context.precision) && !context.exact?
2487
2834
 
2488
2835
  ans = _rescale(exp, context.rounding)
2489
2836
  return context.exception(InvalidOperation,"exponent of rescale result too large for current context") if ans.adjusted_exponent > context.emax
@@ -2496,147 +2843,153 @@ class Decimal
2496
2843
  return ans._fix(context)
2497
2844
  end
2498
2845
 
2499
- # Return true if has the same exponent as other.
2500
- #
2501
- # If either operand is a special value, the following rules are used:
2502
- # * return true if both operands are infinities
2503
- # * return true if both operands are NaNs
2504
- # * otherwise, return false.
2505
- def same_quantum?(other)
2506
- other = Decimal._convert(other)
2507
- if self.special? || other.special?
2508
- return (self.nan? && other.nan?) || (self.infinite? && other.infinite?)
2846
+ # Returns copy with sign inverted
2847
+ def _neg(context=nil)
2848
+ if special?
2849
+ ans = _check_nans(context)
2850
+ return ans if ans
2509
2851
  end
2510
- return self.integral_exponent == other.integral_exponent
2852
+ if zero?
2853
+ ans = copy_abs
2854
+ else
2855
+ ans = copy_negate
2856
+ end
2857
+ context = Decimal.define_context(context)
2858
+ ans._fix(context)
2511
2859
  end
2512
2860
 
2513
- # Rounds to a nearby integer. May raise Inexact or Rounded.
2514
- def to_integral_exact(context=nil)
2515
- context = Decimal.define_context(context)
2861
+ # Returns a copy with precision adjusted
2862
+ def _pos(context=nil)
2516
2863
  if special?
2517
2864
  ans = _check_nans(context)
2518
2865
  return ans if ans
2519
- return Decimal.new(self)
2520
2866
  end
2521
- return Decimal.new(self) if @exp >= 0
2522
- return Decimal.new([@sign, 0, 0]) if zero?
2523
- context.exception Rounded
2524
- ans = _rescale(0, context.rounding)
2525
- context.exception Inexact if ans != self
2526
- return ans
2867
+ if zero?
2868
+ ans = copy_abs
2869
+ else
2870
+ ans = Decimal.new(self)
2871
+ end
2872
+ context = Decimal.define_context(context)
2873
+ ans._fix(context)
2527
2874
  end
2528
2875
 
2529
- # Rounds to a nearby integer. Doesn't raise Inexact or Rounded.
2530
- def to_integral_value(context=nil)
2531
- context = Decimal.define_context(context)
2876
+ # Returns a copy with positive sign
2877
+ def _abs(round=true, context=nil)
2878
+ return copy_abs if not round
2879
+
2532
2880
  if special?
2533
2881
  ans = _check_nans(context)
2534
2882
  return ans if ans
2535
- return Decimal.new(self)
2536
2883
  end
2537
- return Decimal.new(self) if @exp >= 0
2538
- return _rescale(0, context.rounding)
2539
- end
2540
-
2541
- # General rounding.
2542
- #
2543
- # With an integer argument this acts like Float#round: the parameter specifies the number
2544
- # of fractional digits (or digits to the left of the decimal point if negative).
2545
- #
2546
- # Options can be passed as a Hash instead; valid options are:
2547
- # * :rounding method for rounding (see Context#new())
2548
- # The precision can be specified as:
2549
- # * :places number of fractional digits as above.
2550
- # * :exponent specifies the exponent corresponding to the
2551
- # digit to be rounded (exponent == -places)
2552
- # * :precision or :significan_digits is the number of digits
2553
- # * :power 10^exponent, value of the digit to be rounded,
2554
- # should be passed as a type convertible to Decimal.
2555
- # * :index 0-based index of the digit to be rounded
2556
- # * :rindex right 0-based index of the digit to be rounded
2557
- #
2558
- # The default is :places=>0 (round to integer).
2559
- #
2560
- # Example: ways of specifiying the rounding position
2561
- # number: 1 2 3 4 . 5 6 7 8
2562
- # :places -3 -2 -1 0 1 2 3 4
2563
- # :exponent 3 2 1 0 -1 -2 -3 -4
2564
- # :precision 1 2 3 4 5 6 7 8
2565
- # :power 1E3 1E2 10 1 0.1 1E-2 1E-3 1E-4
2566
- # :index 0 1 2 3 4 5 6 7
2567
- # :index 7 6 5 4 3 2 1 0
2568
- def round(opt={})
2569
- opt = { :places=>opt } if opt.kind_of?(Integer)
2570
- r = opt[:rounding] || :half_up
2571
- as_int = false
2572
- if v=(opt[:precision] || opt[:significant_digits])
2573
- prec = v
2574
- elsif v=(opt[:places])
2575
- prec = adjusted_exponent + 1 + v
2576
- elsif v=(opt[:exponent])
2577
- prec = adjusted_exponent + 1 - v
2578
- elsif v=(opt[:power])
2579
- prec = adjusted_exponent + 1 - Decimal(v).adjusted_exponent
2580
- elsif v=(opt[:index])
2581
- prec = i+1
2582
- elsif v=(opt[:rindex])
2583
- prec = number_of_digits - v
2884
+ if sign>0
2885
+ ans = _neg(context)
2584
2886
  else
2585
- prec = adjusted_exponent + 1
2586
- as_int = true
2887
+ ans = _pos(context)
2587
2888
  end
2588
- result = plus(:rounding=>r, :precision=>prec)
2589
- return as_int ? result.to_i : result
2889
+ ans
2590
2890
  end
2591
2891
 
2592
- # General ceiling operation (as for Float) with same options for precision
2593
- # as Decimal#round()
2594
- def ceil(opt={})
2595
- opt[:rounding] = :ceiling
2596
- round opt
2597
- end
2892
+ # Round if it is necessary to keep within precision.
2893
+ def _fix(context)
2894
+ return self if context.exact?
2598
2895
 
2599
- # General floor operation (as for Float) with same options for precision
2600
- # as Decimal#round()
2601
- def floor(opt={})
2602
- opt[:rounding] = :floor
2603
- round opt
2604
- end
2896
+ if special?
2897
+ if nan?
2898
+ return _fix_nan(context)
2899
+ else
2900
+ return Decimal.new(self)
2901
+ end
2902
+ end
2903
+
2904
+ etiny = context.etiny
2905
+ etop = context.etop
2906
+ if zero?
2907
+ exp_max = context.clamp? ? etop : context.emax
2908
+ new_exp = [[@exp, etiny].max, exp_max].min
2909
+ if new_exp!=@exp
2910
+ context.exception Clamped
2911
+ return Decimal.new([sign,0,new_exp])
2912
+ else
2913
+ return Decimal.new(self)
2914
+ end
2915
+ end
2916
+
2917
+ nd = number_of_digits
2918
+ exp_min = nd + @exp - context.precision
2919
+ if exp_min > etop
2920
+ context.exception Inexact
2921
+ context.exception Rounded
2922
+ return context.exception(Overflow, 'above Emax', sign)
2923
+ end
2924
+
2925
+ self_is_subnormal = exp_min < etiny
2926
+
2927
+ if self_is_subnormal
2928
+ context.exception Subnormal
2929
+ exp_min = etiny
2930
+ end
2931
+
2932
+ if @exp < exp_min
2933
+ context.exception Rounded
2934
+ # dig is the digits number from 0 (MS) to number_of_digits-1 (LS)
2935
+ # dg = numberof_digits-dig is from 1 (LS) to number_of_digits (MS)
2936
+ dg = exp_min - @exp # dig = number_of_digits + exp - exp_min
2937
+ if dg > number_of_digits # dig<0
2938
+ d = Decimal.new([sign,1,exp_min-1])
2939
+ dg = number_of_digits # dig = 0
2940
+ else
2941
+ d = Decimal.new(self)
2942
+ end
2943
+ changed = d._round(context.rounding, dg)
2944
+ coeff = Decimal.int_div_radix_power(d.integral_significand, dg)
2945
+ coeff += 1 if changed==1
2946
+ ans = Decimal.new([sign, coeff, exp_min])
2947
+ if changed!=0
2948
+ context.exception Inexact
2949
+ if self_is_subnormal
2950
+ context.exception Underflow
2951
+ if ans.zero?
2952
+ context.exception Clamped
2953
+ end
2954
+ elsif ans.number_of_digits == context.precision+1
2955
+ if ans.integral_exponent< etop
2956
+ ans = Decimal.new([ans.sign, Decimal.int_div_radix_power(ans.integral_significand,1), ans.integral_exponent+1])
2957
+ else
2958
+ ans = context.exception(Overflow, 'above Emax', d.sign)
2959
+ end
2960
+ end
2961
+ end
2962
+ return ans
2963
+ end
2964
+
2965
+ if context.clamp? && @exp>etop
2966
+ context.exception Clamped
2967
+ self_padded = Decimal.int_mult_radix_power(@coeff, @exp-etop)
2968
+ return Decimal.new([sign,self_padded,etop])
2969
+ end
2970
+
2971
+ return Decimal.new(self)
2605
2972
 
2606
- # General truncate operation (as for Float) with same options for precision
2607
- # as Decimal#round()
2608
- def truncate(opt={})
2609
- opt[:rounding] = :down
2610
- round opt
2611
2973
  end
2612
2974
 
2613
- # Fused multiply-add.
2614
- #
2615
- # Computes (self*other+third) with no rounding of the intermediate product self*other.
2616
- def fma(other, third, context=nil)
2617
- context = Decimal.define_context(context)
2618
- other = Decimal._convert(other)
2619
- third = Decimal._convert(third)
2620
- if self.special? || other.special?
2621
- return context.exception(InvalidOperation, 'sNaN', self) if self.snan?
2622
- return context.exception(InvalidOperation, 'sNaN', other) if other.snan?
2623
- if self.nan?
2624
- product = self
2625
- elsif other.nan?
2626
- product = other
2627
- elsif self.infinite?
2628
- return context.exception(InvalidOperation, 'INF * 0 in fma') if other.zero?
2629
- product = Decimal.infinity(self.sign*other.sign)
2630
- elsif other.infinite?
2631
- return context.exception(InvalidOperation, '0 * INF in fma') if self.zero?
2632
- product = Decimal.infinity(self.sign*other.sign)
2975
+ # adjust payload of a NaN to the context
2976
+ def _fix_nan(context)
2977
+ if !context.exact?
2978
+ payload = @coeff
2979
+ payload = nil if payload==0
2980
+
2981
+ max_payload_len = context.maximum_nan_diagnostic_digits
2982
+
2983
+ if number_of_digits > max_payload_len
2984
+ payload = payload.to_s[-max_payload_len..-1].to_i
2985
+ return Decimal([@sign, payload, @exp])
2633
2986
  end
2634
- else
2635
- product = Decimal.new([self.sign*other.sign,self.integral_significand*other.integral_significand, self.integral_exponent+other.integral_exponent])
2636
2987
  end
2637
- return product.add(third, context)
2988
+ Decimal(self)
2638
2989
  end
2639
2990
 
2991
+ protected
2992
+
2640
2993
  def _divide_truncate(other, context)
2641
2994
  context = Decimal.define_context(context)
2642
2995
  sign = self.sign * other.sign
@@ -2715,28 +3068,869 @@ class Decimal
2715
3068
 
2716
3069
  end
2717
3070
 
2718
- # Convert a numeric value to decimal (internal use)
2719
- def Decimal._convert(x, error=true)
2720
- case x
2721
- when Decimal
2722
- x
2723
- when *Decimal.context.coercible_types
2724
- Decimal.new(x)
3071
+ # Power-modulo: self._power_modulo(other, modulo) == (self**other) % modulo
3072
+ # This is equivalent to Python's 3-argument version of pow()
3073
+ def _power_modulo(other, modulo, context=nil)
3074
+
3075
+ context = Decimal.define_context(context)
3076
+ other = _convert(other)
3077
+ modulo = _convert(third)
3078
+
3079
+ if self.nan? || other.nan? || modulo.nan?
3080
+ return context.exception(InvalidOperation, 'sNaN', self) if self.snan?
3081
+ return context.exception(InvalidOperation, 'sNaN', other) if other.snan?
3082
+ return context.exception(InvalidOperation, 'sNaN', modulo) if other.modulo?
3083
+ return self._fix_nan(context) if self.nan?
3084
+ return other._fix_nan(context) if other.nan?
3085
+ return modulo._fix_nan(context) # if modulo.nan?
3086
+ end
3087
+
3088
+ if !(self.integral? && other.integral? && modulo.integral?)
3089
+ return context.exception(InvalidOperation, '3-argument power not allowed unless all arguments are integers.')
3090
+ end
3091
+
3092
+ if other < 0
3093
+ return context.exception(InvalidOperation, '3-argument power cannot have a negative 2nd argument.')
3094
+ end
3095
+
3096
+ if modulo.zero?
3097
+ return context.exception(InvalidOperation, '3-argument power cannot have a 0 3rd argument.')
3098
+ end
3099
+
3100
+ if modulo.adjusted_exponent >= context.precision
3101
+ return context.exception(InvalidOperation, 'insufficient precision: power 3rd argument must not have more than precision digits')
3102
+ end
3103
+
3104
+ if other.zero? && self.zero?
3105
+ return context.exception(InvalidOperation, "0**0 not defined")
3106
+ end
3107
+
3108
+ sign = other.even? ? +1 : -1
3109
+ modulo = modulo.to_i.abs
3110
+
3111
+ base = (self.integral_significand % modulo * (Decimal.int_radix_power(self.integral_exponent) % modulo)) % modulo
3112
+
3113
+ other.integral_exponent.times do
3114
+ base = (base**Decimal.radix) % modulo
3115
+ end
3116
+ base = (base**other.integral_significand) % modulo
3117
+
3118
+ Decimal(sign, base, 0)
3119
+ end
3120
+
3121
+ # Attempt to compute self**other exactly
3122
+ # Given Decimals self and other and an integer p, attempt to
3123
+ # compute an exact result for the power self**other, with p
3124
+ # digits of precision. Return nil if self**other is not
3125
+ # exactly representable in p digits.
3126
+ #
3127
+ # Assumes that elimination of special cases has already been
3128
+ # performed: self and other must both be nonspecial; self must
3129
+ # be positive and not numerically equal to 1; other must be
3130
+ # nonzero. For efficiency, other.integral_exponent should not be too large,
3131
+ # so that 10**other.integral.exponent.abs is a feasible calculation.
3132
+ def _power_exact(other, p)
3133
+
3134
+ # In the comments below, we write x for the value of self and
3135
+ # y for the value of other. Write x = xc*10**xe and y =
3136
+ # yc*10**ye.
3137
+
3138
+ # The main purpose of this method is to identify the *failure*
3139
+ # of x**y to be exactly representable with as little effort as
3140
+ # possible. So we look for cheap and easy tests that
3141
+ # eliminate the possibility of x**y being exact. Only if all
3142
+ # these tests are passed do we go on to actually compute x**y.
3143
+
3144
+ # Here's the main idea. First normalize both x and y. We
3145
+ # express y as a rational m/n, with m and n relatively prime
3146
+ # and n>0. Then for x**y to be exactly representable (at
3147
+ # *any* precision), xc must be the nth power of a positive
3148
+ # integer and xe must be divisible by n. If m is negative
3149
+ # then additionally xc must be a power of either 2 or 5, hence
3150
+ # a power of 2**n or 5**n.
3151
+ #
3152
+ # There's a limit to how small |y| can be: if y=m/n as above
3153
+ # then:
3154
+ #
3155
+ # (1) if xc != 1 then for the result to be representable we
3156
+ # need xc**(1/n) >= 2, and hence also xc**|y| >= 2. So
3157
+ # if |y| <= 1/nbits(xc) then xc < 2**nbits(xc) <=
3158
+ # 2**(1/|y|), hence xc**|y| < 2 and the result is not
3159
+ # representable.
3160
+ #
3161
+ # (2) if xe != 0, |xe|*(1/n) >= 1, so |xe|*|y| >= 1. Hence if
3162
+ # |y| < 1/|xe| then the result is not representable.
3163
+ #
3164
+ # Note that since x is not equal to 1, at least one of (1) and
3165
+ # (2) must apply. Now |y| < 1/nbits(xc) iff |yc|*nbits(xc) <
3166
+ # 10**-ye iff len(str(|yc|*nbits(xc)) <= -ye.
3167
+ #
3168
+ # There's also a limit to how large y can be, at least if it's
3169
+ # positive: the normalized result will have coefficient xc**y,
3170
+ # so if it's representable then xc**y < 10**p, and y <
3171
+ # p/log10(xc). Hence if y*log10(xc) >= p then the result is
3172
+ # not exactly representable.
3173
+
3174
+ # if len(str(abs(yc*xe)) <= -ye then abs(yc*xe) < 10**-ye,
3175
+ # so |y| < 1/xe and the result is not representable.
3176
+ # Similarly, len(str(abs(yc)*xc_bits)) <= -ye implies |y|
3177
+ # < 1/nbits(xc).
3178
+
3179
+ xc = self.integral_significand
3180
+ xe = self.integral_exponent
3181
+ while (xc % Decimal.radix) == 0
3182
+ xc /= Decimal.radix
3183
+ xe += 1
3184
+ end
3185
+
3186
+ yc = other.integral_significand
3187
+ ye = other.integral_exponent
3188
+ while (yc % Decimal.radix) == 0
3189
+ yc /= Decimal.radix
3190
+ ye += 1
3191
+ end
3192
+
3193
+ # case where xc == 1: result is 10**(xe*y), with xe*y
3194
+ # required to be an integer
3195
+ if xc == 1
3196
+ if ye >= 0
3197
+ exponent = xe*yc*Decimal.int_radix_power(ye)
3198
+ else
3199
+ exponent, remainder = (xe*yc).divmod(Decimal.int_radix_power(-ye))
3200
+ return nil if remainder!=0
3201
+ end
3202
+ exponent = -exponent if other.sign == -1
3203
+ # if other is a nonnegative integer, use ideal exponent
3204
+ if other.integral? and (other.sign == +1)
3205
+ ideal_exponent = self.integral_exponent*other.to_i
3206
+ zeros = [exponent-ideal_exponent, p-1].min
3207
+ else
3208
+ zeros = 0
3209
+ end
3210
+ return Decimal(+1, Decimal.int_radix_power(zeros), exponent-zeros)
3211
+ end
3212
+
3213
+ # case where y is negative: xc must be either a power
3214
+ # of 2 or a power of 5.
3215
+ if other.sign == -1
3216
+ last_digit = (xc % 10)
3217
+ if [2,4,6,8].include?(last_digit)
3218
+ # quick test for power of 2
3219
+ return nil if xc & -xc != xc
3220
+ # now xc is a power of 2; e is its exponent
3221
+ e = _nbits(xc)-1
3222
+ # find e*y and xe*y; both must be integers
3223
+ if ye >= 0
3224
+ y_as_int = yc*Decimal.int_radix_power(ye)
3225
+ e = e*y_as_int
3226
+ xe = xe*y_as_int
3227
+ else
3228
+ ten_pow = Decimal.int_radix_power(-ye)
3229
+ e, remainder = (e*yc).divmod(ten_pow)
3230
+ return nil if remainder!=0
3231
+ xe, remainder = (xe*yc).divmod(ten_pow)
3232
+ return nil if remainder!=0
3233
+ end
3234
+
3235
+ return nil if e*65 >= p*93 # 93/65 > log(10)/log(5)
3236
+ xc = 5**e
3237
+ elsif last_digit == 5
3238
+ # e >= log_5(xc) if xc is a power of 5; we have
3239
+ # equality all the way up to xc=5**2658
3240
+ e = _nbits(xc)*28/65
3241
+ xc, remainder = (5**e).divmod(xc)
3242
+ return nil if remainder!=0
3243
+ while (xc % 5) == 0
3244
+ xc /= 5
3245
+ e -= 1
3246
+ end
3247
+ if ye >= 0
3248
+ y_as_integer = Decimal.int_mult_radix_power(yc,ye)
3249
+ e = e*y_as_integer
3250
+ xe = xe*y_as_integer
3251
+ else
3252
+ ten_pow = Decimal.int_radix_power(-ye)
3253
+ e, remainder = (e*yc).divmod(ten_pow)
3254
+ return nil if remainder
3255
+ xe, remainder = (xe*yc).divmod(ten_pow)
3256
+ return nil if remainder
3257
+ end
3258
+ return nil if e*3 >= p*10 # 10/3 > log(10)/log(2)
3259
+ xc = 2**e
3260
+ else
3261
+ return nil
3262
+ end
3263
+
3264
+ return nil if xc >= Decimal.int_radix_power(p)
3265
+ xe = -e-xe
3266
+ return Decimal(+1, xc, xe)
3267
+
3268
+ end
3269
+
3270
+ # now y is positive; find m and n such that y = m/n
3271
+ if ye >= 0
3272
+ m, n = yc*10**ye, 1
2725
3273
  else
2726
- raise TypeError, "Unable to convert #{x.class} to Decimal" if error
2727
- nil
3274
+ return nil if (xe != 0) and ((yc*xe).abs.to_s.length <= -ye)
3275
+ xc_bits = _nbits(xc)
3276
+ return nil if (xc != 1) and ((yc.abs*xc_bits).to_s.length <= -ye)
3277
+ m, n = yc, Decimal.int_radix_power(-ye)
3278
+ while ((m % 2) == 0) && ((n % 2) == 0)
3279
+ m /= 2
3280
+ n /= 2
3281
+ end
3282
+ while ((m % 5) == 0) && ((n % 5) == 0)
3283
+ m /= 5
3284
+ n /= 5
3285
+ end
3286
+ end
3287
+
3288
+ # compute nth root of xc*10**xe
3289
+ if n > 1
3290
+ # if 1 < xc < 2**n then xc isn't an nth power
3291
+ return nil if xc != 1 and xc_bits <= n
3292
+
3293
+ xe, rem = xe.divmod(n)
3294
+ return nil if rem != 0
3295
+
3296
+ # compute nth root of xc using Newton's method
3297
+ a = 1 << -(-_nbits(xc)/n) # initial estimate
3298
+ q = r = nil
3299
+ loop do
3300
+ q, r = xc.divmod(a**(n-1))
3301
+ break if a <= q
3302
+ a = (a*(n-1) + q)/n
3303
+ end
3304
+ return nil if !((a == q) and (r == 0))
3305
+ xc = a
3306
+ end
3307
+
3308
+ # now xc*10**xe is the nth root of the original xc*10**xe
3309
+ # compute mth power of xc*10**xe
3310
+
3311
+ # if m > p*100/_log10_lb(xc) then m > p/log10(xc), hence xc**m >
3312
+ # 10**p and the result is not representable.
3313
+ return nil if (xc > 1) and (m > p*100/_log10_lb(xc))
3314
+ xc = xc**m
3315
+ xe *= m
3316
+ return nil if xc > 10**p
3317
+
3318
+ # by this point the result *is* exactly representable
3319
+ # adjust the exponent to get as close as possible to the ideal
3320
+ # exponent, if necessary
3321
+ str_xc = xc.to_s
3322
+ if other.integral? && other.sign == +1
3323
+ ideal_exponent = self.integral_exponent*other.to_i
3324
+ zeros = [xe-ideal_exponent, p-str_xc.length].min
3325
+ else
3326
+ zeros = 0
3327
+ end
3328
+ return Decimal(+1, Decimal.int_mult_radix_power(xc, zeros), xe-zeros)
3329
+ end
3330
+
3331
+ ROUND_ARITHMETIC = true
3332
+
3333
+ # Round to i digits using the specified method
3334
+ def _round(rounding, i)
3335
+ send("_round_#{rounding}", i)
3336
+ end
3337
+
3338
+ # Round down (toward 0, truncate) to i digits
3339
+ def _round_down(i)
3340
+ if ROUND_ARITHMETIC
3341
+ (@coeff % Decimal.int_radix_power(i))==0 ? 0 : -1
3342
+ else
3343
+ d = @coeff.to_s
3344
+ p = d.size - i
3345
+ d[p..-1].match(/\A0+\Z/) ? 0 : -1
3346
+ end
3347
+ end
3348
+
3349
+ # Round up (away from 0) to i digits
3350
+ def _round_up(i)
3351
+ -_round_down(i)
3352
+ end
3353
+
3354
+ # Round to closest i-digit number with ties down (rounds 5 toward 0)
3355
+ def _round_half_down(i)
3356
+ if ROUND_ARITHMETIC
3357
+ m = Decimal.int_radix_power(i)
3358
+ if (m>1) && ((@coeff%m) == m/2)
3359
+ -1
3360
+ else
3361
+ _round_half_up(i)
3362
+ end
3363
+ else
3364
+ d = @coeff.to_s
3365
+ p = d.size - i
3366
+ d[p..-1].match(/^5d*$/) ? -1 : _round_half_up(i)
3367
+ end
3368
+
3369
+ end
3370
+
3371
+ # Round to closest i-digit number with ties up (rounds 5 away from 0)
3372
+ def _round_half_up(i)
3373
+ if ROUND_ARITHMETIC
3374
+ m = Decimal.int_radix_power(i)
3375
+ if (m>1) && ((@coeff % m) >= m/2)
3376
+ 1
3377
+ else
3378
+ (@coeff % m)==0 ? 0 : -1
3379
+ end
3380
+ else
3381
+ d = @coeff.to_s
3382
+ p = d.size - i
3383
+ if '56789'.include?(d[p,1])
3384
+ 1
3385
+ else
3386
+ d[p..-1].match(/^0+$/) ? 0 : -1
3387
+ end
3388
+ end
3389
+
3390
+ end
3391
+
3392
+ # Round to closest i-digit number with ties (5) to an even digit
3393
+ def _round_half_even(i)
3394
+ if ROUND_ARITHMETIC
3395
+ m = Decimal.int_radix_power(i)
3396
+ if (m>1) && ((@coeff%m) == m/2 && ((@coeff/m)%2)==0)
3397
+ -1
3398
+ else
3399
+ _round_half_up(i)
3400
+ end
3401
+ else
3402
+ d = @coeff.to_s
3403
+ p = d.size - i
3404
+
3405
+ if d[p..-1].match(/\A#{Decimal.radix/2}0*\Z/) && (p==0 || ((d[p-1,1].to_i%2)==0))
3406
+ -1
3407
+ else
3408
+ _round_half_up(i)
3409
+ end
3410
+
2728
3411
  end
2729
3412
  end
2730
3413
 
2731
- # Parse numeric text literals (internal use)
2732
- def _parser(txt)
2733
- md = /^\s*([-+])?(?:(?:(\d+)(?:\.(\d*))?|\.(\d+))(?:[eE]([-+]?\d+))?|Inf(?:inity)?|(s)?NaN(\d*))\s*$/i.match(txt)
2734
- if md
2735
- OpenStruct.new :sign=>md[1], :int=>md[2], :frac=>md[3], :onlyfrac=>md[4], :exp=>md[5],
2736
- :signal=>md[6], :diag=>md[7]
3414
+ # Round up (not away from 0 if negative) to i digits
3415
+ def _round_ceiling(i)
3416
+ sign<0 ? _round_down(i) : -_round_down(i)
3417
+ end
3418
+
3419
+ # Round down (not toward 0 if negative) to i digits
3420
+ def _round_floor(i)
3421
+ sign>0 ? _round_down(i) : -_round_down(i)
3422
+ end
3423
+
3424
+ # Round down unless digit i-1 is 0 or 5
3425
+ def _round_up05(i)
3426
+ if ROUND_ARITHMETIC
3427
+ dg = (@coeff%Decimal.int_radix_power(i+1))/Decimal.int_radix_power(i)
3428
+ else
3429
+ d = @coeff.to_s
3430
+ p = d.size - i
3431
+ dg = (p>0) ? d[p-1,1].to_i : 0
3432
+ end
3433
+ if [0,Decimal.radix/2].include?(dg)
3434
+ -_round_down(i)
3435
+ else
3436
+ _round_down(i)
2737
3437
  end
2738
3438
  end
2739
3439
 
3440
+
3441
+ # Compute a lower bound for the adjusted exponent of self.log10()
3442
+ # In other words, find r such that self.log10() >= 10**r.
3443
+ # Assumes that self is finite and positive and that self != 1.
3444
+ def _log10_exp_bound
3445
+ # For x >= 10 or x < 0.1 we only need a bound on the integer
3446
+ # part of log10(self), and this comes directly from the
3447
+ # exponent of x. For 0.1 <= x <= 10 we use the inequalities
3448
+ # 1-1/x <= log(x) <= x-1. If x > 1 we have |log10(x)| >
3449
+ # (1-1/x)/2.31 > 0. If x < 1 then |log10(x)| > (1-x)/2.31 > 0
3450
+
3451
+ adj = self.integral_exponent + number_of_digits - 1
3452
+ return adj.to_s.length - 1 if adj >= 1 # self >= 10
3453
+ return (-1-adj).to_s.length-1 if adj <= -2 # self < 0.1
3454
+
3455
+ c = self.integral_significand
3456
+ e = self.integral_exponent
3457
+ if adj == 0
3458
+ # 1 < self < 10
3459
+ num = (c - Decimal.int_radix_power(-e)).to_s
3460
+ den = (231*c).to_s
3461
+ return num.length - den.length - ((num < den) ? 1 : 0) + 2
3462
+ end
3463
+ # adj == -1, 0.1 <= self < 1
3464
+ num = (Decimal.int_radix_power(-e)-c).to_s
3465
+ return num.length + e - ((num < "231") ? 1 : 0) - 1
3466
+ end
3467
+
3468
+ # Compute a lower bound for the adjusted exponent of self.ln().
3469
+ # In other words, compute r such that self.ln() >= 10**r. Assumes
3470
+ # that self is finite and positive and that self != 1.
3471
+ def _ln_exp_bound
3472
+ # for 0.1 <= x <= 10 we use the inequalities 1-1/x <= ln(x) <= x-1
3473
+ adj = self.integral_exponent + number_of_digits - 1
3474
+ if adj >= 1
3475
+ # argument >= 10; we use 23/10 = 2.3 as a lower bound for ln(10)
3476
+ return (adj*23/10).to_s.length - 1
3477
+ end
3478
+ if adj <= -2
3479
+ # argument <= 0.1
3480
+ return ((-1-adj)*23/10).to_s.length - 1
3481
+ end
3482
+ c = self.integral_significand
3483
+ e = self.integral_exponent
3484
+ if adj == 0
3485
+ # 1 < self < 10
3486
+ num = (c-(10**-e)).to_s
3487
+ den = c.to_s
3488
+ return num.length - den.length - ((num < den) ? 1 : 0)
3489
+ end
3490
+ # adj == -1, 0.1 <= self < 1
3491
+ return e + (10**-e - c).to_s.length - 1
3492
+ end
3493
+
3494
+ module AuxiliarFunctions #:nodoc:
3495
+
3496
+ module_function
3497
+
3498
+ # Convert a numeric value to decimal (internal use)
3499
+ def _convert(x, error=true)
3500
+ case x
3501
+ when Decimal
3502
+ x
3503
+ when *Decimal.context.coercible_types
3504
+ Decimal.new(x)
3505
+ else
3506
+ raise TypeError, "Unable to convert #{x.class} to Decimal" if error
3507
+ nil
3508
+ end
3509
+ end
3510
+
3511
+ # Parse numeric text literals (internal use)
3512
+ def _parser(txt)
3513
+ md = /^\s*([-+])?(?:(?:(\d+)(?:\.(\d*))?|\.(\d+))(?:[eE]([-+]?\d+))?|Inf(?:inity)?|(s)?NaN(\d*))\s*$/i.match(txt)
3514
+ if md
3515
+ OpenStruct.new :sign=>md[1], :int=>md[2], :frac=>md[3], :onlyfrac=>md[4], :exp=>md[5],
3516
+ :signal=>md[6], :diag=>md[7]
3517
+ end
3518
+ end
3519
+
3520
+ # Normalizes op1, op2 to have the same exp and length of coefficient. Used for addition.
3521
+ def _normalize(op1, op2, prec=0)
3522
+ if op1.integral_exponent < op2.integral_exponent
3523
+ swap = true
3524
+ tmp,other = op2,op1
3525
+ else
3526
+ swap = false
3527
+ tmp,other = op1,op2
3528
+ end
3529
+ tmp_len = tmp.number_of_digits
3530
+ other_len = other.number_of_digits
3531
+ exp = tmp.integral_exponent + [-1, tmp_len - prec - 2].min
3532
+ if (other_len+other.integral_exponent-1 < exp) && prec>0
3533
+ other = Decimal.new([other.sign, 1, exp])
3534
+ end
3535
+ tmp = Decimal.new(tmp.sign,
3536
+ Decimal.int_mult_radix_power(tmp.integral_significand, tmp.integral_exponent-other.integral_exponent),
3537
+ other.integral_exponent)
3538
+ return swap ? [other, tmp] : [tmp, other]
3539
+ end
3540
+
3541
+ # Number of bits in binary representation of the positive integer n, or 0 if n == 0.
3542
+ #--
3543
+ # This function from Tim Peters was taken from here:
3544
+ # http://mail.python.org/pipermail/python-list/1999-July/007758.html
3545
+ # The correction being in the function definition is for speed, and
3546
+ # the whole function is not resolved with math.log because of avoiding
3547
+ # the use of floats.
3548
+ #++
3549
+ def _nbits(n, correction = { #:nodoc:
3550
+ '0'=> 4, '1'=> 3, '2'=> 2, '3'=> 2,
3551
+ '4'=> 1, '5'=> 1, '6'=> 1, '7'=> 1,
3552
+ '8'=> 0, '9'=> 0, 'a'=> 0, 'b'=> 0,
3553
+ 'c'=> 0, 'd'=> 0, 'e'=> 0, 'f'=> 0})
3554
+ raise TypeError, "The argument to _nbits should be nonnegative." if n < 0
3555
+ hex_n = "%x" % n
3556
+ 4*hex_n.length - correction[hex_n[0,1]]
3557
+ end
3558
+
3559
+ # Given integers xc, xe, yc and ye representing Decimals x = xc*10**xe and
3560
+ # y = yc*10**ye, compute x**y. Returns a pair of integers (c, e) such that:
3561
+ #
3562
+ # 10**(p-1) <= c <= 10**p, and
3563
+ # (c-1)*10**e < x**y < (c+1)*10**e
3564
+ #
3565
+ # in other words, c*10**e is an approximation to x**y with p digits
3566
+ # of precision, and with an error in c of at most 1. (This is
3567
+ # almost, but not quite, the same as the error being < 1ulp: when c
3568
+ # == 10**(p-1) we can only guarantee error < 10ulp.)
3569
+ #
3570
+ # We assume that: x is positive and not equal to 1, and y is nonzero.
3571
+ def _dpower(xc, xe, yc, ye, p)
3572
+ # Find b such that 10**(b-1) <= |y| <= 10**b
3573
+ b = yc.abs.to_s.length + ye
3574
+
3575
+ # log(x) = lxc*10**(-p-b-1), to p+b+1 places after the decimal point
3576
+ lxc = _dlog(xc, xe, p+b+1)
3577
+
3578
+ # compute product y*log(x) = yc*lxc*10**(-p-b-1+ye) = pc*10**(-p-1)
3579
+ shift = ye-b
3580
+ if shift >= 0
3581
+ pc = lxc*yc*10**shift
3582
+ else
3583
+ pc = _div_nearest(lxc*yc, 10**-shift)
3584
+ end
3585
+
3586
+ if pc == 0
3587
+ # we prefer a result that isn't exactly 1; this makes it
3588
+ # easier to compute a correctly rounded result in __pow__
3589
+ if (xc.to_s.length + xe >= 1) == (yc > 0) # if x**y > 1:
3590
+ coeff, exp = 10**(p-1)+1, 1-p
3591
+ else
3592
+ coeff, exp = 10**p-1, -p
3593
+ end
3594
+ else
3595
+ coeff, exp = _dexp(pc, -(p+1), p+1)
3596
+ coeff = _div_nearest(coeff, 10)
3597
+ exp += 1
3598
+ end
3599
+
3600
+ return coeff, exp
3601
+ end
3602
+
3603
+ # Compute an approximation to exp(c*10**e), with p decimal places of precision.
3604
+ # Returns integers d, f such that:
3605
+ #
3606
+ # 10**(p-1) <= d <= 10**p, and
3607
+ # (d-1)*10**f < exp(c*10**e) < (d+1)*10**f
3608
+ #
3609
+ # In other words, d*10**f is an approximation to exp(c*10**e) with p
3610
+ # digits of precision, and with an error in d of at most 1. This is
3611
+ # almost, but not quite, the same as the error being < 1ulp: when d
3612
+ # = 10**(p-1) the error could be up to 10 ulp.
3613
+ def _dexp(c, e, p)
3614
+ # we'll call iexp with M = 10**(p+2), giving p+3 digits of precision
3615
+ p += 2
3616
+
3617
+ # compute log(10) with extra precision = adjusted exponent of c*10**e
3618
+ extra = [0, e + c.to_s.length - 1].max
3619
+ q = p + extra
3620
+
3621
+ # compute quotient c*10**e/(log(10)) = c*10**(e+q)/(log(10)*10**q),
3622
+ # rounding down
3623
+ shift = e+q
3624
+ if shift >= 0
3625
+ cshift = c*10**shift
3626
+ else
3627
+ cshift = c/10**-shift
3628
+ end
3629
+ quot, rem = cshift.divmod(_log10_digits(q))
3630
+
3631
+ # reduce remainder back to original precision
3632
+ rem = _div_nearest(rem, 10**extra)
3633
+
3634
+ # error in result of _iexp < 120; error after division < 0.62
3635
+ return _div_nearest(_iexp(rem, 10**p), 1000), quot - p + 3
3636
+ end
3637
+
3638
+ # Closest integer to a/b, a and b positive integers; rounds to even
3639
+ # in the case of a tie.
3640
+ def _div_nearest(a, b)
3641
+ q, r = a.divmod(b)
3642
+ q + (((2*r + (q&1)) > b) ? 1 : 0)
3643
+ end
3644
+
3645
+ # Closest integer to the square root of the positive integer n. a is
3646
+ # an initial approximation to the square root. Any positive integer
3647
+ # will do for a, but the closer a is to the square root of n the
3648
+ # faster convergence will be.
3649
+ def _sqrt_nearest(n, a)
3650
+
3651
+ if n <= 0 or a <= 0
3652
+ raise ArgumentError, "Both arguments to _sqrt_nearest should be positive."
3653
+ end
3654
+
3655
+ b=0
3656
+ while a != b
3657
+ b, a = a, a--n/a>>1 # ??
3658
+ end
3659
+ return a
3660
+ end
3661
+
3662
+ # Given an integer x and a nonnegative integer shift, return closest
3663
+ # integer to x / 2**shift; use round-to-even in case of a tie.
3664
+ def _rshift_nearest(x, shift)
3665
+ b, q = (1 << shift), (x >> shift)
3666
+ return q + (((2*(x & (b-1)) + (q&1)) > b) ? 1 : 0)
3667
+ #return q + (2*(x & (b-1)) + (((q&1) > b) ? 1 : 0))
3668
+ end
3669
+
3670
+ # Integer approximation to M*log(x/M), with absolute error boundable
3671
+ # in terms only of x/M.
3672
+ #
3673
+ # Given positive integers x and M, return an integer approximation to
3674
+ # M * log(x/M). For L = 8 and 0.1 <= x/M <= 10 the difference
3675
+ # between the approximation and the exact result is at most 22. For
3676
+ # L = 8 and 1.0 <= x/M <= 10.0 the difference is at most 15. In
3677
+ # both cases these are upper bounds on the error; it will usually be
3678
+ # much smaller.
3679
+ def _ilog(x, m, l = 8)
3680
+ # The basic algorithm is the following: let log1p be the function
3681
+ # log1p(x) = log(1+x). Then log(x/M) = log1p((x-M)/M). We use
3682
+ # the reduction
3683
+ #
3684
+ # log1p(y) = 2*log1p(y/(1+sqrt(1+y)))
3685
+ #
3686
+ # repeatedly until the argument to log1p is small (< 2**-L in
3687
+ # absolute value). For small y we can use the Taylor series
3688
+ # expansion
3689
+ #
3690
+ # log1p(y) ~ y - y**2/2 + y**3/3 - ... - (-y)**T/T
3691
+ #
3692
+ # truncating at T such that y**T is small enough. The whole
3693
+ # computation is carried out in a form of fixed-point arithmetic,
3694
+ # with a real number z being represented by an integer
3695
+ # approximation to z*M. To avoid loss of precision, the y below
3696
+ # is actually an integer approximation to 2**R*y*M, where R is the
3697
+ # number of reductions performed so far.
3698
+
3699
+ y = x-m
3700
+ # argument reduction; R = number of reductions performed
3701
+ r = 0
3702
+ # while (r <= l && y.abs << l-r >= m ||
3703
+ # r > l and y.abs>> r-l >= m)
3704
+ while (((r <= l) && ((y.abs << (l-r)) >= m)) ||
3705
+ ((r > l) && ((y.abs>>(r-l)) >= m)))
3706
+ y = _div_nearest((m*y) << 1,
3707
+ m + _sqrt_nearest(m*(m+_rshift_nearest(y, r)), m))
3708
+ r += 1
3709
+ end
3710
+
3711
+ # Taylor series with T terms
3712
+ t = -(-10*m.to_s.length/(3*l)).to_i
3713
+ yshift = _rshift_nearest(y, r)
3714
+ w = _div_nearest(m, t)
3715
+ # (1...t).reverse_each do |k| # Ruby 1.9
3716
+ (1...t).to_a.reverse.each do |k|
3717
+ w = _div_nearest(m, k) - _div_nearest(yshift*w, m)
3718
+ end
3719
+
3720
+ return _div_nearest(w*y, m)
3721
+ end
3722
+
3723
+ # Given integers c, e and p with c > 0, p >= 0, compute an integer
3724
+ # approximation to 10**p * log10(c*10**e), with an absolute error of
3725
+ # at most 1. Assumes that c*10**e is not exactly 1.
3726
+ def _dlog10(c, e, p)
3727
+ # increase precision by 2; compensate for this by dividing
3728
+ # final result by 100
3729
+ p += 2
3730
+
3731
+ # write c*10**e as d*10**f with either:
3732
+ # f >= 0 and 1 <= d <= 10, or
3733
+ # f <= 0 and 0.1 <= d <= 1.
3734
+ # Thus for c*10**e close to 1, f = 0
3735
+ l = c.to_s.length
3736
+ f = e+l - ((e+l >= 1) ? 1 : 0)
3737
+
3738
+ if p > 0
3739
+ m = 10**p
3740
+ k = e+p-f
3741
+ if k >= 0
3742
+ c *= 10**k
3743
+ else
3744
+ c = _div_nearest(c, 10**-k)
3745
+ end
3746
+ log_d = _ilog(c, m) # error < 5 + 22 = 27
3747
+ log_10 = _log10_digits(p) # error < 1
3748
+ log_d = _div_nearest(log_d*m, log_10)
3749
+ log_tenpower = f*m # exact
3750
+ else
3751
+ log_d = 0 # error < 2.31
3752
+ log_tenpower = _div_nearest(f, 10**-p) # error < 0.5
3753
+ end
3754
+
3755
+ return _div_nearest(log_tenpower+log_d, 100)
3756
+ end
3757
+
3758
+ # Compute a lower bound for 100*log10(c) for a positive integer c.
3759
+ def _log10_lb(c, correction = {
3760
+ '1'=> 100, '2'=> 70, '3'=> 53, '4'=> 40, '5'=> 31,
3761
+ '6'=> 23, '7'=> 16, '8'=> 10, '9'=> 5})
3762
+ raise ArgumentError, "The argument to _log10_lb should be nonnegative." if c <= 0
3763
+ str_c = c.to_s
3764
+ return 100*str_c.length - correction[str_c[0,1]]
3765
+ end
3766
+
3767
+ # Given integers c, e and p with c > 0, compute an integer
3768
+ # approximation to 10**p * log(c*10**e), with an absolute error of
3769
+ # at most 1. Assumes that c*10**e is not exactly 1.
3770
+ def _dlog(c, e, p)
3771
+
3772
+ # Increase precision by 2. The precision increase is compensated
3773
+ # for at the end with a division by 100.
3774
+ p += 2
3775
+
3776
+ # rewrite c*10**e as d*10**f with either f >= 0 and 1 <= d <= 10,
3777
+ # or f <= 0 and 0.1 <= d <= 1. Then we can compute 10**p * log(c*10**e)
3778
+ # as 10**p * log(d) + 10**p*f * log(10).
3779
+ l = c.to_s.length
3780
+ f = e+l - ((e+l >= 1) ? 1 : 0)
3781
+
3782
+ # compute approximation to 10**p*log(d), with error < 27
3783
+ if p > 0
3784
+ k = e+p-f
3785
+ if k >= 0
3786
+ c *= 10**k
3787
+ else
3788
+ c = _div_nearest(c, 10**-k) # error of <= 0.5 in c
3789
+ end
3790
+
3791
+ # _ilog magnifies existing error in c by a factor of at most 10
3792
+ log_d = _ilog(c, 10**p) # error < 5 + 22 = 27
3793
+ else
3794
+ # p <= 0: just approximate the whole thing by 0; error < 2.31
3795
+ log_d = 0
3796
+ end
3797
+
3798
+ # compute approximation to f*10**p*log(10), with error < 11.
3799
+ if f
3800
+ extra = f.abs.to_s.length - 1
3801
+ if p + extra >= 0
3802
+ # error in f * _log10_digits(p+extra) < |f| * 1 = |f|
3803
+ # after division, error < |f|/10**extra + 0.5 < 10 + 0.5 < 11
3804
+ f_log_ten = _div_nearest(f*_log10_digits(p+extra), 10**extra)
3805
+ else
3806
+ f_log_ten = 0
3807
+ end
3808
+ else
3809
+ f_log_ten = 0
3810
+ end
3811
+
3812
+ # error in sum < 11+27 = 38; error after division < 0.38 + 0.5 < 1
3813
+ return _div_nearest(f_log_ten + log_d, 100)
3814
+ end
3815
+
3816
+ # Given integers x and M, M > 0, such that x/M is small in absolute
3817
+ # value, compute an integer approximation to M*exp(x/M). For 0 <=
3818
+ # x/M <= 2.4, the absolute error in the result is bounded by 60 (and
3819
+ # is usually much smaller).
3820
+ def _iexp(x, m, l=8)
3821
+
3822
+ # Algorithm: to compute exp(z) for a real number z, first divide z
3823
+ # by a suitable power R of 2 so that |z/2**R| < 2**-L. Then
3824
+ # compute expm1(z/2**R) = exp(z/2**R) - 1 using the usual Taylor
3825
+ # series
3826
+ #
3827
+ # expm1(x) = x + x**2/2! + x**3/3! + ...
3828
+ #
3829
+ # Now use the identity
3830
+ #
3831
+ # expm1(2x) = expm1(x)*(expm1(x)+2)
3832
+ #
3833
+ # R times to compute the sequence expm1(z/2**R),
3834
+ # expm1(z/2**(R-1)), ... , exp(z/2), exp(z).
3835
+
3836
+ # Find R such that x/2**R/M <= 2**-L
3837
+ r = _nbits((x<<l)/m)
3838
+
3839
+ # Taylor series. (2**L)**T > M
3840
+ t = -(-10*m.to_s.length/(3*l)).to_i
3841
+ y = _div_nearest(x, t)
3842
+ mshift = m<<r
3843
+ (1...t).to_a.reverse.each do |i|
3844
+ y = _div_nearest(x*(mshift + y), mshift * i)
3845
+ end
3846
+
3847
+ # Expansion
3848
+ (0...r).to_a.reverse.each do |k|
3849
+ mshift = m<<(k+2)
3850
+ y = _div_nearest(y*(y+mshift), mshift)
3851
+ end
3852
+
3853
+ return m+y
3854
+ end
3855
+
3856
+ # We'll memoize the digits of log(10):
3857
+ @log10_digits = "23025850929940456840179914546843642076011014886"
3858
+ class <<self
3859
+ attr_accessor :log10_digits
3860
+ end
3861
+
3862
+ # Given an integer p >= 0, return floor(10**p)*log(10).
3863
+ def _log10_digits(p)
3864
+ # digits are stored as a string, for quick conversion to
3865
+ # integer in the case that we've already computed enough
3866
+ # digits; the stored digits should always be correct
3867
+ # (truncated, not rounded to nearest).
3868
+ raise ArgumentError, "p should be nonnegative" if p<0
3869
+ if p >= AuxiliarFunctions.log10_digits.length
3870
+ digits = nil
3871
+ # compute p+3, p+6, p+9, ... digits; continue until at
3872
+ # least one of the extra digits is nonzero
3873
+ extra = 3
3874
+ loop do
3875
+ # compute p+extra digits, correct to within 1ulp
3876
+ m = 10**(p+extra+2)
3877
+ digits = _div_nearest(_ilog(10*m, m), 100).to_s
3878
+ break if digits[-extra..-1] != '0'*extra
3879
+ extra += 3
3880
+ end
3881
+ # keep all reliable digits so far; remove trailing zeros
3882
+ # and next nonzero digit
3883
+ AuxiliarFunctions.log10_digits = digits.sub(/0*$/,'')[0...-1]
3884
+ end
3885
+ return (AuxiliarFunctions.log10_digits[0...p+1]).to_i
3886
+ end
3887
+
3888
+ # Compute an approximation to exp(c*10**e), with p decimal places of
3889
+ # precision.
3890
+ #
3891
+ # Returns integers d, f such that:
3892
+ #
3893
+ # 10**(p-1) <= d <= 10**p, and
3894
+ # (d-1)*10**f < exp(c*10**e) < (d+1)*10**f
3895
+ #
3896
+ # In other words, d*10**f is an approximation to exp(c*10**e) with p
3897
+ # digits of precision, and with an error in d of at most 1. This is
3898
+ # almost, but not quite, the same as the error being < 1ulp: when d
3899
+ # = 10**(p-1) the error could be up to 10 ulp.
3900
+ def dexp(c, e, p)
3901
+ # we'll call iexp with M = 10**(p+2), giving p+3 digits of precision
3902
+ p += 2
3903
+
3904
+ # compute log(10) with extra precision = adjusted exponent of c*10**e
3905
+ extra = [0, e + c.to_s.length - 1].max
3906
+ q = p + extra
3907
+
3908
+ # compute quotient c*10**e/(log(10)) = c*10**(e+q)/(log(10)*10**q),
3909
+ # rounding down
3910
+ shift = e+q
3911
+ if shift >= 0
3912
+ cshift = c*10**shift
3913
+ else
3914
+ cshift = c/10**-shift
3915
+ end
3916
+ quot, rem = cshift.divmod(_log10_digits(q))
3917
+
3918
+ # reduce remainder back to original precision
3919
+ rem = _div_nearest(rem, 10**extra)
3920
+
3921
+ # error in result of _iexp < 120; error after division < 0.62
3922
+ return _div_nearest(_iexp(rem, 10**p), 1000), quot - p + 3
3923
+ end
3924
+
3925
+ end # AuxiliarFunctions
3926
+
3927
+ # This is for using auxiliar functions from Decimal instance method
3928
+ # without the "AuxiliarFunctions." prefix
3929
+ include AuxiliarFunctions
3930
+ # If we need to use them from Decimal class methods, we can avoid
3931
+ # the use of the prefix with:
3932
+ # extend AuxiliarFunctions
3933
+
2740
3934
  end
2741
3935
 
2742
3936
  # Decimal constructor. See Decimal#new for the parameters.