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