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