Fix a2p manpage (from Debian)
[p5sagit/p5-mst-13.2.git] / lib / bigrat.pm
1 package bigrat;
2 require 5.005;
3
4 $VERSION = '0.07';
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 = '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; $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   # Math::BigInt::Trace or plain Math::BigInt
142   $class->import(@import, upgrade => $upgrade, lib => $lib);
143
144   require Math::BigFloat;
145   Math::BigFloat->import( upgrade => 'Math::BigRat', ':constant' );
146   require Math::BigRat;
147
148   bigrat->accuracy($a) if defined $a;
149   bigrat->precision($p) if defined $p;
150   if ($ver)
151     {
152     print "bigrat\t\t\t v$VERSION\n";
153     print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite;  
154     print "Math::BigInt\t\t v$Math::BigInt::VERSION";
155     my $config = Math::BigInt->config();
156     print " lib => $config->{lib} v$config->{lib_version}\n";
157     print "Math::BigFloat\t\t v$Math::BigFloat::VERSION\n";
158     print "Math::BigRat\t\t v$Math::BigRat::VERSION\n";
159     exit;
160     }
161   $self->export_to_level(1,$self,@a);           # export inf and NaN
162   }
163
164 sub inf () { Math::BigInt->binf(); }
165 sub NaN () { Math::BigInt->bnan(); }
166
167 1;
168
169 __END__
170
171 =head1 NAME
172
173 bigrat - Transparent BigNumber/BigRational support for Perl
174
175 =head1 SYNOPSIS
176
177   use bigrat;
178
179   $x = 2 + 4.5,"\n";                    # BigFloat 6.5
180   print 1/3 + 1/4,"\n";                 # produces 7/12
181
182 =head1 DESCRIPTION
183
184 All operators (inlcuding basic math operations) are overloaded. Integer and
185 floating-point constants are created as proper BigInts or BigFloats,
186 respectively.
187
188 Other than L<bignum>, this module upgrades to Math::BigRat, meaning that
189 instead of 2.5 you will get 2+1/2 as output.
190
191 =head2 Modules Used
192
193 C<bigrat> is just a thin wrapper around various modules of the Math::BigInt
194 family. Think of it as the head of the family, who runs the shop, and orders
195 the others to do the work.
196
197 The following modules are currently used by bignum:
198
199         Math::BigInt::Lite      (for speed, and only if it is loadable)
200         Math::BigInt
201         Math::BigFloat
202         Math::BigRat
203
204 =head2 Math Library
205
206 Math with the numbers is done (by default) by a module called
207 Math::BigInt::Calc. This is equivalent to saying:
208
209         use bigrat lib => 'Calc';
210
211 You can change this by using:
212
213         use bigrat lib => 'BitVect';
214
215 The following would first try to find Math::BigInt::Foo, then
216 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
217
218         use bigrat lib => 'Foo,Math::BigInt::Bar';
219
220 Please see respective module documentation for further details.
221
222 =head2 Sign
223
224 The sign is either '+', '-', 'NaN', '+inf' or '-inf'.
225
226 A sign of 'NaN' is used to represent the result when input arguments are not
227 numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
228 minus infinity. You will get '+inf' when dividing a positive number by 0, and
229 '-inf' when dividing any negative number by 0.
230
231 =head2 Methods
232
233 Since all numbers are not objects, you can use all functions that are part of
234 the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not
235 the fxxx() notation, though. This makes you independed on the fact that the
236 underlying object might morph into a different class than BigFloat.
237
238 =head2 Cavaet
239
240 But a warning is in order. When using the following to make a copy of a number,
241 only a shallow copy will be made.
242
243         $x = 9; $y = $x;
244         $x = $y = 7;
245
246 If you want to make a real copy, use the following:
247
248         $y = $x->copy();
249
250 Using the copy or the original with overloaded math is okay, e.g. the
251 following work:
252
253         $x = 9; $y = $x;
254         print $x + 1, " ", $y,"\n";     # prints 10 9
255
256 but calling any method that modifies the number directly will result in
257 B<both> the original and the copy beeing destroyed:
258
259         $x = 9; $y = $x;
260         print $x->badd(1), " ", $y,"\n";        # prints 10 10
261
262         $x = 9; $y = $x;
263         print $x->binc(1), " ", $y,"\n";        # prints 10 10
264
265         $x = 9; $y = $x;
266         print $x->bmul(2), " ", $y,"\n";        # prints 18 18
267
268 Using methods that do not modify, but testthe contents works:
269
270         $x = 9; $y = $x;
271         $z = 9 if $x->is_zero();                # works fine
272
273 See the documentation about the copy constructor and C<=> in overload, as
274 well as the documentation in BigInt for further details.
275
276 =head2 Options
277
278 bignum recognizes some options that can be passed while loading it via use.
279 The options can (currently) be either a single letter form, or the long form.
280 The following options exist:
281
282 =over 2
283
284 =item a or accuracy
285
286 This sets the accuracy for all math operations. The argument must be greater
287 than or equal to zero. See Math::BigInt's bround() function for details.
288
289         perl -Mbigrat=a,50 -le 'print sqrt(20)'
290
291 =item p or precision
292
293 This sets the precision for all math operations. The argument can be any
294 integer. Negative values mean a fixed number of digits after the dot, while
295 a positive value rounds to this digit left from the dot. 0 or 1 mean round to
296 integer. See Math::BigInt's bfround() function for details.
297
298         perl -Mbigrat=p,-50 -le 'print sqrt(20)'
299
300 =item t or trace
301
302 This enables a trace mode and is primarily for debugging bignum or
303 Math::BigInt/Math::BigFloat.
304
305 =item l or lib
306
307 Load a different math lib, see L<MATH LIBRARY>.
308
309         perl -Mbigrat=l,GMP -e 'print 2 ** 512'
310
311 Currently there is no way to specify more than one library on the command
312 line. This will be hopefully fixed soon ;)
313
314 =item v or version
315
316 This prints out the name and version of all modules used and then exits.
317
318         perl -Mbigrat=v
319
320 =head1 EXAMPLES
321  
322         perl -Mbigrat -le 'print sqrt(33)'
323         perl -Mbigrat -le 'print 2*255'
324         perl -Mbigrat -le 'print 4.5+2*255'
325         perl -Mbigrat -le 'print 3/7 + 5/7 + 8/3'       
326         perl -Mbigrat -le 'print 12->is_odd()';
327
328 =head1 LICENSE
329
330 This program is free software; you may redistribute it and/or modify it under
331 the same terms as Perl itself.
332
333 =head1 SEE ALSO
334
335 Especially L<bignum>.
336
337 L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
338 as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and  L<Math::BigInt::GMP>.
339
340 =head1 AUTHORS
341
342 (C) by Tels L<http://bloodgate.com/> in early 2002 - 2005.
343
344 =cut