Re: Can't usemymalloc on OS X
[p5sagit/p5-mst-13.2.git] / lib / bigrat.pm
1 package bigrat;
2 require 5.005;
3
4 $VERSION = '0.06';
5 use Exporter;
6 @ISA            = qw( Exporter );
7 @EXPORT_OK      = qw( ); 
8 @EXPORT         = qw( inf NaN ); 
9
10 use strict;
11
12 ############################################################################## 
13
14 # These are all alike, and thus faked by AUTOLOAD
15
16 my @faked = qw/round_mode accuracy precision div_scale/;
17 use vars qw/$VERSION $AUTOLOAD $_lite/;         # _lite for testsuite
18
19 sub 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
50 sub 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
62 sub 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
149 sub inf () { Math::BigInt->binf(); }
150 sub NaN () { Math::BigInt->bnan(); }
151
152 1;
153
154 __END__
155
156 =head1 NAME
157
158 bigrat - Transparent BigNumber/BigRationale 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
169 All operators (inlcuding basic math operations) are overloaded. Integer and
170 floating-point constants are created as proper BigInts or BigFloats,
171 respectively.
172
173 Other than L<bignum>, this module upgrades to Math::BigRat, meaning that
174 instead of 2.5 you will get 2+1/2 as output.
175
176 =head2 MODULES USED
177
178 C<bigrat> is just a thin wrapper around various modules of the Math::BigInt
179 family. Think of it as the head of the family, who runs the shop, and orders
180 the others to do the work.
181
182 The 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
191 Math with the numbers is done (by default) by a module called
192 Math::BigInt::Calc. This is equivalent to saying:
193
194         use bigrat lib => 'Calc';
195
196 You can change this by using:
197
198         use bigrat lib => 'BitVect';
199
200 The following would first try to find Math::BigInt::Foo, then
201 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
202
203         use bigrat lib => 'Foo,Math::BigInt::Bar';
204
205 Please see respective module documentation for further details.
206
207 =head2 SIGN
208
209 The sign is either '+', '-', 'NaN', '+inf' or '-inf' and stored seperately.
210
211 A sign of 'NaN' is used to represent the result when input arguments are not
212 numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
213 minus 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
218 Since all numbers are not objects, you can use all functions that are part of
219 the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not
220 the fxxx() notation, though. This makes you independed on the fact that the
221 underlying object might morph into a different class than BigFloat.
222
223 =head2 CAVEAT
224
225 But a warning is in order. When using the following to make a copy of a number,
226 only a shallow copy will be made.
227
228         $x = 9; $y = $x;
229         $x = $y = 7;
230
231 Using the copy or the original with overloaded math is okay, e.g. the
232 following work:
233
234         $x = 9; $y = $x;
235         print $x + 1, " ", $y,"\n";     # prints 10 9
236
237 but calling any method that modifies the number directly will result in
238 B<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
249 Using 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
254 See the documentation about the copy constructor and C<=> in overload, as
255 well 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
267 This program is free software; you may redistribute it and/or modify it under
268 the same terms as Perl itself.
269
270 =head1 SEE ALSO
271
272 Especially L<bignum>.
273
274 L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
275 as 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