ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/staticperl/perl/lib/bigint.pm
Revision: 1.1
Committed: Thu Jun 30 14:27:08 2005 UTC (21 years, 4 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 bigint;
2     require 5.005;
3    
4     $VERSION = '0.07';
5     use Exporter;
6     @ISA = qw( Exporter );
7     @EXPORT_OK = qw( );
8     @EXPORT = qw( inf NaN );
9    
10     use strict;
11     use overload;
12    
13     ##############################################################################
14    
15     # These are all alike, and thus faked by AUTOLOAD
16    
17     my @faked = qw/round_mode accuracy precision div_scale/;
18     use vars qw/$VERSION $AUTOLOAD $_lite/; # _lite for testsuite
19    
20     sub 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     *{"bigint::$name"} = sub
31     {
32     my $self = shift;
33     no strict 'refs';
34     if (defined $_[0])
35     {
36     return Math::BigInt->$name($_[0]);
37     }
38     return Math::BigInt->$name();
39     };
40     return &$name;
41     }
42     }
43    
44     # delayed load of Carp and avoid recursion
45     require Carp;
46     Carp::croak ("Can't call bigint\-\>$name, not a valid method");
47     }
48    
49     sub upgrade
50     {
51     my $self = shift;
52     no strict 'refs';
53     # if (defined $_[0])
54     # {
55     # $Math::BigInt::upgrade = $_[0];
56     # }
57     return $Math::BigInt::upgrade;
58     }
59    
60     sub _constant
61     {
62     # this takes a floating point constant string and returns it truncated to
63     # integer. For instance, '4.5' => '4', '1.234e2' => '123' etc
64     my $float = shift;
65    
66     # some simple cases first
67     return $float if ($float =~ /^[+-]?[0-9]+$/); # '+123','-1','0' etc
68     return $float
69     if ($float =~ /^[+-]?[0-9]+\.?[eE]\+?[0-9]+$/); # 123e2, 123.e+2
70     return '0' if ($float =~ /^[+-]?[0]*\.[0-9]+$/); # .2, 0.2, -.1
71     if ($float =~ /^[+-]?[0-9]+\.[0-9]*$/) # 1., 1.23, -1.2 etc
72     {
73     $float =~ s/\..*//;
74     return $float;
75     }
76     my ($mis,$miv,$mfv,$es,$ev) = Math::BigInt::_split($float);
77     return $float if !defined $mis; # doesn't look like a number to me
78     my $ec = int($$ev);
79     my $sign = $$mis; $sign = '' if $sign eq '+';
80     if ($$es eq '-')
81     {
82     # ignore fraction part entirely
83     if ($ec >= length($$miv)) # 123.23E-4
84     {
85     return '0';
86     }
87     return $sign . substr ($$miv,0,length($$miv)-$ec); # 1234.45E-2 = 12
88     }
89     # xE+y
90     if ($ec >= length($$mfv))
91     {
92     $ec -= length($$mfv);
93     return $sign.$$miv.$$mfv if $ec == 0; # 123.45E+2 => 12345
94     return $sign.$$miv.$$mfv.'E'.$ec; # 123.45e+3 => 12345e1
95     }
96     $mfv = substr($$mfv,0,$ec);
97     return $sign.$$miv.$mfv; # 123.45e+1 => 1234
98     }
99    
100     sub import
101     {
102     my $self = shift;
103    
104     # some defaults
105     my $lib = '';
106    
107     my @import = ( ':constant' ); # drive it w/ constant
108     my @a = @_; my $l = scalar @_; my $j = 0;
109     my ($ver,$trace); # version? trace?
110     my ($a,$p); # accuracy, precision
111     for ( my $i = 0; $i < $l ; $i++,$j++ )
112     {
113     if ($_[$i] =~ /^(l|lib)$/)
114     {
115     # this causes a different low lib to take care...
116     $lib = $_[$i+1] || '';
117     my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
118     splice @a, $j, $s; $j -= $s; $i++;
119     }
120     elsif ($_[$i] =~ /^(a|accuracy)$/)
121     {
122     $a = $_[$i+1];
123     my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
124     splice @a, $j, $s; $j -= $s; $i++;
125     }
126     elsif ($_[$i] =~ /^(p|precision)$/)
127     {
128     $p = $_[$i+1];
129     my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
130     splice @a, $j, $s; $j -= $s; $i++;
131     }
132     elsif ($_[$i] =~ /^(v|version)$/)
133     {
134     $ver = 1;
135     splice @a, $j, 1; $j --;
136     }
137     elsif ($_[$i] =~ /^(t|trace)$/)
138     {
139     $trace = 1;
140     splice @a, $j, 1; $j --;
141     }
142     else { die "unknown option $_[$i]"; }
143     }
144     my $class;
145     $_lite = 0; # using M::BI::L ?
146     if ($trace)
147     {
148     require Math::BigInt::Trace; $class = 'Math::BigInt::Trace';
149     }
150     else
151     {
152     # see if we can find Math::BigInt::Lite
153     if (!defined $a && !defined $p) # rounding won't work to well
154     {
155     eval 'require Math::BigInt::Lite;';
156     if ($@ eq '')
157     {
158     @import = ( ); # :constant in Lite, not MBI
159     Math::BigInt::Lite->import( ':constant' );
160     $_lite= 1; # signal okay
161     }
162     }
163     require Math::BigInt if $_lite == 0; # not already loaded?
164     $class = 'Math::BigInt'; # regardless of MBIL or not
165     }
166     push @import, 'lib' => $lib if $lib ne '';
167     # Math::BigInt::Trace or plain Math::BigInt
168     $class->import(@import);
169    
170     bigint->accuracy($a) if defined $a;
171     bigint->precision($p) if defined $p;
172     if ($ver)
173     {
174     print "bigint\t\t\t v$VERSION\n";
175     print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite;
176     print "Math::BigInt\t\t v$Math::BigInt::VERSION";
177     my $config = Math::BigInt->config();
178     print " lib => $config->{lib} v$config->{lib_version}\n";
179     exit;
180     }
181     # we take care of floating point constants, since BigFloat isn't available
182     # and BigInt doesn't like them:
183     overload::constant float => sub { Math::BigInt->new( _constant(shift) ); };
184    
185     $self->export_to_level(1,$self,@a); # export inf and NaN
186     }
187    
188     sub inf () { Math::BigInt->binf(); }
189     sub NaN () { Math::BigInt->bnan(); }
190    
191     1;
192    
193     __END__
194    
195     =head1 NAME
196    
197     bigint - Transparent BigInteger support for Perl
198    
199     =head1 SYNOPSIS
200    
201     use bigint;
202    
203     $x = 2 + 4.5,"\n"; # BigInt 6
204     print 2 ** 512,"\n"; # really is what you think it is
205     print inf + 42,"\n"; # inf
206     print NaN * 7,"\n"; # NaN
207    
208     =head1 DESCRIPTION
209    
210     All operators (including basic math operations) are overloaded. Integer
211     constants are created as proper BigInts.
212    
213     Floating point constants are truncated to integer. All results are also
214     truncated.
215    
216     =head2 Options
217    
218     bigint recognizes some options that can be passed while loading it via use.
219     The options can (currently) be either a single letter form, or the long form.
220     The following options exist:
221    
222     =over 2
223    
224     =item a or accuracy
225    
226     This sets the accuracy for all math operations. The argument must be greater
227     than or equal to zero. See Math::BigInt's bround() function for details.
228    
229     perl -Mbigint=a,2 -le 'print 12345+1'
230    
231     =item p or precision
232    
233     This sets the precision for all math operations. The argument can be any
234     integer. Negative values mean a fixed number of digits after the dot, and
235     are <B>ignored</B> since all operations happen in integer space.
236     A positive value rounds to this digit left from the dot. 0 or 1 mean round to
237     integer and are ignore like negative values.
238    
239     See Math::BigInt's bfround() function for details.
240    
241     perl -Mbignum=p,5 -le 'print 123456789+123'
242    
243     =item t or trace
244    
245     This enables a trace mode and is primarily for debugging bigint or
246     Math::BigInt.
247    
248     =item l or lib
249    
250     Load a different math lib, see L<MATH LIBRARY>.
251    
252     perl -Mbigint=l,GMP -e 'print 2 ** 512'
253    
254     Currently there is no way to specify more than one library on the command
255     line. This will be hopefully fixed soon ;)
256    
257     =item v or version
258    
259     This prints out the name and version of all modules used and then exits.
260    
261     perl -Mbigint=v
262    
263     =head2 Math Library
264    
265     Math with the numbers is done (by default) by a module called
266     Math::BigInt::Calc. This is equivalent to saying:
267    
268     use bigint lib => 'Calc';
269    
270     You can change this by using:
271    
272     use bigint lib => 'BitVect';
273    
274     The following would first try to find Math::BigInt::Foo, then
275     Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
276    
277     use bigint lib => 'Foo,Math::BigInt::Bar';
278    
279     Please see respective module documentation for further details.
280    
281     =head2 Internal Format
282    
283     The numbers are stored as objects, and their internals might change at anytime,
284     especially between math operations. The objects also might belong to different
285     classes, like Math::BigInt, or Math::BigInt::Lite. Mixing them together, even
286     with normal scalars is not extraordinary, but normal and expected.
287    
288     You should not depend on the internal format, all accesses must go through
289     accessor methods. E.g. looking at $x->{sign} is not a good idea since there
290     is no guaranty that the object in question has such a hash key, nor is a hash
291     underneath at all.
292    
293     =head2 Sign
294    
295     The sign is either '+', '-', 'NaN', '+inf' or '-inf'.
296     You can access it with the sign() method.
297    
298     A sign of 'NaN' is used to represent the result when input arguments are not
299     numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
300     minus infinity. You will get '+inf' when dividing a positive number by 0, and
301     '-inf' when dividing any negative number by 0.
302    
303     =head2 Methods
304    
305     Since all numbers are now objects, you can use all functions that are part of
306     the BigInt API. You can only use the bxxx() notation, and not the fxxx()
307     notation, though.
308    
309     =head2 Caveat
310    
311     But a warning is in order. When using the following to make a copy of a number,
312     only a shallow copy will be made.
313    
314     $x = 9; $y = $x;
315     $x = $y = 7;
316    
317     Using the copy or the original with overloaded math is okay, e.g. the
318     following work:
319    
320     $x = 9; $y = $x;
321     print $x + 1, " ", $y,"\n"; # prints 10 9
322    
323     but calling any method that modifies the number directly will result in
324     B<both> the original and the copy beeing destroyed:
325    
326     $x = 9; $y = $x;
327     print $x->badd(1), " ", $y,"\n"; # prints 10 10
328    
329     $x = 9; $y = $x;
330     print $x->binc(1), " ", $y,"\n"; # prints 10 10
331    
332     $x = 9; $y = $x;
333     print $x->bmul(2), " ", $y,"\n"; # prints 18 18
334    
335     Using methods that do not modify, but testthe contents works:
336    
337     $x = 9; $y = $x;
338     $z = 9 if $x->is_zero(); # works fine
339    
340     See the documentation about the copy constructor and C<=> in overload, as
341     well as the documentation in BigInt for further details.
342    
343     =head1 MODULES USED
344    
345     C<bigint> is just a thin wrapper around various modules of the Math::BigInt
346     family. Think of it as the head of the family, who runs the shop, and orders
347     the others to do the work.
348    
349     The following modules are currently used by bigint:
350    
351     Math::BigInt::Lite (for speed, and only if it is loadable)
352     Math::BigInt
353    
354     =head1 EXAMPLES
355    
356     Some cool command line examples to impress the Python crowd ;) You might want
357     to compare them to the results under -Mbignum or -Mbigrat:
358    
359     perl -Mbigint -le 'print sqrt(33)'
360     perl -Mbigint -le 'print 2*255'
361     perl -Mbigint -le 'print 4.5+2*255'
362     perl -Mbigint -le 'print 3/7 + 5/7 + 8/3'
363     perl -Mbigint -le 'print 123->is_odd()'
364     perl -Mbigint -le 'print log(2)'
365     perl -Mbigint -le 'print 2 ** 0.5'
366     perl -Mbigint=a,65 -le 'print 2 ** 0.2'
367    
368     =head1 LICENSE
369    
370     This program is free software; you may redistribute it and/or modify it under
371     the same terms as Perl itself.
372    
373     =head1 SEE ALSO
374    
375     Especially L<bigrat> as in C<perl -Mbigrat -le 'print 1/3+1/4'> and
376     L<bignum> as in C<perl -Mbignum -le 'print sqrt(2)'>.
377    
378     L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
379     as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and L<Math::BigInt::GMP>.
380    
381     =head1 AUTHORS
382    
383     (C) by Tels L<http://bloodgate.com/> in early 2002 - 2005.
384    
385     =cut