ruby-decimal 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +7 -1
- data/README.txt +6 -3
- data/lib/decimal/decimal.rb +1680 -486
- data/lib/decimal/version.rb +1 -1
- data/test/test_dectest.rb +15 -6
- data/test/test_exact.rb +120 -5
- data/test/test_odd_even.rb +78 -0
- metadata +4 -2
data/History.txt
CHANGED
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
|
-
==
|
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:
|
data/lib/decimal/decimal.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
494
|
+
_convert(x).abs(self)
|
474
495
|
end
|
475
496
|
|
476
497
|
# Unary prefix plus operator
|
477
498
|
def plus(x)
|
478
|
-
|
499
|
+
_convert(x).plus(self)
|
479
500
|
end
|
480
501
|
|
481
502
|
# Unary prefix minus operator
|
482
503
|
def minus(x)
|
483
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 =
|
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 =
|
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 =
|
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
|
-
|
583
|
+
_convert(x).normal?(self)
|
544
584
|
end
|
545
585
|
|
546
586
|
# Is a subnormal number?
|
547
587
|
def subnormal?(x)
|
548
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
# *
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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
|
-
|
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 =
|
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
|
2080
|
-
def
|
2081
|
-
|
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
|
2095
|
-
def
|
2096
|
-
|
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
|
2110
|
-
def
|
2111
|
-
|
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
|
-
#
|
2126
|
-
def
|
2127
|
-
|
2128
|
-
|
2129
|
-
|
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
|
-
|
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
|
-
|
2138
|
-
|
2139
|
-
|
2140
|
-
|
2141
|
-
|
2142
|
-
|
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
|
-
|
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
|
-
|
2151
|
-
|
2152
|
-
|
2153
|
-
|
2154
|
-
|
2155
|
-
|
2156
|
-
|
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
|
-
|
2176
|
-
|
2177
|
-
|
2178
|
-
|
2179
|
-
|
2180
|
-
|
2181
|
-
|
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
|
-
|
2216
|
+
false
|
2193
2217
|
end
|
2194
2218
|
end
|
2195
2219
|
end
|
2196
|
-
|
2220
|
+
else
|
2221
|
+
false
|
2197
2222
|
end
|
2223
|
+
end
|
2198
2224
|
|
2199
|
-
|
2200
|
-
|
2201
|
-
|
2202
|
-
|
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
|
-
|
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
|
-
|
2211
|
-
|
2212
|
-
#
|
2213
|
-
|
2214
|
-
|
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
|
-
#
|
2218
|
-
def
|
2219
|
-
|
2220
|
-
|
2221
|
-
|
2222
|
-
|
2223
|
-
|
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
|
-
#
|
2229
|
-
def
|
2230
|
-
|
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
|
-
#
|
2234
|
-
|
2235
|
-
|
2236
|
-
|
2237
|
-
|
2238
|
-
|
2239
|
-
|
2240
|
-
|
2241
|
-
|
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
|
-
|
2244
|
-
|
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
|
-
#
|
2251
|
-
|
2252
|
-
|
2253
|
-
|
2254
|
-
|
2255
|
-
|
2256
|
-
|
2257
|
-
|
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
|
-
|
2261
|
-
|
2262
|
-
|
2263
|
-
|
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
|
-
|
2440
|
+
return Decimal(1)
|
2266
2441
|
end
|
2267
2442
|
end
|
2268
2443
|
|
2269
|
-
|
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
|
-
|
2272
|
-
|
2273
|
-
|
2274
|
-
|
2275
|
-
|
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
|
-
|
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
|
-
|
2282
|
-
|
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
|
-
|
2285
|
-
|
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
|
-
|
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
|
-
|
2294
|
-
|
2295
|
-
|
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
|
-
#
|
2299
|
-
def
|
2300
|
-
|
2301
|
-
end
|
2603
|
+
# Returns the base 10 logarithm
|
2604
|
+
def log10(context=nil)
|
2605
|
+
context = Decimal.define_context(context)
|
2302
2606
|
|
2303
|
-
|
2304
|
-
|
2305
|
-
if
|
2306
|
-
|
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
|
-
|
2309
|
-
|
2310
|
-
|
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
|
-
|
2313
|
-
|
2314
|
-
|
2315
|
-
|
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
|
-
#
|
2320
|
-
def
|
2321
|
-
|
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
|
-
|
2657
|
+
# exp(NaN) = NaN
|
2658
|
+
ans = _check_nans(context)
|
2659
|
+
return ans if ans
|
2326
2660
|
|
2327
|
-
|
2328
|
-
|
2329
|
-
|
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
|
-
|
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
|
-
|
2381
|
-
|
2382
|
-
|
2383
|
-
|
2384
|
-
|
2385
|
-
|
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
|
-
|
2391
|
-
|
2392
|
-
|
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
|
-
|
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
|
-
|
2409
|
-
|
2410
|
-
|
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
|
-
#
|
2500
|
-
|
2501
|
-
|
2502
|
-
|
2503
|
-
|
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
|
-
|
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
|
-
#
|
2514
|
-
def
|
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
|
-
|
2522
|
-
|
2523
|
-
|
2524
|
-
|
2525
|
-
|
2526
|
-
|
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
|
-
#
|
2530
|
-
def
|
2531
|
-
|
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
|
-
|
2538
|
-
|
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
|
-
|
2586
|
-
as_int = true
|
2887
|
+
ans = _pos(context)
|
2587
2888
|
end
|
2588
|
-
|
2589
|
-
return as_int ? result.to_i : result
|
2889
|
+
ans
|
2590
2890
|
end
|
2591
2891
|
|
2592
|
-
#
|
2593
|
-
|
2594
|
-
|
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
|
-
|
2600
|
-
|
2601
|
-
|
2602
|
-
|
2603
|
-
|
2604
|
-
|
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
|
-
#
|
2614
|
-
|
2615
|
-
|
2616
|
-
|
2617
|
-
|
2618
|
-
|
2619
|
-
|
2620
|
-
|
2621
|
-
|
2622
|
-
|
2623
|
-
|
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
|
-
|
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
|
-
#
|
2719
|
-
|
2720
|
-
|
2721
|
-
|
2722
|
-
|
2723
|
-
|
2724
|
-
|
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
|
-
|
2727
|
-
|
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
|
-
#
|
2732
|
-
def
|
2733
|
-
|
2734
|
-
|
2735
|
-
|
2736
|
-
|
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.
|