1# -*- mode: perl; -*- 2 3use strict; 4use warnings; 5 6use Test::More tests => 203; 7 8# basic testing of Math::BigRat 9 10use Math::BigRat; 11use Math::BigInt; 12use Math::BigFloat; 13 14# shortcuts 15my $mbr = 'Math::BigRat'; 16my $mbi = 'Math::BigInt'; 17my $mbf = 'Math::BigFloat'; 18 19my ($x, $y, $z); 20 21$x = Math::BigRat->new(1234); 22is($x, 1234, 'value of $x'); 23isa_ok($x, 'Math::BigRat'); 24ok(!$x->isa('Math::BigInt'), 25 "An object of class '" . ref($x) . "' isn't a 'Math::BigInt'"); 26ok(!$x->isa('Math::BigFloat'), 27 "An object of class '" . ref($x) . "' isn't a 'Math::BigFloat'"); 28 29############################################################################## 30# new and bnorm() 31 32foreach my $method (qw/ new bnorm /) { 33 $x = $mbr->$method(1234); 34 is($x, 1234, qq|\$x = $mbr->$method(1234)|); 35 36 $x = $mbr->$method("1234/1"); 37 is($x, 1234, qq|\$x = $mbr->$method("1234/1")|); 38 39 $x = $mbr->$method("1234/2"); 40 is($x, 617, qq|\$x = $mbr->$method("1234/2")|); 41 42 $x = $mbr->$method("100/1.0"); 43 is($x, 100, qq|\$x = $mbr->$method("100/1.0")|); 44 45 $x = $mbr->$method("10.0/1.0"); 46 is($x, 10, qq|\$x = $mbr->$method("10.0/1.0")|); 47 48 $x = $mbr->$method("0.1/10"); 49 is($x, "1/100", qq|\$x = $mbr->$method("0.1/10")|); 50 51 $x = $mbr->$method("0.1/0.1"); 52 is($x, "1", qq|\$x = $mbr->$method("0.1/0.1")|); 53 54 $x = $mbr->$method("1e2/10"); 55 is($x, 10, qq|\$x = $mbr->$method("1e2/10")|); 56 57 $x = $mbr->$method("5/1e2"); 58 is($x, "1/20", qq|\$x = $mbr->$method("5/1e2")|); 59 60 $x = $mbr->$method("1e2/1e1"); 61 is($x, 10, qq|\$x = $mbr->$method("1e2/1e1")|); 62 63 $x = $mbr->$method("1 / 3"); 64 is($x, "1/3", qq|\$x = $mbr->$method("1 / 3")|); 65 66 $x = $mbr->$method("-1 / 3"); 67 is($x, "-1/3", qq|\$x = $mbr->$method("-1 / 3")|); 68 69 $x = $mbr->$method("NaN"); 70 is($x, "NaN", qq|\$x = $mbr->$method("NaN")|); 71 72 $x = $mbr->$method("inf"); 73 is($x, "inf", qq|\$x = $mbr->$method("inf")|); 74 75 $x = $mbr->$method("-inf"); 76 is($x, "-inf", qq|\$x = $mbr->$method("-inf")|); 77 78 $x = $mbr->$method("1/"); 79 is($x, "NaN", qq|\$x = $mbr->$method("1/")|); 80 81 $x = $mbr->$method("0x7e"); 82 is($x, 126, qq|\$x = $mbr->$method("0x7e")|); 83 84 # input ala "1+1/3" isn"t parsed ok yet 85 $x = $mbr->$method("1+1/3"); 86 is($x, "NaN", qq|\$x = $mbr->$method("1+1/3")|); 87 88 $x = $mbr->$method("1/1.2"); 89 is($x, "5/6", qq|\$x = $mbr->$method("1/1.2")|); 90 91 $x = $mbr->$method("1.3/1.2"); 92 is($x, "13/12", qq|\$x = $mbr->$method("1.3/1.2")|); 93 94 $x = $mbr->$method("1.2/1"); 95 is($x, "6/5", qq|\$x = $mbr->$method("1.2/1")|); 96 97 ############################################################################ 98 # other classes as input 99 100 $x = $mbr->$method($mbi->new(1231)); 101 is($x, "1231", qq|\$x = $mbr->$method($mbi->new(1231))|); 102 103 $x = $mbr->$method($mbf->new(1232)); 104 is($x, "1232", qq|\$x = $mbr->$method($mbf->new(1232))|); 105 106 $x = $mbr->$method($mbf->new(1232.3)); 107 is($x, "12323/10", qq|\$x = $mbr->$method($mbf->new(1232.3))|); 108} 109 110my $n = 'numerator'; 111my $d = 'denominator'; 112 113$x = $mbr->new('-0'); 114is($x, '0'); 115is($x->$n(), '0'); 116is($x->$d(), '1'); 117 118$x = $mbr->new('NaN'); 119is($x, 'NaN'); is($x->$n(), 'NaN'); 120is($x->$d(), 'NaN'); 121 122$x = $mbr->new('-NaN'); 123is($x, 'NaN'); is($x->$n(), 'NaN'); 124is($x->$d(), 'NaN'); 125 126$x = $mbr->new('-1r4'); 127is($x, 'NaN'); is($x->$n(), 'NaN'); 128is($x->$d(), 'NaN'); 129 130$x = $mbr->new('+inf'); 131is($x, 'inf'); is($x->$n(), 'inf'); 132is($x->$d(), '1'); 133 134$x = $mbr->new('-inf'); 135is($x, '-inf'); 136is($x->$n(), '-inf'); 137is($x->$d(), '1'); 138 139$x = $mbr->new('123a4'); 140is($x, 'NaN'); 141is($x->$n(), 'NaN'); 142is($x->$d(), 'NaN'); 143 144# wrong inputs 145$x = $mbr->new('1e2e2'); 146is($x, 'NaN'); 147is($x->$n(), 'NaN'); 148is($x->$d(), 'NaN'); 149 150$x = $mbr->new('1+2+2'); 151is($x, 'NaN'); 152is($x->$n(), 'NaN'); 153is($x->$d(), 'NaN'); 154 155# failed due to BigFloat bug 156$x = $mbr->new('1.2.2'); 157is($x, 'NaN'); 158is($x->$n(), 'NaN'); 159is($x->$d(), 'NaN'); 160 161is($mbr->new('123a4'), 'NaN'); 162is($mbr->new('123e4'), '1230000'); 163is($mbr->new('-NaN'), 'NaN'); 164is($mbr->new('NaN'), 'NaN'); 165is($mbr->new('+inf'), 'inf'); 166is($mbr->new('-inf'), '-inf'); 167 168############################################################################## 169# two Bigints 170 171is($mbr->new($mbi->new(3), $mbi->new(7))->badd(1), '10/7'); 172is($mbr->new($mbi->new(-13), $mbi->new(7)), '-13/7'); 173is($mbr->new($mbi->new(13), $mbi->new(-7)), '-13/7'); 174is($mbr->new($mbi->new(-13), $mbi->new(-7)), '13/7'); 175 176############################################################################## 177# mixed arguments 178 179is($mbr->new('3/7')->badd(1), '10/7'); 180is($mbr->new('3/10')->badd(1.1), '7/5'); 181is($mbr->new('3/7')->badd($mbi->new(1)), '10/7'); 182is($mbr->new('3/10')->badd($mbf->new('1.1')), '7/5'); 183 184is($mbr->new('3/7')->bsub(1), '-4/7'); 185is($mbr->new('3/10')->bsub(1.1), '-4/5'); 186is($mbr->new('3/7')->bsub($mbi->new(1)), '-4/7'); 187is($mbr->new('3/10')->bsub($mbf->new('1.1')), '-4/5'); 188 189is($mbr->new('3/7')->bmul(1), '3/7'); 190is($mbr->new('3/10')->bmul(1.1), '33/100'); 191is($mbr->new('3/7')->bmul($mbi->new(1)), '3/7'); 192is($mbr->new('3/10')->bmul($mbf->new('1.1')), '33/100'); 193 194is($mbr->new('3/7')->bdiv(1), '3/7'); 195is($mbr->new('3/10')->bdiv(1.1), '3/11'); 196is($mbr->new('3/7')->bdiv($mbi->new(1)), '3/7'); 197is($mbr->new('3/10')->bdiv($mbf->new('1.1')), '3/11'); 198 199############################################################################## 200$x = $mbr->new('1/4'); 201$y = $mbr->new('1/3'); 202 203is($x + $y, '7/12'); 204is($x * $y, '1/12'); 205is($x / $y, '3/4'); 206 207$x = $mbr->new('7/5'); 208$x *= '3/2'; 209is($x, '21/10'); 210$x -= '0.1'; 211is($x, '2'); # not 21/10 212 213$x = $mbr->new('2/3'); 214$y = $mbr->new('3/2'); 215is($x > $y, ''); 216is($x < $y, 1); 217is($x == $y, ''); 218 219$x = $mbr->new('-2/3'); 220$y = $mbr->new('3/2'); 221is($x > $y, ''); 222is($x < $y, '1'); 223is($x == $y, ''); 224 225$x = $mbr->new('-2/3'); 226$y = $mbr->new('-2/3'); 227is($x > $y, ''); 228is($x < $y, ''); 229is($x == $y, '1'); 230 231$x = $mbr->new('-2/3'); 232$y = $mbr->new('-1/3'); 233is($x > $y, ''); 234is($x < $y, '1'); 235is($x == $y, ''); 236 237$x = $mbr->new('-124'); 238$y = $mbr->new('-122'); 239is($x->bacmp($y), 1); 240 241$x = $mbr->new('-124'); 242$y = $mbr->new('-122'); 243is($x->bcmp($y), -1); 244 245$x = $mbr->new('3/7'); 246$y = $mbr->new('5/7'); 247is($x+$y, '8/7'); 248 249$x = $mbr->new('3/7'); 250$y = $mbr->new('5/7'); 251is($x*$y, '15/49'); 252 253$x = $mbr->new('3/5'); 254$y = $mbr->new('5/7'); 255is($x*$y, '3/7'); 256 257$x = $mbr->new('3/5'); 258$y = $mbr->new('5/7'); 259is($x/$y, '21/25'); 260 261$x = $mbr->new('7/4'); 262$y = $mbr->new('1'); 263is($x % $y, '3/4'); 264 265$x = $mbr->new('7/4'); 266$y = $mbr->new('5/13'); 267is($x % $y, '11/52'); 268 269$x = $mbr->new('7/4'); 270$y = $mbr->new('5/9'); 271is($x % $y, '1/12'); 272 273$x = $mbr->new('-144/9')->bsqrt(); 274is($x, 'NaN'); 275 276$x = $mbr->new('144/9')->bsqrt(); 277is($x, '4'); 278 279$x = $mbr->new('3/4')->bsqrt(); 280is($x, 281 '4330127018922193233818615853764680917357/' . 282 '5000000000000000000000000000000000000000'); 283 284############################################################################## 285# bpow 286 287$x = $mbr->new('2/1'); 288$z = $x->bpow('3/1'); 289is($x, '8'); 290 291$x = $mbr->new('1/2'); 292$z = $x->bpow('3/1'); 293is($x, '1/8'); 294 295$x = $mbr->new('1/3'); 296$z = $x->bpow('4/1'); 297is($x, '1/81'); 298 299$x = $mbr->new('2/3'); 300$z = $x->bpow('4/1'); 301is($x, '16/81'); 302 303$x = $mbr->new('2/3'); 304$z = $x->bpow('5/3'); 305is($x, '31797617848703662994667839220546583581/62500000000000000000000000000000000000'); 306 307############################################################################## 308# bfac 309 310$x = $mbr->new('1'); 311$x->bfac(); 312is($x, '1'); 313 314for (my $i = 0; $i < 8; $i++) { 315 $x = $mbr->new("$i/1")->bfac(); 316 is($x, $mbi->new($i)->bfac()); 317} 318 319# test for $self->bnan() vs. $x->bnan(); 320$x = $mbr->new('-1'); 321$x->bfac(); 322is($x, 'NaN'); 323 324############################################################################## 325# binc/bdec 326 327note("binc()"); 328$x = $mbr->new('3/2'); 329is($x->binc(), '5/2'); 330 331note("bdec()"); 332 333$x = $mbr->new('15/6'); 334is($x->bdec(), '3/2'); 335 336############################################################################## 337# bfloor 338 339note("bfloor()"); 340$x = $mbr->new('-7/7'); 341is($x->$n(), '-1'); 342is($x->$d(), '1'); 343$x = $mbr->new('-7/7')->bfloor(); 344is($x->$n(), '-1'); 345is($x->$d(), '1'); 346 347############################################################################## 348# bsstr 349 350$x = $mbr->new('7/5')->bsstr(); 351is($x, '7/5'); 352$x = $mbr->new('-7/5')->bsstr(); 353is($x, '-7/5'); 354 355############################################################################## 356 357note("numify()"); 358 359my @array = qw/1 2 3 4 5 6 7 8 9/; 360$x = $mbr->new('8/8'); 361is($array[$x], 2); 362 363$x = $mbr->new('16/8'); 364is($array[$x], 3); 365 366$x = $mbr->new('17/8'); 367is($array[$x], 3); 368 369$x = $mbr->new('33/8'); 370is($array[$x], 5); 371 372$x = $mbr->new('-33/8'); 373is($array[$x], 6); 374 375$x = $mbr->new('-8/1'); 376is($array[$x], 2); # -8 => 2 377 378require Math::Complex; 379 380my $inf = $Math::Complex::Inf; 381my $nan = $inf - $inf; 382 383sub isnumeric { 384 my $value = shift; 385 ($value ^ $value) eq "0"; 386} 387 388subtest qq|$mbr -> new("33/8") -> numify()| => sub { 389 plan tests => 3; 390 391 $x = $mbr -> new("33/8") -> numify(); 392 is(ref($x), "", '$x is a scalar'); 393 ok(isnumeric($x), '$x is numeric'); 394 cmp_ok($x, "==", 4.125, '$x has the right value'); 395}; 396 397subtest qq|$mbr -> new("-33/8") -> numify()| => sub { 398 plan tests => 3; 399 400 $x = $mbr -> new("-33/8") -> numify(); 401 is(ref($x), "", '$x is a scalar'); 402 ok(isnumeric($x), '$x is numeric'); 403 cmp_ok($x, "==", -4.125, '$x has the right value'); 404}; 405 406subtest qq|$mbr -> new("inf") -> numify()| => sub { 407 plan tests => 3; 408 409 $x = $mbr -> new("inf") -> numify(); 410 is(ref($x), "", '$x is a scalar'); 411 ok(isnumeric($x), '$x is numeric'); 412 cmp_ok($x, "==", $inf, '$x has the right value'); 413}; 414 415subtest qq|$mbr -> new("-inf") -> numify()| => sub { 416 plan tests => 3; 417 418 $x = $mbr -> new("-inf") -> numify(); 419 is(ref($x), "", '$x is a scalar'); 420 ok(isnumeric($x), '$x is numeric'); 421 cmp_ok($x, "==", -$inf, '$x has the right value'); 422}; 423 424subtest qq|$mbr -> new("NaN") -> numify()| => sub { 425 plan tests => 3; 426 427 $x = $mbr -> new("NaN") -> numify(); 428 is(ref($x), "", '$x is a scalar'); 429 ok(isnumeric($x), '$x is numeric'); 430 cmp_ok($x, "!=", $nan, '$x has the right value'); # Note: NaN != NaN 431}; 432 433############################################################################## 434# as_hex(), as_bin(), as_oct() 435 436note("as_hex(), as_bin(), as_oct()"); 437 438$x = $mbr->new('8/8'); 439is($x->as_hex(), '0x1'); 440is($x->as_bin(), '0b1'); 441is($x->as_oct(), '01'); 442 443$x = $mbr->new('80/8'); 444is($x->as_hex(), '0xa'); 445is($x->as_bin(), '0b1010'); 446is($x->as_oct(), '012'); 447 448############################################################################## 449# broot(), blog(), bmodpow() and bmodinv() 450 451note("broot(), blog(), bmodpow(), bmodinv()"); 452 453$x = $mbr->new(2) ** 32; 454$y = $mbr->new(4); 455$z = $mbr->new(3); 456 457is($x->copy()->broot($y), 2 ** 8); 458is(ref($x->copy()->broot($y)), $mbr, "\$x is a $mbr"); 459 460is($x->copy()->bmodpow($y, $z), 1); 461is(ref($x->copy()->bmodpow($y, $z)), $mbr, "\$x is a $mbr"); 462 463$x = $mbr->new(8); 464$y = $mbr->new(5033); 465$z = $mbr->new(4404); 466 467is($x->copy()->bmodinv($y), $z); 468is(ref($x->copy()->bmodinv($y)), $mbr, "\$x is a $mbr"); 469 470# square root with exact result 471$x = $mbr->new('1.44'); 472is($x->copy()->broot(2), '6/5'); 473is(ref($x->copy()->broot(2)), $mbr, "\$x is a $mbr"); 474 475# log with exact result 476$x = $mbr->new('256.1'); 477is($x->copy()->blog(2), 478 '8000563442710106079310294693803606983661/1000000000000000000000000000000000000000', 479 "\$x = $mbr->new('256.1')->blog(2)"); 480is(ref($x->copy()->blog(2)), $mbr, "\$x is a $mbr"); 481 482$x = $mbr->new(144); 483is($x->copy()->broot('2'), 12, 'v/144 = 12'); 484 485$x = $mbr->new(12*12*12); 486is($x->copy()->broot('3'), 12, '(12*12*12) ** 1/3 = 12'); 487 488############################################################################## 489# from_hex(), from_bin(), from_oct() 490 491note("from_hex(), from_bin(), from_oct()"); 492 493$x = Math::BigRat->from_hex('0x100'); 494is($x, '256', 'from_hex'); 495 496$x = $mbr->from_hex('0x100'); 497is($x, '256', 'from_hex'); 498 499$x = Math::BigRat->from_bin('0b100'); 500is($x, '4', 'from_bin'); 501 502$x = $mbr->from_bin('0b100'); 503is($x, '4', 'from_bin'); 504 505$x = Math::BigRat->from_oct('0100'); 506is($x, '64', 'from_oct'); 507 508$x = $mbr->from_oct('0100'); 509is($x, '64', 'from_oct'); 510 511############################################################################## 512# as_float() 513 514$x = Math::BigRat->new('1/2'); 515my $f = $x->as_float(); 516 517is($x, '1/2', '$x unmodified'); 518is($f, '0.5', 'as_float(0.5)'); 519 520$x = Math::BigRat->new('2/3'); 521$f = $x->as_float(5); 522 523is($x, '2/3', '$x unmodified'); 524is($f, '0.66667', 'as_float(2/3, 5)'); 525 526# Integers should be converted exactly. 527$x = Math::BigRat->new("3141592653589793238462643383279502884197169399375106"); 528$f = $x->as_float(); 529 530is($x, "3141592653589793238462643383279502884197169399375106", '$x unmodified'); 531is($f, "3141592653589793238462643383279502884197169399375106", 532 'as_float(3141592653589793238462643383279502884197169399375106, 5)'); 533 534############################################################################## 535# int() 536 537$x = Math::BigRat->new('5/2'); 538is(int($x), '2', '5/2 converted to integer'); 539 540$x = Math::BigRat->new('-1/2'); 541is(int($x), '0', '-1/2 converted to integer'); 542 543############################################################################## 544# done 545 5461; 547