1package bigrat; 2 3use strict; 4use warnings; 5 6use Carp qw< carp croak >; 7 8our $VERSION = '0.66'; 9 10use Exporter; 11our @ISA = qw( Exporter ); 12our @EXPORT_OK = qw( PI e bpi bexp hex oct ); 13our @EXPORT = qw( inf NaN ); 14 15use overload; 16 17my $obj_class = "Math::BigRat"; 18 19############################################################################## 20 21sub accuracy { 22 my $self = shift; 23 $obj_class -> accuracy(@_); 24} 25 26sub precision { 27 my $self = shift; 28 $obj_class -> precision(@_); 29} 30 31sub round_mode { 32 my $self = shift; 33 $obj_class -> round_mode(@_); 34} 35 36sub div_scale { 37 my $self = shift; 38 $obj_class -> div_scale(@_); 39} 40 41sub in_effect { 42 my $level = shift || 0; 43 my $hinthash = (caller($level))[10]; 44 $hinthash->{bigrat}; 45} 46 47sub _float_constant { 48 my $str = shift; 49 50 # See if we can convert the input string to a string using a normalized form 51 # consisting of the significand as a signed integer, the character "e", and 52 # the exponent as a signed integer, e.g., "+0e+0", "+314e-2", and "-1e+3". 53 54 my $nstr; 55 56 if ( 57 # See if it is an octal number. An octal number like '0377' is also 58 # accepted by the functions parsing decimal and hexadecimal numbers, so 59 # handle octal numbers before decimal and hexadecimal numbers. 60 61 $str =~ /^0(?:[Oo]|_*[0-7])/ and 62 $nstr = Math::BigInt -> oct_str_to_dec_flt_str($str) 63 64 or 65 66 # See if it is decimal number. 67 68 $nstr = Math::BigInt -> dec_str_to_dec_flt_str($str) 69 70 or 71 72 # See if it is a hexadecimal number. Every hexadecimal number has a 73 # prefix, but the functions parsing numbers don't require it, so check 74 # to see if it actually is a hexadecimal number. 75 76 $str =~ /^0[Xx]/ and 77 $nstr = Math::BigInt -> hex_str_to_dec_flt_str($str) 78 79 or 80 81 # See if it is a binary numbers. Every binary number has a prefix, but 82 # the functions parsing numbers don't require it, so check to see if it 83 # actually is a binary number. 84 85 $str =~ /^0[Bb]/ and 86 $nstr = Math::BigInt -> bin_str_to_dec_flt_str($str)) 87 { 88 return $obj_class -> new($nstr); 89 } 90 91 # If we get here, there is a bug in the code above this point. 92 93 warn "Internal error: unable to handle literal constant '$str'.", 94 " This is a bug, so please report this to the module author."; 95 return $obj_class -> bnan(); 96} 97 98############################################################################# 99# the following two routines are for "use bigrat qw/hex oct/;": 100 101use constant LEXICAL => $] > 5.009004; 102 103# Internal function with the same semantics as CORE::hex(). This function is 104# not used directly, but rather by other front-end functions. 105 106sub _hex_core { 107 my $str = shift; 108 109 # Strip off, clean, and parse as much as we can from the beginning. 110 111 my $x; 112 if ($str =~ s/ ^ ( 0? [xX] )? ( [0-9a-fA-F]* ( _ [0-9a-fA-F]+ )* ) //x) { 113 my $chrs = $2; 114 $chrs =~ tr/_//d; 115 $chrs = '0' unless CORE::length $chrs; 116 $x = $obj_class -> from_hex($chrs); 117 } else { 118 $x = $obj_class -> bzero(); 119 } 120 121 # Warn about trailing garbage. 122 123 if (CORE::length($str)) { 124 require Carp; 125 Carp::carp(sprintf("Illegal hexadecimal digit '%s' ignored", 126 substr($str, 0, 1))); 127 } 128 129 return $x; 130} 131 132# Internal function with the same semantics as CORE::oct(). This function is 133# not used directly, but rather by other front-end functions. 134 135sub _oct_core { 136 my $str = shift; 137 138 $str =~ s/^\s*//; 139 140 # Hexadecimal input. 141 142 return _hex_core($str) if $str =~ /^0?[xX]/; 143 144 my $x; 145 146 # Binary input. 147 148 if ($str =~ /^0?[bB]/) { 149 150 # Strip off, clean, and parse as much as we can from the beginning. 151 152 if ($str =~ s/ ^ ( 0? [bB] )? ( [01]* ( _ [01]+ )* ) //x) { 153 my $chrs = $2; 154 $chrs =~ tr/_//d; 155 $chrs = '0' unless CORE::length $chrs; 156 $x = $obj_class -> from_bin($chrs); 157 } 158 159 # Warn about trailing garbage. 160 161 if (CORE::length($str)) { 162 require Carp; 163 Carp::carp(sprintf("Illegal binary digit '%s' ignored", 164 substr($str, 0, 1))); 165 } 166 167 return $x; 168 } 169 170 # Octal input. Strip off, clean, and parse as much as we can from the 171 # beginning. 172 173 if ($str =~ s/ ^ ( 0? [oO] )? ( [0-7]* ( _ [0-7]+ )* ) //x) { 174 my $chrs = $2; 175 $chrs =~ tr/_//d; 176 $chrs = '0' unless CORE::length $chrs; 177 $x = $obj_class -> from_oct($chrs); 178 } 179 180 # Warn about trailing garbage. CORE::oct() only warns about 8 and 9, but it 181 # is more helpful to warn about all invalid digits. 182 183 if (CORE::length($str)) { 184 require Carp; 185 Carp::carp(sprintf("Illegal octal digit '%s' ignored", 186 substr($str, 0, 1))); 187 } 188 189 return $x; 190} 191 192{ 193 my $proto = LEXICAL ? '_' : ';$'; 194 eval ' 195sub hex(' . $proto . ') {' . <<'.'; 196 my $str = @_ ? $_[0] : $_; 197 _hex_core($str); 198} 199. 200 201 eval ' 202sub oct(' . $proto . ') {' . <<'.'; 203 my $str = @_ ? $_[0] : $_; 204 _oct_core($str); 205} 206. 207} 208 209############################################################################# 210# the following two routines are for Perl 5.9.4 or later and are lexical 211 212my ($prev_oct, $prev_hex, $overridden); 213 214if (LEXICAL) { eval <<'.' } 215sub _hex(_) { 216 my $hh = (caller 0)[10]; 217 return $$hh{bigrat} ? bigrat::_hex_core($_[0]) 218 : $$hh{bigfloat} ? bigfloat::_hex_core($_[0]) 219 : $$hh{bigint} ? bigint::_hex_core($_[0]) 220 : $prev_hex ? &$prev_hex($_[0]) 221 : CORE::hex($_[0]); 222} 223 224sub _oct(_) { 225 my $hh = (caller 0)[10]; 226 return $$hh{bigrat} ? bigrat::_oct_core($_[0]) 227 : $$hh{bigfloat} ? bigfloat::_oct_core($_[0]) 228 : $$hh{bigint} ? bigint::_oct_core($_[0]) 229 : $prev_oct ? &$prev_oct($_[0]) 230 : CORE::oct($_[0]); 231} 232. 233 234sub _override { 235 return if $overridden; 236 $prev_oct = *CORE::GLOBAL::oct{CODE}; 237 $prev_hex = *CORE::GLOBAL::hex{CODE}; 238 no warnings 'redefine'; 239 *CORE::GLOBAL::oct = \&_oct; 240 *CORE::GLOBAL::hex = \&_hex; 241 $overridden = 1; 242} 243 244sub unimport { 245 $^H{bigrat} = undef; # no longer in effect 246 overload::remove_constant('binary', '', 'float', '', 'integer'); 247} 248 249sub import { 250 my $class = shift; 251 252 $^H{bigrat} = 1; # we are in effect 253 $^H{bigint} = undef; 254 $^H{bigfloat} = undef; 255 256 # for newer Perls always override hex() and oct() with a lexical version: 257 if (LEXICAL) { 258 _override(); 259 } 260 261 my @import = (); 262 my @a = (); # unrecognized arguments 263 my $ver; # version? 264 265 while (@_) { 266 my $param = shift; 267 268 # Accuracy. 269 270 if ($param =~ /^a(ccuracy)?$/) { 271 push @import, 'accuracy', shift(); 272 next; 273 } 274 275 # Precision. 276 277 if ($param =~ /^p(recision)?$/) { 278 push @import, 'precision', shift(); 279 next; 280 } 281 282 # Rounding mode. 283 284 if ($param eq 'round_mode') { 285 push @import, 'round_mode', shift(); 286 next; 287 } 288 289 # Backend library. 290 291 if ($param =~ /^(l|lib|try|only)$/) { 292 push @import, $param eq 'l' ? 'lib' : $param; 293 push @import, shift() if @_; 294 next; 295 } 296 297 if ($param =~ /^(v|version)$/) { 298 $ver = 1; 299 next; 300 } 301 302 if ($param =~ /^(t|trace)$/) { 303 $obj_class .= "::Trace"; 304 eval "require $obj_class"; 305 die $@ if $@; 306 next; 307 } 308 309 if ($param =~ /^(PI|e|bexp|bpi|hex|oct)\z/) { 310 push @a, $param; 311 next; 312 } 313 314 croak("Unknown option '$param'"); 315 } 316 317 eval "require $obj_class"; 318 die $@ if $@; 319 $obj_class -> import(@import); 320 321 if ($ver) { 322 printf "%-31s v%s\n", $class, $class -> VERSION(); 323 printf " lib => %-23s v%s\n", 324 $obj_class -> config("lib"), $obj_class -> config("lib_version"); 325 printf "%-31s v%s\n", $obj_class, $obj_class -> VERSION(); 326 exit; 327 } 328 329 $class -> export_to_level(1, $class, @a); # export inf, NaN, etc. 330 331 overload::constant 332 333 # This takes care each number written as decimal integer and within the 334 # range of what perl can represent as an integer, e.g., "314", but not 335 # "3141592653589793238462643383279502884197169399375105820974944592307". 336 337 integer => sub { 338 #printf "Value '%s' handled by the 'integer' sub.\n", $_[0]; 339 my $str = shift; 340 return $obj_class -> new($str); 341 }, 342 343 # This takes care of each number written with a decimal point and/or 344 # using floating point notation, e.g., "3.", "3.0", "3.14e+2" (decimal), 345 # "0b1.101p+2" (binary), "03.14p+2" and "0o3.14p+2" (octal), and 346 # "0x3.14p+2" (hexadecimal). 347 348 float => sub { 349 #printf "# Value '%s' handled by the 'float' sub.\n", $_[0]; 350 _float_constant(shift); 351 }, 352 353 # Take care of each number written as an integer (no decimal point or 354 # exponent) using binary, octal, or hexadecimal notation, e.g., "0b101" 355 # (binary), "0314" and "0o314" (octal), and "0x314" (hexadecimal). 356 357 binary => sub { 358 #printf "# Value '%s' handled by the 'binary' sub.\n", $_[0]; 359 my $str = shift; 360 return $obj_class -> new($str) if $str =~ /^0[XxBb]/; 361 $obj_class -> from_oct($str); 362 }; 363} 364 365sub inf () { $obj_class -> binf(); } 366sub NaN () { $obj_class -> bnan(); } 367 368# This should depend on the current accuracy/precision. Fixme! 369sub PI () { $obj_class -> new('3.141592653589793238462643383279502884197'); } 370sub e () { $obj_class -> new('2.718281828459045235360287471352662497757'); } 371 372sub bpi ($) { 373 my $up = Math::BigFloat -> upgrade(); # get current upgrading, if any ... 374 Math::BigFloat -> upgrade(undef); # ... and disable 375 my $x = Math::BigFloat -> bpi(@_); 376 Math::BigFloat -> upgrade($up); # reset the upgrading 377 return $obj_class -> new($x); 378} 379 380sub bexp ($$) { 381 my $up = Math::BigFloat -> upgrade(); # get current upgrading, if any ... 382 Math::BigFloat -> upgrade(undef); # ... and disable 383 my $x = Math::BigFloat -> new(shift); 384 $x -> bexp(@_); 385 Math::BigFloat -> upgrade($up); # reset the upgrading 386 return $obj_class -> new($x); 387} 388 3891; 390 391__END__ 392 393=pod 394 395=head1 NAME 396 397bigrat - transparent big rational number support for Perl 398 399=head1 SYNOPSIS 400 401 use bigrat; 402 403 print 2 + 4.5; # Math::BigRat 13/2 404 print 1/3 + 1/4; # Math::BigRat 7/12 405 print inf + 42; # Math::BigRat inf 406 print NaN * 7; # Math::BigRat NaN 407 print hex("0x1234567890123490"); # Perl v5.10.0 or later 408 409 { 410 no bigrat; 411 print 1/3; # 0.33333... 412 } 413 414 # for older Perls, import into current package: 415 use bigrat qw/hex oct/; 416 print hex("0x1234567890123490"); 417 print oct("01234567890123490"); 418 419=head1 DESCRIPTION 420 421All numeric literal in the given scope are converted to Math::BigRat objects. 422 423All operators (including basic math operations) except the range operator C<..> 424are overloaded. 425 426So, the following: 427 428 use bigrat; 429 $x = 1234; 430 431creates a Math::BigRat and stores a reference to in $x. This happens 432transparently and behind your back, so to speak. 433 434You can see this with the following: 435 436 perl -Mbigrat -le 'print ref(1234)' 437 438Since numbers are actually objects, you can call all the usual methods from 439Math::BigRat on them. This even works to some extent on expressions: 440 441 perl -Mbigrat -le '$x = 1234; print $x->bdec()' 442 perl -Mbigrat -le 'print 1234->copy()->binc();' 443 perl -Mbigrat -le 'print 1234->copy()->binc->badd(6);' 444 perl -Mbigrat -le 'print +(1234)->copy()->binc()' 445 446(Note that print doesn't do what you expect if the expression starts with 447'(' hence the C<+>) 448 449You can even chain the operations together as usual: 450 451 perl -Mbigrat -le 'print 1234->copy()->binc->badd(6);' 452 1241 453 454Please note the following does not work as expected (prints nothing), since 455overloading of '..' is not yet possible in Perl (as of v5.8.0): 456 457 perl -Mbigrat -le 'for (1..2) { print ref($_); }' 458 459=head2 Options 460 461C<bigrat> recognizes some options that can be passed while loading it via 462C<use>. The following options exist: 463 464=over 4 465 466=item a or accuracy 467 468This sets the accuracy for all math operations. The argument must be greater 469than or equal to zero. See Math::BigInt's bround() method for details. 470 471 perl -Mbigrat=a,50 -le 'print sqrt(20)' 472 473Note that setting precision and accuracy at the same time is not possible. 474 475=item p or precision 476 477This sets the precision for all math operations. The argument can be any 478integer. Negative values mean a fixed number of digits after the dot, while a 479positive value rounds to this digit left from the dot. 0 means round to integer. 480See Math::BigInt's bfround() method for details. 481 482 perl -Mbigrat=p,-50 -le 'print sqrt(20)' 483 484Note that setting precision and accuracy at the same time is not possible. 485 486=item t or trace 487 488This enables a trace mode and is primarily for debugging. 489 490=item l, lib, try, or only 491 492Load a different math lib, see L<Math Library>. 493 494 perl -Mbigrat=l,GMP -e 'print 2 ** 512' 495 perl -Mbigrat=lib,GMP -e 'print 2 ** 512' 496 perl -Mbigrat=try,GMP -e 'print 2 ** 512' 497 perl -Mbigrat=only,GMP -e 'print 2 ** 512' 498 499=item hex 500 501Override the built-in hex() method with a version that can handle big numbers. 502This overrides it by exporting it to the current package. Under Perl v5.10.0 and 503higher, this is not so necessary, as hex() is lexically overridden in the 504current scope whenever the C<bigrat> pragma is active. 505 506=item oct 507 508Override the built-in oct() method with a version that can handle big numbers. 509This overrides it by exporting it to the current package. Under Perl v5.10.0 and 510higher, this is not so necessary, as oct() is lexically overridden in the 511current scope whenever the C<bigrat> pragma is active. 512 513=item v or version 514 515this prints out the name and version of the modules and then exits. 516 517 perl -Mbigrat=v 518 519=back 520 521=head2 Math Library 522 523Math with the numbers is done (by default) by a backend library module called 524Math::BigInt::Calc. The default is equivalent to saying: 525 526 use bigrat lib => 'Calc'; 527 528you can change this by using: 529 530 use bigrat lib => 'GMP'; 531 532The following would first try to find Math::BigInt::Foo, then Math::BigInt::Bar, 533and if this also fails, revert to Math::BigInt::Calc: 534 535 use bigrat lib => 'Foo,Math::BigInt::Bar'; 536 537Using c<lib> warns if none of the specified libraries can be found and 538L<Math::BigInt> fell back to one of the default libraries. To suppress this 539warning, use c<try> instead: 540 541 use bigrat try => 'GMP'; 542 543If you want the code to die instead of falling back, use C<only> instead: 544 545 use bigrat only => 'GMP'; 546 547Please see the respective module documentation for further details. 548 549=head2 Method calls 550 551Since all numbers are now objects, you can use all methods that are part of the 552Math::BigRat API. 553 554But a warning is in order. When using the following to make a copy of a number, 555only a shallow copy will be made. 556 557 $x = 9; $y = $x; 558 $x = $y = 7; 559 560Using the copy or the original with overloaded math is okay, e.g., the following 561work: 562 563 $x = 9; $y = $x; 564 print $x + 1, " ", $y,"\n"; # prints 10 9 565 566but calling any method that modifies the number directly will result in B<both> 567the original and the copy being destroyed: 568 569 $x = 9; $y = $x; 570 print $x->badd(1), " ", $y,"\n"; # prints 10 10 571 572 $x = 9; $y = $x; 573 print $x->binc(1), " ", $y,"\n"; # prints 10 10 574 575 $x = 9; $y = $x; 576 print $x->bmul(2), " ", $y,"\n"; # prints 18 18 577 578Using methods that do not modify, but test that the contents works: 579 580 $x = 9; $y = $x; 581 $z = 9 if $x->is_zero(); # works fine 582 583See the documentation about the copy constructor and C<=> in overload, as well 584as the documentation in Math::BigFloat for further details. 585 586=head2 Methods 587 588=over 4 589 590=item inf() 591 592A shortcut to return Math::BigRat->binf(). Useful because Perl does not always 593handle bareword C<inf> properly. 594 595=item NaN() 596 597A shortcut to return Math::BigRat->bnan(). Useful because Perl does not always 598handle bareword C<NaN> properly. 599 600=item e 601 602 # perl -Mbigrat=e -wle 'print e' 603 604Returns Euler's number C<e>, aka exp(1). 605 606=item PI 607 608 # perl -Mbigrat=PI -wle 'print PI' 609 610Returns PI. 611 612=item bexp() 613 614 bexp($power, $accuracy); 615 616Returns Euler's number C<e> raised to the appropriate power, to the wanted 617accuracy. 618 619Example: 620 621 # perl -Mbigrat=bexp -wle 'print bexp(1,80)' 622 623=item bpi() 624 625 bpi($accuracy); 626 627Returns PI to the wanted accuracy. 628 629Example: 630 631 # perl -Mbigrat=bpi -wle 'print bpi(80)' 632 633=item accuracy() 634 635Set or get the accuracy. 636 637=item precision() 638 639Set or get the precision. 640 641=item round_mode() 642 643Set or get the rounding mode. 644 645=item div_scale() 646 647Set or get the division scale. 648 649=item in_effect() 650 651 use bigrat; 652 653 print "in effect\n" if bigrat::in_effect; # true 654 { 655 no bigrat; 656 print "in effect\n" if bigrat::in_effect; # false 657 } 658 659Returns true or false if C<bigrat> is in effect in the current scope. 660 661This method only works on Perl v5.9.4 or later. 662 663=back 664 665=head1 CAVEATS 666 667=over 4 668 669=item Hexadecimal, octal, and binary floating point literals 670 671Perl (and this module) accepts hexadecimal, octal, and binary floating point 672literals, but use them with care with Perl versions before v5.32.0, because some 673versions of Perl silently give the wrong result. 674 675=item Operator vs literal overloading 676 677C<bigrat> works by overloading handling of integer and floating point literals, 678converting them to L<Math::BigRat> objects. 679 680This means that arithmetic involving only string values or string literals are 681performed using Perl's built-in operators. 682 683For example: 684 685 use bigrat; 686 my $x = "900000000000000009"; 687 my $y = "900000000000000007"; 688 print $x - $y; 689 690outputs C<0> on default 32-bit builds, since C<bigrat> never sees the string 691literals. To ensure the expression is all treated as C<Math::BigRat> objects, 692use a literal number in the expression: 693 694 print +(0+$x) - $y; 695 696=item Ranges 697 698Perl does not allow overloading of ranges, so you can neither safely use ranges 699with C<bigrat> endpoints, nor is the iterator variable a C<Math::BigRat>. 700 701 use 5.010; 702 for my $i (12..13) { 703 for my $j (20..21) { 704 say $i ** $j; # produces a floating-point number, 705 # not an object 706 } 707 } 708 709=item in_effect() 710 711This method only works on Perl v5.9.4 or later. 712 713=item hex()/oct() 714 715C<bigrat> overrides these routines with versions that can also handle big 716integer values. Under Perl prior to version v5.9.4, however, this will not 717happen unless you specifically ask for it with the two import tags "hex" and 718"oct" - and then it will be global and cannot be disabled inside a scope with 719C<no bigrat>: 720 721 use bigrat qw/hex oct/; 722 723 print hex("0x1234567890123456"); 724 { 725 no bigrat; 726 print hex("0x1234567890123456"); 727 } 728 729The second call to hex() will warn about a non-portable constant. 730 731Compare this to: 732 733 use bigrat; 734 735 # will warn only under Perl older than v5.9.4 736 print hex("0x1234567890123456"); 737 738=back 739 740=head1 EXAMPLES 741 742 perl -Mbigrat -le 'print sqrt(33)' 743 perl -Mbigrat -le 'print 2**255' 744 perl -Mbigrat -le 'print 4.5+2**255' 745 perl -Mbigrat -le 'print 3/7 + 5/7 + 8/3' 746 perl -Mbigrat -le 'print 12->is_odd()'; 747 perl -Mbigrat=l,GMP -le 'print 7 ** 7777' 748 749=head1 BUGS 750 751Please report any bugs or feature requests to 752C<bug-bignum at rt.cpan.org>, or through the web interface at 753L<https://rt.cpan.org/Ticket/Create.html?Queue=bignum> (requires login). 754We will be notified, and then you'll automatically be notified of 755progress on your bug as I make changes. 756 757=head1 SUPPORT 758 759You can find documentation for this module with the perldoc command. 760 761 perldoc bigrat 762 763You can also look for information at: 764 765=over 4 766 767=item * GitHub 768 769L<https://github.com/pjacklam/p5-bignum> 770 771=item * RT: CPAN's request tracker 772 773L<https://rt.cpan.org/Dist/Display.html?Name=bignum> 774 775=item * MetaCPAN 776 777L<https://metacpan.org/release/bignum> 778 779=item * CPAN Testers Matrix 780 781L<http://matrix.cpantesters.org/?dist=bignum> 782 783=item * CPAN Ratings 784 785L<https://cpanratings.perl.org/dist/bignum> 786 787=back 788 789=head1 LICENSE 790 791This program is free software; you may redistribute it and/or modify it under 792the same terms as Perl itself. 793 794=head1 SEE ALSO 795 796L<bignum> and L<bigint>. 797 798L<Math::BigInt>, L<Math::BigFloat>, L<Math::BigRat> and L<Math::Big> as well as 799L<Math::BigInt::FastCalc>, L<Math::BigInt::Pari> and L<Math::BigInt::GMP>. 800 801=head1 AUTHORS 802 803=over 4 804 805=item * 806 807(C) by Tels L<http://bloodgate.com/> in early 2002 - 2007. 808 809=item * 810 811Maintained by Peter John Acklam E<lt>pjacklam@gmail.comE<gt>, 2014-. 812 813=back 814 815=cut 816