long-decimal 1.00.02 → 1.00.03
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README +41 -25
- data/Rakefile +2 -1
- data/lib/long-decimal-extra.rb +37 -1
- data/lib/long-decimal.rb +208 -17
- data/lib/long-decimal/version.rb +1 -1
- data/test/testlongdecimal.rb +225 -5
- data/test/testlongdeclib.rb +46 -25
- data/test/testrandlib.rb +2 -1
- data/test/testrandom.rb +2 -1
- data/test/testrandpower.rb +2 -1
- metadata +2 -2
data/lib/long-decimal/version.rb
CHANGED
data/test/testlongdecimal.rb
CHANGED
@@ -2,8 +2,9 @@
|
|
2
2
|
#
|
3
3
|
# testlongdecimal.rb -- runit test for long-decimal.rb
|
4
4
|
#
|
5
|
-
# (C) Karl Brodowsky (IT Sky Consulting GmbH) 2006-
|
5
|
+
# (C) Karl Brodowsky (IT Sky Consulting GmbH) 2006-2015
|
6
6
|
#
|
7
|
+
# TAG: $TAG v1.00.03$
|
7
8
|
# CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/test/testlongdecimal.rb,v 1.86 2011/01/16 22:16:59 bk1 Exp $
|
8
9
|
# CVS-Label: $Name: $
|
9
10
|
# Author: $Author: bk1 $ (Karl Brodowsky)
|
@@ -1147,6 +1148,7 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
1147
1148
|
y = Complex(yr, yi)
|
1148
1149
|
z = x/y
|
1149
1150
|
msg = "x=#{x} y=#{y} z=#{z} xr=#{xr.inspect} (#{tw_c}) xi=#{xi.inspect} (#{fi_c}) yr=#{yr.inspect} (#{th_c}) yi=#{yi.inspect} (#{fo_c})"
|
1151
|
+
# puts msg
|
1150
1152
|
if (xr.kind_of? Integer) && (xi.kind_of? Integer) && (yr.kind_of? Integer) && (yi.kind_of? Integer) # && ! LongDecimal::RUNNING_19
|
1151
1153
|
# ruby 1.9 creates rational result even from integers, ruby 1.8 uses integers as results.
|
1152
1154
|
zc = (x.cdiv y)
|
@@ -2378,8 +2380,8 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
2378
2380
|
#
|
2379
2381
|
# test rounding with ROUND_HARMONIC_ODD
|
2380
2382
|
#
|
2381
|
-
def
|
2382
|
-
print "\
|
2383
|
+
def test_round_to_scale_harmonic_odd
|
2384
|
+
print "\ntest_round_to_scale_harmonic_odd [#{Time.now}]: "
|
2383
2385
|
l = LongDecimal("2.39")
|
2384
2386
|
r = l.round_to_scale(0, ROUND_HARMONIC_ODD)
|
2385
2387
|
assert_equal("2", r.to_s, "l=#{l.inspect} r=#{r.inspect}")
|
@@ -2909,6 +2911,7 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
2909
2911
|
end
|
2910
2912
|
|
2911
2913
|
text0 = "m=#{modulus} x=#{x} s=#{remainders.inspect}"
|
2914
|
+
# puts text0
|
2912
2915
|
print "."
|
2913
2916
|
$stdout.flush
|
2914
2917
|
n = 3*modulus
|
@@ -3061,6 +3064,7 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
3061
3064
|
end
|
3062
3065
|
|
3063
3066
|
text = "m=#{modulus} x=#{x} s=#{remainders.inspect}"
|
3067
|
+
# puts text
|
3064
3068
|
print "."
|
3065
3069
|
$stdout.flush
|
3066
3070
|
|
@@ -3527,6 +3531,11 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
3527
3531
|
#
|
3528
3532
|
def check_int_round_major_to_two_allowed_remainders(remainder_sets, boundary_exact_integral, major_mode, &block)
|
3529
3533
|
|
3534
|
+
if RUBY_VERSION.match /^1\.8/
|
3535
|
+
puts "Warning: this test is not supported for Ruby #{RUBY_VERSION}"
|
3536
|
+
return
|
3537
|
+
end
|
3538
|
+
|
3530
3539
|
mode_up = MODE_LOOKUP[[major_mode, MINOR_UP]]
|
3531
3540
|
mode_down = MODE_LOOKUP[[major_mode, MINOR_DOWN]]
|
3532
3541
|
mode_floor = MODE_LOOKUP[[major_mode, MINOR_FLOOR]]
|
@@ -3534,6 +3543,7 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
3534
3543
|
|
3535
3544
|
20.upto 25 do |modulus|
|
3536
3545
|
remainder_sets.each do |remainders|
|
3546
|
+
# puts text
|
3537
3547
|
print "."
|
3538
3548
|
$stdout.flush
|
3539
3549
|
|
@@ -4026,6 +4036,7 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
4026
4036
|
end
|
4027
4037
|
end
|
4028
4038
|
map.each do |x, x1|
|
4039
|
+
# puts "x=#{x} x1=#{x1}"
|
4029
4040
|
print ":"
|
4030
4041
|
$stdout.flush
|
4031
4042
|
map.each do |y, y1|
|
@@ -5489,15 +5500,20 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
5489
5500
|
#
|
5490
5501
|
def test_sqrt
|
5491
5502
|
print "\ntest_sqrt [#{Time.now}]: "
|
5503
|
+
|
5504
|
+
# sqrt of 0 is always 0 without need to round
|
5492
5505
|
x = LongDecimal.zero!(101)
|
5493
5506
|
y = check_sqrt(x, 120, ROUND_UNNECESSARY, 0, 0, "zero")
|
5494
5507
|
assert(y.zero?, "sqrt(0)")
|
5495
5508
|
|
5509
|
+
# sqrt of 1 is always 1 without need to round
|
5496
5510
|
x = LongDecimal.one!(101)
|
5497
5511
|
y = check_sqrt(x, 120, ROUND_UNNECESSARY, 0, 0, "one")
|
5498
5512
|
assert(y.one?, "sqrt(1)")
|
5499
5513
|
|
5514
|
+
# sqrt of 2 always gets rounded somehow
|
5500
5515
|
x = LongDecimal.two!(101)
|
5516
|
+
x.freeze
|
5501
5517
|
y0 = check_sqrt(x, 120, ROUND_DOWN, 0, 1, "two")
|
5502
5518
|
assert(y0.square < x, "y0*y0")
|
5503
5519
|
assert(y0.succ.square > x, "(y0.succ).square")
|
@@ -5548,6 +5564,7 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
5548
5564
|
assert(y0 <= y1, "y0 y1")
|
5549
5565
|
assert(y1 <= y2, "y1 y2")
|
5550
5566
|
|
5567
|
+
# sqrt of 3 always gets rounded somehow
|
5551
5568
|
x = 3.to_ld
|
5552
5569
|
y0 = check_sqrt(x, 120, ROUND_DOWN, 0, 1, "three")
|
5553
5570
|
assert(y0.square < x, "y0*y0")
|
@@ -5559,6 +5576,7 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
5559
5576
|
assert(y0 <= y1, "y0 y1")
|
5560
5577
|
assert(y1 <= y2, "y1 y2")
|
5561
5578
|
|
5579
|
+
# sqrt of 4 always gets rounded somehow
|
5562
5580
|
x = 4.to_ld(101)
|
5563
5581
|
y0 = check_sqrt(x, 120, ROUND_DOWN, 0, 0, "four")
|
5564
5582
|
y1 = check_sqrt(x, 120, ROUND_HALF_EVEN, 0, 0, "four")
|
@@ -5600,6 +5618,81 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
5600
5618
|
check_sqrt_with_remainder(x, 120, "five")
|
5601
5619
|
end
|
5602
5620
|
|
5621
|
+
# test sqare roots that come to lie exactly on the geometric mean of the two rounding candidates
|
5622
|
+
def test_sqrt_on_geometric_boundary
|
5623
|
+
print "\ntest_sqrt_on_geometric_boundary [#{Time.now}]: "
|
5624
|
+
1.upto(100) do |int_val|
|
5625
|
+
100.times do |scale|
|
5626
|
+
y_lower = LongDecimal(int_val, scale)
|
5627
|
+
y_upper = y_lower.succ
|
5628
|
+
x = y_lower * y_upper
|
5629
|
+
msg = "x=#{x} y_lower=#{y_lower} y_upper=#{y_upper} "
|
5630
|
+
# puts msg
|
5631
|
+
[ ROUND_GEOMETRIC_UP, ROUND_GEOMETRIC_CEILING ].each do |mode|
|
5632
|
+
y = LongMath.sqrt(x, scale, mode)
|
5633
|
+
assert_equal(y_upper, y, msg + "y=#{y} mode=#{mode}")
|
5634
|
+
end
|
5635
|
+
[ ROUND_GEOMETRIC_DOWN, ROUND_GEOMETRIC_FLOOR ].each do |mode|
|
5636
|
+
y = LongMath.sqrt(x, scale, mode)
|
5637
|
+
assert_equal(y_lower, y, msg + "y=#{y} mode=#{mode}")
|
5638
|
+
end
|
5639
|
+
y = LongMath.sqrt(x, scale, ROUND_GEOMETRIC_EVEN)
|
5640
|
+
assert(y == y_lower || y == y_upper, msg + "y=#{y} mode=#{ROUND_GEOMETRIC_EVEN}")
|
5641
|
+
assert(y[0] == 0, msg + "y=#{y} mode=#{ROUND_GEOMETRIC_EVEN}")
|
5642
|
+
y = LongMath.sqrt(x, scale, ROUND_GEOMETRIC_ODD)
|
5643
|
+
assert(y == y_lower || y == y_upper, msg + "y=#{y} mode=#{ROUND_GEOMETRIC_ODD}")
|
5644
|
+
assert(y[0] == 1, msg + "y=#{y} mode=#{ROUND_GEOMETRIC_ODD}")
|
5645
|
+
end
|
5646
|
+
end
|
5647
|
+
end
|
5648
|
+
|
5649
|
+
# test sqare roots that come to lie exactly on the geometric mean of the two rounding candidates
|
5650
|
+
def test_sqrt_zero_on_geometric_boundary
|
5651
|
+
print "\ntest_sqrt_on_geometric_boundary [#{Time.now}]: "
|
5652
|
+
100.times do |scale|
|
5653
|
+
y_lower = LongDecimal(0, scale)
|
5654
|
+
y_upper = y_lower.succ
|
5655
|
+
x = y_lower * y_upper
|
5656
|
+
msg = "x=#{x} y_lower=#{y_lower} y_upper=#{y_upper} "
|
5657
|
+
ALL_MINOR.each do |minor|
|
5658
|
+
if (minor == MINOR_UNUSED)
|
5659
|
+
next
|
5660
|
+
end
|
5661
|
+
mode = MODE_LOOKUP[[MAJOR_GEOMETRIC, minor]]
|
5662
|
+
y = LongMath.sqrt(x, scale, mode)
|
5663
|
+
assert_equal(0, y, msg + "y=#{y} mode=#{mode}")
|
5664
|
+
end
|
5665
|
+
end
|
5666
|
+
end
|
5667
|
+
|
5668
|
+
# test sqare roots that come to lie exactly on the quadratic mean of the two rounding candidates
|
5669
|
+
def test_sqrt_on_quadratic_boundary
|
5670
|
+
print "\ntest_sqrt_on_quadratic_boundary [#{Time.now}]: "
|
5671
|
+
100.times do |int_val|
|
5672
|
+
100.times do |scale|
|
5673
|
+
y_lower = LongDecimal(int_val, scale)
|
5674
|
+
y_upper = y_lower.succ
|
5675
|
+
x = LongMath.arithmetic_mean(2*scale + 2, ROUND_HALF_EVEN, y_lower * y_lower, y_upper * y_upper)
|
5676
|
+
msg = "x=#{x} y_lower=#{y_lower} y_upper=#{y_upper} "
|
5677
|
+
# puts msg
|
5678
|
+
[ ROUND_QUADRATIC_UP, ROUND_QUADRATIC_CEILING ].each do |mode|
|
5679
|
+
y = LongMath.sqrt(x, scale, mode)
|
5680
|
+
assert_equal(y_upper, y, msg + "y=#{y} mode=#{mode}")
|
5681
|
+
end
|
5682
|
+
[ ROUND_QUADRATIC_DOWN, ROUND_QUADRATIC_FLOOR ].each do |mode|
|
5683
|
+
y = LongMath.sqrt(x, scale, mode)
|
5684
|
+
assert_equal(y, y_lower, msg + "y=#{y} mode=#{mode}")
|
5685
|
+
end
|
5686
|
+
y = LongMath.sqrt(x, scale, ROUND_QUADRATIC_EVEN)
|
5687
|
+
assert(y == y_lower || y == y_upper, msg + "y=#{y} mode=#{ROUND_QUADRATIC_EVEN}")
|
5688
|
+
assert(y[0] == 0, msg + "y=#{y} mode=#{ROUND_QUADRATIC_EVEN}")
|
5689
|
+
y = LongMath.sqrt(x, scale, ROUND_QUADRATIC_ODD)
|
5690
|
+
assert(y == y_lower || y == y_upper, msg + "y=#{y} mode=#{ROUND_QUADRATIC_ODD}")
|
5691
|
+
assert(y[0] == 1, msg + "y=#{y} mode=#{ROUND_QUADRATIC_ODD}")
|
5692
|
+
end
|
5693
|
+
end
|
5694
|
+
end
|
5695
|
+
|
5603
5696
|
#
|
5604
5697
|
# test LongMath.sqrt with non-LongDecimal arguments
|
5605
5698
|
#
|
@@ -5740,6 +5833,34 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
5740
5833
|
check_cbrt_with_remainder(x, 120, "five")
|
5741
5834
|
end
|
5742
5835
|
|
5836
|
+
# test sqare roots that come to lie exactly on the cubic mean of the two rounding candidates
|
5837
|
+
def test_cbrt_on_cubic_boundary
|
5838
|
+
print "\ntest_cbrt_on_cubic_boundary [#{Time.now}]: "
|
5839
|
+
100.times do |int_val|
|
5840
|
+
100.times do |scale|
|
5841
|
+
y_lower = LongDecimal(int_val, scale)
|
5842
|
+
y_upper = y_lower.succ
|
5843
|
+
x = LongMath.arithmetic_mean(3*scale + 2, ROUND_HALF_EVEN, y_lower.cube(), y_upper.cube())
|
5844
|
+
msg = "x=#{x} y_lower=#{y_lower} y_upper=#{y_upper} "
|
5845
|
+
# puts msg
|
5846
|
+
[ ROUND_CUBIC_UP, ROUND_CUBIC_CEILING ].each do |mode|
|
5847
|
+
y = LongMath.cbrt(x, scale, mode)
|
5848
|
+
assert_equal(y_upper, y, msg + "y=#{y} mode=#{mode}")
|
5849
|
+
end
|
5850
|
+
[ ROUND_CUBIC_DOWN, ROUND_CUBIC_FLOOR ].each do |mode|
|
5851
|
+
y = LongMath.cbrt(x, scale, mode)
|
5852
|
+
assert_equal(y, y_lower, msg + "y=#{y} mode=#{mode}")
|
5853
|
+
end
|
5854
|
+
y = LongMath.cbrt(x, scale, ROUND_CUBIC_EVEN)
|
5855
|
+
assert(y == y_lower || y == y_upper, msg + "y=#{y} mode=#{ROUND_CUBIC_EVEN}")
|
5856
|
+
assert(y[0] == 0, msg + "y=#{y} mode=#{ROUND_CUBIC_EVEN}")
|
5857
|
+
y = LongMath.cbrt(x, scale, ROUND_CUBIC_ODD)
|
5858
|
+
assert(y == y_lower || y == y_upper, msg + "y=#{y} mode=#{ROUND_CUBIC_ODD}")
|
5859
|
+
assert(y[0] == 1, msg + "y=#{y} mode=#{ROUND_CUBIC_ODD}")
|
5860
|
+
end
|
5861
|
+
end
|
5862
|
+
end
|
5863
|
+
|
5743
5864
|
#
|
5744
5865
|
# test LongMath.cbrt with non-LongDecimal arguments
|
5745
5866
|
#
|
@@ -7354,6 +7475,46 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
7354
7475
|
end
|
7355
7476
|
end
|
7356
7477
|
|
7478
|
+
def test_means_two_param_round_up
|
7479
|
+
print "\ntest_means_two_param_round_up [#{Time.now}] (20 sec): "
|
7480
|
+
arr = [ 0, 1, 2, 7, 0.0, 1.0, 2.0, Math::PI, Rational(40, 9), Rational(0, 1), Rational(1,1), Rational(2,3), LongDecimal(3333333333333333, 10), LongDecimal(33, 10), LongDecimal(0, 10), LongDecimal(10000000000, 10), LongMath.pi(100) ]
|
7481
|
+
x = Math::PI
|
7482
|
+
y = Math::PI
|
7483
|
+
print "."
|
7484
|
+
prec = 0
|
7485
|
+
rm = ROUND_UP
|
7486
|
+
xx = x.to_ld(prec, rm)
|
7487
|
+
yy = y.to_ld(prec, rm)
|
7488
|
+
mi = [xx, yy].min
|
7489
|
+
am = LongMath.arithmetic_mean(prec, rm, x, y)
|
7490
|
+
gm = LongMath.geometric_mean(prec, rm, x, y)
|
7491
|
+
if (x.sgn == 0 || y.sgn == 0)
|
7492
|
+
hm = gm
|
7493
|
+
else
|
7494
|
+
hm = LongMath.harmonic_mean(prec, rm, x, y)
|
7495
|
+
end
|
7496
|
+
qm = LongMath.quadratic_mean(prec, rm, x, y)
|
7497
|
+
cm = LongMath.cubic_mean(prec, rm, x, y)
|
7498
|
+
ma = [xx, yy].max
|
7499
|
+
|
7500
|
+
text = "mi=#{mi} hm=#{hm} gm=#{gm} am=#{am} qm=#{qm} cm=#{cm} ma=#{ma} prec=#{prec} rm=#{rm} x=#{x} y=#{y}"
|
7501
|
+
assert(mi <= hm.succ, text)
|
7502
|
+
assert(hm <= gm.succ, text)
|
7503
|
+
assert(gm <= am.succ, text)
|
7504
|
+
assert(am <= qm.succ, text)
|
7505
|
+
assert(qm <= cm.succ, text)
|
7506
|
+
assert(cm <= ma.succ, text)
|
7507
|
+
if (x == y)
|
7508
|
+
assert_equal(mi, hm, text)
|
7509
|
+
assert_equal(hm, gm, text)
|
7510
|
+
assert_equal(gm, am, text)
|
7511
|
+
assert_equal(am, qm, text)
|
7512
|
+
assert_equal(qm, cm, text)
|
7513
|
+
assert_equal(cm, ma, text)
|
7514
|
+
end
|
7515
|
+
end
|
7516
|
+
|
7517
|
+
# test the right ordering of the means excluding agm/hgm
|
7357
7518
|
def test_means_three_param
|
7358
7519
|
print "\ntest_means_three_param [#{Time.now}] (4 min): "
|
7359
7520
|
arr = [ 0, 1, 2, 0.0, 1.0, Math::PI, Rational(40, 9), Rational(0, 1), Rational(1,1), LongDecimal(3333333333333333, 10), LongDecimal(0, 10), LongDecimal(10000000000, 10), LongMath.pi(100) ]
|
@@ -7363,6 +7524,60 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
7363
7524
|
arr.each do |z|
|
7364
7525
|
print "."
|
7365
7526
|
12.times do |prec|
|
7527
|
+
ALL_ROUNDING_MODES.each do |rm|
|
7528
|
+
if (rm == ROUND_UNNECESSARY)
|
7529
|
+
next
|
7530
|
+
end
|
7531
|
+
xx = x.to_ld(prec, rm)
|
7532
|
+
yy = y.to_ld(prec, rm)
|
7533
|
+
zz = z.to_ld(prec, rm)
|
7534
|
+
mi = [xx, yy, zz].min
|
7535
|
+
am = LongMath.arithmetic_mean(prec, rm, x, y, z)
|
7536
|
+
gm = LongMath.geometric_mean(prec, rm, x, y, z)
|
7537
|
+
if (x.sgn == 0 || y.sgn == 0 || z.sgn == 0)
|
7538
|
+
hm = gm
|
7539
|
+
else
|
7540
|
+
hm = LongMath.harmonic_mean(prec, rm, x, y, z)
|
7541
|
+
end
|
7542
|
+
qm = LongMath.quadratic_mean(prec, rm, x, y, z)
|
7543
|
+
cm = LongMath.cubic_mean(prec, rm, x, y, z)
|
7544
|
+
ma = [xx, yy, zz].max
|
7545
|
+
text = "mi=#{mi} hm=#{hm} gm=#{gm} am=#{am} qm=#{qm} cm=#{cm} ma=#{ma} prec=#{prec} rm=#{rm} x=#{x} y=#{y} z=#{z}"
|
7546
|
+
assert(mi <= hm.succ, text)
|
7547
|
+
assert(hm <= gm.succ, text)
|
7548
|
+
assert(gm <= am.succ, text)
|
7549
|
+
assert(am <= qm.succ, text)
|
7550
|
+
assert(qm <= cm.succ, text)
|
7551
|
+
assert(cm <= ma.succ, text)
|
7552
|
+
if (x == y && y == z)
|
7553
|
+
assert_equal(mi, hm, text)
|
7554
|
+
assert_equal(hm, gm, text)
|
7555
|
+
assert_equal(gm, am, text)
|
7556
|
+
assert_equal(am, qm, text)
|
7557
|
+
assert_equal(qm, cm, text)
|
7558
|
+
assert_equal(cm, ma, text)
|
7559
|
+
end
|
7560
|
+
end
|
7561
|
+
end
|
7562
|
+
end
|
7563
|
+
end
|
7564
|
+
end
|
7565
|
+
end
|
7566
|
+
|
7567
|
+
# test the right ordering of the means (including agm/hgm)
|
7568
|
+
def test_means_three_param_agm_hgm
|
7569
|
+
print "\ntest_means_three_param_agm_hgm [#{Time.now}] (4 min): "
|
7570
|
+
arr = [ 0, 1, 2, 0.0, 1.0, Math::PI, Rational(40, 9), Rational(0, 1), Rational(1,1), LongDecimal(3333333333333333, 10), LongDecimal(0, 10), LongDecimal(10000000000, 10), LongMath.pi(100) ]
|
7571
|
+
arr.each do |x|
|
7572
|
+
x.freeze
|
7573
|
+
arr.each do |y|
|
7574
|
+
y.freeze
|
7575
|
+
print ":"
|
7576
|
+
arr.each do |z|
|
7577
|
+
z.freeze
|
7578
|
+
print "."
|
7579
|
+
prec = 0
|
7580
|
+
3.times do |i|
|
7366
7581
|
ALL_ROUNDING_MODES.each do |rm|
|
7367
7582
|
if (rm == ROUND_UNNECESSARY)
|
7368
7583
|
next
|
@@ -7384,7 +7599,7 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
7384
7599
|
qm = LongMath.quadratic_mean(prec, rm, x, y, z)
|
7385
7600
|
cm = LongMath.cubic_mean(prec, rm, x, y, z)
|
7386
7601
|
ma = [xx, yy, zz].max
|
7387
|
-
text = "mi=#{mi} hm=#{hm} gm=#{gm} am=#{am} qm=#{qm} cm=#{cm} ma=#{ma} prec=#{prec} rm=#{rm} x=#{x} y=#{y} z=#{z}"
|
7602
|
+
text = "mi=#{mi} hm=#{hm} gm=#{gm} am=#{am} qm=#{qm} cm=#{cm} ma=#{ma} prec=#{prec} rm=#{rm} x=#{x} y=#{y} z=#{z} i=#{i}"
|
7388
7603
|
assert(mi <= hm.succ, text)
|
7389
7604
|
assert(hm <= hgm.succ, text)
|
7390
7605
|
assert(hgm <= gm.succ, text)
|
@@ -7398,12 +7613,13 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
7398
7613
|
assert_equal(hm, hgm, text)
|
7399
7614
|
assert_equal(hgm, gm, text)
|
7400
7615
|
assert_equal(gm, agm, text)
|
7401
|
-
assert_equal(
|
7616
|
+
assert_equal(agm, am, text)
|
7402
7617
|
assert_equal(am, qm, text)
|
7403
7618
|
assert_equal(qm, cm, text)
|
7404
7619
|
assert_equal(cm, ma, text)
|
7405
7620
|
end
|
7406
7621
|
end
|
7622
|
+
prec = (prec << 3) + 11
|
7407
7623
|
end
|
7408
7624
|
end
|
7409
7625
|
end
|
@@ -7493,6 +7709,7 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
7493
7709
|
@powers_of_10[x] = zz
|
7494
7710
|
end
|
7495
7711
|
assert_equal(z, zz)
|
7712
|
+
# puts("exp=" + x.to_s)
|
7496
7713
|
$stdout.flush
|
7497
7714
|
else
|
7498
7715
|
@powers_of_10[x] ||= z
|
@@ -7512,10 +7729,12 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
7512
7729
|
|
7513
7730
|
12.times do |i|
|
7514
7731
|
check_npower10(3**i)
|
7732
|
+
# puts(3**i)
|
7515
7733
|
end
|
7516
7734
|
|
7517
7735
|
12.times do |i|
|
7518
7736
|
check_npower10(3**i)
|
7737
|
+
# puts(3**i)
|
7519
7738
|
end
|
7520
7739
|
|
7521
7740
|
y = 1
|
@@ -7530,6 +7749,7 @@ class TestLongDecimal_class < UnitTest # RUNIT::TestCase
|
|
7530
7749
|
x0 = 2046
|
7531
7750
|
y0 = 10**x0
|
7532
7751
|
60.times do |i|
|
7752
|
+
# puts "i=" + i.to_s
|
7533
7753
|
$stdout.flush
|
7534
7754
|
y = y0
|
7535
7755
|
x = x0
|
data/test/testlongdeclib.rb
CHANGED
@@ -2,8 +2,9 @@
|
|
2
2
|
#
|
3
3
|
# library for tests for long-decimal.rb and long-decimal-extra.rb
|
4
4
|
#
|
5
|
-
# (C) Karl Brodowsky (IT Sky Consulting GmbH) 2006-
|
5
|
+
# (C) Karl Brodowsky (IT Sky Consulting GmbH) 2006-2015
|
6
6
|
#
|
7
|
+
# TAG: $TAG v1.00.03$
|
7
8
|
# CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/test/testlongdeclib.rb,v 1.42 2011/02/03 00:22:39 bk1 Exp $
|
8
9
|
# CVS-Label: $Name: $
|
9
10
|
# Author: $Author: bk1 $ (Karl Brodowsky)
|
@@ -26,6 +27,8 @@ end
|
|
26
27
|
#
|
27
28
|
module TestLongDecHelper
|
28
29
|
|
30
|
+
include LongDecimalRoundingMode
|
31
|
+
|
29
32
|
@RCS_ID='-$Id: testlongdeclib.rb,v 1.42 2011/02/03 00:22:39 bk1 Exp $-'
|
30
33
|
|
31
34
|
def assert_equal_float(lhs, rhs, delta=0, msg="")
|
@@ -106,8 +109,8 @@ module TestLongDecHelper
|
|
106
109
|
# full_message = build_message(message, "Expected <?> to match <?> (lhs=#{lhs} rhs=#{rhs})", actual, expected)
|
107
110
|
# assert_block(full_message) {
|
108
111
|
# # prec = actual.scale
|
109
|
-
# # ed = expected.round_to_scale(prec,
|
110
|
-
# # eu = expected.round_to_scale(prec,
|
112
|
+
# # ed = expected.round_to_scale(prec, ROUND_HALF_FLOOR)
|
113
|
+
# # eu = expected.round_to_scale(prec, ROUND_HALF_CEILING)
|
111
114
|
# # # puts("ed=#{ed} eu=#{eu} e=#{expected} a=#{actual}")
|
112
115
|
# # ed <= actual && actual <= eu
|
113
116
|
|
@@ -178,7 +181,7 @@ module TestLongDecHelper
|
|
178
181
|
# eprec = prec+1
|
179
182
|
y = LongMath.exp(x, prec)
|
180
183
|
yy = LongMath.exp(x, prec+10)
|
181
|
-
# assert_equal(yy.round_to_scale(y.scale,
|
184
|
+
# assert_equal(yy.round_to_scale(y.scale, ROUND_HALF_DOWN), y, "x=#{x} y=#{y} yy=#{yy}")
|
182
185
|
assert_equal_rounded(yy, y, "x=#{x} y=#{y} yy=#{yy}")
|
183
186
|
|
184
187
|
# compare y against z = exp(x) calculated using regular floating point arithmetic
|
@@ -206,8 +209,8 @@ module TestLongDecHelper
|
|
206
209
|
end
|
207
210
|
|
208
211
|
# check by doing calculation with different internal rounding modes. They should not differ.
|
209
|
-
yd = LongMath.exp_internal(x, prec, nil, nil, nil, nil,
|
210
|
-
yu = LongMath.exp_internal(x, prec, nil, nil, nil, nil,
|
212
|
+
yd = LongMath.exp_internal(x, prec, nil, nil, nil, nil, ROUND_DOWN)
|
213
|
+
yu = LongMath.exp_internal(x, prec, nil, nil, nil, nil, ROUND_UP)
|
211
214
|
# assert_equal(yd, yu, "the result yd/yu should not depend on the internal rounding mode x0=#{x0} x=#{x} p=#{prec} d=#{(yd-yu).to_f.to_s}")
|
212
215
|
# assert_equal(y, yu, "the result y/yu should not depend on the internal rounding mode x0=#{x0} x=#{x} p=#{prec} d=#{(y -yu).to_f.to_s}")
|
213
216
|
assert_small_interval(yd, yu, y, "the result y/yu should not depend on the internal rounding mode x0=#{x0} x=#{x} p=#{prec} d=#{(yd-yu).to_f.to_s}")
|
@@ -256,7 +259,7 @@ module TestLongDecHelper
|
|
256
259
|
# eprec = prec+1
|
257
260
|
y = LongMath.exp2(x, prec)
|
258
261
|
yy = LongMath.exp2(x, prec+10)
|
259
|
-
# assert_equal(yy.round_to_scale(y.scale,
|
262
|
+
# assert_equal(yy.round_to_scale(y.scale, ROUND_HALF_DOWN), y, "x=#{x} y=#{y} yy=#{yy}")
|
260
263
|
assert_equal_rounded(yy, y, "x=#{x} y=#{y} yy=#{yy}")
|
261
264
|
|
262
265
|
# compare y against z = exp(x) calculated using regular floating point arithmetic
|
@@ -303,7 +306,7 @@ module TestLongDecHelper
|
|
303
306
|
# eprec = prec+1
|
304
307
|
y = LongMath.exp10(x, prec)
|
305
308
|
yy = LongMath.exp10(x, prec+10)
|
306
|
-
# assert_equal(yy.round_to_scale(y.scale,
|
309
|
+
# assert_equal(yy.round_to_scale(y.scale, ROUND_HALF_DOWN), y, "x=#{x} y=#{y} yy=#{yy}")
|
307
310
|
assert_equal_rounded(yy, y, "x=#{x} y=#{y} yy=#{yy}")
|
308
311
|
|
309
312
|
if (y.abs < LongMath::MAX_FLOATABLE) then
|
@@ -369,8 +372,8 @@ module TestLongDecHelper
|
|
369
372
|
x = x.to_ld
|
370
373
|
y = y.to_ld
|
371
374
|
|
372
|
-
z = LongMath.power(x, y, prec,
|
373
|
-
zz = (x ** yi).round_to_scale(prec,
|
375
|
+
z = LongMath.power(x, y, prec, ROUND_HALF_UP)
|
376
|
+
zz = (x ** yi).round_to_scale(prec, ROUND_HALF_UP)
|
374
377
|
assert_equal(z, zz, "power with ** or power-method x=#{x} y=#{y} z=#{z} zz=#{zz}")
|
375
378
|
zz = LongMath.power_internal(x, y, prec)
|
376
379
|
assert((zz - z).abs <= z.unit, "power with and without optimizations x=#{x} y=#{y} z=#{z} zz=#{zz}")
|
@@ -394,8 +397,8 @@ module TestLongDecHelper
|
|
394
397
|
x = x.to_ld
|
395
398
|
y = LongDecimal("0.5") * y2i
|
396
399
|
|
397
|
-
z = LongMath.power(x, y, prec,
|
398
|
-
zz = LongMath.sqrt(x ** y2i, prec,
|
400
|
+
z = LongMath.power(x, y, prec, ROUND_HALF_UP)
|
401
|
+
zz = LongMath.sqrt(x ** y2i, prec, ROUND_HALF_UP)
|
399
402
|
assert_equal(z, zz, "power with ** or power-method x=#{x} y=#{y} z=#{z} zz=#{zz}")
|
400
403
|
zz = LongMath.power_internal(x, y, prec)
|
401
404
|
assert((zz - z).abs <= z.unit, "power with and without optimizations x=#{x} y=#{y} z=#{z} zz=#{zz}")
|
@@ -423,7 +426,7 @@ module TestLongDecHelper
|
|
423
426
|
# calculate y = log(x)
|
424
427
|
y = LongMath.log(x, prec)
|
425
428
|
yy = LongMath.log(x, prec+10)
|
426
|
-
# assert_equal(yy.round_to_scale(y.scale,
|
429
|
+
# assert_equal(yy.round_to_scale(y.scale, ROUND_HALF_DOWN), y, "x=#{x} y=#{y} yy=#{yy}")
|
427
430
|
assert_equal_rounded(yy, y, "x=#{x} y=#{y} yy=#{yy}")
|
428
431
|
|
429
432
|
# compare y against z = log(x) calculated using regular floating
|
@@ -474,10 +477,10 @@ module TestLongDecHelper
|
|
474
477
|
end
|
475
478
|
|
476
479
|
# check by doing calculation with different internal rounding modes. They should not differ.
|
477
|
-
# yd = LongMath.log_internal(x, prec, nil, nil,
|
478
|
-
# yu = LongMath.log_internal(x, prec, nil, nil,
|
479
|
-
yd = LongMath.log_internal(x, prec, nil, nil,
|
480
|
-
yu = LongMath.log_internal(x, prec, nil, nil,
|
480
|
+
# yd = LongMath.log_internal(x, prec, nil, nil, ROUND_DOWN)
|
481
|
+
# yu = LongMath.log_internal(x, prec, nil, nil, ROUND_UP)
|
482
|
+
yd = LongMath.log_internal(x, prec, nil, nil, ROUND_FLOOR)
|
483
|
+
yu = LongMath.log_internal(x, prec, nil, nil, ROUND_CEILING)
|
481
484
|
# assert_equal(yd, yu, "the result yd/yu should not depend on the internal rounding mode yd=#{yd} yu=#{yu} y=#{y} p=#{prec} d=#{(yd-yu).to_f.to_s}")
|
482
485
|
# assert_equal(y, yu, "the result y/yu should not depend on the internal rounding mode yd=#{yd} yu=#{yu} y=#{y} p=#{prec} d=#{(y -yu).to_f.to_s}")
|
483
486
|
assert_small_interval(yd, yu, y, "the result y/yu should not depend on the internal rounding mode x0=#{x0} x=#{x} p=#{prec} d=#{(yd-yu).to_f.to_s}")
|
@@ -503,7 +506,7 @@ module TestLongDecHelper
|
|
503
506
|
prec_dp = 2*prec+1
|
504
507
|
z_dp = LongMath.power(x, y, prec_dp)
|
505
508
|
msg = "x=#{x}\ny=#{y}\nz=#{z}\nz_dp=#{z_dp}\nprec=#{prec}"
|
506
|
-
puts msg
|
509
|
+
# puts msg
|
507
510
|
assert((z - z_dp).abs <= 2*z.unit, msg)
|
508
511
|
|
509
512
|
corr2 = (x - 1).abs*1000000000 # 10**9
|
@@ -515,23 +518,27 @@ module TestLongDecHelper
|
|
515
518
|
zf = z.to_f
|
516
519
|
qf = 1e9
|
517
520
|
delta = [ z.unit.to_f, zf.abs / qf ].max
|
521
|
+
# puts "delta=#{delta} z=#{z} zu=#{z.unit} zuf=#{z.unit.to_f} zf=#{zf} |zf/qf|=#{zf.abs/qf}"
|
518
522
|
if (yf.abs > 1)
|
519
523
|
l = Math.log(yf.abs)
|
520
524
|
if (l > 1)
|
521
525
|
delta *= l
|
522
526
|
end
|
527
|
+
# puts "delta=#{delta} l=#{l}"
|
523
528
|
end
|
524
529
|
corr = corr2 * 0.5
|
525
530
|
if corr > 1
|
526
531
|
corr_f = [ corr.to_f, 5.0 ].min
|
527
532
|
delta *= corr_f
|
528
533
|
end
|
534
|
+
# puts "delta=#{delta} corr_f=#{corr_f} corr=#{corr}"
|
529
535
|
|
530
536
|
diff = (zf - wf).abs
|
531
537
|
msg = "z=#{z}=#{zf} and wf=#{wf.to_s} should be almost equal\nx=#{x}=#{xf}\ny=#{y}=#{yf}\ndelta=#{delta}\nl=#{l}\ndiff=#{diff}\nprec=#{prec}\ncorr=#{corr}=#{corr.to_f}\ncorr2=#{corr2}=#{corr2.to_f}\ncorr_f=#{corr_f}"
|
532
|
-
puts msg
|
538
|
+
# puts msg
|
533
539
|
assert_equal_float(zf, wf, delta, msg)
|
534
|
-
puts "OK"
|
540
|
+
# puts "OK"
|
541
|
+
print "."
|
535
542
|
end
|
536
543
|
|
537
544
|
# check by taking log(z) = y * log(x)
|
@@ -560,8 +567,8 @@ module TestLongDecHelper
|
|
560
567
|
u_dp = LongMath.log(z_dp, lprec_dp)
|
561
568
|
v = LongMath.log(x, lprec+l10y)
|
562
569
|
v_dp = LongMath.log(x, lprec_dp + l10y)
|
563
|
-
yv = (y*v).round_to_scale(lprec,
|
564
|
-
yv_dp = (y * v_dp).round_to_scale(lprec_dp,
|
570
|
+
yv = (y*v).round_to_scale(lprec, ROUND_HALF_DOWN)
|
571
|
+
yv_dp = (y * v_dp).round_to_scale(lprec_dp, ROUND_HALF_DOWN)
|
565
572
|
assert((u_dp - yv_dp).abs <= unit, "u=log(z,#{lprec})=#{u_dp}=#{u} and yv=y*v=y*log(x,#{lprec+l10y})=#{yv_dp}=#{yv} should be almost equal (unit=#{unit} x=#{x.to_s} y=#{y.to_s} z=#{z_dp}=#{z.to_s} u=#{u_dp}=#{u.to_s} v=#{v_dp}=#{v.to_s} lprec=#{lprec} prec=#{prec} lprec_dp=#{lprec_dp} prec_dp=#{prec_dp})")
|
566
573
|
assert((u - yv).abs <= unit, "u=log(z,#{lprec})=#{u} and yv=y*v=y*log(x,#{lprec+l10y})=#{yv} should be almost equal (unit=#{unit} x=#{x.to_s} y=#{y.to_s} z=#{z.to_s} u=#{u.to_s} v=#{v.to_s} lprec=#{lprec} prec=#{prec})")
|
567
574
|
end
|
@@ -661,7 +668,7 @@ module TestLongDecHelper
|
|
661
668
|
# calculate y = log2(x)
|
662
669
|
y = LongMath.log2(x, prec)
|
663
670
|
yy = LongMath.log2(x, prec+10)
|
664
|
-
# assert_equal(yy.round_to_scale(y.scale,
|
671
|
+
# assert_equal(yy.round_to_scale(y.scale, ROUND_HALF_DOWN), y, "x=#{x} y=#{y} yy=#{yy}")
|
665
672
|
assert_equal_rounded(yy, y, "x=#{x} y=#{y} yy=#{yy}")
|
666
673
|
|
667
674
|
# compare y against z = log2(x) calculated using regular floating
|
@@ -778,13 +785,26 @@ module TestLongDecHelper
|
|
778
785
|
|
779
786
|
#
|
780
787
|
# helper method of test_sqrt
|
788
|
+
# su0 and su1 describe how close the sqrt should be to the ideal result in units of the result
|
789
|
+
# usually su0=0 or -1 and su1=0 or 1
|
781
790
|
#
|
782
791
|
def check_sqrt(x, scale, mode, su0, su1, str)
|
783
792
|
y = x.sqrt(scale, mode)
|
784
|
-
if (mode ==
|
793
|
+
if (mode == ROUND_UNNECESSARY)
|
794
|
+
ALL_ROUNDING_MODES.each do |any_mode|
|
795
|
+
if (any_mode == ROUND_UNNECESSARY)
|
796
|
+
next
|
797
|
+
end
|
798
|
+
yy = x.sqrt(scale, any_mode)
|
799
|
+
assert_equal(y, yy, "any_mode=#{any_mode}")
|
800
|
+
end
|
801
|
+
end
|
802
|
+
|
803
|
+
if (mode == ROUND_HALF_UP || mode == ROUND_HALF_DOWN || mode == ROUND_HALF_EVEN)
|
785
804
|
yy = x.sqrt(scale+10, mode)
|
786
805
|
assert_equal(yy.round_to_scale(y.scale, mode), y, "x=#{x} y=#{y} yy=#{yy}")
|
787
806
|
end
|
807
|
+
|
788
808
|
z0 = (y+su0*y.unit).square
|
789
809
|
z1 = (y+su1*y.unit).square
|
790
810
|
assert(0 <= y.sign, "sqrt must be >= 0" + str)
|
@@ -823,6 +843,7 @@ module TestLongDecHelper
|
|
823
843
|
def check_cbrtb_with_remainder(x, s)
|
824
844
|
y, r = LongMath.cbrtb_with_remainder(x)
|
825
845
|
z0 = y.cube
|
846
|
+
# puts "x=#{x} y=#{y} z0=#{z0} r=#{r}"
|
826
847
|
z1 = z0 + r
|
827
848
|
z2 = (y+1).cube
|
828
849
|
assert(0 <= y, "cbrt _with_remainder must be >= 0" + s)
|
@@ -836,7 +857,7 @@ module TestLongDecHelper
|
|
836
857
|
#
|
837
858
|
def check_cbrt(x, scale, mode, su0, su1, str)
|
838
859
|
y = x.cbrt(scale, mode)
|
839
|
-
if (mode ==
|
860
|
+
if (mode == ROUND_HALF_UP || mode == ROUND_HALF_DOWN || mode == ROUND_HALF_EVEN)
|
840
861
|
yy = x.cbrt(scale+10, mode)
|
841
862
|
assert_equal(yy.round_to_scale(y.scale, mode), y, "x=#{x} y=#{y} yy=#{yy}")
|
842
863
|
end
|