This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Let's (un)do the timewarp, again.
[perl5.git] / lib / bigrat.pm
CommitLineData
126f3c5f
JH
1package bigrat;
2require 5.005;
3
b68b7ab1
T
4$VERSION = '0.07';
5require Exporter;
b4bc5691
T
6@ISA = qw( Exporter );
7@EXPORT_OK = qw( );
8@EXPORT = qw( inf NaN );
126f3c5f
JH
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
JH
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
69 my $lib = 'Calc'; my $upgrade = 'Math::BigFloat';
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
T
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
JH
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
JH
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 }
141 # Math::BigInt::Trace or plain Math::BigInt
142 $class->import(@import, upgrade => $upgrade, lib => $lib);
143
144 require Math::BigFloat;
145 Math::BigFloat->import( upgrade => 'Math::BigRat', ':constant' );
146 require Math::BigRat;
b68b7ab1
T
147
148 bigrat->accuracy($a) if defined $a;
149 bigrat->precision($p) if defined $p;
126f3c5f
JH
150 if ($ver)
151 {
152 print "bigrat\t\t\t v$VERSION\n";
153 print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite;
154 print "Math::BigInt\t\t v$Math::BigInt::VERSION";
155 my $config = Math::BigInt->config();
156 print " lib => $config->{lib} v$config->{lib_version}\n";
157 print "Math::BigFloat\t\t v$Math::BigFloat::VERSION\n";
158 print "Math::BigRat\t\t v$Math::BigRat::VERSION\n";
159 exit;
160 }
b4bc5691 161 $self->export_to_level(1,$self,@a); # export inf and NaN
126f3c5f
JH
162 }
163
b4bc5691
T
164sub inf () { Math::BigInt->binf(); }
165sub NaN () { Math::BigInt->bnan(); }
166
126f3c5f
JH
1671;
168
169__END__
170
171=head1 NAME
172
b1f79218 173bigrat - Transparent BigNumber/BigRational support for Perl
126f3c5f
JH
174
175=head1 SYNOPSIS
176
177 use bigrat;
178
179 $x = 2 + 4.5,"\n"; # BigFloat 6.5
180 print 1/3 + 1/4,"\n"; # produces 7/12
181
182=head1 DESCRIPTION
183
184All operators (inlcuding basic math operations) are overloaded. Integer and
185floating-point constants are created as proper BigInts or BigFloats,
186respectively.
187
188Other than L<bignum>, this module upgrades to Math::BigRat, meaning that
189instead of 2.5 you will get 2+1/2 as output.
190
b68b7ab1 191=head2 Modules Used
126f3c5f
JH
192
193C<bigrat> is just a thin wrapper around various modules of the Math::BigInt
194family. Think of it as the head of the family, who runs the shop, and orders
195the others to do the work.
196
197The following modules are currently used by bignum:
198
199 Math::BigInt::Lite (for speed, and only if it is loadable)
200 Math::BigInt
201 Math::BigFloat
202 Math::BigRat
203
b68b7ab1 204=head2 Math Library
126f3c5f
JH
205
206Math with the numbers is done (by default) by a module called
207Math::BigInt::Calc. This is equivalent to saying:
208
209 use bigrat lib => 'Calc';
210
211You can change this by using:
212
213 use bigrat lib => 'BitVect';
214
215The following would first try to find Math::BigInt::Foo, then
216Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
217
218 use bigrat lib => 'Foo,Math::BigInt::Bar';
219
220Please see respective module documentation for further details.
221
b68b7ab1 222=head2 Sign
126f3c5f 223
b68b7ab1 224The sign is either '+', '-', 'NaN', '+inf' or '-inf'.
126f3c5f
JH
225
226A sign of 'NaN' is used to represent the result when input arguments are not
227numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
228minus infinity. You will get '+inf' when dividing a positive number by 0, and
229'-inf' when dividing any negative number by 0.
230
b68b7ab1 231=head2 Methods
126f3c5f
JH
232
233Since all numbers are not objects, you can use all functions that are part of
234the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not
235the fxxx() notation, though. This makes you independed on the fact that the
236underlying object might morph into a different class than BigFloat.
237
b68b7ab1 238=head2 Cavaet
990fb837
RGS
239
240But a warning is in order. When using the following to make a copy of a number,
241only a shallow copy will be made.
242
243 $x = 9; $y = $x;
244 $x = $y = 7;
245
b68b7ab1
T
246If you want to make a real copy, use the following:
247
248 $y = $x->copy();
249
990fb837
RGS
250Using the copy or the original with overloaded math is okay, e.g. the
251following work:
252
253 $x = 9; $y = $x;
254 print $x + 1, " ", $y,"\n"; # prints 10 9
255
256but calling any method that modifies the number directly will result in
257B<both> the original and the copy beeing destroyed:
258
259 $x = 9; $y = $x;
260 print $x->badd(1), " ", $y,"\n"; # prints 10 10
261
262 $x = 9; $y = $x;
263 print $x->binc(1), " ", $y,"\n"; # prints 10 10
264
265 $x = 9; $y = $x;
266 print $x->bmul(2), " ", $y,"\n"; # prints 18 18
267
268Using methods that do not modify, but testthe contents works:
269
270 $x = 9; $y = $x;
271 $z = 9 if $x->is_zero(); # works fine
272
273See the documentation about the copy constructor and C<=> in overload, as
274well as the documentation in BigInt for further details.
275
b68b7ab1
T
276=head2 Options
277
278bignum recognizes some options that can be passed while loading it via use.
279The options can (currently) be either a single letter form, or the long form.
280The following options exist:
281
282=over 2
283
284=item a or accuracy
285
286This sets the accuracy for all math operations. The argument must be greater
287than or equal to zero. See Math::BigInt's bround() function for details.
288
289 perl -Mbigrat=a,50 -le 'print sqrt(20)'
290
291=item p or precision
292
293This sets the precision for all math operations. The argument can be any
294integer. Negative values mean a fixed number of digits after the dot, while
295a positive value rounds to this digit left from the dot. 0 or 1 mean round to
296integer. See Math::BigInt's bfround() function for details.
297
298 perl -Mbigrat=p,-50 -le 'print sqrt(20)'
299
300=item t or trace
301
302This enables a trace mode and is primarily for debugging bignum or
303Math::BigInt/Math::BigFloat.
304
305=item l or lib
306
307Load a different math lib, see L<MATH LIBRARY>.
308
309 perl -Mbigrat=l,GMP -e 'print 2 ** 512'
310
311Currently there is no way to specify more than one library on the command
312line. This will be hopefully fixed soon ;)
313
314=item v or version
315
316This prints out the name and version of all modules used and then exits.
317
318 perl -Mbigrat=v
319
126f3c5f
JH
320=head1 EXAMPLES
321
322 perl -Mbigrat -le 'print sqrt(33)'
323 perl -Mbigrat -le 'print 2*255'
324 perl -Mbigrat -le 'print 4.5+2*255'
325 perl -Mbigrat -le 'print 3/7 + 5/7 + 8/3'
326 perl -Mbigrat -le 'print 12->is_odd()';
327
328=head1 LICENSE
329
330This program is free software; you may redistribute it and/or modify it under
331the same terms as Perl itself.
332
333=head1 SEE ALSO
334
335Especially L<bignum>.
336
337L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
338as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and L<Math::BigInt::GMP>.
339
340=head1 AUTHORS
341
b68b7ab1 342(C) by Tels L<http://bloodgate.com/> in early 2002 - 2005.
126f3c5f
JH
343
344=cut