[ PATCH ] mymalloc on HP-UX
[p5sagit/p5-mst-13.2.git] / lib / bignum.pm
1 package bignum;
2 require 5.005;
3
4 $VERSION = '0.11';
5 use Exporter;
6 @ISA =       qw( Exporter );
7 @EXPORT_OK = qw( ); 
8
9 use strict;
10
11 ############################################################################## 
12
13 # These are all alike, and thus faked by AUTOLOAD
14
15 my @faked = qw/round_mode accuracy precision div_scale/;
16 use vars qw/$VERSION $AUTOLOAD $_lite/;         # _lite for testsuite
17
18 sub AUTOLOAD
19   {
20   my $name = $AUTOLOAD;
21
22   $name =~ s/.*:://;    # split package
23   no strict 'refs';
24   foreach my $n (@faked)
25     {
26     if ($n eq $name)
27       {
28       *{"bignum::$name"} = sub 
29         {
30         my $self = shift;
31         no strict 'refs';
32         if (defined $_[0])
33           {
34           Math::BigInt->$name($_[0]);
35           Math::BigFloat->$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 bignum\-\>$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 #    $Math::BigFloat::upgrade = $_[0];
56 #    }
57   return $Math::BigInt::upgrade;
58   }
59
60 sub import 
61   {
62   my $self = shift;
63
64   # some defaults
65   my $lib = 'Calc';
66   my $upgrade = 'Math::BigFloat';
67   my $downgrade = 'Math::BigInt';
68
69   my @import = ( ':constant' );                         # drive it w/ constant
70   my @a = @_; my $l = scalar @_; my $j = 0;
71   my ($ver,$trace);                                     # version? trace?
72   my ($a,$p);                                           # accuracy, precision
73   for ( my $i = 0; $i < $l ; $i++,$j++ )
74     {
75     if ($_[$i] eq 'upgrade')
76       {
77       # this causes upgrading
78       $upgrade = $_[$i+1];              # or undef to disable
79       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
80       splice @a, $j, $s; $j -= $s; $i++;
81       }
82     elsif ($_[$i] eq 'downgrade')
83       {
84       # this causes downgrading
85       $downgrade = $_[$i+1];            # or undef to disable
86       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
87       splice @a, $j, $s; $j -= $s; $i++;
88       }
89     elsif ($_[$i] =~ /^(l|lib)$/)
90       {
91       # this causes a different low lib to take care...
92       $lib = $_[$i+1] || '';
93       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
94       splice @a, $j, $s; $j -= $s; $i++;
95       }
96     elsif ($_[$i] =~ /^(a|accuracy)$/)
97       {
98       $a = $_[$i+1];
99       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
100       splice @a, $j, $s; $j -= $s; $i++;
101       }
102     elsif ($_[$i] =~ /^(p|precision)$/)
103       {
104       $p = $_[$i+1];
105       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
106       splice @a, $j, $s; $j -= $s; $i++;
107       }
108     elsif ($_[$i] =~ /^(v|version)$/)
109       {
110       $ver = 1;
111       splice @a, $j, 1; $j --;
112       }
113     elsif ($_[$i] =~ /^(t|trace)$/)
114       {
115       $trace = 1;
116       splice @a, $j, 1; $j --;
117       }
118     else { die "unknown option $_[$i]"; }
119     }
120   my $class;
121   $_lite = 0;                                   # using M::BI::L ?
122   if ($trace)
123     {
124     require Math::BigInt::Trace; $class = 'Math::BigInt::Trace';
125     $upgrade = 'Math::BigFloat::Trace'; 
126     }
127   else
128     {
129     # see if we can find Math::BigInt::Lite
130     if (!defined $a && !defined $p)             # rounding won't work to well
131       {
132       eval 'require Math::BigInt::Lite;';
133       if ($@ eq '')
134         {
135         @import = ( );                          # :constant in Lite, not MBI
136         Math::BigInt::Lite->import( ':constant' );
137         $_lite= 1;                              # signal okay
138         }
139       }
140     require Math::BigInt if $_lite == 0;        # not already loaded?
141     $class = 'Math::BigInt';                    # regardless of MBIL or not
142     } 
143   # Math::BigInt::Trace or plain Math::BigInt
144   $class->import(@import, upgrade => $upgrade, lib => $lib);
145
146   if ($trace)
147     {
148     require Math::BigFloat::Trace; $class = 'Math::BigFloat::Trace';
149     $downgrade = 'Math::BigInt::Trace'; 
150     }
151   else
152     {
153     require Math::BigFloat; $class = 'Math::BigFloat';
154     }
155   $class->import(':constant','downgrade',$downgrade);
156
157   bignum->accuracy($a) if defined $a;
158   bignum->precision($p) if defined $p;
159   if ($ver)
160     {
161     print "bignum\t\t\t v$VERSION\n";
162     print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite;
163     print "Math::BigInt\t\t v$Math::BigInt::VERSION";
164     my $config = Math::BigInt->config();
165     print " lib => $config->{lib} v$config->{lib_version}\n";
166     print "Math::BigFloat\t\t v$Math::BigFloat::VERSION\n";
167     exit;
168     }
169   }
170
171 1;
172
173 __END__
174
175 =head1 NAME
176
177 bignum - Transparent BigNumber support for Perl
178
179 =head1 SYNOPSIS
180
181   use bignum;
182
183   $x = 2 + 4.5,"\n";                    # BigFloat 6.5
184   print 2 ** 512 * 0.1;                 # really is what you think it is
185
186 =head1 DESCRIPTION
187
188 All operators (including basic math operations) are overloaded. Integer and
189 floating-point constants are created as proper BigInts or BigFloats,
190 respectively.
191
192 =head2 OPTIONS
193
194 bignum recognizes some options that can be passed while loading it via use.
195 The options can (currently) be either a single letter form, or the long form.
196 The following options exist:
197
198 =over 2
199
200 =item a or accuracy
201
202 This sets the accuracy for all math operations. The argument must be greater
203 than or equal to zero. See Math::BigInt's bround() function for details.
204
205         perl -Mbignum=a,50 -le 'print sqrt(20)'
206
207 =item p or precision
208
209 This sets the precision for all math operations. The argument can be any
210 integer. Negative values mean a fixed number of digits after the dot, while
211 a positive value rounds to this digit left from the dot. 0 or 1 mean round to
212 integer. See Math::BigInt's bfround() function for details.
213
214         perl -Mbignum=p,-50 -le 'print sqrt(20)'
215
216 =item t or trace
217
218 This enables a trace mode and is primarily for debugging bignum or
219 Math::BigInt/Math::BigFloat.
220
221 =item l or lib
222
223 Load a different math lib, see L<MATH LIBRARY>.
224
225         perl -Mbignum=l,GMP -e 'print 2 ** 512'
226
227 Currently there is no way to specify more than one library on the command
228 line. This will be hopefully fixed soon ;)
229
230 =item v or version
231
232 This prints out the name and version of all modules used and then exits.
233
234         perl -Mbignum=v -e ''
235
236 =head2 MATH LIBRARY
237
238 Math with the numbers is done (by default) by a module called
239 Math::BigInt::Calc. This is equivalent to saying:
240
241         use bignum lib => 'Calc';
242
243 You can change this by using:
244
245         use bignum lib => 'BitVect';
246
247 The following would first try to find Math::BigInt::Foo, then
248 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
249
250         use bignum lib => 'Foo,Math::BigInt::Bar';
251
252 Please see respective module documentation for further details.
253
254 =head2 INTERNAL FORMAT
255
256 The numbers are stored as objects, and their internals might change at anytime,
257 especially between math operations. The objects also might belong to different
258 classes, like Math::BigInt, or Math::BigFLoat. Mixing them together, even
259 with normal scalars is not extraordinary, but normal and expected.
260
261 You should not depend on the internal format, all accesses must go through
262 accessor methods. E.g. looking at $x->{sign} is not a bright idea since there
263 is no guaranty that the object in question has such a hashkey, nor is a hash
264 underneath at all.
265
266 =head2 SIGN
267
268 The sign is either '+', '-', 'NaN', '+inf' or '-inf' and stored seperately.
269 You can access it with the sign() method.
270
271 A sign of 'NaN' is used to represent the result when input arguments are not
272 numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
273 minus infinity. You will get '+inf' when dividing a positive number by 0, and
274 '-inf' when dividing any negative number by 0.
275
276 =head2 METHODS
277
278 Since all numbers are now objects, you can use all functions that are part of
279 the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not
280 the fxxx() notation, though. This makes it possible that the underlying object
281 might morph into a different class than BigFloat.
282
283 =head1 MODULES USED
284
285 C<bignum> is just a thin wrapper around various modules of the Math::BigInt
286 family. Think of it as the head of the family, who runs the shop, and orders
287 the others to do the work.
288
289 The following modules are currently used by bignum:
290
291         Math::BigInt::Lite      (for speed, and only if it is loadable)
292         Math::BigInt
293         Math::BigFloat
294
295 =head1 EXAMPLES
296
297 Some cool command line examples to impress the Python crowd ;)
298  
299         perl -Mbignum -le 'print sqrt(33)'
300         perl -Mbignum -le 'print 2*255'
301         perl -Mbignum -le 'print 4.5+2*255'
302         perl -Mbignum -le 'print 3/7 + 5/7 + 8/3'
303         perl -Mbignum -le 'print 123->is_odd()'
304         perl -Mbignum -le 'print log(2)'
305         perl -Mbignum -le 'print 2 ** 0.5'
306         perl -Mbignum=a,65 -le 'print 2 ** 0.2'
307
308 =head1 LICENSE
309
310 This program is free software; you may redistribute it and/or modify it under
311 the same terms as Perl itself.
312
313 =head1 SEE ALSO
314
315 Especially L<bigrat> as in C<perl -Mbigrat -le 'print 1/3+1/4'>.
316
317 L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
318 as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and  L<Math::BigInt::GMP>.
319
320 =head1 AUTHORS
321
322 (C) by Tels L<http://bloodgate.com/> in early 2002.
323
324 =cut