This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Update the CPAN mirrors list.
[perl5.git] / lib / bigrat.pm
CommitLineData
126f3c5f
JH
1package bigrat;
2require 5.005;
3
990fb837 4$VERSION = '0.06';
126f3c5f 5use 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..."
89 splice @a, $j, $s; $j -= $s;
90 }
91 elsif ($_[$i] =~ /^(v|version)$/)
92 {
93 $ver = 1;
94 splice @a, $j, 1; $j --;
95 }
96 elsif ($_[$i] =~ /^(t|trace)$/)
97 {
98 $trace = 1;
99 splice @a, $j, 1; $j --;
100 }
101 else
102 {
103 die ("unknown option $_[$i]");
104 }
105 }
106 my $class;
107 $_lite = 0; # using M::BI::L ?
108 if ($trace)
109 {
110 require Math::BigInt::Trace; $class = 'Math::BigInt::Trace';
111 $upgrade = 'Math::BigFloat::Trace';
126f3c5f
JH
112 }
113 else
114 {
115 # see if we can find Math::BigInt::Lite
116 if (!defined $a && !defined $p) # rounding won't work to well
117 {
118 eval 'require Math::BigInt::Lite;';
119 if ($@ eq '')
120 {
121 @import = ( ); # :constant in Lite, not MBI
122 Math::BigInt::Lite->import( ':constant' );
123 $_lite= 1; # signal okay
124 }
125 }
126 require Math::BigInt if $_lite == 0; # not already loaded?
127 $class = 'Math::BigInt'; # regardless of MBIL or not
128 }
129 # Math::BigInt::Trace or plain Math::BigInt
130 $class->import(@import, upgrade => $upgrade, lib => $lib);
131
132 require Math::BigFloat;
133 Math::BigFloat->import( upgrade => 'Math::BigRat', ':constant' );
134 require Math::BigRat;
135 if ($ver)
136 {
137 print "bigrat\t\t\t v$VERSION\n";
138 print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite;
139 print "Math::BigInt\t\t v$Math::BigInt::VERSION";
140 my $config = Math::BigInt->config();
141 print " lib => $config->{lib} v$config->{lib_version}\n";
142 print "Math::BigFloat\t\t v$Math::BigFloat::VERSION\n";
143 print "Math::BigRat\t\t v$Math::BigRat::VERSION\n";
144 exit;
145 }
b4bc5691 146 $self->export_to_level(1,$self,@a); # export inf and NaN
126f3c5f
JH
147 }
148
b4bc5691
T
149sub inf () { Math::BigInt->binf(); }
150sub NaN () { Math::BigInt->bnan(); }
151
126f3c5f
JH
1521;
153
154__END__
155
156=head1 NAME
157
b4bc5691 158bigrat - Transparent BigNumber/BigRationale support for Perl
126f3c5f
JH
159
160=head1 SYNOPSIS
161
162 use bigrat;
163
164 $x = 2 + 4.5,"\n"; # BigFloat 6.5
165 print 1/3 + 1/4,"\n"; # produces 7/12
166
167=head1 DESCRIPTION
168
169All operators (inlcuding basic math operations) are overloaded. Integer and
170floating-point constants are created as proper BigInts or BigFloats,
171respectively.
172
173Other than L<bignum>, this module upgrades to Math::BigRat, meaning that
174instead of 2.5 you will get 2+1/2 as output.
175
176=head2 MODULES USED
177
178C<bigrat> is just a thin wrapper around various modules of the Math::BigInt
179family. Think of it as the head of the family, who runs the shop, and orders
180the others to do the work.
181
182The following modules are currently used by bignum:
183
184 Math::BigInt::Lite (for speed, and only if it is loadable)
185 Math::BigInt
186 Math::BigFloat
187 Math::BigRat
188
189=head2 MATH LIBRARY
190
191Math with the numbers is done (by default) by a module called
192Math::BigInt::Calc. This is equivalent to saying:
193
194 use bigrat lib => 'Calc';
195
196You can change this by using:
197
198 use bigrat lib => 'BitVect';
199
200The following would first try to find Math::BigInt::Foo, then
201Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
202
203 use bigrat lib => 'Foo,Math::BigInt::Bar';
204
205Please see respective module documentation for further details.
206
207=head2 SIGN
208
209The sign is either '+', '-', 'NaN', '+inf' or '-inf' and stored seperately.
210
211A sign of 'NaN' is used to represent the result when input arguments are not
212numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
213minus infinity. You will get '+inf' when dividing a positive number by 0, and
214'-inf' when dividing any negative number by 0.
215
216=head2 METHODS
217
218Since all numbers are not objects, you can use all functions that are part of
219the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not
220the fxxx() notation, though. This makes you independed on the fact that the
221underlying object might morph into a different class than BigFloat.
222
990fb837
RGS
223=head2 CAVEAT
224
225But a warning is in order. When using the following to make a copy of a number,
226only a shallow copy will be made.
227
228 $x = 9; $y = $x;
229 $x = $y = 7;
230
231Using the copy or the original with overloaded math is okay, e.g. the
232following work:
233
234 $x = 9; $y = $x;
235 print $x + 1, " ", $y,"\n"; # prints 10 9
236
237but calling any method that modifies the number directly will result in
238B<both> the original and the copy beeing destroyed:
239
240 $x = 9; $y = $x;
241 print $x->badd(1), " ", $y,"\n"; # prints 10 10
242
243 $x = 9; $y = $x;
244 print $x->binc(1), " ", $y,"\n"; # prints 10 10
245
246 $x = 9; $y = $x;
247 print $x->bmul(2), " ", $y,"\n"; # prints 18 18
248
249Using methods that do not modify, but testthe contents works:
250
251 $x = 9; $y = $x;
252 $z = 9 if $x->is_zero(); # works fine
253
254See the documentation about the copy constructor and C<=> in overload, as
255well as the documentation in BigInt for further details.
256
126f3c5f
JH
257=head1 EXAMPLES
258
259 perl -Mbigrat -le 'print sqrt(33)'
260 perl -Mbigrat -le 'print 2*255'
261 perl -Mbigrat -le 'print 4.5+2*255'
262 perl -Mbigrat -le 'print 3/7 + 5/7 + 8/3'
263 perl -Mbigrat -le 'print 12->is_odd()';
264
265=head1 LICENSE
266
267This program is free software; you may redistribute it and/or modify it under
268the same terms as Perl itself.
269
270=head1 SEE ALSO
271
272Especially L<bignum>.
273
274L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
275as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and L<Math::BigInt::GMP>.
276
277=head1 AUTHORS
278
279(C) by Tels L<http://bloodgate.com/> in early 2002.
280
281=cut