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