fix warning + carp interaction
[p5sagit/p5-mst-13.2.git] / lib / bigint.pm
1 package bigint;
2 require 5.005;
3
4 $VERSION = '0.02';
5 use Exporter;
6 @ISA =       qw( Exporter );
7 @EXPORT_OK = qw( ); 
8
9 use strict;
10 use overload;
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       *{"bigint::$name"} = sub 
30         {
31         my $self = shift;
32         no strict 'refs';
33         if (defined $_[0])
34           {
35           Math::BigInt->$name($_[0]);
36           }
37         return Math::BigInt->$name();
38         };
39       return &$name;
40       }
41     }
42  
43   # delayed load of Carp and avoid recursion
44   require Carp;
45   Carp::croak ("Can't call bigint\-\>$name, not a valid method");
46   }
47
48 sub upgrade
49   {
50   my $self = shift;
51   no strict 'refs';
52 #  if (defined $_[0])
53 #    {
54 #    $Math::BigInt::upgrade = $_[0];
55 #    }
56   return $Math::BigInt::upgrade;
57   }
58
59 sub _constant
60   {
61   # this takes a floating point constant string and returns it truncated to
62   # integer. For instance, '4.5' => '4', '1.234e2' => '123' etc
63   my $float = shift;
64
65   # some simple cases first
66   return $float if ($float =~ /^[+-]?[0-9]+$/);         # '+123','-1','0' etc
67   return $float 
68     if ($float =~ /^[+-]?[0-9]+\.?[eE]\+?[0-9]+$/);     # 123e2, 123.e+2
69   return '0' if ($float =~ /^[+-]?[0]*\.[0-9]+$/);      # .2, 0.2, -.1
70   if ($float =~ /^[+-]?[0-9]+\.[0-9]*$/)                # 1., 1.23, -1.2 etc
71     {
72     $float =~ s/\..*//;
73     return $float;
74     }
75   my ($mis,$miv,$mfv,$es,$ev) = Math::BigInt::_split(\$float);
76   return $float if !defined $mis;       # doesn't look like a number to me
77   my $ec = int($$ev);
78   my $sign = $$mis; $sign = '' if $sign eq '+';
79   if ($$es eq '-')
80     {
81     # ignore fraction part entirely
82     if ($ec >= length($$miv))                   # 123.23E-4
83       {
84       return '0';
85       }
86     return $sign . substr ($$miv,0,length($$miv)-$ec);  # 1234.45E-2 = 12
87     }
88   # xE+y
89   if ($ec >= length($$mfv))
90     {
91     $ec -= length($$mfv);                       
92     return $sign.$$miv.$$mfv if $ec == 0;       # 123.45E+2 => 12345
93     return $sign.$$miv.$$mfv.'E'.$ec;           # 123.45e+3 => 12345e1
94     }
95   $mfv = substr($$mfv,0,$ec);
96   return $sign.$$miv.$mfv;                      # 123.45e+1 => 1234
97   }
98
99 sub import 
100   {
101   my $self = shift;
102
103   # some defaults
104   my $lib = 'Calc';
105
106   my @import = ( ':constant' );                         # drive it w/ constant
107   my @a = @_; my $l = scalar @_; my $j = 0;
108   my ($ver,$trace);                                     # version? trace?
109   my ($a,$p);                                           # accuracy, precision
110   for ( my $i = 0; $i < $l ; $i++,$j++ )
111     {
112     if ($_[$i] =~ /^(l|lib)$/)
113       {
114       # this causes a different low lib to take care...
115       $lib = $_[$i+1] || '';
116       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
117       splice @a, $j, $s; $j -= $s; $i++;
118       }
119     elsif ($_[$i] =~ /^(a|accuracy)$/)
120       {
121       $a = $_[$i+1];
122       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
123       splice @a, $j, $s; $j -= $s; $i++;
124       }
125     elsif ($_[$i] =~ /^(p|precision)$/)
126       {
127       $p = $_[$i+1];
128       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
129       splice @a, $j, $s; $j -= $s; $i++;
130       }
131     elsif ($_[$i] =~ /^(v|version)$/)
132       {
133       $ver = 1;
134       splice @a, $j, 1; $j --;
135       }
136     elsif ($_[$i] =~ /^(t|trace)$/)
137       {
138       $trace = 1;
139       splice @a, $j, 1; $j --;
140       }
141     else { die "unknown option $_[$i]"; }
142     }
143   my $class;
144   $_lite = 0;                                   # using M::BI::L ?
145   if ($trace)
146     {
147     require Math::BigInt::Trace; $class = 'Math::BigInt::Trace';
148 #    print STDERR "Loading $class";
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
185 1;
186
187 __END__
188
189 =head1 NAME
190
191 bigint - Transparent big integer support for Perl
192
193 =head1 SYNOPSIS
194
195   use bignt;
196
197   $x = 2 + 4.5,"\n";                    # BigInt 6
198   print 2 ** 512;                       # really is what you think it is
199
200 =head1 DESCRIPTION
201
202 All operators (including basic math operations) are overloaded. Integer
203 constants are created as proper BigInts.
204
205 Floating point constants are truncated to integer. All results are also
206 trunctaed.
207
208 =head2 OPTIONS
209
210 bigint recognizes some options that can be passed while loading it via use.
211 The options can (currently) be either a single letter form, or the long form.
212 The following options exist:
213
214 =over 2
215
216 =item a or accuracy
217
218 This sets the accuracy for all math operations. The argument must be greater
219 than or equal to zero. See Math::BigInt's bround() function for details.
220
221         perl -Mbigint=a,2 -le 'print 12345+1'
222
223 =item p or precision
224
225 This sets the precision for all math operations. The argument can be any
226 integer. Negative values mean a fixed number of digits after the dot, and
227 are <B>ignored</B> since all operations happen in integer space.
228 A positive value rounds to this digit left from the dot. 0 or 1 mean round to
229 integer and are ignore like negative values.
230
231 See Math::BigInt's bfround() function for details.
232
233         perl -Mbignum=p,5 -le 'print 123456789+123'
234
235 =item t or trace
236
237 This enables a trace mode and is primarily for debugging bigint or
238 Math::BigInt.
239
240 =item l or lib
241
242 Load a different math lib, see L<MATH LIBRARY>.
243
244         perl -Mbigint=l,GMP -e 'print 2 ** 512'
245
246 Currently there is no way to specify more than one library on the command
247 line. This will be hopefully fixed soon ;)
248
249 =item v or version
250
251 This prints out the name and version of all modules used and then exits.
252
253         perl -Mbigint=v -e ''
254
255 =head2 MATH LIBRARY
256
257 Math with the numbers is done (by default) by a module called
258 Math::BigInt::Calc. This is equivalent to saying:
259
260         use bigint lib => 'Calc';
261
262 You can change this by using:
263
264         use bigint lib => 'BitVect';
265
266 The following would first try to find Math::BigInt::Foo, then
267 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
268
269         use bigint lib => 'Foo,Math::BigInt::Bar';
270
271 Please see respective module documentation for further details.
272
273 =head2 INTERNAL FORMAT
274
275 The numbers are stored as objects, and their internals might change at anytime,
276 especially between math operations. The objects also might belong to different
277 classes, like Math::BigInt, or Math::BigInt::Lite. Mixing them together, even
278 with normal scalars is not extraordinary, but normal and expected.
279
280 You should not depend on the internal format, all accesses must go through
281 accessor methods. E.g. looking at $x->{sign} is not a bright idea since there
282 is no guaranty that the object in question has such a hash key, nor is a hash
283 underneath at all.
284
285 =head2 SIGN
286
287 The sign is either '+', '-', 'NaN', '+inf' or '-inf' and stored seperately.
288 You can access it with the sign() method.
289
290 A sign of 'NaN' is used to represent the result when input arguments are not
291 numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
292 minus infinity. You will get '+inf' when dividing a positive number by 0, and
293 '-inf' when dividing any negative number by 0.
294
295 =head2 METHODS
296
297 Since all numbers are now objects, you can use all functions that are part of
298 the BigInt API. You can only use the bxxx() notation, and not the fxxx()
299 notation, though. 
300
301 =head1 MODULES USED
302
303 C<bigint> is just a thin wrapper around various modules of the Math::BigInt
304 family. Think of it as the head of the family, who runs the shop, and orders
305 the others to do the work.
306
307 The following modules are currently used by bigint:
308
309         Math::BigInt::Lite      (for speed, and only if it is loadable)
310         Math::BigInt
311
312 =head1 EXAMPLES
313
314 Some cool command line examples to impress the Python crowd ;) You might want
315 to compare them to the results under -Mbignum or -Mbigrat:
316  
317         perl -Mbigint -le 'print sqrt(33)'
318         perl -Mbigint -le 'print 2*255'
319         perl -Mbigint -le 'print 4.5+2*255'
320         perl -Mbigint -le 'print 3/7 + 5/7 + 8/3'
321         perl -Mbigint -le 'print 123->is_odd()'
322         perl -Mbigint -le 'print log(2)'
323         perl -Mbigint -le 'print 2 ** 0.5'
324         perl -Mbigint=a,65 -le 'print 2 ** 0.2'
325
326 =head1 LICENSE
327
328 This program is free software; you may redistribute it and/or modify it under
329 the same terms as Perl itself.
330
331 =head1 SEE ALSO
332
333 Especially L<bigrat> as in C<perl -Mbigrat -le 'print 1/3+1/4'> and
334 L<bignum> as in C<perl -Mbignum -le 'print sqrt(2)'>.
335
336 L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
337 as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and  L<Math::BigInt::GMP>.
338
339 =head1 AUTHORS
340
341 (C) by Tels L<http://bloodgate.com/> in early 2002.
342
343 =cut