1# -*- mode: perl; -*- 2 3# Test blog function (and bpow, since it uses blog), as well as bexp(). 4 5# It is too slow to be simple included in bigfltpm.inc, where it would get 6# executed 3 times. One time would be under Math::BigInt::BareCalc, which 7# shouldn't make any difference since there is no $LIB->_log() function, and 8# one time under a subclass, which *should* work. 9 10# But it is better to test the numerical functionality, instead of not testing 11# it at all (which did lead to wrong answers for 0 < $x < 1 in blog() in 12# versions up to v1.63, and for bsqrt($x) when $x << 1 for instance). 13 14use strict; 15use warnings; 16 17use Test::More tests => 73; 18 19use Math::BigFloat only => 'FastCalc'; 20use Math::BigInt; 21 22my $class = "Math::BigInt"; 23 24############################################################################### 25# test $n->blog() in Math::BigInt (broken until 1.80) 26 27is($class->new(2)->blog(), '0', "$class->new(2)->blog()"); 28is($class->new(288)->blog(), '5', "$class->new(288)->blog()"); 29is($class->new(2000)->blog(), '7', "$class->new(2000)->blog()"); 30 31############################################################################### 32# test $n->bexp() in Math::BigInt 33 34is($class->new(1)->bexp(), '2', "$class->new(1)->bexp()"); 35is($class->new(2)->bexp(), '7', "$class->new(2)->bexp()"); 36is($class->new(3)->bexp(), '20', "$class->new(3)->bexp()"); 37 38############################################################################### 39# Math::BigFloat tests 40 41############################################################################### 42# test $n->blog(undef, N) where N > 67 (broken until 1.82) 43 44$class = "Math::BigFloat"; 45 46# These tests can take quite a while, but are necessary. Maybe protect them 47# with some alarm()? 48 49# this triggers the calculation and caching of ln(2): 50is($class->new(5)->blog(undef, 71), 51 '1.6094379124341003746007593332261876395256013542685177219126478914741790', 52 "$class->new(5)->blog(undef, 71)"); 53 54# if the cache was correct, we should get this result, fast: 55is($class->new(2)->blog(undef, 71), 56 '0.69314718055994530941723212145817656807550013436025525412068000949339362', 57 "$class->new(2)->blog(undef, 71)"); 58 59is($class->new(11)->blog(undef, 71), 60 '2.3978952727983705440619435779651292998217068539374171752185677091305736', 61 "$class->new(11)->blog(undef, 71)"); 62 63is($class->new(21)->blog(undef, 71), 64 '3.0445224377234229965005979803657054342845752874046106401940844835750742', 65 "$class->new(21)->blog(undef, 71)"); 66 67############################################################################### 68 69# These tests are now really fast, since they collapse to blog(10), basically 70# Don't attempt to run them with older versions. You are warned. 71 72# $x < 0 => NaN 73is($class->new(-2)->blog(), 'NaN', "$class->new(-2)->blog()"); 74is($class->new(-1)->blog(), 'NaN', "$class->new(-1)->blog()"); 75is($class->new(-10)->blog(), 'NaN', "$class->new(-10)->blog()"); 76is($class->new(-2, 2)->blog(), 'NaN', "$class->new(-2, 2)->blog()"); 77 78my $ten = $class->new(10)->blog(); 79 80# 10 is cached (up to 75 digits) 81is($class->new(10)->blog(), 82 '2.302585092994045684017991454684364207601', 83 qq|$class->new(10)->blog()|); 84 85# 0.1 is using the cached value for log(10), too 86 87is($class->new("0.1")->blog(), -$ten, 88 qq|$class->new("0.1")->blog()|); 89is($class->new("0.01")->blog(), -$ten * 2, 90 qq|$class->new("0.01")->blog()|); 91is($class->new("0.001")->blog(), -$ten * 3, 92 qq|$class->new("0.001")->blog()|); 93is($class->new("0.0001")->blog(), -$ten * 4, 94 qq|$class->new("0.0001")->blog()|); 95 96# also cached 97is($class->new(2)->blog(), 98 '0.6931471805599453094172321214581765680755', 99 qq|$class->new(2)->blog()|); 100is($class->new(4)->blog(), $class->new(2)->blog * 2, 101 qq|$class->new(4)->blog()|); 102 103# These are still slow, so do them only to 10 digits 104 105is($class->new("0.2")->blog(undef, 10), "-1.609437912", 106 qq|$class->new("0.2")->blog(undef, 10)|); 107is($class->new("0.3")->blog(undef, 10), "-1.203972804", 108 qq|$class->new("0.3")->blog(undef, 10)|); 109is($class->new("0.4")->blog(undef, 10), "-0.9162907319", 110 qq|$class->new("0.4")->blog(undef, 10)|); 111is($class->new("0.5")->blog(undef, 10), "-0.6931471806", 112 qq|$class->new("0.5")->blog(undef, 10)|); 113is($class->new("0.6")->blog(undef, 10), "-0.5108256238", 114 qq|$class->new("0.6")->blog(undef, 10)|); 115is($class->new("0.7")->blog(undef, 10), "-0.3566749439", 116 qq|$class->new("0.7")->blog(undef, 10)|); 117is($class->new("0.8")->blog(undef, 10), "-0.2231435513", 118 qq|$class->new("0.8")->blog(undef, 10)|); 119is($class->new("0.9")->blog(undef, 10), "-0.1053605157", 120 qq|$class->new("0.9")->blog(undef, 10)|); 121 122is($class->new("9")->blog(undef, 10), "2.197224577", 123 qq|$class->new("9")->blog(undef, 10)|); 124 125is($class->new("10")->blog(10, 10), "1.000000000", 126 qq|$class->new("10")->blog(10, 10)|); 127is($class->new("20")->blog(20, 10), "1.000000000", 128 qq|$class->new("20")->blog(20, 10)|); 129is($class->new("100")->blog(100, 10), "1.000000000", 130 qq|$class->new("100")->blog(100, 10)|); 131 132is($class->new("100")->blog(10, 10), "2.000000000", # 10 ** 2 == 100 133 qq|$class->new("100")->blog(10, 10)|); 134is($class->new("400")->blog(20, 10), "2.000000000", # 20 ** 2 == 400 135 qq|$class->new("400")->blog(20, 10)|); 136 137is($class->new("4")->blog(2, 10), "2.000000000", # 2 ** 2 == 4 138 qq|$class->new("4")->blog(2, 10)|); 139is($class->new("16")->blog(2, 10), "4.000000000", # 2 ** 4 == 16 140 qq|$class->new("16")->blog(2, 10)|); 141 142is($class->new("1.2")->bpow("0.3", 10), "1.056219968", 143 qq|$class->new("1.2")->bpow("0.3", 10)|); 144is($class->new("10")->bpow("0.6", 10), "3.981071706", 145 qq|$class->new("10")->bpow("0.6", 10)|); 146 147# blog should handle bigint input 148is(Math::BigFloat->blog(Math::BigInt->new(100), 10), 2, "blog(100)"); 149 150############################################################################### 151# some integer results 152is($class->new(2)->bpow(32)->blog(2), "32", "2 ** 32"); 153is($class->new(3)->bpow(32)->blog(3), "32", "3 ** 32"); 154is($class->new(2)->bpow(65)->blog(2), "65", "2 ** 65"); 155 156my $x = Math::BigInt->new('777') ** 256; 157my $base = Math::BigInt->new('12345678901234'); 158is($x->copy()->blog($base), 56, 'blog(777**256, 12345678901234)'); 159 160$x = Math::BigInt->new('777') ** 777; 161$base = Math::BigInt->new('777'); 162is($x->copy()->blog($base), 777, 'blog(777**777, 777)'); 163 164############################################################################### 165# test for bug in bsqrt() not taking negative _e into account 166test_bpow('200', '0.5', 10, '14.14213562'); 167test_bpow('20', '0.5', 10, '4.472135955'); 168test_bpow('2', '0.5', 10, '1.414213562'); 169test_bpow('0.2', '0.5', 10, '0.4472135955'); 170test_bpow('0.02', '0.5', 10, '0.1414213562'); 171test_bpow('0.49', '0.5', undef, '0.7'); 172test_bpow('0.49', '0.5', 10, '0.7000000000'); 173test_bpow('0.002', '0.5', 10, '0.04472135955'); 174test_bpow('0.0002', '0.5', 10, '0.01414213562'); 175test_bpow('0.0049', '0.5', undef, '0.07'); 176test_bpow('0.0049', '0.5', 10, '0.07000000000'); 177test_bpow('0.000002', '0.5', 10, '0.001414213562'); 178test_bpow('0.021', '0.5', 10, '0.1449137675'); 179test_bpow('1.2', '0.5', 10, '1.095445115'); 180test_bpow('1.23', '0.5', 10, '1.109053651'); 181test_bpow('12.3', '0.5', 10, '3.507135583'); 182 183test_bpow('9.9', '0.5', 10, '3.146426545'); 184test_bpow('9.86902225', '0.5', 10, '3.141500000'); 185test_bpow('9.86902225', '0.5', undef, '3.1415'); 186 187############################################################################### 188# other tests for bpow() 189 190test_bpow('0.2', '0.41', 10, '0.5169187652'); 191 192is($class->new("0.1")->bpow("28.4", 40)->bsstr(), 193 '3981071705534972507702523050877520434877e-68', 194 qq|$class->new("0.1")->bpow("28.4", 40)->bsstr()|); 195 196# The following test takes too long. 197#is($class->new("2")->bpow("-1034.5", 40)->bsstr(), 198# '3841222690408590466868250378242558090957e-351', 199# qq|$class->new("2")->bpow("-1034.5", 40)|); 200 201############################################################################### 202# test bexp() with cached results 203 204is($class->new(1)->bexp(), '2.718281828459045235360287471352662497757', 205 'bexp(1)'); 206is($class->new(2)->bexp(40), $class->new(1)->bexp(45)->bpow(2, 40), 207 'bexp(2)'); 208 209is($class->new("12.5")->bexp(61), $class->new(1)->bexp(65)->bpow(12.5, 61), 210 'bexp(12.5)'); 211 212############################################################################### 213# test bexp() with big values (non-cached) 214 215is($class->new(1)->bexp(100), 216 '2.7182818284590452353602874713526624977572470936999' 217 . '59574966967627724076630353547594571382178525166427', 218 qq|$class->new(1)->bexp(100)|); 219 220is($class->new("12.5")->bexp(91), $class->new(1)->bexp(95)->bpow(12.5, 91), 221 qq|$class->new("12.5")->bexp(91)|); 222 223is($class->new("-118.5")->bexp(20)->bsstr(), 224 '34364014567198602057e-71', 225 qq|$class->new("-118.5")->bexp(20)->bsstr()|); 226 227is($class->new("-394.84010945715266885")->bexp(20)->bsstr(), 228 '33351796227864913873e-191', 229 qq|$class->new("-118.5")->bexp(20)->bsstr()|); 230 231# all done 232 233############################################################################### 234 235sub test_bpow { 236 my ($x, $y, $scale, $result) = @_; 237 is($class->new($x)->bpow($y, $scale), $result, 238 qq|$class->new($x)->bpow($y, | 239 . (defined($scale) ? $scale : 'undef') 240 . qq|)|); 241} 242