extra code in pp_concat, Take 2
[p5sagit/p5-mst-13.2.git] / lib / bigint.pm
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