884e9dab315a4c528c4953873c62f2c333571d5a
[p5sagit/p5-mst-13.2.git] / lib / bigrat.pm
1 package bigrat;
2 use 5.006002;
3
4 $VERSION = '0.22';
5 require Exporter;
6 @ISA            = qw( bigint );
7 @EXPORT_OK      = qw( ); 
8 @EXPORT         = qw( inf NaN ); 
9
10 use strict;
11 use overload;
12 require bigint;         # no "use" to avoid callind import
13
14 ############################################################################## 
15
16 BEGIN 
17   {
18   *inf = \&bigint::inf;
19   *NaN = \&bigint::NaN;
20   }
21
22 # These are all alike, and thus faked by AUTOLOAD
23
24 my @faked = qw/round_mode accuracy precision div_scale/;
25 use vars qw/$VERSION $AUTOLOAD $_lite/;         # _lite for testsuite
26
27 sub AUTOLOAD
28   {
29   my $name = $AUTOLOAD;
30
31   $name =~ s/.*:://;    # split package
32   no strict 'refs';
33   foreach my $n (@faked)
34     {
35     if ($n eq $name)
36       {
37       *{"bigrat::$name"} = sub 
38         {
39         my $self = shift;
40         no strict 'refs';
41         if (defined $_[0])
42           {
43           Math::BigInt->$name($_[0]);
44           Math::BigFloat->$name($_[0]);
45           return Math::BigRat->$name($_[0]);
46           }
47         return Math::BigInt->$name();
48         };
49       return &$name;
50       }
51     }
52  
53   # delayed load of Carp and avoid recursion
54   require Carp;
55   Carp::croak ("Can't call bigrat\-\>$name, not a valid method");
56   }
57
58 sub unimport
59   {
60   $^H{bigrat} = undef;                                  # no longer in effect
61   overload::remove_constant('binary','','float','','integer');
62   }
63
64 sub in_effect
65   {
66   my $level = shift || 0;
67   my $hinthash = (caller($level))[10];
68   $hinthash->{bigrat};
69   }
70
71 #############################################################################
72 # the following two routines are for Perl 5.9.4 or later and are lexical
73
74 sub _hex
75   {
76   return CORE::hex($_[0]) unless in_effect(1);
77   my $i = $_[0];
78   $i = '0x'.$i unless $i =~ /^0x/;
79   Math::BigInt->new($i);
80   }
81
82 sub _oct
83   {
84   return CORE::oct($_[0]) unless in_effect(1);
85   my $i = $_[0];
86   return Math::BigInt->from_oct($i) if $i =~ /^0[0-7]/;
87   Math::BigInt->new($i);
88   }
89
90 sub import 
91   {
92   my $self = shift;
93
94   # see also bignum->import() for additional comments
95
96   $^H{bigrat} = 1;                                      # we are in effect
97
98   # for newer Perls always override hex() and oct() with a lexical version:
99   if ($] > 5.009004)
100     {
101     no warnings 'redefine';
102     *CORE::GLOBAL::oct = \&_oct;
103     *CORE::GLOBAL::hex = \&_hex;
104     }
105   # some defaults
106   my $lib = ''; my $lib_kind = 'try'; my $upgrade = 'Math::BigFloat';
107
108   my @import = ( ':constant' );                         # drive it w/ constant
109   my @a = @_; my $l = scalar @_; my $j = 0;
110   my ($a,$p);
111   my ($ver,$trace);                                     # version? trace?
112   for ( my $i = 0; $i < $l ; $i++,$j++ )
113     {
114     if ($_[$i] eq 'upgrade')
115       {
116       # this causes upgrading
117       $upgrade = $_[$i+1];              # or undef to disable
118       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
119       splice @a, $j, $s; $j -= $s;
120       }
121     elsif ($_[$i] =~ /^(l|lib|try|only)$/)
122       {
123       # this causes a different low lib to take care...
124       $lib_kind = $1; $lib_kind = 'lib' if $lib_kind eq 'l';
125       $lib = $_[$i+1] || '';
126       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
127       splice @a, $j, $s; $j -= $s; $i++;
128       }
129     elsif ($_[$i] =~ /^(a|accuracy)$/)
130       {
131       $a = $_[$i+1];
132       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
133       splice @a, $j, $s; $j -= $s; $i++;
134       }
135     elsif ($_[$i] =~ /^(p|precision)$/)
136       {
137       $p = $_[$i+1];
138       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
139       splice @a, $j, $s; $j -= $s; $i++;
140       }
141     elsif ($_[$i] =~ /^(v|version)$/)
142       {
143       $ver = 1;
144       splice @a, $j, 1; $j --;
145       }
146     elsif ($_[$i] =~ /^(t|trace)$/)
147       {
148       $trace = 1;
149       splice @a, $j, 1; $j --;
150       }
151     elsif ($_[$i] eq 'hex')
152       {
153       splice @a, $j, 1; $j --;
154       no warnings 'redefine';
155       *CORE::GLOBAL::hex = \&bigint::_hex_global;
156       }
157     elsif ($_[$i] eq 'oct')
158       {
159       splice @a, $j, 1; $j --;
160       no warnings 'redefine';
161       *CORE::GLOBAL::oct = \&bigint::_oct_global;
162       }
163     else
164       {
165       die ("unknown option $_[$i]");
166       }
167     }
168   my $class;
169   $_lite = 0;                                   # using M::BI::L ?
170   if ($trace)
171     {
172     require Math::BigInt::Trace; $class = 'Math::BigInt::Trace';
173     $upgrade = 'Math::BigFloat::Trace';
174     }
175   else
176     {
177     # see if we can find Math::BigInt::Lite
178     if (!defined $a && !defined $p)             # rounding won't work to well
179       {
180       eval 'require Math::BigInt::Lite;';
181       if ($@ eq '')
182         {
183         @import = ( );                          # :constant in Lite, not MBI
184         Math::BigInt::Lite->import( ':constant' );
185         $_lite= 1;                              # signal okay
186         }
187       }
188     require Math::BigInt if $_lite == 0;        # not already loaded?
189     $class = 'Math::BigInt';                    # regardless of MBIL or not
190     }
191   push @import, $lib_kind => $lib if $lib ne ''; 
192   # Math::BigInt::Trace or plain Math::BigInt
193   $class->import(@import, upgrade => $upgrade);
194
195   require Math::BigFloat;
196   Math::BigFloat->import( upgrade => 'Math::BigRat', ':constant' );
197   require Math::BigRat;
198
199   bigrat->accuracy($a) if defined $a;
200   bigrat->precision($p) if defined $p;
201   if ($ver)
202     {
203     print "bigrat\t\t\t v$VERSION\n";
204     print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite;  
205     print "Math::BigInt\t\t v$Math::BigInt::VERSION";
206     my $config = Math::BigInt->config();
207     print " lib => $config->{lib} v$config->{lib_version}\n";
208     print "Math::BigFloat\t\t v$Math::BigFloat::VERSION\n";
209     print "Math::BigRat\t\t v$Math::BigRat::VERSION\n";
210     exit;
211     }
212
213   # Take care of octal/hexadecimal constants
214   overload::constant binary => sub { bigint::_binary_constant(shift) };
215
216   # if another big* was already loaded:
217   my ($package) = caller();
218
219   no strict 'refs';
220   if (!defined *{"${package}::inf"})
221     {
222     $self->export_to_level(1,$self,@a);           # export inf and NaN
223     }
224   }
225
226 1;
227
228 __END__
229
230 =head1 NAME
231
232 bigrat - Transparent BigNumber/BigRational support for Perl
233
234 =head1 SYNOPSIS
235
236   use bigrat;
237
238   print 2 + 4.5,"\n";                   # BigFloat 6.5
239   print 1/3 + 1/4,"\n";                 # produces 7/12
240
241   {
242     no bigrat;
243     print 1/3,"\n";                     # 0.33333...
244   }
245
246   # Note that this will make hex() and oct() be globally overriden:
247   use bigrat qw/hex oct/;
248   print hex("0x1234567890123490"),"\n";
249   print oct("01234567890123490"),"\n";
250
251 =head1 DESCRIPTION
252
253 All operators (including basic math operations) are overloaded. Integer and
254 floating-point constants are created as proper BigInts or BigFloats,
255 respectively.
256
257 Other than L<bignum>, this module upgrades to Math::BigRat, meaning that
258 instead of 2.5 you will get 2+1/2 as output.
259
260 =head2 Modules Used
261
262 C<bigrat> is just a thin wrapper around various modules of the Math::BigInt
263 family. Think of it as the head of the family, who runs the shop, and orders
264 the others to do the work.
265
266 The following modules are currently used by bignum:
267
268         Math::BigInt::Lite      (for speed, and only if it is loadable)
269         Math::BigInt
270         Math::BigFloat
271         Math::BigRat
272
273 =head2 Math Library
274
275 Math with the numbers is done (by default) by a module called
276 Math::BigInt::Calc. This is equivalent to saying:
277
278         use bigrat lib => 'Calc';
279
280 You can change this by using:
281
282         use bignum lib => 'GMP';
283
284 The following would first try to find Math::BigInt::Foo, then
285 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
286
287         use bigrat lib => 'Foo,Math::BigInt::Bar';
288
289 Using C<lib> warns if none of the specified libraries can be found and
290 L<Math::BigInt> did fall back to one of the default libraries.
291 To supress this warning, use C<try> instead:
292
293         use bignum try => 'GMP';
294
295 If you want the code to die instead of falling back, use C<only> instead:
296
297         use bignum only => 'GMP';
298
299 Please see respective module documentation for further details.
300
301 =head2 Sign
302
303 The sign is either '+', '-', 'NaN', '+inf' or '-inf'.
304
305 A sign of 'NaN' is used to represent the result when input arguments are not
306 numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
307 minus infinity. You will get '+inf' when dividing a positive number by 0, and
308 '-inf' when dividing any negative number by 0.
309
310 =head2 Methods
311
312 Since all numbers are not objects, you can use all functions that are part of
313 the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not
314 the fxxx() notation, though. This makes you independed on the fact that the
315 underlying object might morph into a different class than BigFloat.
316
317 =over 2
318
319 =item inf()
320
321 A shortcut to return Math::BigInt->binf(). Useful because Perl does not always
322 handle bareword C<inf> properly.
323
324 =item NaN()
325
326 A shortcut to return Math::BigInt->bnan(). Useful because Perl does not always
327 handle bareword C<NaN> properly.
328
329 =item upgrade()
330
331 Return the class that numbers are upgraded to, is in fact returning
332 C<$Math::BigInt::upgrade>.
333
334 =item in_effect()
335
336         use bigrat;
337
338         print "in effect\n" if bigrat::in_effect;       # true
339         {
340           no bigrat;
341           print "in effect\n" if bigrat::in_effect;     # false
342         }
343
344 Returns true or false if C<bigrat> is in effect in the current scope.
345
346 This method only works on Perl v5.9.4 or later.
347
348 =back
349
350 =head2 MATH LIBRARY
351
352 Math with the numbers is done (by default) by a module called
353
354 =head2 Cavaet
355
356 But a warning is in order. When using the following to make a copy of a number,
357 only a shallow copy will be made.
358
359         $x = 9; $y = $x;
360         $x = $y = 7;
361
362 If you want to make a real copy, use the following:
363
364         $y = $x->copy();
365
366 Using the copy or the original with overloaded math is okay, e.g. the
367 following work:
368
369         $x = 9; $y = $x;
370         print $x + 1, " ", $y,"\n";     # prints 10 9
371
372 but calling any method that modifies the number directly will result in
373 B<both> the original and the copy being destroyed:
374
375         $x = 9; $y = $x;
376         print $x->badd(1), " ", $y,"\n";        # prints 10 10
377
378         $x = 9; $y = $x;
379         print $x->binc(1), " ", $y,"\n";        # prints 10 10
380
381         $x = 9; $y = $x;
382         print $x->bmul(2), " ", $y,"\n";        # prints 18 18
383
384 Using methods that do not modify, but testthe contents works:
385
386         $x = 9; $y = $x;
387         $z = 9 if $x->is_zero();                # works fine
388
389 See the documentation about the copy constructor and C<=> in overload, as
390 well as the documentation in BigInt for further details.
391
392 =head2 Options
393
394 bignum recognizes some options that can be passed while loading it via use.
395 The options can (currently) be either a single letter form, or the long form.
396 The following options exist:
397
398 =over 2
399
400 =item a or accuracy
401
402 This sets the accuracy for all math operations. The argument must be greater
403 than or equal to zero. See Math::BigInt's bround() function for details.
404
405         perl -Mbigrat=a,50 -le 'print sqrt(20)'
406
407 Note that setting precision and accurary at the same time is not possible.
408
409 =item p or precision
410
411 This sets the precision for all math operations. The argument can be any
412 integer. Negative values mean a fixed number of digits after the dot, while
413 a positive value rounds to this digit left from the dot. 0 or 1 mean round to
414 integer. See Math::BigInt's bfround() function for details.
415
416         perl -Mbigrat=p,-50 -le 'print sqrt(20)'
417
418 Note that setting precision and accurary at the same time is not possible.
419
420 =item t or trace
421
422 This enables a trace mode and is primarily for debugging bignum or
423 Math::BigInt/Math::BigFloat.
424
425 =item l or lib
426
427 Load a different math lib, see L<MATH LIBRARY>.
428
429         perl -Mbigrat=l,GMP -e 'print 2 ** 512'
430
431 Currently there is no way to specify more than one library on the command
432 line. This means the following does not work:
433
434         perl -Mbignum=l,GMP,Pari -e 'print 2 ** 512'
435
436 This will be hopefully fixed soon ;)
437
438 =item hex
439
440 Override the build-in hex() method with a version that can handle big
441 integers. Note that under Perl v5.9.4 or ealier, this will be global
442 and cannot be disabled with "no bigint;".
443
444 =item oct
445
446 Override the build-in oct() method with a version that can handle big
447 integers. Note that under Perl v5.9.4 or ealier, this will be global
448 and cannot be disabled with "no bigint;".
449
450 =item v or version
451
452 This prints out the name and version of all modules used and then exits.
453
454         perl -Mbigrat=v
455
456 =back
457
458 =head1 CAVAETS
459
460 =over 2
461
462 =item in_effect()
463
464 This method only works on Perl v5.9.4 or later.
465
466 =item hex()/oct()
467
468 C<bigint> overrides these routines with versions that can also handle
469 big integer values. Under Perl prior to version v5.9.4, however, this
470 will not happen unless you specifically ask for it with the two
471 import tags "hex" and "oct" - and then it will be global and cannot be
472 disabled inside a scope with "no bigint":
473
474         use bigint qw/hex oct/;
475
476         print hex("0x1234567890123456");
477         {
478                 no bigint;
479                 print hex("0x1234567890123456");
480         }
481
482 The second call to hex() will warn about a non-portable constant.
483
484 Compare this to:
485
486         use bigint;
487
488         # will warn only under Perl older than v5.9.4
489         print hex("0x1234567890123456");
490
491 =back
492
493 =head1 EXAMPLES
494  
495         perl -Mbigrat -le 'print sqrt(33)'
496         perl -Mbigrat -le 'print 2*255'
497         perl -Mbigrat -le 'print 4.5+2*255'
498         perl -Mbigrat -le 'print 3/7 + 5/7 + 8/3'       
499         perl -Mbigrat -le 'print 12->is_odd()';
500         perl -Mbignum=l,GMP -le 'print 7 ** 7777'
501
502 =head1 LICENSE
503
504 This program is free software; you may redistribute it and/or modify it under
505 the same terms as Perl itself.
506
507 =head1 SEE ALSO
508
509 Especially L<bignum>.
510
511 L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
512 as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and  L<Math::BigInt::GMP>.
513
514 =head1 AUTHORS
515
516 (C) by Tels L<http://bloodgate.com/> in early 2002 - 2007.
517
518 =cut