Some escapes were mentioned twice, although they're not qr//-specific
[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( PI e bpi bexp );
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     elsif ($_[$i] !~ /^(PI|e|bpi|bexp)\z/)
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 sub PI () { Math::BigFloat->new('3.141592653589793238462643383279502884197'); }
230 sub e () { Math::BigFloat->new('2.718281828459045235360287471352662497757'); }
231
232 sub bpi ($) { local $Math::BigFloat::upgrade; Math::BigFloat::bpi(@_); }
233
234 sub bexp ($$)
235   {
236   local $Math::BigFloat::upgrade;
237   my $x = Math::BigFloat->new($_[0]); $x->bexp($_[1]);
238   }
239
240 1;
241
242 __END__
243
244 =head1 NAME
245
246 bigrat - Transparent BigNumber/BigRational support for Perl
247
248 =head1 SYNOPSIS
249
250   use bigrat;
251
252   print 2 + 4.5,"\n";                   # BigFloat 6.5
253   print 1/3 + 1/4,"\n";                 # produces 7/12
254
255   {
256     no bigrat;
257     print 1/3,"\n";                     # 0.33333...
258   }
259
260   # Note that this will make hex() and oct() be globally overriden:
261   use bigrat qw/hex oct/;
262   print hex("0x1234567890123490"),"\n";
263   print oct("01234567890123490"),"\n";
264
265 =head1 DESCRIPTION
266
267 All operators (including basic math operations) are overloaded. Integer and
268 floating-point constants are created as proper BigInts or BigFloats,
269 respectively.
270
271 Other than L<bignum>, this module upgrades to Math::BigRat, meaning that
272 instead of 2.5 you will get 2+1/2 as output.
273
274 =head2 Modules Used
275
276 C<bigrat> is just a thin wrapper around various modules of the Math::BigInt
277 family. Think of it as the head of the family, who runs the shop, and orders
278 the others to do the work.
279
280 The following modules are currently used by bignum:
281
282         Math::BigInt::Lite      (for speed, and only if it is loadable)
283         Math::BigInt
284         Math::BigFloat
285         Math::BigRat
286
287 =head2 Math Library
288
289 Math with the numbers is done (by default) by a module called
290 Math::BigInt::Calc. This is equivalent to saying:
291
292         use bigrat lib => 'Calc';
293
294 You can change this by using:
295
296         use bignum lib => 'GMP';
297
298 The following would first try to find Math::BigInt::Foo, then
299 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
300
301         use bigrat lib => 'Foo,Math::BigInt::Bar';
302
303 Using C<lib> warns if none of the specified libraries can be found and
304 L<Math::BigInt> did fall back to one of the default libraries.
305 To supress this warning, use C<try> instead:
306
307         use bignum try => 'GMP';
308
309 If you want the code to die instead of falling back, use C<only> instead:
310
311         use bignum only => 'GMP';
312
313 Please see respective module documentation for further details.
314
315 =head2 Sign
316
317 The sign is either '+', '-', 'NaN', '+inf' or '-inf'.
318
319 A sign of 'NaN' is used to represent the result when input arguments are not
320 numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
321 minus infinity. You will get '+inf' when dividing a positive number by 0, and
322 '-inf' when dividing any negative number by 0.
323
324 =head2 Methods
325
326 Since all numbers are not objects, you can use all functions that are part of
327 the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not
328 the fxxx() notation, though. This makes you independed on the fact that the
329 underlying object might morph into a different class than BigFloat.
330
331 =over 2
332
333 =item inf()
334
335 A shortcut to return Math::BigInt->binf(). Useful because Perl does not always
336 handle bareword C<inf> properly.
337
338 =item NaN()
339
340 A shortcut to return Math::BigInt->bnan(). Useful because Perl does not always
341 handle bareword C<NaN> properly.
342
343 =item e
344
345         # perl -Mbigrat=e -wle 'print e'
346
347 Returns Euler's number C<e>, aka exp(1).
348
349 =item PI
350
351         # perl -Mbigrat=PI -wle 'print PI'
352
353 Returns PI.
354
355 =item bexp()
356
357         bexp($power,$accuracy);
358
359
360 Returns Euler's number C<e> raised to the appropriate power, to
361 the wanted accuracy.
362
363 Example:
364
365         # perl -Mbigrat=bexp -wle 'print bexp(1,80)'
366
367 =item bpi()
368
369         bpi($accuracy);
370
371 Returns PI to the wanted accuracy.
372
373 Example:
374
375         # perl -Mbigrat=bpi -wle 'print bpi(80)'
376
377 =item upgrade()
378
379 Return the class that numbers are upgraded to, is in fact returning
380 C<$Math::BigInt::upgrade>.
381
382 =item in_effect()
383
384         use bigrat;
385
386         print "in effect\n" if bigrat::in_effect;       # true
387         {
388           no bigrat;
389           print "in effect\n" if bigrat::in_effect;     # false
390         }
391
392 Returns true or false if C<bigrat> is in effect in the current scope.
393
394 This method only works on Perl v5.9.4 or later.
395
396 =back
397
398 =head2 MATH LIBRARY
399
400 Math with the numbers is done (by default) by a module called
401
402 =head2 Cavaet
403
404 But a warning is in order. When using the following to make a copy of a number,
405 only a shallow copy will be made.
406
407         $x = 9; $y = $x;
408         $x = $y = 7;
409
410 If you want to make a real copy, use the following:
411
412         $y = $x->copy();
413
414 Using the copy or the original with overloaded math is okay, e.g. the
415 following work:
416
417         $x = 9; $y = $x;
418         print $x + 1, " ", $y,"\n";     # prints 10 9
419
420 but calling any method that modifies the number directly will result in
421 B<both> the original and the copy being destroyed:
422
423         $x = 9; $y = $x;
424         print $x->badd(1), " ", $y,"\n";        # prints 10 10
425
426         $x = 9; $y = $x;
427         print $x->binc(1), " ", $y,"\n";        # prints 10 10
428
429         $x = 9; $y = $x;
430         print $x->bmul(2), " ", $y,"\n";        # prints 18 18
431
432 Using methods that do not modify, but testthe contents works:
433
434         $x = 9; $y = $x;
435         $z = 9 if $x->is_zero();                # works fine
436
437 See the documentation about the copy constructor and C<=> in overload, as
438 well as the documentation in BigInt for further details.
439
440 =head2 Options
441
442 bignum recognizes some options that can be passed while loading it via use.
443 The options can (currently) be either a single letter form, or the long form.
444 The following options exist:
445
446 =over 2
447
448 =item a or accuracy
449
450 This sets the accuracy for all math operations. The argument must be greater
451 than or equal to zero. See Math::BigInt's bround() function for details.
452
453         perl -Mbigrat=a,50 -le 'print sqrt(20)'
454
455 Note that setting precision and accurary at the same time is not possible.
456
457 =item p or precision
458
459 This sets the precision for all math operations. The argument can be any
460 integer. Negative values mean a fixed number of digits after the dot, while
461 a positive value rounds to this digit left from the dot. 0 or 1 mean round to
462 integer. See Math::BigInt's bfround() function for details.
463
464         perl -Mbigrat=p,-50 -le 'print sqrt(20)'
465
466 Note that setting precision and accurary at the same time is not possible.
467
468 =item t or trace
469
470 This enables a trace mode and is primarily for debugging bignum or
471 Math::BigInt/Math::BigFloat.
472
473 =item l or lib
474
475 Load a different math lib, see L<MATH LIBRARY>.
476
477         perl -Mbigrat=l,GMP -e 'print 2 ** 512'
478
479 Currently there is no way to specify more than one library on the command
480 line. This means the following does not work:
481
482         perl -Mbignum=l,GMP,Pari -e 'print 2 ** 512'
483
484 This will be hopefully fixed soon ;)
485
486 =item hex
487
488 Override the built-in hex() method with a version that can handle big
489 integers. Note that under Perl v5.9.4 or ealier, this will be global
490 and cannot be disabled with "no bigint;".
491
492 =item oct
493
494 Override the built-in oct() method with a version that can handle big
495 integers. Note that under Perl v5.9.4 or ealier, this will be global
496 and cannot be disabled with "no bigint;".
497
498 =item v or version
499
500 This prints out the name and version of all modules used and then exits.
501
502         perl -Mbigrat=v
503
504 =back
505
506 =head1 CAVAETS
507
508 =over 2
509
510 =item in_effect()
511
512 This method only works on Perl v5.9.4 or later.
513
514 =item hex()/oct()
515
516 C<bigint> overrides these routines with versions that can also handle
517 big integer values. Under Perl prior to version v5.9.4, however, this
518 will not happen unless you specifically ask for it with the two
519 import tags "hex" and "oct" - and then it will be global and cannot be
520 disabled inside a scope with "no bigint":
521
522         use bigint qw/hex oct/;
523
524         print hex("0x1234567890123456");
525         {
526                 no bigint;
527                 print hex("0x1234567890123456");
528         }
529
530 The second call to hex() will warn about a non-portable constant.
531
532 Compare this to:
533
534         use bigint;
535
536         # will warn only under Perl older than v5.9.4
537         print hex("0x1234567890123456");
538
539 =back
540
541 =head1 EXAMPLES
542  
543         perl -Mbigrat -le 'print sqrt(33)'
544         perl -Mbigrat -le 'print 2*255'
545         perl -Mbigrat -le 'print 4.5+2*255'
546         perl -Mbigrat -le 'print 3/7 + 5/7 + 8/3'       
547         perl -Mbigrat -le 'print 12->is_odd()';
548         perl -Mbignum=l,GMP -le 'print 7 ** 7777'
549
550 =head1 LICENSE
551
552 This program is free software; you may redistribute it and/or modify it under
553 the same terms as Perl itself.
554
555 =head1 SEE ALSO
556
557 Especially L<bignum>.
558
559 L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
560 as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and  L<Math::BigInt::GMP>.
561
562 =head1 AUTHORS
563
564 (C) by Tels L<http://bloodgate.com/> in early 2002 - 2007.
565
566 =cut