1package bigrat; 2require 5.005; 3 4$VERSION = '0.08'; 5require Exporter; 6@ISA = qw( Exporter ); 7@EXPORT_OK = qw( ); 8@EXPORT = qw( inf NaN ); 9 10use strict; 11 12############################################################################## 13 14# These are all alike, and thus faked by AUTOLOAD 15 16my @faked = qw/round_mode accuracy precision div_scale/; 17use vars qw/$VERSION $AUTOLOAD $_lite/; # _lite for testsuite 18 19sub AUTOLOAD 20 { 21 my $name = $AUTOLOAD; 22 23 $name =~ s/.*:://; # split package 24 no strict 'refs'; 25 foreach my $n (@faked) 26 { 27 if ($n eq $name) 28 { 29 *{"bigrat::$name"} = sub 30 { 31 my $self = shift; 32 no strict 'refs'; 33 if (defined $_[0]) 34 { 35 Math::BigInt->$name($_[0]); 36 Math::BigFloat->$name($_[0]); 37 return Math::BigRat->$name($_[0]); 38 } 39 return Math::BigInt->$name(); 40 }; 41 return &$name; 42 } 43 } 44 45 # delayed load of Carp and avoid recursion 46 require Carp; 47 Carp::croak ("Can't call bigrat\-\>$name, not a valid method"); 48 } 49 50sub upgrade 51 { 52 my $self = shift; 53 no strict 'refs'; 54# if (defined $_[0]) 55# { 56# $Math::BigInt::upgrade = $_[0]; 57# $Math::BigFloat::upgrade = $_[0]; 58# } 59 return $Math::BigInt::upgrade; 60 } 61 62sub import 63 { 64 my $self = shift; 65 66 # see also bignum->import() for additional comments 67 68 # some defaults 69 my $lib = ''; my $upgrade = 'Math::BigFloat'; 70 71 my @import = ( ':constant' ); # drive it w/ constant 72 my @a = @_; my $l = scalar @_; my $j = 0; 73 my ($a,$p); 74 my ($ver,$trace); # version? trace? 75 for ( my $i = 0; $i < $l ; $i++,$j++ ) 76 { 77 if ($_[$i] eq 'upgrade') 78 { 79 # this causes upgrading 80 $upgrade = $_[$i+1]; # or undef to disable 81 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..." 82 splice @a, $j, $s; $j -= $s; 83 } 84 elsif ($_[$i] =~ /^(l|lib)$/) 85 { 86 # this causes a different low lib to take care... 87 $lib = $_[$i+1] || ''; 88 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..." 89 splice @a, $j, $s; $j -= $s; $i++; 90 } 91 elsif ($_[$i] =~ /^(a|accuracy)$/) 92 { 93 $a = $_[$i+1]; 94 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..." 95 splice @a, $j, $s; $j -= $s; $i++; 96 } 97 elsif ($_[$i] =~ /^(p|precision)$/) 98 { 99 $p = $_[$i+1]; 100 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..." 101 splice @a, $j, $s; $j -= $s; $i++; 102 } 103 elsif ($_[$i] =~ /^(v|version)$/) 104 { 105 $ver = 1; 106 splice @a, $j, 1; $j --; 107 } 108 elsif ($_[$i] =~ /^(t|trace)$/) 109 { 110 $trace = 1; 111 splice @a, $j, 1; $j --; 112 } 113 else 114 { 115 die ("unknown option $_[$i]"); 116 } 117 } 118 my $class; 119 $_lite = 0; # using M::BI::L ? 120 if ($trace) 121 { 122 require Math::BigInt::Trace; $class = 'Math::BigInt::Trace'; 123 $upgrade = 'Math::BigFloat::Trace'; 124 } 125 else 126 { 127 # see if we can find Math::BigInt::Lite 128 if (!defined $a && !defined $p) # rounding won't work to well 129 { 130 eval 'require Math::BigInt::Lite;'; 131 if ($@ eq '') 132 { 133 @import = ( ); # :constant in Lite, not MBI 134 Math::BigInt::Lite->import( ':constant' ); 135 $_lite= 1; # signal okay 136 } 137 } 138 require Math::BigInt if $_lite == 0; # not already loaded? 139 $class = 'Math::BigInt'; # regardless of MBIL or not 140 } 141 push @import, 'lib' => $lib if $lib ne ''; 142 # Math::BigInt::Trace or plain Math::BigInt 143 $class->import(@import, upgrade => $upgrade); 144 145 require Math::BigFloat; 146 Math::BigFloat->import( upgrade => 'Math::BigRat', ':constant' ); 147 require Math::BigRat; 148 149 bigrat->accuracy($a) if defined $a; 150 bigrat->precision($p) if defined $p; 151 if ($ver) 152 { 153 print "bigrat\t\t\t v$VERSION\n"; 154 print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite; 155 print "Math::BigInt\t\t v$Math::BigInt::VERSION"; 156 my $config = Math::BigInt->config(); 157 print " lib => $config->{lib} v$config->{lib_version}\n"; 158 print "Math::BigFloat\t\t v$Math::BigFloat::VERSION\n"; 159 print "Math::BigRat\t\t v$Math::BigRat::VERSION\n"; 160 exit; 161 } 162 $self->export_to_level(1,$self,@a); # export inf and NaN 163 } 164 165sub inf () { Math::BigInt->binf(); } 166sub NaN () { Math::BigInt->bnan(); } 167 1681; 169 170__END__ 171 172=head1 NAME 173 174bigrat - Transparent BigNumber/BigRational support for Perl 175 176=head1 SYNOPSIS 177 178 use bigrat; 179 180 $x = 2 + 4.5,"\n"; # BigFloat 6.5 181 print 1/3 + 1/4,"\n"; # produces 7/12 182 183=head1 DESCRIPTION 184 185All operators (inlcuding basic math operations) are overloaded. Integer and 186floating-point constants are created as proper BigInts or BigFloats, 187respectively. 188 189Other than L<bignum>, this module upgrades to Math::BigRat, meaning that 190instead of 2.5 you will get 2+1/2 as output. 191 192=head2 Modules Used 193 194C<bigrat> is just a thin wrapper around various modules of the Math::BigInt 195family. Think of it as the head of the family, who runs the shop, and orders 196the others to do the work. 197 198The following modules are currently used by bignum: 199 200 Math::BigInt::Lite (for speed, and only if it is loadable) 201 Math::BigInt 202 Math::BigFloat 203 Math::BigRat 204 205=head2 Math Library 206 207Math with the numbers is done (by default) by a module called 208Math::BigInt::Calc. This is equivalent to saying: 209 210 use bigrat lib => 'Calc'; 211 212You can change this by using: 213 214 use bigrat lib => 'BitVect'; 215 216The following would first try to find Math::BigInt::Foo, then 217Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc: 218 219 use bigrat lib => 'Foo,Math::BigInt::Bar'; 220 221Please see respective module documentation for further details. 222 223=head2 Sign 224 225The sign is either '+', '-', 'NaN', '+inf' or '-inf'. 226 227A sign of 'NaN' is used to represent the result when input arguments are not 228numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively 229minus infinity. You will get '+inf' when dividing a positive number by 0, and 230'-inf' when dividing any negative number by 0. 231 232=head2 Methods 233 234Since all numbers are not objects, you can use all functions that are part of 235the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not 236the fxxx() notation, though. This makes you independed on the fact that the 237underlying object might morph into a different class than BigFloat. 238 239=head2 Cavaet 240 241But a warning is in order. When using the following to make a copy of a number, 242only a shallow copy will be made. 243 244 $x = 9; $y = $x; 245 $x = $y = 7; 246 247If you want to make a real copy, use the following: 248 249 $y = $x->copy(); 250 251Using the copy or the original with overloaded math is okay, e.g. the 252following work: 253 254 $x = 9; $y = $x; 255 print $x + 1, " ", $y,"\n"; # prints 10 9 256 257but calling any method that modifies the number directly will result in 258B<both> the original and the copy beeing destroyed: 259 260 $x = 9; $y = $x; 261 print $x->badd(1), " ", $y,"\n"; # prints 10 10 262 263 $x = 9; $y = $x; 264 print $x->binc(1), " ", $y,"\n"; # prints 10 10 265 266 $x = 9; $y = $x; 267 print $x->bmul(2), " ", $y,"\n"; # prints 18 18 268 269Using methods that do not modify, but testthe contents works: 270 271 $x = 9; $y = $x; 272 $z = 9 if $x->is_zero(); # works fine 273 274See the documentation about the copy constructor and C<=> in overload, as 275well as the documentation in BigInt for further details. 276 277=head2 Options 278 279bignum recognizes some options that can be passed while loading it via use. 280The options can (currently) be either a single letter form, or the long form. 281The following options exist: 282 283=over 2 284 285=item a or accuracy 286 287This sets the accuracy for all math operations. The argument must be greater 288than or equal to zero. See Math::BigInt's bround() function for details. 289 290 perl -Mbigrat=a,50 -le 'print sqrt(20)' 291 292=item p or precision 293 294This sets the precision for all math operations. The argument can be any 295integer. Negative values mean a fixed number of digits after the dot, while 296a positive value rounds to this digit left from the dot. 0 or 1 mean round to 297integer. See Math::BigInt's bfround() function for details. 298 299 perl -Mbigrat=p,-50 -le 'print sqrt(20)' 300 301=item t or trace 302 303This enables a trace mode and is primarily for debugging bignum or 304Math::BigInt/Math::BigFloat. 305 306=item l or lib 307 308Load a different math lib, see L<MATH LIBRARY>. 309 310 perl -Mbigrat=l,GMP -e 'print 2 ** 512' 311 312Currently there is no way to specify more than one library on the command 313line. This will be hopefully fixed soon ;) 314 315=item v or version 316 317This prints out the name and version of all modules used and then exits. 318 319 perl -Mbigrat=v 320 321=head1 EXAMPLES 322 323 perl -Mbigrat -le 'print sqrt(33)' 324 perl -Mbigrat -le 'print 2*255' 325 perl -Mbigrat -le 'print 4.5+2*255' 326 perl -Mbigrat -le 'print 3/7 + 5/7 + 8/3' 327 perl -Mbigrat -le 'print 12->is_odd()'; 328 329=head1 LICENSE 330 331This program is free software; you may redistribute it and/or modify it under 332the same terms as Perl itself. 333 334=head1 SEE ALSO 335 336Especially L<bignum>. 337 338L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well 339as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and L<Math::BigInt::GMP>. 340 341=head1 AUTHORS 342 343(C) by Tels L<http://bloodgate.com/> in early 2002 - 2005. 344 345=cut 346