extra code in pp_concat, Take 2
[p5sagit/p5-mst-13.2.git] / lib / bigrat.pm
1 package bigrat;
2 require 5.005;
3
4 $VERSION = '0.08';
5 require 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 = ''; 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
165 sub inf () { Math::BigInt->binf(); }
166 sub NaN () { Math::BigInt->bnan(); }
167
168 1;
169
170 __END__
171
172 =head1 NAME
173
174 bigrat - 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
185 All operators (inlcuding basic math operations) are overloaded. Integer and
186 floating-point constants are created as proper BigInts or BigFloats,
187 respectively.
188
189 Other than L<bignum>, this module upgrades to Math::BigRat, meaning that
190 instead of 2.5 you will get 2+1/2 as output.
191
192 =head2 Modules Used
193
194 C<bigrat> is just a thin wrapper around various modules of the Math::BigInt
195 family. Think of it as the head of the family, who runs the shop, and orders
196 the others to do the work.
197
198 The 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
207 Math with the numbers is done (by default) by a module called
208 Math::BigInt::Calc. This is equivalent to saying:
209
210         use bigrat lib => 'Calc';
211
212 You can change this by using:
213
214         use bigrat lib => 'BitVect';
215
216 The following would first try to find Math::BigInt::Foo, then
217 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
218
219         use bigrat lib => 'Foo,Math::BigInt::Bar';
220
221 Please see respective module documentation for further details.
222
223 =head2 Sign
224
225 The sign is either '+', '-', 'NaN', '+inf' or '-inf'.
226
227 A sign of 'NaN' is used to represent the result when input arguments are not
228 numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
229 minus 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
234 Since all numbers are not objects, you can use all functions that are part of
235 the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not
236 the fxxx() notation, though. This makes you independed on the fact that the
237 underlying object might morph into a different class than BigFloat.
238
239 =head2 Cavaet
240
241 But a warning is in order. When using the following to make a copy of a number,
242 only a shallow copy will be made.
243
244         $x = 9; $y = $x;
245         $x = $y = 7;
246
247 If you want to make a real copy, use the following:
248
249         $y = $x->copy();
250
251 Using the copy or the original with overloaded math is okay, e.g. the
252 following work:
253
254         $x = 9; $y = $x;
255         print $x + 1, " ", $y,"\n";     # prints 10 9
256
257 but calling any method that modifies the number directly will result in
258 B<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
269 Using 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
274 See the documentation about the copy constructor and C<=> in overload, as
275 well as the documentation in BigInt for further details.
276
277 =head2 Options
278
279 bignum recognizes some options that can be passed while loading it via use.
280 The options can (currently) be either a single letter form, or the long form.
281 The following options exist:
282
283 =over 2
284
285 =item a or accuracy
286
287 This sets the accuracy for all math operations. The argument must be greater
288 than 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
294 This sets the precision for all math operations. The argument can be any
295 integer. Negative values mean a fixed number of digits after the dot, while
296 a positive value rounds to this digit left from the dot. 0 or 1 mean round to
297 integer. 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
303 This enables a trace mode and is primarily for debugging bignum or
304 Math::BigInt/Math::BigFloat.
305
306 =item l or lib
307
308 Load a different math lib, see L<MATH LIBRARY>.
309
310         perl -Mbigrat=l,GMP -e 'print 2 ** 512'
311
312 Currently there is no way to specify more than one library on the command
313 line. This will be hopefully fixed soon ;)
314
315 =item v or version
316
317 This 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
331 This program is free software; you may redistribute it and/or modify it under
332 the same terms as Perl itself.
333
334 =head1 SEE ALSO
335
336 Especially L<bignum>.
337
338 L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
339 as 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