ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/staticperl/perl/lib/bigrat.pm
Revision: 1.1
Committed: Thu Jun 30 14:27:08 2005 UTC (21 years, 3 months ago) by root
Branch: MAIN
CVS Tags: PERL-5-8-7, HEAD
Branch point for: PERL
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 package bigrat;
2     require 5.005;
3    
4     $VERSION = '0.08';
5     require Exporter;
6     @ISA = qw( Exporter );
7     @EXPORT_OK = qw( );
8     @EXPORT = qw( inf NaN );
9    
10     use strict;
11    
12     ##############################################################################
13    
14     # These are all alike, and thus faked by AUTOLOAD
15    
16     my @faked = qw/round_mode accuracy precision div_scale/;
17     use vars qw/$VERSION $AUTOLOAD $_lite/; # _lite for testsuite
18    
19     sub 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]);
37     return Math::BigRat->$name($_[0]);
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    
50     sub 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    
62     sub import
63     {
64     my $self = shift;
65    
66     # see also bignum->import() for additional comments
67    
68     # some defaults
69     my $lib = ''; 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; $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++;
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';
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     push @import, 'lib' => $lib if $lib ne '';
142     # Math::BigInt::Trace or plain Math::BigInt
143     $class->import(@import, upgrade => $upgrade);
144    
145     require Math::BigFloat;
146     Math::BigFloat->import( upgrade => 'Math::BigRat', ':constant' );
147     require Math::BigRat;
148    
149     bigrat->accuracy($a) if defined $a;
150     bigrat->precision($p) if defined $p;
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     }
162     $self->export_to_level(1,$self,@a); # export inf and NaN
163     }
164    
165     sub inf () { Math::BigInt->binf(); }
166     sub NaN () { Math::BigInt->bnan(); }
167    
168     1;
169    
170     __END__
171    
172     =head1 NAME
173    
174     bigrat - Transparent BigNumber/BigRational support for Perl
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    
185     All operators (inlcuding basic math operations) are overloaded. Integer and
186     floating-point constants are created as proper BigInts or BigFloats,
187     respectively.
188    
189     Other than L<bignum>, this module upgrades to Math::BigRat, meaning that
190     instead of 2.5 you will get 2+1/2 as output.
191    
192     =head2 Modules Used
193    
194     C<bigrat> is just a thin wrapper around various modules of the Math::BigInt
195     family. Think of it as the head of the family, who runs the shop, and orders
196     the others to do the work.
197    
198     The 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    
205     =head2 Math Library
206    
207     Math with the numbers is done (by default) by a module called
208     Math::BigInt::Calc. This is equivalent to saying:
209    
210     use bigrat lib => 'Calc';
211    
212     You can change this by using:
213    
214     use bigrat lib => 'BitVect';
215    
216     The following would first try to find Math::BigInt::Foo, then
217     Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
218    
219     use bigrat lib => 'Foo,Math::BigInt::Bar';
220    
221     Please see respective module documentation for further details.
222    
223     =head2 Sign
224    
225     The sign is either '+', '-', 'NaN', '+inf' or '-inf'.
226    
227     A sign of 'NaN' is used to represent the result when input arguments are not
228     numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
229     minus infinity. You will get '+inf' when dividing a positive number by 0, and
230     '-inf' when dividing any negative number by 0.
231    
232     =head2 Methods
233    
234     Since all numbers are not objects, you can use all functions that are part of
235     the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not
236     the fxxx() notation, though. This makes you independed on the fact that the
237     underlying object might morph into a different class than BigFloat.
238    
239     =head2 Cavaet
240    
241     But a warning is in order. When using the following to make a copy of a number,
242     only a shallow copy will be made.
243    
244     $x = 9; $y = $x;
245     $x = $y = 7;
246    
247     If you want to make a real copy, use the following:
248    
249     $y = $x->copy();
250    
251     Using the copy or the original with overloaded math is okay, e.g. the
252     following work:
253    
254     $x = 9; $y = $x;
255     print $x + 1, " ", $y,"\n"; # prints 10 9
256    
257     but calling any method that modifies the number directly will result in
258     B<both> the original and the copy beeing destroyed:
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    
269     Using 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    
274     See the documentation about the copy constructor and C<=> in overload, as
275     well as the documentation in BigInt for further details.
276    
277     =head2 Options
278    
279     bignum recognizes some options that can be passed while loading it via use.
280     The options can (currently) be either a single letter form, or the long form.
281     The following options exist:
282    
283     =over 2
284    
285     =item a or accuracy
286    
287     This sets the accuracy for all math operations. The argument must be greater
288     than 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    
294     This sets the precision for all math operations. The argument can be any
295     integer. Negative values mean a fixed number of digits after the dot, while
296     a positive value rounds to this digit left from the dot. 0 or 1 mean round to
297     integer. 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    
303     This enables a trace mode and is primarily for debugging bignum or
304     Math::BigInt/Math::BigFloat.
305    
306     =item l or lib
307    
308     Load a different math lib, see L<MATH LIBRARY>.
309    
310     perl -Mbigrat=l,GMP -e 'print 2 ** 512'
311    
312     Currently there is no way to specify more than one library on the command
313     line. This will be hopefully fixed soon ;)
314    
315     =item v or version
316    
317     This prints out the name and version of all modules used and then exits.
318    
319     perl -Mbigrat=v
320    
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    
331     This program is free software; you may redistribute it and/or modify it under
332     the same terms as Perl itself.
333    
334     =head1 SEE ALSO
335    
336     Especially L<bignum>.
337    
338     L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
339     as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and L<Math::BigInt::GMP>.
340    
341     =head1 AUTHORS
342    
343     (C) by Tels L<http://bloodgate.com/> in early 2002 - 2005.
344    
345     =cut