1package bigrat; 2use 5.006; 3 4$VERSION = '0.23'; 5require Exporter; 6@ISA = qw( bigint ); 7@EXPORT_OK = qw( PI e bpi bexp ); 8@EXPORT = qw( inf NaN ); 9 10use strict; 11use overload; 12require bigint; # no "use" to avoid callind import 13 14############################################################################## 15 16BEGIN 17 { 18 *inf = \&bigint::inf; 19 *NaN = \&bigint::NaN; 20 } 21 22# These are all alike, and thus faked by AUTOLOAD 23 24my @faked = qw/round_mode accuracy precision div_scale/; 25use vars qw/$VERSION $AUTOLOAD $_lite/; # _lite for testsuite 26 27sub AUTOLOAD 28 { 29 my $name = $AUTOLOAD; 30 31 $name =~ s/.*:://; # split package 32 no strict 'refs'; 33 foreach my $n (@faked) 34 { 35 if ($n eq $name) 36 { 37 *{"bigrat::$name"} = sub 38 { 39 my $self = shift; 40 no strict 'refs'; 41 if (defined $_[0]) 42 { 43 Math::BigInt->$name($_[0]); 44 Math::BigFloat->$name($_[0]); 45 return Math::BigRat->$name($_[0]); 46 } 47 return Math::BigInt->$name(); 48 }; 49 return &$name; 50 } 51 } 52 53 # delayed load of Carp and avoid recursion 54 require Carp; 55 Carp::croak ("Can't call bigrat\-\>$name, not a valid method"); 56 } 57 58sub unimport 59 { 60 $^H{bigrat} = undef; # no longer in effect 61 overload::remove_constant('binary','','float','','integer'); 62 } 63 64sub in_effect 65 { 66 my $level = shift || 0; 67 my $hinthash = (caller($level))[10]; 68 $hinthash->{bigrat}; 69 } 70 71############################################################################# 72# the following two routines are for Perl 5.9.4 or later and are lexical 73 74sub _hex 75 { 76 return CORE::hex($_[0]) unless in_effect(1); 77 my $i = $_[0]; 78 $i = '0x'.$i unless $i =~ /^0x/; 79 Math::BigInt->new($i); 80 } 81 82sub _oct 83 { 84 return CORE::oct($_[0]) unless in_effect(1); 85 my $i = $_[0]; 86 return Math::BigInt->from_oct($i) if $i =~ /^0[0-7]/; 87 Math::BigInt->new($i); 88 } 89 90sub import 91 { 92 my $self = shift; 93 94 # see also bignum->import() for additional comments 95 96 $^H{bigrat} = 1; # we are in effect 97 98 my ($hex,$oct); 99 # for newer Perls always override hex() and oct() with a lexical version: 100 if ($] > 5.009004) 101 { 102 $oct = \&_oct; 103 $hex = \&_hex; 104 } 105 # some defaults 106 my $lib = ''; my $lib_kind = 'try'; my $upgrade = 'Math::BigFloat'; 107 108 my @import = ( ':constant' ); # drive it w/ constant 109 my @a = @_; my $l = scalar @_; my $j = 0; 110 my ($a,$p); 111 my ($ver,$trace); # version? trace? 112 for ( my $i = 0; $i < $l ; $i++,$j++ ) 113 { 114 if ($_[$i] eq 'upgrade') 115 { 116 # this causes upgrading 117 $upgrade = $_[$i+1]; # or undef to disable 118 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..." 119 splice @a, $j, $s; $j -= $s; 120 } 121 elsif ($_[$i] =~ /^(l|lib|try|only)$/) 122 { 123 # this causes a different low lib to take care... 124 $lib_kind = $1; $lib_kind = 'lib' if $lib_kind eq 'l'; 125 $lib = $_[$i+1] || ''; 126 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..." 127 splice @a, $j, $s; $j -= $s; $i++; 128 } 129 elsif ($_[$i] =~ /^(a|accuracy)$/) 130 { 131 $a = $_[$i+1]; 132 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..." 133 splice @a, $j, $s; $j -= $s; $i++; 134 } 135 elsif ($_[$i] =~ /^(p|precision)$/) 136 { 137 $p = $_[$i+1]; 138 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..." 139 splice @a, $j, $s; $j -= $s; $i++; 140 } 141 elsif ($_[$i] =~ /^(v|version)$/) 142 { 143 $ver = 1; 144 splice @a, $j, 1; $j --; 145 } 146 elsif ($_[$i] =~ /^(t|trace)$/) 147 { 148 $trace = 1; 149 splice @a, $j, 1; $j --; 150 } 151 elsif ($_[$i] eq 'hex') 152 { 153 splice @a, $j, 1; $j --; 154 $hex = \&bigint::_hex_global; 155 } 156 elsif ($_[$i] eq 'oct') 157 { 158 splice @a, $j, 1; $j --; 159 $oct = \&bigint::_oct_global; 160 } 161 elsif ($_[$i] !~ /^(PI|e|bpi|bexp)\z/) 162 { 163 die ("unknown option $_[$i]"); 164 } 165 } 166 my $class; 167 $_lite = 0; # using M::BI::L ? 168 if ($trace) 169 { 170 require Math::BigInt::Trace; $class = 'Math::BigInt::Trace'; 171 $upgrade = 'Math::BigFloat::Trace'; 172 } 173 else 174 { 175 # see if we can find Math::BigInt::Lite 176 if (!defined $a && !defined $p) # rounding won't work to well 177 { 178 eval 'require Math::BigInt::Lite;'; 179 if ($@ eq '') 180 { 181 @import = ( ); # :constant in Lite, not MBI 182 Math::BigInt::Lite->import( ':constant' ); 183 $_lite= 1; # signal okay 184 } 185 } 186 require Math::BigInt if $_lite == 0; # not already loaded? 187 $class = 'Math::BigInt'; # regardless of MBIL or not 188 } 189 push @import, $lib_kind => $lib if $lib ne ''; 190 # Math::BigInt::Trace or plain Math::BigInt 191 $class->import(@import, upgrade => $upgrade); 192 193 require Math::BigFloat; 194 Math::BigFloat->import( upgrade => 'Math::BigRat', ':constant' ); 195 require Math::BigRat; 196 197 bigrat->accuracy($a) if defined $a; 198 bigrat->precision($p) if defined $p; 199 if ($ver) 200 { 201 print "bigrat\t\t\t v$VERSION\n"; 202 print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite; 203 print "Math::BigInt\t\t v$Math::BigInt::VERSION"; 204 my $config = Math::BigInt->config(); 205 print " lib => $config->{lib} v$config->{lib_version}\n"; 206 print "Math::BigFloat\t\t v$Math::BigFloat::VERSION\n"; 207 print "Math::BigRat\t\t v$Math::BigRat::VERSION\n"; 208 exit; 209 } 210 211 # Take care of octal/hexadecimal constants 212 overload::constant binary => sub { bigint::_binary_constant(shift) }; 213 214 # if another big* was already loaded: 215 my ($package) = caller(); 216 217 no strict 'refs'; 218 if (!defined *{"${package}::inf"}) 219 { 220 $self->export_to_level(1,$self,@a); # export inf and NaN 221 } 222 { 223 no warnings 'redefine'; 224 *CORE::GLOBAL::oct = $oct if $oct; 225 *CORE::GLOBAL::hex = $hex if $hex; 226 } 227 } 228 229sub PI () { Math::BigFloat->new('3.141592653589793238462643383279502884197'); } 230sub e () { Math::BigFloat->new('2.718281828459045235360287471352662497757'); } 231 232sub bpi ($) { local $Math::BigFloat::upgrade; Math::BigFloat::bpi(@_); } 233 234sub bexp ($$) 235 { 236 local $Math::BigFloat::upgrade; 237 my $x = Math::BigFloat->new($_[0]); $x->bexp($_[1]); 238 } 239 2401; 241 242__END__ 243 244=head1 NAME 245 246bigrat - Transparent BigNumber/BigRational support for Perl 247 248=head1 SYNOPSIS 249 250 use bigrat; 251 252 print 2 + 4.5,"\n"; # BigFloat 6.5 253 print 1/3 + 1/4,"\n"; # produces 7/12 254 255 { 256 no bigrat; 257 print 1/3,"\n"; # 0.33333... 258 } 259 260 # Note that this will make hex() and oct() be globally overriden: 261 use bigrat qw/hex oct/; 262 print hex("0x1234567890123490"),"\n"; 263 print oct("01234567890123490"),"\n"; 264 265=head1 DESCRIPTION 266 267All operators (including basic math operations) are overloaded. Integer and 268floating-point constants are created as proper BigInts or BigFloats, 269respectively. 270 271Other than L<bignum>, this module upgrades to Math::BigRat, meaning that 272instead of 2.5 you will get 2+1/2 as output. 273 274=head2 Modules Used 275 276C<bigrat> is just a thin wrapper around various modules of the Math::BigInt 277family. Think of it as the head of the family, who runs the shop, and orders 278the others to do the work. 279 280The following modules are currently used by bignum: 281 282 Math::BigInt::Lite (for speed, and only if it is loadable) 283 Math::BigInt 284 Math::BigFloat 285 Math::BigRat 286 287=head2 Math Library 288 289Math with the numbers is done (by default) by a module called 290Math::BigInt::Calc. This is equivalent to saying: 291 292 use bigrat lib => 'Calc'; 293 294You can change this by using: 295 296 use bignum lib => 'GMP'; 297 298The following would first try to find Math::BigInt::Foo, then 299Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc: 300 301 use bigrat lib => 'Foo,Math::BigInt::Bar'; 302 303Using C<lib> warns if none of the specified libraries can be found and 304L<Math::BigInt> did fall back to one of the default libraries. 305To supress this warning, use C<try> instead: 306 307 use bignum try => 'GMP'; 308 309If you want the code to die instead of falling back, use C<only> instead: 310 311 use bignum only => 'GMP'; 312 313Please see respective module documentation for further details. 314 315=head2 Sign 316 317The sign is either '+', '-', 'NaN', '+inf' or '-inf'. 318 319A sign of 'NaN' is used to represent the result when input arguments are not 320numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively 321minus infinity. You will get '+inf' when dividing a positive number by 0, and 322'-inf' when dividing any negative number by 0. 323 324=head2 Methods 325 326Since all numbers are not objects, you can use all functions that are part of 327the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not 328the fxxx() notation, though. This makes you independed on the fact that the 329underlying object might morph into a different class than BigFloat. 330 331=over 2 332 333=item inf() 334 335A shortcut to return Math::BigInt->binf(). Useful because Perl does not always 336handle bareword C<inf> properly. 337 338=item NaN() 339 340A shortcut to return Math::BigInt->bnan(). Useful because Perl does not always 341handle bareword C<NaN> properly. 342 343=item e 344 345 # perl -Mbigrat=e -wle 'print e' 346 347Returns Euler's number C<e>, aka exp(1). 348 349=item PI 350 351 # perl -Mbigrat=PI -wle 'print PI' 352 353Returns PI. 354 355=item bexp() 356 357 bexp($power,$accuracy); 358 359 360Returns Euler's number C<e> raised to the appropriate power, to 361the wanted accuracy. 362 363Example: 364 365 # perl -Mbigrat=bexp -wle 'print bexp(1,80)' 366 367=item bpi() 368 369 bpi($accuracy); 370 371Returns PI to the wanted accuracy. 372 373Example: 374 375 # perl -Mbigrat=bpi -wle 'print bpi(80)' 376 377=item upgrade() 378 379Return the class that numbers are upgraded to, is in fact returning 380C<$Math::BigInt::upgrade>. 381 382=item in_effect() 383 384 use bigrat; 385 386 print "in effect\n" if bigrat::in_effect; # true 387 { 388 no bigrat; 389 print "in effect\n" if bigrat::in_effect; # false 390 } 391 392Returns true or false if C<bigrat> is in effect in the current scope. 393 394This method only works on Perl v5.9.4 or later. 395 396=back 397 398=head2 MATH LIBRARY 399 400Math with the numbers is done (by default) by a module called 401 402=head2 Cavaet 403 404But a warning is in order. When using the following to make a copy of a number, 405only a shallow copy will be made. 406 407 $x = 9; $y = $x; 408 $x = $y = 7; 409 410If you want to make a real copy, use the following: 411 412 $y = $x->copy(); 413 414Using the copy or the original with overloaded math is okay, e.g. the 415following work: 416 417 $x = 9; $y = $x; 418 print $x + 1, " ", $y,"\n"; # prints 10 9 419 420but calling any method that modifies the number directly will result in 421B<both> the original and the copy being destroyed: 422 423 $x = 9; $y = $x; 424 print $x->badd(1), " ", $y,"\n"; # prints 10 10 425 426 $x = 9; $y = $x; 427 print $x->binc(1), " ", $y,"\n"; # prints 10 10 428 429 $x = 9; $y = $x; 430 print $x->bmul(2), " ", $y,"\n"; # prints 18 18 431 432Using methods that do not modify, but testthe contents works: 433 434 $x = 9; $y = $x; 435 $z = 9 if $x->is_zero(); # works fine 436 437See the documentation about the copy constructor and C<=> in overload, as 438well as the documentation in BigInt for further details. 439 440=head2 Options 441 442bignum recognizes some options that can be passed while loading it via use. 443The options can (currently) be either a single letter form, or the long form. 444The following options exist: 445 446=over 2 447 448=item a or accuracy 449 450This sets the accuracy for all math operations. The argument must be greater 451than or equal to zero. See Math::BigInt's bround() function for details. 452 453 perl -Mbigrat=a,50 -le 'print sqrt(20)' 454 455Note that setting precision and accurary at the same time is not possible. 456 457=item p or precision 458 459This sets the precision for all math operations. The argument can be any 460integer. Negative values mean a fixed number of digits after the dot, while 461a positive value rounds to this digit left from the dot. 0 or 1 mean round to 462integer. See Math::BigInt's bfround() function for details. 463 464 perl -Mbigrat=p,-50 -le 'print sqrt(20)' 465 466Note that setting precision and accurary at the same time is not possible. 467 468=item t or trace 469 470This enables a trace mode and is primarily for debugging bignum or 471Math::BigInt/Math::BigFloat. 472 473=item l or lib 474 475Load a different math lib, see L<MATH LIBRARY>. 476 477 perl -Mbigrat=l,GMP -e 'print 2 ** 512' 478 479Currently there is no way to specify more than one library on the command 480line. This means the following does not work: 481 482 perl -Mbignum=l,GMP,Pari -e 'print 2 ** 512' 483 484This will be hopefully fixed soon ;) 485 486=item hex 487 488Override the built-in hex() method with a version that can handle big 489integers. Note that under Perl v5.9.4 or ealier, this will be global 490and cannot be disabled with "no bigint;". 491 492=item oct 493 494Override the built-in oct() method with a version that can handle big 495integers. Note that under Perl v5.9.4 or ealier, this will be global 496and cannot be disabled with "no bigint;". 497 498=item v or version 499 500This prints out the name and version of all modules used and then exits. 501 502 perl -Mbigrat=v 503 504=back 505 506=head1 CAVAETS 507 508=over 2 509 510=item in_effect() 511 512This method only works on Perl v5.9.4 or later. 513 514=item hex()/oct() 515 516C<bigint> overrides these routines with versions that can also handle 517big integer values. Under Perl prior to version v5.9.4, however, this 518will not happen unless you specifically ask for it with the two 519import tags "hex" and "oct" - and then it will be global and cannot be 520disabled inside a scope with "no bigint": 521 522 use bigint qw/hex oct/; 523 524 print hex("0x1234567890123456"); 525 { 526 no bigint; 527 print hex("0x1234567890123456"); 528 } 529 530The second call to hex() will warn about a non-portable constant. 531 532Compare this to: 533 534 use bigint; 535 536 # will warn only under Perl older than v5.9.4 537 print hex("0x1234567890123456"); 538 539=back 540 541=head1 EXAMPLES 542 543 perl -Mbigrat -le 'print sqrt(33)' 544 perl -Mbigrat -le 'print 2*255' 545 perl -Mbigrat -le 'print 4.5+2*255' 546 perl -Mbigrat -le 'print 3/7 + 5/7 + 8/3' 547 perl -Mbigrat -le 'print 12->is_odd()'; 548 perl -Mbignum=l,GMP -le 'print 7 ** 7777' 549 550=head1 LICENSE 551 552This program is free software; you may redistribute it and/or modify it under 553the same terms as Perl itself. 554 555=head1 SEE ALSO 556 557Especially L<bignum>. 558 559L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well 560as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and L<Math::BigInt::GMP>. 561 562=head1 AUTHORS 563 564(C) by Tels L<http://bloodgate.com/> in early 2002 - 2007. 565 566=cut 567