This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
fa59d3bac966486fee69f513430d9953d991b859
[perl5.git] / lib / bigint.pm
1 package bigint;
2 require 5.005;
3
4 $VERSION = '0.03';
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           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 = 'Calc';
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   # Math::BigInt::Trace or plain Math::BigInt
167   $class->import(@import, lib => $lib);
168
169   bigint->accuracy($a) if defined $a;
170   bigint->precision($p) if defined $p;
171   if ($ver)
172     {
173     print "bigint\t\t\t v$VERSION\n";
174     print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite;
175     print "Math::BigInt\t\t v$Math::BigInt::VERSION";
176     my $config = Math::BigInt->config();
177     print " lib => $config->{lib} v$config->{lib_version}\n";
178     exit;
179     }
180   # we take care of floating point constants, since BigFloat isn't available
181   # and BigInt doesn't like them:
182   overload::constant float => sub { Math::BigInt->new( _constant(shift) ); };
183
184   $self->export_to_level(1,$self,@a);           # export inf and NaN
185   }
186
187 sub inf () { Math::BigInt->binf(); }
188 sub NaN () { Math::BigInt->bnan(); }
189
190 1;
191
192 __END__
193
194 =head1 NAME
195
196 bigint - Transparent BigInteger support for Perl
197
198 =head1 SYNOPSIS
199
200   use bignt;
201
202   $x = 2 + 4.5,"\n";                    # BigInt 6
203   print 2 ** 512,"\n";                  # really is what you think it is
204   print inf + 42,"\n";                  # inf
205   print NaN * 7,"\n";                   # NaN
206
207 =head1 DESCRIPTION
208
209 All operators (including basic math operations) are overloaded. Integer
210 constants are created as proper BigInts.
211
212 Floating point constants are truncated to integer. All results are also
213 trunctaed.
214
215 =head2 OPTIONS
216
217 bigint recognizes some options that can be passed while loading it via use.
218 The options can (currently) be either a single letter form, or the long form.
219 The following options exist:
220
221 =over 2
222
223 =item a or accuracy
224
225 This sets the accuracy for all math operations. The argument must be greater
226 than or equal to zero. See Math::BigInt's bround() function for details.
227
228         perl -Mbigint=a,2 -le 'print 12345+1'
229
230 =item p or precision
231
232 This sets the precision for all math operations. The argument can be any
233 integer. Negative values mean a fixed number of digits after the dot, and
234 are <B>ignored</B> since all operations happen in integer space.
235 A positive value rounds to this digit left from the dot. 0 or 1 mean round to
236 integer and are ignore like negative values.
237
238 See Math::BigInt's bfround() function for details.
239
240         perl -Mbignum=p,5 -le 'print 123456789+123'
241
242 =item t or trace
243
244 This enables a trace mode and is primarily for debugging bigint or
245 Math::BigInt.
246
247 =item l or lib
248
249 Load a different math lib, see L<MATH LIBRARY>.
250
251         perl -Mbigint=l,GMP -e 'print 2 ** 512'
252
253 Currently there is no way to specify more than one library on the command
254 line. This will be hopefully fixed soon ;)
255
256 =item v or version
257
258 This prints out the name and version of all modules used and then exits.
259
260         perl -Mbigint=v -e ''
261
262 =head2 MATH LIBRARY
263
264 Math with the numbers is done (by default) by a module called
265 Math::BigInt::Calc. This is equivalent to saying:
266
267         use bigint lib => 'Calc';
268
269 You can change this by using:
270
271         use bigint lib => 'BitVect';
272
273 The following would first try to find Math::BigInt::Foo, then
274 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
275
276         use bigint lib => 'Foo,Math::BigInt::Bar';
277
278 Please see respective module documentation for further details.
279
280 =head2 INTERNAL FORMAT
281
282 The numbers are stored as objects, and their internals might change at anytime,
283 especially between math operations. The objects also might belong to different
284 classes, like Math::BigInt, or Math::BigInt::Lite. Mixing them together, even
285 with normal scalars is not extraordinary, but normal and expected.
286
287 You should not depend on the internal format, all accesses must go through
288 accessor methods. E.g. looking at $x->{sign} is not a bright idea since there
289 is no guaranty that the object in question has such a hash key, nor is a hash
290 underneath at all.
291
292 =head2 SIGN
293
294 The sign is either '+', '-', 'NaN', '+inf' or '-inf' and stored seperately.
295 You can access it with the sign() method.
296
297 A sign of 'NaN' is used to represent the result when input arguments are not
298 numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
299 minus infinity. You will get '+inf' when dividing a positive number by 0, and
300 '-inf' when dividing any negative number by 0.
301
302 =head2 METHODS
303
304 Since all numbers are now objects, you can use all functions that are part of
305 the BigInt API. You can only use the bxxx() notation, and not the fxxx()
306 notation, though. 
307
308 =head1 MODULES USED
309
310 C<bigint> is just a thin wrapper around various modules of the Math::BigInt
311 family. Think of it as the head of the family, who runs the shop, and orders
312 the others to do the work.
313
314 The following modules are currently used by bigint:
315
316         Math::BigInt::Lite      (for speed, and only if it is loadable)
317         Math::BigInt
318
319 =head1 EXAMPLES
320
321 Some cool command line examples to impress the Python crowd ;) You might want
322 to compare them to the results under -Mbignum or -Mbigrat:
323  
324         perl -Mbigint -le 'print sqrt(33)'
325         perl -Mbigint -le 'print 2*255'
326         perl -Mbigint -le 'print 4.5+2*255'
327         perl -Mbigint -le 'print 3/7 + 5/7 + 8/3'
328         perl -Mbigint -le 'print 123->is_odd()'
329         perl -Mbigint -le 'print log(2)'
330         perl -Mbigint -le 'print 2 ** 0.5'
331         perl -Mbigint=a,65 -le 'print 2 ** 0.2'
332
333 =head1 LICENSE
334
335 This program is free software; you may redistribute it and/or modify it under
336 the same terms as Perl itself.
337
338 =head1 SEE ALSO
339
340 Especially L<bigrat> as in C<perl -Mbigrat -le 'print 1/3+1/4'> and
341 L<bignum> as in C<perl -Mbignum -le 'print sqrt(2)'>.
342
343 L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
344 as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and  L<Math::BigInt::GMP>.
345
346 =head1 AUTHORS
347
348 (C) by Tels L<http://bloodgate.com/> in early 2002.
349
350 =cut