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