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