extra code in pp_concat, Take 2
[p5sagit/p5-mst-13.2.git] / lib / bignum.pm
1 package bignum;
2 require 5.005;
3
4 $VERSION = '0.17';
5 use Exporter;
6 @EXPORT_OK      = qw( ); 
7 @EXPORT         = qw( inf NaN ); 
8 @ISA            = qw( Exporter );
9
10 use strict;
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       *{"bignum::$name"} = sub 
30         {
31         my $self = shift;
32         no strict 'refs';
33         if (defined $_[0])
34           {
35           Math::BigInt->$name($_[0]);
36           return Math::BigFloat->$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 bignum\-\>$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 #    $Math::BigFloat::upgrade = $_[0];
57 #    }
58   return $Math::BigInt::upgrade;
59   }
60
61 sub import 
62   {
63   my $self = shift;
64
65   # some defaults
66   my $lib = '';
67   my $upgrade = 'Math::BigFloat';
68   my $downgrade = 'Math::BigInt';
69
70   my @import = ( ':constant' );                         # drive it w/ constant
71   my @a = @_; my $l = scalar @_; my $j = 0;
72   my ($ver,$trace);                                     # version? trace?
73   my ($a,$p);                                           # accuracy, precision
74   for ( my $i = 0; $i < $l ; $i++,$j++ )
75     {
76     if ($_[$i] eq 'upgrade')
77       {
78       # this causes upgrading
79       $upgrade = $_[$i+1];              # or undef to disable
80       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
81       splice @a, $j, $s; $j -= $s; $i++;
82       }
83     elsif ($_[$i] eq 'downgrade')
84       {
85       # this causes downgrading
86       $downgrade = $_[$i+1];            # or undef to disable
87       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
88       splice @a, $j, $s; $j -= $s; $i++;
89       }
90     elsif ($_[$i] =~ /^(l|lib)$/)
91       {
92       # this causes a different low lib to take care...
93       $lib = $_[$i+1] || '';
94       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
95       splice @a, $j, $s; $j -= $s; $i++;
96       }
97     elsif ($_[$i] =~ /^(a|accuracy)$/)
98       {
99       $a = $_[$i+1];
100       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
101       splice @a, $j, $s; $j -= $s; $i++;
102       }
103     elsif ($_[$i] =~ /^(p|precision)$/)
104       {
105       $p = $_[$i+1];
106       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
107       splice @a, $j, $s; $j -= $s; $i++;
108       }
109     elsif ($_[$i] =~ /^(v|version)$/)
110       {
111       $ver = 1;
112       splice @a, $j, 1; $j --;
113       }
114     elsif ($_[$i] =~ /^(t|trace)$/)
115       {
116       $trace = 1;
117       splice @a, $j, 1; $j --;
118       }
119     else { die "unknown option $_[$i]"; }
120     }
121   my $class;
122   $_lite = 0;                                   # using M::BI::L ?
123   if ($trace)
124     {
125     require Math::BigInt::Trace; $class = 'Math::BigInt::Trace';
126     $upgrade = 'Math::BigFloat::Trace'; 
127     }
128   else
129     {
130     # see if we can find Math::BigInt::Lite
131     if (!defined $a && !defined $p)             # rounding won't work to well
132       {
133       eval 'require Math::BigInt::Lite;';
134       if ($@ eq '')
135         {
136         @import = ( );                          # :constant in Lite, not MBI
137         Math::BigInt::Lite->import( ':constant' );
138         $_lite= 1;                              # signal okay
139         }
140       }
141     require Math::BigInt if $_lite == 0;        # not already loaded?
142     $class = 'Math::BigInt';                    # regardless of MBIL or not
143     }
144   push @import, 'lib' => $lib if $lib ne ''; 
145   # Math::BigInt::Trace or plain Math::BigInt
146   $class->import(@import, upgrade => $upgrade);
147
148   if ($trace)
149     {
150     require Math::BigFloat::Trace; $class = 'Math::BigFloat::Trace';
151     $downgrade = 'Math::BigInt::Trace'; 
152     }
153   else
154     {
155     require Math::BigFloat; $class = 'Math::BigFloat';
156     }
157   $class->import(':constant','downgrade',$downgrade);
158
159   bignum->accuracy($a) if defined $a;
160   bignum->precision($p) if defined $p;
161   if ($ver)
162     {
163     print "bignum\t\t\t v$VERSION\n";
164     print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite;
165     print "Math::BigInt\t\t v$Math::BigInt::VERSION";
166     my $config = Math::BigInt->config();
167     print " lib => $config->{lib} v$config->{lib_version}\n";
168     print "Math::BigFloat\t\t v$Math::BigFloat::VERSION\n";
169     exit;
170     }
171   $self->export_to_level(1,$self,@a);           # export inf and NaN
172   }
173
174 sub inf () { Math::BigInt->binf(); }
175 sub NaN () { Math::BigInt->bnan(); }
176
177 1;
178
179 __END__
180
181 =head1 NAME
182
183 bignum - Transparent BigNumber support for Perl
184
185 =head1 SYNOPSIS
186
187   use bignum;
188
189   $x = 2 + 4.5,"\n";                    # BigFloat 6.5
190   print 2 ** 512 * 0.1,"\n";            # really is what you think it is
191   print inf * inf,"\n";                 # prints inf
192   print NaN * 3,"\n";                   # prints NaN
193
194 =head1 DESCRIPTION
195
196 All operators (including basic math operations) are overloaded. Integer and
197 floating-point constants are created as proper BigInts or BigFloats,
198 respectively.
199
200 If you do 
201
202         use bignum;
203
204 at the top of your script, Math::BigFloat and Math::BigInt will be loaded
205 and any constant number will be converted to an object (Math::BigFloat for
206 floats like 3.1415 and Math::BigInt for integers like 1234).
207
208 So, the following line:
209
210         $x = 1234;
211
212 creates actually a Math::BigInt and stores a reference to in $x.
213 This happens transparently and behind your back, so to speak.
214
215 You can see this with the following:
216
217         perl -Mbignum -le 'print ref(1234)'
218
219 Don't worry if it says Math::BigInt::Lite, bignum and friends will use Lite
220 if it is installed since it is faster for some operations. It will be
221 automatically upgraded to BigInt whenever neccessary:
222
223         perl -Mbignum -le 'print ref(2**255)'
224
225 This also means it is a bad idea to check for some specific package, since
226 the actual contents of $x might be something unexpected. Due to the
227 transparent way of bignum C<ref()> should not be neccessary, anyway.
228
229 Since Math::BigInt and BigFloat also overload the normal math operations,
230 the following line will still work:
231
232         perl -Mbignum -le 'print ref(1234+1234)'
233
234 Since numbers are actually objects, you can call all the usual methods from
235 BigInt/BigFloat on them. This even works to some extent on expressions:
236
237         perl -Mbignum -le '$x = 1234; print $x->bdec()'
238         perl -Mbignum -le 'print 1234->binc();'
239         perl -Mbignum -le 'print 1234->binc->badd(6);'
240         perl -Mbignum -le 'print +(1234)->binc()'
241
242 (Note that print doesn't do what you expect if the expression starts with
243 '(' hence the C<+>)
244
245 You can even chain the operations together as usual:
246
247         perl -Mbignum -le 'print 1234->binc->badd(6);'
248         1241
249
250 Under bignum (or bigint or bigrat), Perl will "upgrade" the numbers
251 appropriately. This means that:
252
253         perl -Mbignum -le 'print 1234+4.5'
254         1238.5
255
256 will work correctly. These mixed cases don't do always work when using
257 Math::BigInt or Math::BigFloat alone, or at least not in the way normal Perl
258 scalars work. 
259
260 If you do want to work with large integers like under C<use integer;>, try
261 C<use bigint;>:
262
263         perl -Mbigint -le 'print 1234.5+4.5'
264         1238
265
266 There is also C<use bigrat;> which gives you big rationals:
267
268         perl -Mbigrat -le 'print 1234+4.1'
269         12381/10
270
271 The entire upgrading/downgrading is still experimental and might not work
272 as you expect or may even have bugs.
273
274 You might get errors like this:
275
276         Can't use an undefined value as an ARRAY reference at
277         /usr/local/lib/perl5/5.8.0/Math/BigInt/Calc.pm line 864
278
279 This means somewhere a routine got a BigFloat/Lite but expected a BigInt (or
280 vice versa) and the upgrade/downgrad path was missing. This is a bug, please
281 report it so that we can fix it.
282
283 You might consider using just Math::BigInt or Math::BigFloat, since they
284 allow you finer control over what get's done in which module/space. For
285 instance, simple loop counters will be Math::BigInts under C<use bignum;> and
286 this is slower than keeping them as Perl scalars:
287
288         perl -Mbignum -le 'for ($i = 0; $i < 10; $i++) { print ref($i); }'
289
290 Please note the following does not work as expected (prints nothing), since
291 overloading of '..' is not yet possible in Perl (as of v5.8.0):
292
293         perl -Mbignum -le 'for (1..2) { print ref($_); }'
294
295 =head2 Options
296
297 bignum recognizes some options that can be passed while loading it via use.
298 The options can (currently) be either a single letter form, or the long form.
299 The following options exist:
300
301 =over 2
302
303 =item a or accuracy
304
305 This sets the accuracy for all math operations. The argument must be greater
306 than or equal to zero. See Math::BigInt's bround() function for details.
307
308         perl -Mbignum=a,50 -le 'print sqrt(20)'
309
310 =item p or precision
311
312 This sets the precision for all math operations. The argument can be any
313 integer. Negative values mean a fixed number of digits after the dot, while
314 a positive value rounds to this digit left from the dot. 0 or 1 mean round to
315 integer. See Math::BigInt's bfround() function for details.
316
317         perl -Mbignum=p,-50 -le 'print sqrt(20)'
318
319 =item t or trace
320
321 This enables a trace mode and is primarily for debugging bignum or
322 Math::BigInt/Math::BigFloat.
323
324 =item l or lib
325
326 Load a different math lib, see L<MATH LIBRARY>.
327
328         perl -Mbignum=l,GMP -e 'print 2 ** 512'
329
330 Currently there is no way to specify more than one library on the command
331 line. This will be hopefully fixed soon ;)
332
333 =item v or version
334
335 This prints out the name and version of all modules used and then exits.
336
337         perl -Mbignum=v
338
339 =head2 Methods
340
341 Beside import() and AUTOLOAD() there are only a few other methods.
342
343 Since all numbers are now objects, you can use all functions that are part of
344 the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not
345 the fxxx() notation, though. This makes it possible that the underlying object
346 might morph into a different class than BigFloat.
347
348 =head2 Caveat
349
350 But a warning is in order. When using the following to make a copy of a number,
351 only a shallow copy will be made.
352
353         $x = 9; $y = $x;
354         $x = $y = 7;
355
356 If you want to make a real copy, use the following:
357
358         $y = $x->copy();
359
360 Using the copy or the original with overloaded math is okay, e.g. the
361 following work:
362
363         $x = 9; $y = $x;
364         print $x + 1, " ", $y,"\n";     # prints 10 9
365
366 but calling any method that modifies the number directly will result in
367 B<both> the original and the copy beeing destroyed:
368
369         $x = 9; $y = $x;
370         print $x->badd(1), " ", $y,"\n";        # prints 10 10
371
372         $x = 9; $y = $x;
373         print $x->binc(1), " ", $y,"\n";        # prints 10 10
374
375         $x = 9; $y = $x;
376         print $x->bmul(2), " ", $y,"\n";        # prints 18 18
377
378 Using methods that do not modify, but testthe contents works:
379
380         $x = 9; $y = $x;
381         $z = 9 if $x->is_zero();                # works fine
382
383 See the documentation about the copy constructor and C<=> in overload, as
384 well as the documentation in BigInt for further details.
385
386 =over 2
387
388 =item inf()
389
390 A shortcut to return Math::BigInt->binf(). Usefull because Perl does not always
391 handle bareword C<inf> properly.
392
393 =item NaN()
394
395 A shortcut to return Math::BigInt->bnan(). Usefull because Perl does not always
396 handle bareword C<NaN> properly.
397
398 =item upgrade()
399
400 Return the class that numbers are upgraded to, is in fact returning
401 C<$Math::BigInt::upgrade>.
402
403 =back
404
405 =head2 MATH LIBRARY
406
407 Math with the numbers is done (by default) by a module called
408 Math::BigInt::Calc. This is equivalent to saying:
409
410         use bignum lib => 'Calc';
411
412 You can change this by using:
413
414         use bignum lib => 'BitVect';
415
416 The following would first try to find Math::BigInt::Foo, then
417 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
418
419         use bignum lib => 'Foo,Math::BigInt::Bar';
420
421 Please see respective module documentation for further details.
422
423 =head2 INTERNAL FORMAT
424
425 The numbers are stored as objects, and their internals might change at anytime,
426 especially between math operations. The objects also might belong to different
427 classes, like Math::BigInt, or Math::BigFLoat. Mixing them together, even
428 with normal scalars is not extraordinary, but normal and expected.
429
430 You should not depend on the internal format, all accesses must go through
431 accessor methods. E.g. looking at $x->{sign} is not a bright idea since there
432 is no guaranty that the object in question has such a hashkey, nor is a hash
433 underneath at all.
434
435 =head2 SIGN
436
437 The sign is either '+', '-', 'NaN', '+inf' or '-inf' and stored seperately.
438 You can access it with the sign() method.
439
440 A sign of 'NaN' is used to represent the result when input arguments are not
441 numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
442 minus infinity. You will get '+inf' when dividing a positive number by 0, and
443 '-inf' when dividing any negative number by 0.
444
445 =head1 MODULES USED
446
447 C<bignum> is just a thin wrapper around various modules of the Math::BigInt
448 family. Think of it as the head of the family, who runs the shop, and orders
449 the others to do the work.
450
451 The following modules are currently used by bignum:
452
453         Math::BigInt::Lite      (for speed, and only if it is loadable)
454         Math::BigInt
455         Math::BigFloat
456
457 =head1 EXAMPLES
458
459 Some cool command line examples to impress the Python crowd ;)
460  
461         perl -Mbignum -le 'print sqrt(33)'
462         perl -Mbignum -le 'print 2*255'
463         perl -Mbignum -le 'print 4.5+2*255'
464         perl -Mbignum -le 'print 3/7 + 5/7 + 8/3'
465         perl -Mbignum -le 'print 123->is_odd()'
466         perl -Mbignum -le 'print log(2)'
467         perl -Mbignum -le 'print 2 ** 0.5'
468         perl -Mbignum=a,65 -le 'print 2 ** 0.2'
469
470 =head1 LICENSE
471
472 This program is free software; you may redistribute it and/or modify it under
473 the same terms as Perl itself.
474
475 =head1 SEE ALSO
476
477 Especially L<bigrat> as in C<perl -Mbigrat -le 'print 1/3+1/4'>.
478
479 L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
480 as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and  L<Math::BigInt::GMP>.
481
482 =head1 AUTHORS
483
484 (C) by Tels L<http://bloodgate.com/> in early 2002, 2003.
485
486 =cut