1package bigint; 2require 5.005; 3 4$VERSION = '0.07'; 5use Exporter; 6@ISA = qw( Exporter ); 7@EXPORT_OK = qw( ); 8@EXPORT = qw( inf NaN ); 9 10use strict; 11use overload; 12 13############################################################################## 14 15# These are all alike, and thus faked by AUTOLOAD 16 17my @faked = qw/round_mode accuracy precision div_scale/; 18use vars qw/$VERSION $AUTOLOAD $_lite/; # _lite for testsuite 19 20sub AUTOLOAD 21 { 22 my $name = $AUTOLOAD; 23 24 $name =~ s/.*:://; # split package 25 no strict 'refs'; 26 foreach my $n (@faked) 27 { 28 if ($n eq $name) 29 { 30 *{"bigint::$name"} = sub 31 { 32 my $self = shift; 33 no strict 'refs'; 34 if (defined $_[0]) 35 { 36 return Math::BigInt->$name($_[0]); 37 } 38 return Math::BigInt->$name(); 39 }; 40 return &$name; 41 } 42 } 43 44 # delayed load of Carp and avoid recursion 45 require Carp; 46 Carp::croak ("Can't call bigint\-\>$name, not a valid method"); 47 } 48 49sub upgrade 50 { 51 my $self = shift; 52 no strict 'refs'; 53# if (defined $_[0]) 54# { 55# $Math::BigInt::upgrade = $_[0]; 56# } 57 return $Math::BigInt::upgrade; 58 } 59 60sub _constant 61 { 62 # this takes a floating point constant string and returns it truncated to 63 # integer. For instance, '4.5' => '4', '1.234e2' => '123' etc 64 my $float = shift; 65 66 # some simple cases first 67 return $float if ($float =~ /^[+-]?[0-9]+$/); # '+123','-1','0' etc 68 return $float 69 if ($float =~ /^[+-]?[0-9]+\.?[eE]\+?[0-9]+$/); # 123e2, 123.e+2 70 return '0' if ($float =~ /^[+-]?[0]*\.[0-9]+$/); # .2, 0.2, -.1 71 if ($float =~ /^[+-]?[0-9]+\.[0-9]*$/) # 1., 1.23, -1.2 etc 72 { 73 $float =~ s/\..*//; 74 return $float; 75 } 76 my ($mis,$miv,$mfv,$es,$ev) = Math::BigInt::_split($float); 77 return $float if !defined $mis; # doesn't look like a number to me 78 my $ec = int($$ev); 79 my $sign = $$mis; $sign = '' if $sign eq '+'; 80 if ($$es eq '-') 81 { 82 # ignore fraction part entirely 83 if ($ec >= length($$miv)) # 123.23E-4 84 { 85 return '0'; 86 } 87 return $sign . substr ($$miv,0,length($$miv)-$ec); # 1234.45E-2 = 12 88 } 89 # xE+y 90 if ($ec >= length($$mfv)) 91 { 92 $ec -= length($$mfv); 93 return $sign.$$miv.$$mfv if $ec == 0; # 123.45E+2 => 12345 94 return $sign.$$miv.$$mfv.'E'.$ec; # 123.45e+3 => 12345e1 95 } 96 $mfv = substr($$mfv,0,$ec); 97 return $sign.$$miv.$mfv; # 123.45e+1 => 1234 98 } 99 100sub import 101 { 102 my $self = shift; 103 104 # some defaults 105 my $lib = ''; 106 107 my @import = ( ':constant' ); # drive it w/ constant 108 my @a = @_; my $l = scalar @_; my $j = 0; 109 my ($ver,$trace); # version? trace? 110 my ($a,$p); # accuracy, precision 111 for ( my $i = 0; $i < $l ; $i++,$j++ ) 112 { 113 if ($_[$i] =~ /^(l|lib)$/) 114 { 115 # this causes a different low lib to take care... 116 $lib = $_[$i+1] || ''; 117 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..." 118 splice @a, $j, $s; $j -= $s; $i++; 119 } 120 elsif ($_[$i] =~ /^(a|accuracy)$/) 121 { 122 $a = $_[$i+1]; 123 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..." 124 splice @a, $j, $s; $j -= $s; $i++; 125 } 126 elsif ($_[$i] =~ /^(p|precision)$/) 127 { 128 $p = $_[$i+1]; 129 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..." 130 splice @a, $j, $s; $j -= $s; $i++; 131 } 132 elsif ($_[$i] =~ /^(v|version)$/) 133 { 134 $ver = 1; 135 splice @a, $j, 1; $j --; 136 } 137 elsif ($_[$i] =~ /^(t|trace)$/) 138 { 139 $trace = 1; 140 splice @a, $j, 1; $j --; 141 } 142 else { die "unknown option $_[$i]"; } 143 } 144 my $class; 145 $_lite = 0; # using M::BI::L ? 146 if ($trace) 147 { 148 require Math::BigInt::Trace; $class = 'Math::BigInt::Trace'; 149 } 150 else 151 { 152 # see if we can find Math::BigInt::Lite 153 if (!defined $a && !defined $p) # rounding won't work to well 154 { 155 eval 'require Math::BigInt::Lite;'; 156 if ($@ eq '') 157 { 158 @import = ( ); # :constant in Lite, not MBI 159 Math::BigInt::Lite->import( ':constant' ); 160 $_lite= 1; # signal okay 161 } 162 } 163 require Math::BigInt if $_lite == 0; # not already loaded? 164 $class = 'Math::BigInt'; # regardless of MBIL or not 165 } 166 push @import, 'lib' => $lib if $lib ne ''; 167 # Math::BigInt::Trace or plain Math::BigInt 168 $class->import(@import); 169 170 bigint->accuracy($a) if defined $a; 171 bigint->precision($p) if defined $p; 172 if ($ver) 173 { 174 print "bigint\t\t\t v$VERSION\n"; 175 print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite; 176 print "Math::BigInt\t\t v$Math::BigInt::VERSION"; 177 my $config = Math::BigInt->config(); 178 print " lib => $config->{lib} v$config->{lib_version}\n"; 179 exit; 180 } 181 # we take care of floating point constants, since BigFloat isn't available 182 # and BigInt doesn't like them: 183 overload::constant float => sub { Math::BigInt->new( _constant(shift) ); }; 184 185 $self->export_to_level(1,$self,@a); # export inf and NaN 186 } 187 188sub inf () { Math::BigInt->binf(); } 189sub NaN () { Math::BigInt->bnan(); } 190 1911; 192 193__END__ 194 195=head1 NAME 196 197bigint - Transparent BigInteger support for Perl 198 199=head1 SYNOPSIS 200 201 use bigint; 202 203 $x = 2 + 4.5,"\n"; # BigInt 6 204 print 2 ** 512,"\n"; # really is what you think it is 205 print inf + 42,"\n"; # inf 206 print NaN * 7,"\n"; # NaN 207 208=head1 DESCRIPTION 209 210All operators (including basic math operations) are overloaded. Integer 211constants are created as proper BigInts. 212 213Floating point constants are truncated to integer. All results are also 214truncated. 215 216=head2 Options 217 218bigint recognizes some options that can be passed while loading it via use. 219The options can (currently) be either a single letter form, or the long form. 220The following options exist: 221 222=over 2 223 224=item a or accuracy 225 226This sets the accuracy for all math operations. The argument must be greater 227than or equal to zero. See Math::BigInt's bround() function for details. 228 229 perl -Mbigint=a,2 -le 'print 12345+1' 230 231=item p or precision 232 233This sets the precision for all math operations. The argument can be any 234integer. Negative values mean a fixed number of digits after the dot, and 235are <B>ignored</B> since all operations happen in integer space. 236A positive value rounds to this digit left from the dot. 0 or 1 mean round to 237integer and are ignore like negative values. 238 239See Math::BigInt's bfround() function for details. 240 241 perl -Mbignum=p,5 -le 'print 123456789+123' 242 243=item t or trace 244 245This enables a trace mode and is primarily for debugging bigint or 246Math::BigInt. 247 248=item l or lib 249 250Load a different math lib, see L<MATH LIBRARY>. 251 252 perl -Mbigint=l,GMP -e 'print 2 ** 512' 253 254Currently there is no way to specify more than one library on the command 255line. This will be hopefully fixed soon ;) 256 257=item v or version 258 259This prints out the name and version of all modules used and then exits. 260 261 perl -Mbigint=v 262 263=head2 Math Library 264 265Math with the numbers is done (by default) by a module called 266Math::BigInt::Calc. This is equivalent to saying: 267 268 use bigint lib => 'Calc'; 269 270You can change this by using: 271 272 use bigint lib => 'BitVect'; 273 274The following would first try to find Math::BigInt::Foo, then 275Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc: 276 277 use bigint lib => 'Foo,Math::BigInt::Bar'; 278 279Please see respective module documentation for further details. 280 281=head2 Internal Format 282 283The numbers are stored as objects, and their internals might change at anytime, 284especially between math operations. The objects also might belong to different 285classes, like Math::BigInt, or Math::BigInt::Lite. Mixing them together, even 286with normal scalars is not extraordinary, but normal and expected. 287 288You should not depend on the internal format, all accesses must go through 289accessor methods. E.g. looking at $x->{sign} is not a good idea since there 290is no guaranty that the object in question has such a hash key, nor is a hash 291underneath at all. 292 293=head2 Sign 294 295The sign is either '+', '-', 'NaN', '+inf' or '-inf'. 296You can access it with the sign() method. 297 298A sign of 'NaN' is used to represent the result when input arguments are not 299numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively 300minus infinity. You will get '+inf' when dividing a positive number by 0, and 301'-inf' when dividing any negative number by 0. 302 303=head2 Methods 304 305Since all numbers are now objects, you can use all functions that are part of 306the BigInt API. You can only use the bxxx() notation, and not the fxxx() 307notation, though. 308 309=head2 Caveat 310 311But a warning is in order. When using the following to make a copy of a number, 312only a shallow copy will be made. 313 314 $x = 9; $y = $x; 315 $x = $y = 7; 316 317Using the copy or the original with overloaded math is okay, e.g. the 318following work: 319 320 $x = 9; $y = $x; 321 print $x + 1, " ", $y,"\n"; # prints 10 9 322 323but calling any method that modifies the number directly will result in 324B<both> the original and the copy beeing destroyed: 325 326 $x = 9; $y = $x; 327 print $x->badd(1), " ", $y,"\n"; # prints 10 10 328 329 $x = 9; $y = $x; 330 print $x->binc(1), " ", $y,"\n"; # prints 10 10 331 332 $x = 9; $y = $x; 333 print $x->bmul(2), " ", $y,"\n"; # prints 18 18 334 335Using methods that do not modify, but testthe contents works: 336 337 $x = 9; $y = $x; 338 $z = 9 if $x->is_zero(); # works fine 339 340See the documentation about the copy constructor and C<=> in overload, as 341well as the documentation in BigInt for further details. 342 343=head1 MODULES USED 344 345C<bigint> is just a thin wrapper around various modules of the Math::BigInt 346family. Think of it as the head of the family, who runs the shop, and orders 347the others to do the work. 348 349The following modules are currently used by bigint: 350 351 Math::BigInt::Lite (for speed, and only if it is loadable) 352 Math::BigInt 353 354=head1 EXAMPLES 355 356Some cool command line examples to impress the Python crowd ;) You might want 357to compare them to the results under -Mbignum or -Mbigrat: 358 359 perl -Mbigint -le 'print sqrt(33)' 360 perl -Mbigint -le 'print 2*255' 361 perl -Mbigint -le 'print 4.5+2*255' 362 perl -Mbigint -le 'print 3/7 + 5/7 + 8/3' 363 perl -Mbigint -le 'print 123->is_odd()' 364 perl -Mbigint -le 'print log(2)' 365 perl -Mbigint -le 'print 2 ** 0.5' 366 perl -Mbigint=a,65 -le 'print 2 ** 0.2' 367 368=head1 LICENSE 369 370This program is free software; you may redistribute it and/or modify it under 371the same terms as Perl itself. 372 373=head1 SEE ALSO 374 375Especially L<bigrat> as in C<perl -Mbigrat -le 'print 1/3+1/4'> and 376L<bignum> as in C<perl -Mbignum -le 'print sqrt(2)'>. 377 378L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well 379as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and L<Math::BigInt::GMP>. 380 381=head1 AUTHORS 382 383(C) by Tels L<http://bloodgate.com/> in early 2002 - 2005. 384 385=cut 386