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