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