1package bigrat; 2require 5.005; 3 4$VERSION = '0.06'; 5use 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 = 'Calc'; 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; 90 } 91 elsif ($_[$i] =~ /^(v|version)$/) 92 { 93 $ver = 1; 94 splice @a, $j, 1; $j --; 95 } 96 elsif ($_[$i] =~ /^(t|trace)$/) 97 { 98 $trace = 1; 99 splice @a, $j, 1; $j --; 100 } 101 else 102 { 103 die ("unknown option $_[$i]"); 104 } 105 } 106 my $class; 107 $_lite = 0; # using M::BI::L ? 108 if ($trace) 109 { 110 require Math::BigInt::Trace; $class = 'Math::BigInt::Trace'; 111 $upgrade = 'Math::BigFloat::Trace'; 112 } 113 else 114 { 115 # see if we can find Math::BigInt::Lite 116 if (!defined $a && !defined $p) # rounding won't work to well 117 { 118 eval 'require Math::BigInt::Lite;'; 119 if ($@ eq '') 120 { 121 @import = ( ); # :constant in Lite, not MBI 122 Math::BigInt::Lite->import( ':constant' ); 123 $_lite= 1; # signal okay 124 } 125 } 126 require Math::BigInt if $_lite == 0; # not already loaded? 127 $class = 'Math::BigInt'; # regardless of MBIL or not 128 } 129 # Math::BigInt::Trace or plain Math::BigInt 130 $class->import(@import, upgrade => $upgrade, lib => $lib); 131 132 require Math::BigFloat; 133 Math::BigFloat->import( upgrade => 'Math::BigRat', ':constant' ); 134 require Math::BigRat; 135 if ($ver) 136 { 137 print "bigrat\t\t\t v$VERSION\n"; 138 print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite; 139 print "Math::BigInt\t\t v$Math::BigInt::VERSION"; 140 my $config = Math::BigInt->config(); 141 print " lib => $config->{lib} v$config->{lib_version}\n"; 142 print "Math::BigFloat\t\t v$Math::BigFloat::VERSION\n"; 143 print "Math::BigRat\t\t v$Math::BigRat::VERSION\n"; 144 exit; 145 } 146 $self->export_to_level(1,$self,@a); # export inf and NaN 147 } 148 149sub inf () { Math::BigInt->binf(); } 150sub NaN () { Math::BigInt->bnan(); } 151 1521; 153 154__END__ 155 156=head1 NAME 157 158bigrat - Transparent BigNumber/BigRational support for Perl 159 160=head1 SYNOPSIS 161 162 use bigrat; 163 164 $x = 2 + 4.5,"\n"; # BigFloat 6.5 165 print 1/3 + 1/4,"\n"; # produces 7/12 166 167=head1 DESCRIPTION 168 169All operators (inlcuding basic math operations) are overloaded. Integer and 170floating-point constants are created as proper BigInts or BigFloats, 171respectively. 172 173Other than L<bignum>, this module upgrades to Math::BigRat, meaning that 174instead of 2.5 you will get 2+1/2 as output. 175 176=head2 MODULES USED 177 178C<bigrat> is just a thin wrapper around various modules of the Math::BigInt 179family. Think of it as the head of the family, who runs the shop, and orders 180the others to do the work. 181 182The following modules are currently used by bignum: 183 184 Math::BigInt::Lite (for speed, and only if it is loadable) 185 Math::BigInt 186 Math::BigFloat 187 Math::BigRat 188 189=head2 MATH LIBRARY 190 191Math with the numbers is done (by default) by a module called 192Math::BigInt::Calc. This is equivalent to saying: 193 194 use bigrat lib => 'Calc'; 195 196You can change this by using: 197 198 use bigrat lib => 'BitVect'; 199 200The following would first try to find Math::BigInt::Foo, then 201Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc: 202 203 use bigrat lib => 'Foo,Math::BigInt::Bar'; 204 205Please see respective module documentation for further details. 206 207=head2 SIGN 208 209The sign is either '+', '-', 'NaN', '+inf' or '-inf' and stored seperately. 210 211A sign of 'NaN' is used to represent the result when input arguments are not 212numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively 213minus infinity. You will get '+inf' when dividing a positive number by 0, and 214'-inf' when dividing any negative number by 0. 215 216=head2 METHODS 217 218Since all numbers are not objects, you can use all functions that are part of 219the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not 220the fxxx() notation, though. This makes you independed on the fact that the 221underlying object might morph into a different class than BigFloat. 222 223=head2 CAVEAT 224 225But a warning is in order. When using the following to make a copy of a number, 226only a shallow copy will be made. 227 228 $x = 9; $y = $x; 229 $x = $y = 7; 230 231Using the copy or the original with overloaded math is okay, e.g. the 232following work: 233 234 $x = 9; $y = $x; 235 print $x + 1, " ", $y,"\n"; # prints 10 9 236 237but calling any method that modifies the number directly will result in 238B<both> the original and the copy beeing destroyed: 239 240 $x = 9; $y = $x; 241 print $x->badd(1), " ", $y,"\n"; # prints 10 10 242 243 $x = 9; $y = $x; 244 print $x->binc(1), " ", $y,"\n"; # prints 10 10 245 246 $x = 9; $y = $x; 247 print $x->bmul(2), " ", $y,"\n"; # prints 18 18 248 249Using methods that do not modify, but testthe contents works: 250 251 $x = 9; $y = $x; 252 $z = 9 if $x->is_zero(); # works fine 253 254See the documentation about the copy constructor and C<=> in overload, as 255well as the documentation in BigInt for further details. 256 257=head1 EXAMPLES 258 259 perl -Mbigrat -le 'print sqrt(33)' 260 perl -Mbigrat -le 'print 2*255' 261 perl -Mbigrat -le 'print 4.5+2*255' 262 perl -Mbigrat -le 'print 3/7 + 5/7 + 8/3' 263 perl -Mbigrat -le 'print 12->is_odd()'; 264 265=head1 LICENSE 266 267This program is free software; you may redistribute it and/or modify it under 268the same terms as Perl itself. 269 270=head1 SEE ALSO 271 272Especially L<bignum>. 273 274L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well 275as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and L<Math::BigInt::GMP>. 276 277=head1 AUTHORS 278 279(C) by Tels L<http://bloodgate.com/> in early 2002. 280 281=cut 282