Math::BigInt v1.87 take 6
[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;
b4bc5691 6@ISA = qw( Exporter );
7@EXPORT_OK = qw( );
8@EXPORT = qw( inf NaN );
126f3c5f 9
10use strict;
95a2d02c 11use overload;
126f3c5f 12
13##############################################################################
14
15# These are all alike, and thus faked by AUTOLOAD
16
17my @faked = qw/round_mode accuracy precision div_scale/;
18use vars qw/$VERSION $AUTOLOAD $_lite/; # _lite for testsuite
19
20sub AUTOLOAD
21 {
22 my $name = $AUTOLOAD;
23
24 $name =~ s/.*:://; # split package
25 no strict 'refs';
26 foreach my $n (@faked)
27 {
28 if ($n eq $name)
29 {
30 *{"bigrat::$name"} = sub
31 {
32 my $self = shift;
33 no strict 'refs';
34 if (defined $_[0])
35 {
36 Math::BigInt->$name($_[0]);
37 Math::BigFloat->$name($_[0]);
990fb837 38 return Math::BigRat->$name($_[0]);
126f3c5f 39 }
40 return Math::BigInt->$name();
41 };
42 return &$name;
43 }
44 }
45
46 # delayed load of Carp and avoid recursion
47 require Carp;
48 Carp::croak ("Can't call bigrat\-\>$name, not a valid method");
49 }
50
51sub upgrade
52 {
95a2d02c 53 $Math::BigInt::upgrade;
54 }
55
56sub _binary_constant
57 {
58 # this takes a binary/hexadecimal/octal constant string and returns it
59 # as string suitable for new. Basically it converts octal to decimal, and
60 # passes every thing else unmodified back.
61 my $string = shift;
62
63 return Math::BigInt->new($string) if $string =~ /^0[bx]/;
64
65 # so it must be an octal constant
66 Math::BigInt->from_oct($string);
126f3c5f 67 }
68
4440d13a 69sub unimport
70 {
71 $^H{bigrat} = undef; # no longer in effect
72 overload::remove_constant('binary','','float','','integer');
73 }
74
75sub in_effect
76 {
77 my $level = shift || 0;
78 my $hinthash = (caller($level))[10];
79 $hinthash->{bigrat};
80 }
81
126f3c5f 82sub import
83 {
84 my $self = shift;
85
86 # see also bignum->import() for additional comments
87
4440d13a 88 $^H{bigrat} = 1; # we are in effect
89
126f3c5f 90 # some defaults
bd49aa09 91 my $lib = ''; my $lib_kind = 'try'; my $upgrade = 'Math::BigFloat';
126f3c5f 92
93 my @import = ( ':constant' ); # drive it w/ constant
94 my @a = @_; my $l = scalar @_; my $j = 0;
95 my ($a,$p);
96 my ($ver,$trace); # version? trace?
97 for ( my $i = 0; $i < $l ; $i++,$j++ )
98 {
99 if ($_[$i] eq 'upgrade')
100 {
101 # this causes upgrading
102 $upgrade = $_[$i+1]; # or undef to disable
103 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
104 splice @a, $j, $s; $j -= $s;
105 }
bd49aa09 106 elsif ($_[$i] =~ /^(l|lib|try|only)$/)
126f3c5f 107 {
108 # this causes a different low lib to take care...
bd49aa09 109 $lib_kind = $1; $lib_kind = 'lib' if $lib_kind eq 'l';
126f3c5f 110 $lib = $_[$i+1] || '';
111 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
b68b7ab1 112 splice @a, $j, $s; $j -= $s; $i++;
113 }
114 elsif ($_[$i] =~ /^(a|accuracy)$/)
115 {
116 $a = $_[$i+1];
117 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
118 splice @a, $j, $s; $j -= $s; $i++;
119 }
120 elsif ($_[$i] =~ /^(p|precision)$/)
121 {
122 $p = $_[$i+1];
123 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
124 splice @a, $j, $s; $j -= $s; $i++;
126f3c5f 125 }
126 elsif ($_[$i] =~ /^(v|version)$/)
127 {
128 $ver = 1;
129 splice @a, $j, 1; $j --;
130 }
131 elsif ($_[$i] =~ /^(t|trace)$/)
132 {
133 $trace = 1;
134 splice @a, $j, 1; $j --;
135 }
136 else
137 {
138 die ("unknown option $_[$i]");
139 }
140 }
141 my $class;
142 $_lite = 0; # using M::BI::L ?
143 if ($trace)
144 {
145 require Math::BigInt::Trace; $class = 'Math::BigInt::Trace';
146 $upgrade = 'Math::BigFloat::Trace';
126f3c5f 147 }
148 else
149 {
150 # see if we can find Math::BigInt::Lite
151 if (!defined $a && !defined $p) # rounding won't work to well
152 {
153 eval 'require Math::BigInt::Lite;';
154 if ($@ eq '')
155 {
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 }
bd49aa09 164 push @import, $lib_kind => $lib if $lib ne '';
126f3c5f 165 # Math::BigInt::Trace or plain Math::BigInt
233f7bc0 166 $class->import(@import, upgrade => $upgrade);
126f3c5f 167
168 require Math::BigFloat;
169 Math::BigFloat->import( upgrade => 'Math::BigRat', ':constant' );
170 require Math::BigRat;
b68b7ab1 171
172 bigrat->accuracy($a) if defined $a;
173 bigrat->precision($p) if defined $p;
126f3c5f 174 if ($ver)
175 {
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 }
95a2d02c 185
186 # Take care of octal/hexadecimal constants
187 overload::constant binary => sub { _binary_constant(shift) };
188
4440d13a 189 # if another big* was already loaded:
190 my ($package) = caller();
191
192 no strict 'refs';
193 if (!defined *{"${package}::inf"})
194 {
195 $self->export_to_level(1,$self,@a); # export inf and NaN
196 }
126f3c5f 197 }
198
b4bc5691 199sub inf () { Math::BigInt->binf(); }
200sub NaN () { Math::BigInt->bnan(); }
201
126f3c5f 2021;
203
204__END__
205
206=head1 NAME
207
b1f79218 208bigrat - Transparent BigNumber/BigRational support for Perl
126f3c5f 209
210=head1 SYNOPSIS
211
212 use bigrat;
213
4440d13a 214 print 2 + 4.5,"\n"; # BigFloat 6.5
126f3c5f 215 print 1/3 + 1/4,"\n"; # produces 7/12
216
4440d13a 217 {
218 no bigrat;
219 print 1/3,"\n"; # 0.33333...
220 }
221
126f3c5f 222=head1 DESCRIPTION
223
3c4b39be 224All operators (including basic math operations) are overloaded. Integer and
126f3c5f 225floating-point constants are created as proper BigInts or BigFloats,
226respectively.
227
228Other than L<bignum>, this module upgrades to Math::BigRat, meaning that
229instead of 2.5 you will get 2+1/2 as output.
230
b68b7ab1 231=head2 Modules Used
126f3c5f 232
233C<bigrat> is just a thin wrapper around various modules of the Math::BigInt
234family. Think of it as the head of the family, who runs the shop, and orders
235the others to do the work.
236
237The following modules are currently used by bignum:
238
239 Math::BigInt::Lite (for speed, and only if it is loadable)
240 Math::BigInt
241 Math::BigFloat
242 Math::BigRat
243
b68b7ab1 244=head2 Math Library
126f3c5f 245
246Math with the numbers is done (by default) by a module called
247Math::BigInt::Calc. This is equivalent to saying:
248
249 use bigrat lib => 'Calc';
250
251You can change this by using:
252
bd49aa09 253 use bignum lib => 'GMP';
126f3c5f 254
255The following would first try to find Math::BigInt::Foo, then
256Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
257
258 use bigrat lib => 'Foo,Math::BigInt::Bar';
259
bd49aa09 260Using C<lib> warns if none of the specified libraries can be found and
261L<Math::BigInt> did fall back to one of the default libraries.
262To supress this warning, use C<try> instead:
263
264 use bignum try => 'GMP';
265
266If you want the code to die instead of falling back, use C<only> instead:
267
268 use bignum only => 'GMP';
269
126f3c5f 270Please see respective module documentation for further details.
271
b68b7ab1 272=head2 Sign
126f3c5f 273
b68b7ab1 274The sign is either '+', '-', 'NaN', '+inf' or '-inf'.
126f3c5f 275
276A sign of 'NaN' is used to represent the result when input arguments are not
277numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
278minus infinity. You will get '+inf' when dividing a positive number by 0, and
279'-inf' when dividing any negative number by 0.
280
b68b7ab1 281=head2 Methods
126f3c5f 282
283Since all numbers are not objects, you can use all functions that are part of
284the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not
285the fxxx() notation, though. This makes you independed on the fact that the
286underlying object might morph into a different class than BigFloat.
287
95a2d02c 288=over 2
289
290=item inf()
291
292A shortcut to return Math::BigInt->binf(). Useful because Perl does not always
293handle bareword C<inf> properly.
294
295=item NaN()
296
297A shortcut to return Math::BigInt->bnan(). Useful because Perl does not always
298handle bareword C<NaN> properly.
299
300=item upgrade()
301
302Return the class that numbers are upgraded to, is in fact returning
303C<$Math::BigInt::upgrade>.
304
4440d13a 305=item in_effect()
306
307 use bigrat;
308
309 print "in effect\n" if bigrat::in_effect; # true
310 {
311 no bigrat;
312 print "in effect\n" if bigrat::in_effect; # false
313 }
314
315Returns true or false if C<bigrat> is in effect in the current scope.
316
317This method only works on Perl v5.9.4 or later.
318
95a2d02c 319=back
320
321=head2 MATH LIBRARY
322
323Math with the numbers is done (by default) by a module called
324
325=head2 Cavaet
990fb837 326
327But a warning is in order. When using the following to make a copy of a number,
328only a shallow copy will be made.
329
330 $x = 9; $y = $x;
331 $x = $y = 7;
332
b68b7ab1 333If you want to make a real copy, use the following:
334
335 $y = $x->copy();
336
990fb837 337Using the copy or the original with overloaded math is okay, e.g. the
338following work:
339
340 $x = 9; $y = $x;
341 print $x + 1, " ", $y,"\n"; # prints 10 9
342
343but calling any method that modifies the number directly will result in
3c4b39be 344B<both> the original and the copy being destroyed:
990fb837 345
346 $x = 9; $y = $x;
347 print $x->badd(1), " ", $y,"\n"; # prints 10 10
348
349 $x = 9; $y = $x;
350 print $x->binc(1), " ", $y,"\n"; # prints 10 10
351
352 $x = 9; $y = $x;
353 print $x->bmul(2), " ", $y,"\n"; # prints 18 18
354
355Using methods that do not modify, but testthe contents works:
356
357 $x = 9; $y = $x;
358 $z = 9 if $x->is_zero(); # works fine
359
360See the documentation about the copy constructor and C<=> in overload, as
361well as the documentation in BigInt for further details.
362
b68b7ab1 363=head2 Options
364
365bignum recognizes some options that can be passed while loading it via use.
366The options can (currently) be either a single letter form, or the long form.
367The following options exist:
368
369=over 2
370
371=item a or accuracy
372
373This sets the accuracy for all math operations. The argument must be greater
374than or equal to zero. See Math::BigInt's bround() function for details.
375
376 perl -Mbigrat=a,50 -le 'print sqrt(20)'
377
95a2d02c 378Note that setting precision and accurary at the same time is not possible.
379
b68b7ab1 380=item p or precision
381
382This sets the precision for all math operations. The argument can be any
383integer. Negative values mean a fixed number of digits after the dot, while
384a positive value rounds to this digit left from the dot. 0 or 1 mean round to
385integer. See Math::BigInt's bfround() function for details.
386
387 perl -Mbigrat=p,-50 -le 'print sqrt(20)'
388
95a2d02c 389Note that setting precision and accurary at the same time is not possible.
390
b68b7ab1 391=item t or trace
392
393This enables a trace mode and is primarily for debugging bignum or
394Math::BigInt/Math::BigFloat.
395
396=item l or lib
397
398Load a different math lib, see L<MATH LIBRARY>.
399
400 perl -Mbigrat=l,GMP -e 'print 2 ** 512'
401
402Currently there is no way to specify more than one library on the command
95a2d02c 403line. This means the following does not work:
404
405 perl -Mbignum=l,GMP,Pari -e 'print 2 ** 512'
406
407This will be hopefully fixed soon ;)
b68b7ab1 408
409=item v or version
410
411This prints out the name and version of all modules used and then exits.
412
413 perl -Mbigrat=v
414
95a2d02c 415=back
416
126f3c5f 417=head1 EXAMPLES
418
419 perl -Mbigrat -le 'print sqrt(33)'
420 perl -Mbigrat -le 'print 2*255'
421 perl -Mbigrat -le 'print 4.5+2*255'
422 perl -Mbigrat -le 'print 3/7 + 5/7 + 8/3'
423 perl -Mbigrat -le 'print 12->is_odd()';
95a2d02c 424 perl -Mbignum=l,GMP -le 'print 7 ** 7777'
126f3c5f 425
426=head1 LICENSE
427
428This program is free software; you may redistribute it and/or modify it under
429the same terms as Perl itself.
430
431=head1 SEE ALSO
432
433Especially L<bignum>.
434
435L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
436as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and L<Math::BigInt::GMP>.
437
438=head1 AUTHORS
439
95a2d02c 440(C) by Tels L<http://bloodgate.com/> in early 2002 - 2007.
126f3c5f 441
442=cut