long-decimal 0.00.09 → 0.00.10
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/doc/classes/LongDecimalRoundingMode.html +2 -3
- data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.html +5 -5
- data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.src/M000128.html +22 -0
- data/doc/classes/LongMath.html +237 -91
- data/doc/classes/LongMath.src/M000122.html +73 -0
- data/doc/classes/LongMath.src/M000123.html +35 -0
- data/doc/classes/LongMath.src/M000124.html +50 -0
- data/doc/classes/LongMath.src/M000125.html +47 -0
- data/doc/classes/LongMath.src/M000126.html +21 -0
- data/doc/classes/LongMath.src/M000127.html +108 -0
- data/doc/created.rid +1 -1
- data/doc/dot/f_0.dot +44 -44
- data/doc/dot/f_0.png +0 -0
- data/doc/dot/m_0_0.dot +50 -7
- data/doc/dot/m_0_0.png +0 -0
- data/doc/files/lib/longdecimal_rb.html +6 -52
- data/doc/fr_class_index.html +3 -3
- data/doc/fr_method_index.html +136 -128
- data/lib/longdecimal.rb +300 -37
- data/test/testlongdecimal.rb +98 -8
- metadata +9 -2
data/lib/longdecimal.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
#
|
2
2
|
# longdecimal.rb -- Arbitrary precision decimals with fixed decimal point
|
3
3
|
#
|
4
|
-
# CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/lib/longdecimal.rb,v 1.
|
5
|
-
# CVS-Label: $Name:
|
4
|
+
# CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/lib/longdecimal.rb,v 1.6 2006/03/10 20:10:45 bk1 Exp $
|
5
|
+
# CVS-Label: $Name: PRE_ALPHA_0_10 $
|
6
6
|
# Author: $Author: bk1 $ (Karl Brodowsky)
|
7
7
|
#
|
8
8
|
require "complex"
|
@@ -44,7 +44,7 @@ module LongDecimalRoundingMode
|
|
44
44
|
ROUND_HALF_EVEN = RoundingModeClass.new(:ROUND_HALF_EVEN, 6)
|
45
45
|
ROUND_UNNECESSARY = RoundingModeClass.new(:ROUND_UNNECESSARY, 7)
|
46
46
|
|
47
|
-
end
|
47
|
+
end # LongDecimalRoundingMode
|
48
48
|
|
49
49
|
#
|
50
50
|
# helper functions to support LongDecimal and LongDecimalQuot
|
@@ -195,7 +195,7 @@ module LongMath
|
|
195
195
|
# the wordwise algorithm is used, which works well for relatively
|
196
196
|
# large values of x. n defines the word size to be used for the
|
197
197
|
# algorithm. It is good to use half of the machine word, but the
|
198
|
-
# algorithm would also work for other values.
|
198
|
+
# algorithm would also work for other values.
|
199
199
|
#
|
200
200
|
def LongMath.sqrtw_with_remainder(x, n = 16)
|
201
201
|
check_is_int(x)
|
@@ -347,14 +347,14 @@ module LongMath
|
|
347
347
|
pi = 0
|
348
348
|
last_pi = 0
|
349
349
|
last_diff = 1
|
350
|
-
|
350
|
+
|
351
351
|
loop do
|
352
352
|
a, b = ((a + b) / 2).round_to_scale(sprec, mode), (a * b).round_to_scale(iprec, mode).sqrt(sprec, mode)
|
353
353
|
c = (c - pow_k * (a * a - b * b)).round_to_scale(iprec, mode)
|
354
354
|
pi = (2 * a * a / c).round_to_scale(sprec, mode)
|
355
355
|
diff = (pi - last_pi).round_to_scale(dprec, mode).abs
|
356
356
|
if (diff.zero? && last_diff.zero?) then
|
357
|
-
|
357
|
+
break
|
358
358
|
end
|
359
359
|
last_pi = pi
|
360
360
|
last_diff = diff
|
@@ -372,11 +372,28 @@ module LongMath
|
|
372
372
|
#
|
373
373
|
def LongMath.exp(x, prec, mode = LongDecimal::ROUND_HALF_DOWN)
|
374
374
|
check_is_ld(x, "x")
|
375
|
+
raise TypeError, "x=#{x.inspect} must not be greater #{MAX_EXP_ABLE}" unless x <= MAX_EXP_ABLE
|
375
376
|
check_is_prec(prec, "prec")
|
376
377
|
check_is_mode(mode, "mode")
|
377
378
|
exp_internal(x, prec, mode)
|
378
379
|
end
|
379
380
|
|
381
|
+
#
|
382
|
+
# calc the power of x with exponent y to the given precision as
|
383
|
+
# LongDecimal. Only supports values of y such that exp(y) still
|
384
|
+
# fits into a float (y <= 709)
|
385
|
+
#
|
386
|
+
def LongMath.power(x, y, prec, mode = LongDecimal::ROUND_HALF_DOWN)
|
387
|
+
check_is_ld(x, "x")
|
388
|
+
check_is_ld(y, "y")
|
389
|
+
raise TypeError, "y=#{y.inspect} must not be greater #{MAX_EXP_ABLE}" unless y <= MAX_EXP_ABLE
|
390
|
+
check_is_prec(prec, "prec")
|
391
|
+
check_is_mode(mode, "mode")
|
392
|
+
iprec = prec+2
|
393
|
+
logx = log(x, iprec, mode)
|
394
|
+
exp_internal(logx * y, prec, mode)
|
395
|
+
end
|
396
|
+
|
380
397
|
#
|
381
398
|
# internal functionality of exp. exposes some more parameters, that
|
382
399
|
# should usually be set to defaut values, in order to allow better testing.
|
@@ -386,7 +403,6 @@ module LongMath
|
|
386
403
|
#
|
387
404
|
def LongMath.exp_internal(x, prec = nil, final_mode = LongDecimal::ROUND_HALF_DOWN, j = nil, k = nil, iprec = nil, mode = LongDecimal::ROUND_HALF_DOWN)
|
388
405
|
check_is_ld(x)
|
389
|
-
raise TypeError, "x=#{x.inspect} must not be greater #{MAX_EXP_ABLE}" unless x <= MAX_EXP_ABLE
|
390
406
|
if (prec == nil) then
|
391
407
|
prec = x.scale
|
392
408
|
end
|
@@ -400,7 +416,7 @@ module LongMath
|
|
400
416
|
|
401
417
|
# if the result would come out to zero anyway, cut the work
|
402
418
|
xi = x.to_i
|
403
|
-
if (xi < -LongMath::MAX_FLOATABLE) || -((xi.to_f - 1) / Math.log(10)) > prec+1 then
|
419
|
+
if (xi < -LongMath::MAX_FLOATABLE) || -((xi.to_f - 1) / Math.log(10)) > prec+1 then
|
404
420
|
return LongDecimal(25, prec+2).round_to_scale(prec, final_mode)
|
405
421
|
end
|
406
422
|
|
@@ -409,10 +425,10 @@ module LongMath
|
|
409
425
|
lb = Math.log(10.0)
|
410
426
|
s1 = (prec * lb / l2) ** (1.0/3.0)
|
411
427
|
if (j == nil) then
|
412
|
-
|
428
|
+
j = s1.round
|
413
429
|
end
|
414
430
|
if (k == nil) then
|
415
|
-
|
431
|
+
k = (s1 + Math.log([1, prec].max) / l2).round
|
416
432
|
end
|
417
433
|
end
|
418
434
|
if (j <= 0) then
|
@@ -439,7 +455,7 @@ module LongMath
|
|
439
455
|
check_is_prec(iprec, "iprec")
|
440
456
|
|
441
457
|
dprec = [ iprec, (prec + 1) << 1 ].min
|
442
|
-
|
458
|
+
|
443
459
|
x_k = (x / (1 << k)).round_to_scale(iprec, mode)
|
444
460
|
x_j = (x_k ** j).round_to_scale(iprec, mode)
|
445
461
|
s = [ LongDecimal(0) ] * j
|
@@ -448,9 +464,9 @@ module LongMath
|
|
448
464
|
f = 0
|
449
465
|
loop do
|
450
466
|
j.times do |i|
|
451
|
-
|
452
|
-
|
453
|
-
|
467
|
+
s[i] += t
|
468
|
+
f += 1
|
469
|
+
t = (t / f).round_to_scale(iprec, mode)
|
454
470
|
end
|
455
471
|
t = (t * x_j).round_to_scale(iprec, mode)
|
456
472
|
break if (t.zero?)
|
@@ -464,7 +480,7 @@ module LongMath
|
|
464
480
|
y_k = LongDecimal(0)
|
465
481
|
j.times do |i|
|
466
482
|
if (i > 0) then
|
467
|
-
|
483
|
+
x_i = (x_i * x_k).round_to_scale(iprec, mode)
|
468
484
|
end
|
469
485
|
# puts("y_k=#{y_k}\ni=#{i} j=#{j} k=#{k} x=#{x}\nx_k=#{x_k}\nx_j=#{x_j}\nx_i=#{x_i}\ns[i]=#{s[i]}\n\n")
|
470
486
|
y_k += (s[i] * x_i).round_to_scale(iprec, mode)
|
@@ -478,7 +494,164 @@ module LongMath
|
|
478
494
|
y
|
479
495
|
end
|
480
496
|
|
481
|
-
|
497
|
+
#
|
498
|
+
# calc the natural logarithm function of x to the given precision as
|
499
|
+
# LongDecimal.
|
500
|
+
#
|
501
|
+
def LongMath.log(x, prec, mode = LongDecimal::ROUND_HALF_DOWN)
|
502
|
+
check_is_ld(x, "x")
|
503
|
+
check_is_prec(prec, "prec")
|
504
|
+
check_is_mode(mode, "mode")
|
505
|
+
log_internal(x, prec, mode)
|
506
|
+
end
|
507
|
+
|
508
|
+
#
|
509
|
+
# calc the base 10 logarithm of x to the given precision as
|
510
|
+
# LongDecimal.
|
511
|
+
#
|
512
|
+
def LongMath.log10(x, prec, mode = LongDecimal::ROUND_HALF_DOWN)
|
513
|
+
check_is_ld(x, "x")
|
514
|
+
check_is_prec(prec, "prec")
|
515
|
+
if (x.one?) then
|
516
|
+
return LongDecimal.zero!(prec)
|
517
|
+
end
|
518
|
+
check_is_mode(mode, "mode")
|
519
|
+
iprec = prec + 2
|
520
|
+
id = x.int_digits10
|
521
|
+
xx = x.move_point_left(id)
|
522
|
+
# puts("x=#{x} xx=#{xx} id=#{id} iprec=#{iprec}\n")
|
523
|
+
lnxx = log_internal(xx, iprec, mode)
|
524
|
+
ln10 = log_internal(10.to_ld, iprec, mode)
|
525
|
+
y = id + (lnxx / ln10).to_ld
|
526
|
+
end
|
527
|
+
|
528
|
+
#
|
529
|
+
# calc the base 2 logarithm of x to the given precision as
|
530
|
+
# LongDecimal.
|
531
|
+
#
|
532
|
+
def LongMath.log2(x, prec, mode = LongDecimal::ROUND_HALF_DOWN)
|
533
|
+
check_is_ld(x, "x")
|
534
|
+
check_is_prec(prec, "prec")
|
535
|
+
if (x.one?) then
|
536
|
+
return LongDecimal.zero!(prec)
|
537
|
+
end
|
538
|
+
check_is_mode(mode, "mode")
|
539
|
+
iprec = prec + 2
|
540
|
+
id = x.int_digits2
|
541
|
+
xx = (x / (1 << id)).round_to_scale(x.scale+id)
|
542
|
+
# puts("x=#{x} xx=#{xx} id=#{id} iprec=#{iprec}\n")
|
543
|
+
lnxx = log_internal(xx, iprec, mode)
|
544
|
+
ln2 = log_internal(2.to_ld, iprec, mode)
|
545
|
+
y = id + (lnxx / ln2).to_ld
|
546
|
+
end
|
547
|
+
|
548
|
+
#
|
549
|
+
# internal functionality of log. exposes some more parameters, that
|
550
|
+
# should usually be set to defaut values, in order to allow better testing.
|
551
|
+
# do not actually call this method unless you are testing log.
|
552
|
+
# create a bug report, if the default settings for the parameters do
|
553
|
+
# not work correctly
|
554
|
+
#
|
555
|
+
def LongMath.log_internal(x, prec = nil, final_mode = LongDecimal::ROUND_HALF_DOWN, iprec = nil, mode = LongDecimal::ROUND_HALF_DOWN)
|
556
|
+
check_is_ld(x)
|
557
|
+
raise TypeError, "x=#{x.inspect} must not be positive" unless x > 0
|
558
|
+
if (prec == nil) then
|
559
|
+
prec = x.scale
|
560
|
+
end
|
561
|
+
check_is_prec(prec, "prec")
|
562
|
+
if (x.one?) then
|
563
|
+
return LongDecimal.zero!(prec)
|
564
|
+
end
|
565
|
+
|
566
|
+
if (final_mode == nil)
|
567
|
+
final_mode = LongDecimal::ROUND_HALF_DOWN
|
568
|
+
end
|
569
|
+
check_is_mode(final_mode, "final_mode")
|
570
|
+
check_is_mode(mode, "mode")
|
571
|
+
|
572
|
+
if (iprec == nil) then
|
573
|
+
iprec = ((prec+10)*1.20).round
|
574
|
+
end
|
575
|
+
if (iprec < prec) then
|
576
|
+
iprec = prec
|
577
|
+
end
|
578
|
+
check_is_prec(iprec, "iprec")
|
579
|
+
|
580
|
+
# dprec = [ iprec - 1, (prec + 1) << 1 ].min
|
581
|
+
dprec = iprec - 1
|
582
|
+
|
583
|
+
y = 0
|
584
|
+
s = 1
|
585
|
+
if (x < 1) then
|
586
|
+
# puts("x=#{x} iprec=#{iprec}\n")
|
587
|
+
x = (1 / x).round_to_scale(iprec, mode)
|
588
|
+
s = -1
|
589
|
+
# puts("s=#{s} x=#{x} iprec=#{iprec}\n")
|
590
|
+
end
|
591
|
+
exp_part = 0
|
592
|
+
estimate = 0
|
593
|
+
while (x > MAX_FLOATABLE) do
|
594
|
+
if (exp_part == 0) then
|
595
|
+
estimate = MAX_EXP_ABLE.to_ld
|
596
|
+
exp_part = exp(estimate, iprec)
|
597
|
+
end
|
598
|
+
x = (x / exp_part).round_to_scale(iprec, mode)
|
599
|
+
if (s < 0) then
|
600
|
+
y -= estimate
|
601
|
+
else
|
602
|
+
y += estimate
|
603
|
+
end
|
604
|
+
end
|
605
|
+
|
606
|
+
delta = LongDecimal(1, 3)
|
607
|
+
while (x - 1).abs > delta do
|
608
|
+
# puts("too far from 1: x=#{x}\n")
|
609
|
+
xf = x.to_f
|
610
|
+
# puts("xf=#{xf}\n")
|
611
|
+
mlx = Math.log(xf)
|
612
|
+
# puts("log(xf)=#{mlx}\n")
|
613
|
+
estimate = mlx.to_ld.round_to_scale(20, mode)
|
614
|
+
exp_part = exp(estimate, iprec << 1)
|
615
|
+
# puts("y=#{y} s=#{s} est=#{estimate} part=#{exp_part} x=#{x}\n")
|
616
|
+
x = (x / exp_part).round_to_scale(iprec, mode)
|
617
|
+
# puts("divided by exp_part=#{exp_part}: #{x}\n")
|
618
|
+
if (s < 0) then
|
619
|
+
y -= estimate
|
620
|
+
else
|
621
|
+
y += estimate
|
622
|
+
end
|
623
|
+
# puts("y=#{y} s=#{s} est=#{estimate} part=#{exp_part} x=#{x}\n")
|
624
|
+
end
|
625
|
+
|
626
|
+
factor = 1
|
627
|
+
# delta = LongDecimal(1, (iprec.to_f**(1/3)).round)
|
628
|
+
# while (x - 1).abs > delta do
|
629
|
+
# x = sqrt(x)
|
630
|
+
# factor *= 2
|
631
|
+
# end
|
632
|
+
|
633
|
+
sum = 0
|
634
|
+
z = 1 - x
|
635
|
+
i = 1
|
636
|
+
p = 1.to_ld
|
637
|
+
d = 1.to_ld
|
638
|
+
until p.abs.round_to_scale(dprec, LongDecimal::ROUND_DOWN).zero? do
|
639
|
+
p = (p * z).round_to_scale(iprec, mode)
|
640
|
+
d = (p / i).round_to_scale(iprec, mode)
|
641
|
+
i += 1
|
642
|
+
sum += d
|
643
|
+
|
644
|
+
# puts("s=#{sum} d=#{d} x=#{x} i=#{i}\n")
|
645
|
+
end
|
646
|
+
|
647
|
+
# puts("y=#{y} s=#{s} f=#{factor} sum=#{sum}\n")
|
648
|
+
y -= ((s * factor) * sum).round_to_scale(iprec, mode)
|
649
|
+
# puts("y=#{y} s=#{s} f=#{factor} sum=#{sum}\n")
|
650
|
+
return y.round_to_scale(prec, final_mode)
|
651
|
+
|
652
|
+
end
|
653
|
+
|
654
|
+
end # LongMath
|
482
655
|
|
483
656
|
#
|
484
657
|
# class for holding fixed point long decimal numbers
|
@@ -486,7 +659,7 @@ end
|
|
486
659
|
# digits and the other one the position of the decimal point.
|
487
660
|
#
|
488
661
|
class LongDecimal < Numeric
|
489
|
-
@RCS_ID='-$Id: longdecimal.rb,v 1.
|
662
|
+
@RCS_ID='-$Id: longdecimal.rb,v 1.6 2006/03/10 20:10:45 bk1 Exp $-'
|
490
663
|
|
491
664
|
include LongDecimalRoundingMode
|
492
665
|
|
@@ -610,7 +783,7 @@ class LongDecimal < Numeric
|
|
610
783
|
else
|
611
784
|
# we assume a string or a floating point number
|
612
785
|
# floating point number or BigDecimal is converted to string, so
|
613
|
-
# we only deal with strings
|
786
|
+
# we only deal with strings
|
614
787
|
# this operation is not so common, so there is no urgent need to
|
615
788
|
# optimize it
|
616
789
|
num_str = x.to_s
|
@@ -794,7 +967,7 @@ class LongDecimal < Numeric
|
|
794
967
|
# power of 10 as denominator
|
795
968
|
#
|
796
969
|
def to_r
|
797
|
-
Rational(
|
970
|
+
Rational(numerator, denominator)
|
798
971
|
end
|
799
972
|
|
800
973
|
#
|
@@ -803,10 +976,31 @@ class LongDecimal < Numeric
|
|
803
976
|
# float-arithmetic.
|
804
977
|
#
|
805
978
|
def to_f
|
806
|
-
|
807
|
-
|
979
|
+
divisor = denominator
|
980
|
+
if (divisor == 1) then
|
981
|
+
return numerator.to_f
|
982
|
+
elsif int_val.abs <= LongMath::MAX_FLOATABLE then
|
983
|
+
if (divisor.abs > LongMath::MAX_FLOATABLE) then
|
984
|
+
return 0.0
|
985
|
+
else
|
986
|
+
# puts("int_val=#{int_val}")
|
987
|
+
# $defout.flush
|
988
|
+
f = int_val.to_f
|
989
|
+
# puts(" f=#{f}\n")
|
990
|
+
# $defout.flush
|
991
|
+
return f / divisor
|
992
|
+
# int_val.to_f / 10**scale
|
993
|
+
end
|
994
|
+
elsif numerator.abs < divisor
|
995
|
+
# number is between -1 and 1
|
996
|
+
# factor = numerator.abs.div(LongMath::MAX_FLOATABLE)
|
997
|
+
# digits = factor.to_ld.int_digits10
|
998
|
+
# return LongDecimal(numerator.div(10**digits), scale -digits).to_f
|
999
|
+
return self.to_s.to_f
|
808
1000
|
else
|
809
|
-
|
1001
|
+
# s2 = [scale.div(2), 1].max
|
1002
|
+
# return LongDecimal(numerator.div(10**s2), scale - s2).to_f
|
1003
|
+
return self.to_s.to_f
|
810
1004
|
end
|
811
1005
|
end
|
812
1006
|
|
@@ -817,7 +1011,7 @@ class LongDecimal < Numeric
|
|
817
1011
|
# to_i when the number represented by self is actually an integer.
|
818
1012
|
#
|
819
1013
|
def to_i
|
820
|
-
|
1014
|
+
(numerator / denominator).to_i
|
821
1015
|
end
|
822
1016
|
|
823
1017
|
#
|
@@ -851,6 +1045,59 @@ class LongDecimal < Numeric
|
|
851
1045
|
#
|
852
1046
|
alias numerator int_val
|
853
1047
|
|
1048
|
+
#
|
1049
|
+
# number of binary digits before the decimal point, not counting a single 0.
|
1050
|
+
#
|
1051
|
+
def int_digits2
|
1052
|
+
int_part = self.to_i.abs
|
1053
|
+
if int_part.zero? then
|
1054
|
+
return 0
|
1055
|
+
end
|
1056
|
+
|
1057
|
+
n = int_part.size * 8 - 31
|
1058
|
+
int_part = int_part >> n
|
1059
|
+
until int_part.zero? do
|
1060
|
+
int_part = int_part >> 1
|
1061
|
+
n += 1
|
1062
|
+
end
|
1063
|
+
n
|
1064
|
+
end
|
1065
|
+
|
1066
|
+
#
|
1067
|
+
# number of decimal digits before the decimal point, not counting a single 0.
|
1068
|
+
#
|
1069
|
+
def int_digits10
|
1070
|
+
int_part = self.to_i.abs
|
1071
|
+
if int_part.zero? then
|
1072
|
+
return 0
|
1073
|
+
end
|
1074
|
+
|
1075
|
+
id = 1
|
1076
|
+
powers = []
|
1077
|
+
power = 10
|
1078
|
+
idx = 0
|
1079
|
+
until int_part.zero? do
|
1080
|
+
expon = 1 << idx
|
1081
|
+
powers[idx] = power
|
1082
|
+
break if int_part < power
|
1083
|
+
id += expon
|
1084
|
+
int_part = (int_part / power).to_i
|
1085
|
+
idx += 1
|
1086
|
+
power = power * power
|
1087
|
+
end
|
1088
|
+
until int_part < 10 do
|
1089
|
+
idx -= 1
|
1090
|
+
expon = 1 << idx
|
1091
|
+
power = powers[idx]
|
1092
|
+
# puts("i=#{int_part} p=#{power}\n")
|
1093
|
+
while int_part >= power
|
1094
|
+
id += expon
|
1095
|
+
int_part = (int_part / power).to_i
|
1096
|
+
end
|
1097
|
+
end
|
1098
|
+
id
|
1099
|
+
end
|
1100
|
+
|
854
1101
|
#
|
855
1102
|
# before adding or subtracting two LongDecimal numbers
|
856
1103
|
# it is mandatory to set them to the same scale. The maximum of the
|
@@ -999,10 +1246,18 @@ class LongDecimal < Numeric
|
|
999
1246
|
end
|
1000
1247
|
end
|
1001
1248
|
|
1249
|
+
#
|
1250
|
+
# divide self by other and round result to scale of self using the
|
1251
|
+
# given rounding mode
|
1252
|
+
#
|
1002
1253
|
def divide(other, rounding_mode)
|
1003
1254
|
divide_s(other, nil, rounding_mode)
|
1004
1255
|
end
|
1005
1256
|
|
1257
|
+
#
|
1258
|
+
# divide self by other and round result to new_scale using the
|
1259
|
+
# given rounding mode. If new_scale is nil, use scale of self.
|
1260
|
+
#
|
1006
1261
|
def divide_s(other, new_scale, rounding_mode)
|
1007
1262
|
q = self / other
|
1008
1263
|
if (q.kind_of? Float) then
|
@@ -1018,10 +1273,14 @@ class LongDecimal < Numeric
|
|
1018
1273
|
end
|
1019
1274
|
end
|
1020
1275
|
|
1276
|
+
#
|
1277
|
+
# divide self by other and return result as Rational, if other
|
1278
|
+
# allowed exact calculations.
|
1279
|
+
#
|
1021
1280
|
def rdiv(other)
|
1022
1281
|
q = self / other
|
1023
|
-
if (q.kind_of? LongDecimalQuot)
|
1024
|
-
|
1282
|
+
if (q.kind_of? LongDecimalQuot) then
|
1283
|
+
q.to_r
|
1025
1284
|
else
|
1026
1285
|
q
|
1027
1286
|
end
|
@@ -1050,9 +1309,9 @@ class LongDecimal < Numeric
|
|
1050
1309
|
end
|
1051
1310
|
else
|
1052
1311
|
if (other.kind_of? LongDecimal) || (other.kind_of? LongDecimalQuot) then
|
1053
|
-
other = other.
|
1312
|
+
other = other.to_r
|
1054
1313
|
end
|
1055
|
-
self.
|
1314
|
+
self.to_r ** other
|
1056
1315
|
end
|
1057
1316
|
end
|
1058
1317
|
|
@@ -1264,8 +1523,10 @@ class LongDecimal < Numeric
|
|
1264
1523
|
elsif other.kind_of? LongDecimalQuot then
|
1265
1524
|
return other, LongDecimalQuot(self.to_r, scale)
|
1266
1525
|
elsif other.kind_of? Rational then
|
1267
|
-
|
1268
|
-
|
1526
|
+
sc = scale
|
1527
|
+
o = LongDecimalQuot(other, sc)
|
1528
|
+
s = LongDecimalQuot(self.to_r, sc)
|
1529
|
+
return o, s
|
1269
1530
|
elsif (other.kind_of? Integer) || (other.kind_of? Float) then
|
1270
1531
|
other = LongDecimal(other)
|
1271
1532
|
if (other.scale > scale) then
|
@@ -1308,6 +1569,10 @@ class LongDecimal < Numeric
|
|
1308
1569
|
int_val.zero?
|
1309
1570
|
end
|
1310
1571
|
|
1572
|
+
def one?
|
1573
|
+
(self-1).zero?
|
1574
|
+
end
|
1575
|
+
|
1311
1576
|
#
|
1312
1577
|
# Returns a hash code for the complex number.
|
1313
1578
|
#
|
@@ -1322,7 +1587,7 @@ class LongDecimal < Numeric
|
|
1322
1587
|
sprintf("LongDecimal(%s, %s)", int_val.inspect, scale.inspect)
|
1323
1588
|
end
|
1324
1589
|
|
1325
|
-
end
|
1590
|
+
end # LongDecimal
|
1326
1591
|
|
1327
1592
|
#
|
1328
1593
|
# This class is used for storing intermediate results after having
|
@@ -1331,7 +1596,7 @@ end
|
|
1331
1596
|
#
|
1332
1597
|
class LongDecimalQuot < Numeric
|
1333
1598
|
|
1334
|
-
@RCS_ID='-$Id: longdecimal.rb,v 1.
|
1599
|
+
@RCS_ID='-$Id: longdecimal.rb,v 1.6 2006/03/10 20:10:45 bk1 Exp $-'
|
1335
1600
|
|
1336
1601
|
include LongDecimalRoundingMode
|
1337
1602
|
|
@@ -1343,7 +1608,7 @@ class LongDecimalQuot < Numeric
|
|
1343
1608
|
# create a new LongDecimalQuot from a rational and a scale or a
|
1344
1609
|
# pair of LongDecimals
|
1345
1610
|
def initialize(first, second)
|
1346
|
-
if (first.kind_of? Rational) && (second.kind_of? Integer) then
|
1611
|
+
if ((first.kind_of? Rational) || (first.kind_of? Integer)) && (second.kind_of? Integer) then
|
1347
1612
|
@rat = Rational(first.numerator, first.denominator)
|
1348
1613
|
@scale = second
|
1349
1614
|
elsif (first.kind_of? LongDecimal) && (second.kind_of? LongDecimal) then
|
@@ -1402,7 +1667,7 @@ class LongDecimalQuot < Numeric
|
|
1402
1667
|
end
|
1403
1668
|
|
1404
1669
|
def to_ld
|
1405
|
-
|
1670
|
+
round_to_scale(scale, ROUND_HALF_UP)
|
1406
1671
|
end
|
1407
1672
|
|
1408
1673
|
def +@
|
@@ -1537,7 +1802,6 @@ class LongDecimalQuot < Numeric
|
|
1537
1802
|
divisor = denominator
|
1538
1803
|
quot, rem = prod.divmod(divisor)
|
1539
1804
|
sign_rem = rem <=> 0
|
1540
|
-
# puts("self=#{self.to_s} f=#{factor} prod=#{prod} divisor=#{divisor} quot=#{quot} rem=#{rem} sign_rem=#{sign_rem.to_s} sign_quot=#{sign_quot.to_s}")
|
1541
1805
|
if (sign_rem == 0)
|
1542
1806
|
return LongDecimal(quot, new_scale)
|
1543
1807
|
end
|
@@ -1548,7 +1812,6 @@ class LongDecimalQuot < Numeric
|
|
1548
1812
|
sign_rem = rem <=> 0
|
1549
1813
|
raise Error, "signs do not match self=#{self.to_s} f=#{factor} prod=#{prod} divisor=#{divisor} quot=#{quot} rem=#{rem}" if sign_rem >= 0
|
1550
1814
|
end
|
1551
|
-
# puts("self=#{self.to_s} f=#{factor} prod=#{prod} divisor=#{divisor} quot=#{quot} rem=#{rem} sign_rem=#{sign_rem.to_s} sign_quot=#{sign_quot.to_s}")
|
1552
1815
|
|
1553
1816
|
if mode == ROUND_UNNECESSARY then
|
1554
1817
|
raise ArgumentError, "mode ROUND_UNNECESSARY not applicable, remainder #{rem.to_s} is not zero"
|
@@ -1665,7 +1928,7 @@ class LongDecimalQuot < Numeric
|
|
1665
1928
|
sprintf("LongDecimalQuot(Rational(%s, %s), %s)", numerator.inspect, denominator.inspect, scale.inspect)
|
1666
1929
|
end
|
1667
1930
|
|
1668
|
-
end
|
1931
|
+
end # LongDecimalQuot
|
1669
1932
|
|
1670
1933
|
#
|
1671
1934
|
# Creates a LongDecimal number. +a+ and +b+ should be Numeric.
|
@@ -1688,6 +1951,6 @@ class Numeric
|
|
1688
1951
|
LongDecimal(self)
|
1689
1952
|
end
|
1690
1953
|
|
1691
|
-
end
|
1954
|
+
end # Numeric
|
1692
1955
|
|
1693
1956
|
# end of file longdecimal.rb
|