xref: /openbsd-src/gnu/usr.bin/perl/cpan/bignum/lib/bigrat.pm (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1package bigrat;
2use 5.006;
3
4$VERSION = '0.23';
5require Exporter;
6@ISA		= qw( bigint );
7@EXPORT_OK 	= qw( PI e bpi bexp );
8@EXPORT		= qw( inf NaN );
9
10use strict;
11use overload;
12require bigint;		# no "use" to avoid callind import
13
14##############################################################################
15
16BEGIN
17  {
18  *inf = \&bigint::inf;
19  *NaN = \&bigint::NaN;
20  }
21
22# These are all alike, and thus faked by AUTOLOAD
23
24my @faked = qw/round_mode accuracy precision div_scale/;
25use vars qw/$VERSION $AUTOLOAD $_lite/;		# _lite for testsuite
26
27sub 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
58sub unimport
59  {
60  $^H{bigrat} = undef;					# no longer in effect
61  overload::remove_constant('binary','','float','','integer');
62  }
63
64sub 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
74sub _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
82sub _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
90sub 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
229sub PI () { Math::BigFloat->new('3.141592653589793238462643383279502884197'); }
230sub e () { Math::BigFloat->new('2.718281828459045235360287471352662497757'); }
231
232sub bpi ($) { local $Math::BigFloat::upgrade; Math::BigFloat::bpi(@_); }
233
234sub bexp ($$)
235  {
236  local $Math::BigFloat::upgrade;
237  my $x = Math::BigFloat->new($_[0]); $x->bexp($_[1]);
238  }
239
2401;
241
242__END__
243
244=head1 NAME
245
246bigrat - 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
267All operators (including basic math operations) are overloaded. Integer and
268floating-point constants are created as proper BigInts or BigFloats,
269respectively.
270
271Other than L<bignum>, this module upgrades to Math::BigRat, meaning that
272instead of 2.5 you will get 2+1/2 as output.
273
274=head2 Modules Used
275
276C<bigrat> is just a thin wrapper around various modules of the Math::BigInt
277family. Think of it as the head of the family, who runs the shop, and orders
278the others to do the work.
279
280The 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
289Math with the numbers is done (by default) by a module called
290Math::BigInt::Calc. This is equivalent to saying:
291
292	use bigrat lib => 'Calc';
293
294You can change this by using:
295
296        use bignum lib => 'GMP';
297
298The following would first try to find Math::BigInt::Foo, then
299Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
300
301	use bigrat lib => 'Foo,Math::BigInt::Bar';
302
303Using C<lib> warns if none of the specified libraries can be found and
304L<Math::BigInt> did fall back to one of the default libraries.
305To supress this warning, use C<try> instead:
306
307        use bignum try => 'GMP';
308
309If you want the code to die instead of falling back, use C<only> instead:
310
311        use bignum only => 'GMP';
312
313Please see respective module documentation for further details.
314
315=head2 Sign
316
317The sign is either '+', '-', 'NaN', '+inf' or '-inf'.
318
319A sign of 'NaN' is used to represent the result when input arguments are not
320numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
321minus 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
326Since all numbers are not objects, you can use all functions that are part of
327the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not
328the fxxx() notation, though. This makes you independed on the fact that the
329underlying object might morph into a different class than BigFloat.
330
331=over 2
332
333=item inf()
334
335A shortcut to return Math::BigInt->binf(). Useful because Perl does not always
336handle bareword C<inf> properly.
337
338=item NaN()
339
340A shortcut to return Math::BigInt->bnan(). Useful because Perl does not always
341handle bareword C<NaN> properly.
342
343=item e
344
345	# perl -Mbigrat=e -wle 'print e'
346
347Returns Euler's number C<e>, aka exp(1).
348
349=item PI
350
351	# perl -Mbigrat=PI -wle 'print PI'
352
353Returns PI.
354
355=item bexp()
356
357	bexp($power,$accuracy);
358
359
360Returns Euler's number C<e> raised to the appropriate power, to
361the wanted accuracy.
362
363Example:
364
365	# perl -Mbigrat=bexp -wle 'print bexp(1,80)'
366
367=item bpi()
368
369	bpi($accuracy);
370
371Returns PI to the wanted accuracy.
372
373Example:
374
375	# perl -Mbigrat=bpi -wle 'print bpi(80)'
376
377=item upgrade()
378
379Return the class that numbers are upgraded to, is in fact returning
380C<$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
392Returns true or false if C<bigrat> is in effect in the current scope.
393
394This method only works on Perl v5.9.4 or later.
395
396=back
397
398=head2 MATH LIBRARY
399
400Math with the numbers is done (by default) by a module called
401
402=head2 Cavaet
403
404But a warning is in order. When using the following to make a copy of a number,
405only a shallow copy will be made.
406
407        $x = 9; $y = $x;
408        $x = $y = 7;
409
410If you want to make a real copy, use the following:
411
412	$y = $x->copy();
413
414Using the copy or the original with overloaded math is okay, e.g. the
415following work:
416
417        $x = 9; $y = $x;
418        print $x + 1, " ", $y,"\n";     # prints 10 9
419
420but calling any method that modifies the number directly will result in
421B<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
432Using 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
437See the documentation about the copy constructor and C<=> in overload, as
438well as the documentation in BigInt for further details.
439
440=head2 Options
441
442bignum recognizes some options that can be passed while loading it via use.
443The options can (currently) be either a single letter form, or the long form.
444The following options exist:
445
446=over 2
447
448=item a or accuracy
449
450This sets the accuracy for all math operations. The argument must be greater
451than or equal to zero. See Math::BigInt's bround() function for details.
452
453	perl -Mbigrat=a,50 -le 'print sqrt(20)'
454
455Note that setting precision and accurary at the same time is not possible.
456
457=item p or precision
458
459This sets the precision for all math operations. The argument can be any
460integer. Negative values mean a fixed number of digits after the dot, while
461a positive value rounds to this digit left from the dot. 0 or 1 mean round to
462integer. See Math::BigInt's bfround() function for details.
463
464	perl -Mbigrat=p,-50 -le 'print sqrt(20)'
465
466Note that setting precision and accurary at the same time is not possible.
467
468=item t or trace
469
470This enables a trace mode and is primarily for debugging bignum or
471Math::BigInt/Math::BigFloat.
472
473=item l or lib
474
475Load a different math lib, see L<MATH LIBRARY>.
476
477	perl -Mbigrat=l,GMP -e 'print 2 ** 512'
478
479Currently there is no way to specify more than one library on the command
480line. This means the following does not work:
481
482	perl -Mbignum=l,GMP,Pari -e 'print 2 ** 512'
483
484This will be hopefully fixed soon ;)
485
486=item hex
487
488Override the built-in hex() method with a version that can handle big
489integers. Note that under Perl v5.9.4 or ealier, this will be global
490and cannot be disabled with "no bigint;".
491
492=item oct
493
494Override the built-in oct() method with a version that can handle big
495integers. Note that under Perl v5.9.4 or ealier, this will be global
496and cannot be disabled with "no bigint;".
497
498=item v or version
499
500This 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
512This method only works on Perl v5.9.4 or later.
513
514=item hex()/oct()
515
516C<bigint> overrides these routines with versions that can also handle
517big integer values. Under Perl prior to version v5.9.4, however, this
518will not happen unless you specifically ask for it with the two
519import tags "hex" and "oct" - and then it will be global and cannot be
520disabled 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
530The second call to hex() will warn about a non-portable constant.
531
532Compare 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
552This program is free software; you may redistribute it and/or modify it under
553the same terms as Perl itself.
554
555=head1 SEE ALSO
556
557Especially L<bignum>.
558
559L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
560as 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
567