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