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