1package bigint; 2require 5.005; 3 4$VERSION = '0.05'; 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 = 'Calc'; 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 # Math::BigInt::Trace or plain Math::BigInt 167 $class->import(@import, lib => $lib); 168 169 bigint->accuracy($a) if defined $a; 170 bigint->precision($p) if defined $p; 171 if ($ver) 172 { 173 print "bigint\t\t\t v$VERSION\n"; 174 print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite; 175 print "Math::BigInt\t\t v$Math::BigInt::VERSION"; 176 my $config = Math::BigInt->config(); 177 print " lib => $config->{lib} v$config->{lib_version}\n"; 178 exit; 179 } 180 # we take care of floating point constants, since BigFloat isn't available 181 # and BigInt doesn't like them: 182 overload::constant float => sub { Math::BigInt->new( _constant(shift) ); }; 183 184 $self->export_to_level(1,$self,@a); # export inf and NaN 185 } 186 187sub inf () { Math::BigInt->binf(); } 188sub NaN () { Math::BigInt->bnan(); } 189 1901; 191 192__END__ 193 194=head1 NAME 195 196bigint - Transparent BigInteger support for Perl 197 198=head1 SYNOPSIS 199 200 use bignt; 201 202 $x = 2 + 4.5,"\n"; # BigInt 6 203 print 2 ** 512,"\n"; # really is what you think it is 204 print inf + 42,"\n"; # inf 205 print NaN * 7,"\n"; # NaN 206 207=head1 DESCRIPTION 208 209All operators (including basic math operations) are overloaded. Integer 210constants are created as proper BigInts. 211 212Floating point constants are truncated to integer. All results are also 213truncated. 214 215=head2 OPTIONS 216 217bigint recognizes some options that can be passed while loading it via use. 218The options can (currently) be either a single letter form, or the long form. 219The following options exist: 220 221=over 2 222 223=item a or accuracy 224 225This sets the accuracy for all math operations. The argument must be greater 226than or equal to zero. See Math::BigInt's bround() function for details. 227 228 perl -Mbigint=a,2 -le 'print 12345+1' 229 230=item p or precision 231 232This sets the precision for all math operations. The argument can be any 233integer. Negative values mean a fixed number of digits after the dot, and 234are <B>ignored</B> since all operations happen in integer space. 235A positive value rounds to this digit left from the dot. 0 or 1 mean round to 236integer and are ignore like negative values. 237 238See Math::BigInt's bfround() function for details. 239 240 perl -Mbignum=p,5 -le 'print 123456789+123' 241 242=item t or trace 243 244This enables a trace mode and is primarily for debugging bigint or 245Math::BigInt. 246 247=item l or lib 248 249Load a different math lib, see L<MATH LIBRARY>. 250 251 perl -Mbigint=l,GMP -e 'print 2 ** 512' 252 253Currently there is no way to specify more than one library on the command 254line. This will be hopefully fixed soon ;) 255 256=item v or version 257 258This prints out the name and version of all modules used and then exits. 259 260 perl -Mbigint=v -e '' 261 262=head2 MATH LIBRARY 263 264Math with the numbers is done (by default) by a module called 265Math::BigInt::Calc. This is equivalent to saying: 266 267 use bigint lib => 'Calc'; 268 269You can change this by using: 270 271 use bigint lib => 'BitVect'; 272 273The following would first try to find Math::BigInt::Foo, then 274Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc: 275 276 use bigint lib => 'Foo,Math::BigInt::Bar'; 277 278Please see respective module documentation for further details. 279 280=head2 INTERNAL FORMAT 281 282The numbers are stored as objects, and their internals might change at anytime, 283especially between math operations. The objects also might belong to different 284classes, like Math::BigInt, or Math::BigInt::Lite. Mixing them together, even 285with normal scalars is not extraordinary, but normal and expected. 286 287You should not depend on the internal format, all accesses must go through 288accessor methods. E.g. looking at $x->{sign} is not a good idea since there 289is no guaranty that the object in question has such a hash key, nor is a hash 290underneath at all. 291 292=head2 SIGN 293 294The sign is either '+', '-', 'NaN', '+inf' or '-inf' and stored seperately. 295You can access it with the sign() method. 296 297A sign of 'NaN' is used to represent the result when input arguments are not 298numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively 299minus infinity. You will get '+inf' when dividing a positive number by 0, and 300'-inf' when dividing any negative number by 0. 301 302=head2 METHODS 303 304Since all numbers are now objects, you can use all functions that are part of 305the BigInt API. You can only use the bxxx() notation, and not the fxxx() 306notation, though. 307 308=head2 CAVEAT 309 310But a warning is in order. When using the following to make a copy of a number, 311only a shallow copy will be made. 312 313 $x = 9; $y = $x; 314 $x = $y = 7; 315 316Using the copy or the original with overloaded math is okay, e.g. the 317following work: 318 319 $x = 9; $y = $x; 320 print $x + 1, " ", $y,"\n"; # prints 10 9 321 322but calling any method that modifies the number directly will result in 323B<both> the original and the copy beeing destroyed: 324 325 $x = 9; $y = $x; 326 print $x->badd(1), " ", $y,"\n"; # prints 10 10 327 328 $x = 9; $y = $x; 329 print $x->binc(1), " ", $y,"\n"; # prints 10 10 330 331 $x = 9; $y = $x; 332 print $x->bmul(2), " ", $y,"\n"; # prints 18 18 333 334Using methods that do not modify, but testthe contents works: 335 336 $x = 9; $y = $x; 337 $z = 9 if $x->is_zero(); # works fine 338 339See the documentation about the copy constructor and C<=> in overload, as 340well as the documentation in BigInt for further details. 341 342=head1 MODULES USED 343 344C<bigint> is just a thin wrapper around various modules of the Math::BigInt 345family. Think of it as the head of the family, who runs the shop, and orders 346the others to do the work. 347 348The following modules are currently used by bigint: 349 350 Math::BigInt::Lite (for speed, and only if it is loadable) 351 Math::BigInt 352 353=head1 EXAMPLES 354 355Some cool command line examples to impress the Python crowd ;) You might want 356to compare them to the results under -Mbignum or -Mbigrat: 357 358 perl -Mbigint -le 'print sqrt(33)' 359 perl -Mbigint -le 'print 2*255' 360 perl -Mbigint -le 'print 4.5+2*255' 361 perl -Mbigint -le 'print 3/7 + 5/7 + 8/3' 362 perl -Mbigint -le 'print 123->is_odd()' 363 perl -Mbigint -le 'print log(2)' 364 perl -Mbigint -le 'print 2 ** 0.5' 365 perl -Mbigint=a,65 -le 'print 2 ** 0.2' 366 367=head1 LICENSE 368 369This program is free software; you may redistribute it and/or modify it under 370the same terms as Perl itself. 371 372=head1 SEE ALSO 373 374Especially L<bigrat> as in C<perl -Mbigrat -le 'print 1/3+1/4'> and 375L<bignum> as in C<perl -Mbignum -le 'print sqrt(2)'>. 376 377L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well 378as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and L<Math::BigInt::GMP>. 379 380=head1 AUTHORS 381 382(C) by Tels L<http://bloodgate.com/> in early 2002, 2003. 383 384=cut 385