This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Shell.pm: pod rewrite and new mini-feature $Shell::raw
[perl5.git] / lib / bigint.pm
CommitLineData
126f3c5f
JH
1package bigint;
2require 5.005;
3
27e7b8bb 4$VERSION = '0.05';
126f3c5f 5use Exporter;
b4bc5691
T
6@ISA = qw( Exporter );
7@EXPORT_OK = qw( );
8@EXPORT = qw( inf NaN );
126f3c5f
JH
9
10use strict;
11use overload;
12
13##############################################################################
14
15# These are all alike, and thus faked by AUTOLOAD
16
17my @faked = qw/round_mode accuracy precision div_scale/;
18use vars qw/$VERSION $AUTOLOAD $_lite/; # _lite for testsuite
19
20sub 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 {
990fb837 36 return Math::BigInt->$name($_[0]);
126f3c5f
JH
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
49sub 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
60sub _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 }
9b924220 76 my ($mis,$miv,$mfv,$es,$ev) = Math::BigInt::_split($float);
126f3c5f
JH
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
100sub import
101 {
102 my $self = shift;
103
104 # some defaults
105 my $lib = 'Calc';
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';
126f3c5f
JH
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 # Math::BigInt::Trace or plain Math::BigInt
167 $class->import(@import, lib => $lib);
168
169 bigint->accuracy($a) if defined $a;
170 bigint->precision($p) if defined $p;
171 if ($ver)
172 {
173 print "bigint\t\t\t v$VERSION\n";
174 print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite;
175 print "Math::BigInt\t\t v$Math::BigInt::VERSION";
176 my $config = Math::BigInt->config();
177 print " lib => $config->{lib} v$config->{lib_version}\n";
178 exit;
179 }
180 # we take care of floating point constants, since BigFloat isn't available
181 # and BigInt doesn't like them:
182 overload::constant float => sub { Math::BigInt->new( _constant(shift) ); };
b4bc5691
T
183
184 $self->export_to_level(1,$self,@a); # export inf and NaN
126f3c5f
JH
185 }
186
b4bc5691
T
187sub inf () { Math::BigInt->binf(); }
188sub NaN () { Math::BigInt->bnan(); }
189
126f3c5f
JH
1901;
191
192__END__
193
194=head1 NAME
195
b4bc5691 196bigint - Transparent BigInteger support for Perl
126f3c5f
JH
197
198=head1 SYNOPSIS
199
200 use bignt;
201
202 $x = 2 + 4.5,"\n"; # BigInt 6
b4bc5691
T
203 print 2 ** 512,"\n"; # really is what you think it is
204 print inf + 42,"\n"; # inf
205 print NaN * 7,"\n"; # NaN
126f3c5f
JH
206
207=head1 DESCRIPTION
208
209All operators (including basic math operations) are overloaded. Integer
210constants are created as proper BigInts.
211
212Floating point constants are truncated to integer. All results are also
990fb837 213truncated.
126f3c5f
JH
214
215=head2 OPTIONS
216
217bigint recognizes some options that can be passed while loading it via use.
218The options can (currently) be either a single letter form, or the long form.
219The following options exist:
220
221=over 2
222
223=item a or accuracy
224
225This sets the accuracy for all math operations. The argument must be greater
226than or equal to zero. See Math::BigInt's bround() function for details.
227
228 perl -Mbigint=a,2 -le 'print 12345+1'
229
230=item p or precision
231
232This sets the precision for all math operations. The argument can be any
233integer. Negative values mean a fixed number of digits after the dot, and
234are <B>ignored</B> since all operations happen in integer space.
235A positive value rounds to this digit left from the dot. 0 or 1 mean round to
236integer and are ignore like negative values.
237
238See Math::BigInt's bfround() function for details.
239
240 perl -Mbignum=p,5 -le 'print 123456789+123'
241
242=item t or trace
243
244This enables a trace mode and is primarily for debugging bigint or
245Math::BigInt.
246
247=item l or lib
248
249Load a different math lib, see L<MATH LIBRARY>.
250
251 perl -Mbigint=l,GMP -e 'print 2 ** 512'
252
253Currently there is no way to specify more than one library on the command
254line. This will be hopefully fixed soon ;)
255
256=item v or version
257
258This prints out the name and version of all modules used and then exits.
259
260 perl -Mbigint=v -e ''
261
262=head2 MATH LIBRARY
263
264Math with the numbers is done (by default) by a module called
265Math::BigInt::Calc. This is equivalent to saying:
266
267 use bigint lib => 'Calc';
268
269You can change this by using:
270
271 use bigint lib => 'BitVect';
272
273The following would first try to find Math::BigInt::Foo, then
274Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
275
276 use bigint lib => 'Foo,Math::BigInt::Bar';
277
278Please see respective module documentation for further details.
279
280=head2 INTERNAL FORMAT
281
282The numbers are stored as objects, and their internals might change at anytime,
283especially between math operations. The objects also might belong to different
284classes, like Math::BigInt, or Math::BigInt::Lite. Mixing them together, even
285with normal scalars is not extraordinary, but normal and expected.
286
287You should not depend on the internal format, all accesses must go through
990fb837 288accessor methods. E.g. looking at $x->{sign} is not a good idea since there
126f3c5f
JH
289is no guaranty that the object in question has such a hash key, nor is a hash
290underneath at all.
291
292=head2 SIGN
293
294The sign is either '+', '-', 'NaN', '+inf' or '-inf' and stored seperately.
295You can access it with the sign() method.
296
297A sign of 'NaN' is used to represent the result when input arguments are not
298numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
299minus infinity. You will get '+inf' when dividing a positive number by 0, and
300'-inf' when dividing any negative number by 0.
301
302=head2 METHODS
303
304Since all numbers are now objects, you can use all functions that are part of
305the BigInt API. You can only use the bxxx() notation, and not the fxxx()
306notation, though.
307
990fb837
RGS
308=head2 CAVEAT
309
310But a warning is in order. When using the following to make a copy of a number,
311only a shallow copy will be made.
312
313 $x = 9; $y = $x;
314 $x = $y = 7;
315
316Using the copy or the original with overloaded math is okay, e.g. the
317following work:
318
319 $x = 9; $y = $x;
320 print $x + 1, " ", $y,"\n"; # prints 10 9
321
322but calling any method that modifies the number directly will result in
323B<both> the original and the copy beeing destroyed:
324
325 $x = 9; $y = $x;
326 print $x->badd(1), " ", $y,"\n"; # prints 10 10
327
328 $x = 9; $y = $x;
329 print $x->binc(1), " ", $y,"\n"; # prints 10 10
330
331 $x = 9; $y = $x;
332 print $x->bmul(2), " ", $y,"\n"; # prints 18 18
333
334Using methods that do not modify, but testthe contents works:
335
336 $x = 9; $y = $x;
337 $z = 9 if $x->is_zero(); # works fine
338
339See the documentation about the copy constructor and C<=> in overload, as
340well as the documentation in BigInt for further details.
341
126f3c5f
JH
342=head1 MODULES USED
343
344C<bigint> is just a thin wrapper around various modules of the Math::BigInt
345family. Think of it as the head of the family, who runs the shop, and orders
346the others to do the work.
347
348The following modules are currently used by bigint:
349
350 Math::BigInt::Lite (for speed, and only if it is loadable)
351 Math::BigInt
352
353=head1 EXAMPLES
354
355Some cool command line examples to impress the Python crowd ;) You might want
356to compare them to the results under -Mbignum or -Mbigrat:
357
358 perl -Mbigint -le 'print sqrt(33)'
359 perl -Mbigint -le 'print 2*255'
360 perl -Mbigint -le 'print 4.5+2*255'
361 perl -Mbigint -le 'print 3/7 + 5/7 + 8/3'
362 perl -Mbigint -le 'print 123->is_odd()'
363 perl -Mbigint -le 'print log(2)'
364 perl -Mbigint -le 'print 2 ** 0.5'
365 perl -Mbigint=a,65 -le 'print 2 ** 0.2'
366
367=head1 LICENSE
368
369This program is free software; you may redistribute it and/or modify it under
370the same terms as Perl itself.
371
372=head1 SEE ALSO
373
374Especially L<bigrat> as in C<perl -Mbigrat -le 'print 1/3+1/4'> and
375L<bignum> as in C<perl -Mbignum -le 'print sqrt(2)'>.
376
377L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
378as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and L<Math::BigInt::GMP>.
379
380=head1 AUTHORS
381
27e7b8bb 382(C) by Tels L<http://bloodgate.com/> in early 2002, 2003.
126f3c5f
JH
383
384=cut