This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Merge bignum 0.10, from Tels.
[perl5.git] / lib / bigint.pm
CommitLineData
126f3c5f
JH
1package bigint;
2require 5.005;
3
4$VERSION = '0.02';
5use Exporter;
6@ISA = qw( Exporter );
7@EXPORT_OK = qw( );
8
9use strict;
10use overload;
11
12##############################################################################
13
14# These are all alike, and thus faked by AUTOLOAD
15
16my @faked = qw/round_mode accuracy precision div_scale/;
17use vars qw/$VERSION $AUTOLOAD $_lite/; # _lite for testsuite
18
19sub 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 *{"bigint::$name"} = sub
30 {
31 my $self = shift;
32 no strict 'refs';
33 if (defined $_[0])
34 {
35 Math::BigInt->$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 bigint\-\>$name, not a valid method");
46 }
47
48sub upgrade
49 {
50 my $self = shift;
51 no strict 'refs';
52# if (defined $_[0])
53# {
54# $Math::BigInt::upgrade = $_[0];
55# }
56 return $Math::BigInt::upgrade;
57 }
58
59sub _constant
60 {
61 # this takes a floating point constant string and returns it truncated to
62 # integer. For instance, '4.5' => '4', '1.234e2' => '123' etc
63 my $float = shift;
64
65 # some simple cases first
66 return $float if ($float =~ /^[+-]?[0-9]+$/); # '+123','-1','0' etc
67 return $float
68 if ($float =~ /^[+-]?[0-9]+\.?[eE]\+?[0-9]+$/); # 123e2, 123.e+2
69 return '0' if ($float =~ /^[+-]?[0]*\.[0-9]+$/); # .2, 0.2, -.1
70 if ($float =~ /^[+-]?[0-9]+\.[0-9]*$/) # 1., 1.23, -1.2 etc
71 {
72 $float =~ s/\..*//;
73 return $float;
74 }
75 my ($mis,$miv,$mfv,$es,$ev) = Math::BigInt::_split(\$float);
76 return $float if !defined $mis; # doesn't look like a number to me
77 my $ec = int($$ev);
78 my $sign = $$mis; $sign = '' if $sign eq '+';
79 if ($$es eq '-')
80 {
81 # ignore fraction part entirely
82 if ($ec >= length($$miv)) # 123.23E-4
83 {
84 return '0';
85 }
86 return $sign . substr ($$miv,0,length($$miv)-$ec); # 1234.45E-2 = 12
87 }
88 # xE+y
89 if ($ec >= length($$mfv))
90 {
91 $ec -= length($$mfv);
92 return $sign.$$miv.$$mfv if $ec == 0; # 123.45E+2 => 12345
93 return $sign.$$miv.$$mfv.'E'.$ec; # 123.45e+3 => 12345e1
94 }
95 $mfv = substr($$mfv,0,$ec);
96 return $sign.$$miv.$mfv; # 123.45e+1 => 1234
97 }
98
99sub import
100 {
101 my $self = shift;
102
103 # some defaults
104 my $lib = 'Calc';
105
106 my @import = ( ':constant' ); # drive it w/ constant
107 my @a = @_; my $l = scalar @_; my $j = 0;
108 my ($ver,$trace); # version? trace?
109 my ($a,$p); # accuracy, precision
110 for ( my $i = 0; $i < $l ; $i++,$j++ )
111 {
112 if ($_[$i] =~ /^(l|lib)$/)
113 {
114 # this causes a different low lib to take care...
115 $lib = $_[$i+1] || '';
116 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
117 splice @a, $j, $s; $j -= $s; $i++;
118 }
119 elsif ($_[$i] =~ /^(a|accuracy)$/)
120 {
121 $a = $_[$i+1];
122 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
123 splice @a, $j, $s; $j -= $s; $i++;
124 }
125 elsif ($_[$i] =~ /^(p|precision)$/)
126 {
127 $p = $_[$i+1];
128 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
129 splice @a, $j, $s; $j -= $s; $i++;
130 }
131 elsif ($_[$i] =~ /^(v|version)$/)
132 {
133 $ver = 1;
134 splice @a, $j, 1; $j --;
135 }
136 elsif ($_[$i] =~ /^(t|trace)$/)
137 {
138 $trace = 1;
139 splice @a, $j, 1; $j --;
140 }
141 else { die "unknown option $_[$i]"; }
142 }
143 my $class;
144 $_lite = 0; # using M::BI::L ?
145 if ($trace)
146 {
147 require Math::BigInt::Trace; $class = 'Math::BigInt::Trace';
148 print STDERR "Loading $class";
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) ); };
183 }
184
1851;
186
187__END__
188
189=head1 NAME
190
191bigint - Transparent big integer support for Perl
192
193=head1 SYNOPSIS
194
195 use bignt;
196
197 $x = 2 + 4.5,"\n"; # BigInt 6
198 print 2 ** 512; # really is what you think it is
199
200=head1 DESCRIPTION
201
202All operators (including basic math operations) are overloaded. Integer
203constants are created as proper BigInts.
204
205Floating point constants are truncated to integer. All results are also
206trunctaed.
207
208=head2 OPTIONS
209
210bigint recognizes some options that can be passed while loading it via use.
211The options can (currently) be either a single letter form, or the long form.
212The following options exist:
213
214=over 2
215
216=item a or accuracy
217
218This sets the accuracy for all math operations. The argument must be greater
219than or equal to zero. See Math::BigInt's bround() function for details.
220
221 perl -Mbigint=a,2 -le 'print 12345+1'
222
223=item p or precision
224
225This sets the precision for all math operations. The argument can be any
226integer. Negative values mean a fixed number of digits after the dot, and
227are <B>ignored</B> since all operations happen in integer space.
228A positive value rounds to this digit left from the dot. 0 or 1 mean round to
229integer and are ignore like negative values.
230
231See Math::BigInt's bfround() function for details.
232
233 perl -Mbignum=p,5 -le 'print 123456789+123'
234
235=item t or trace
236
237This enables a trace mode and is primarily for debugging bigint or
238Math::BigInt.
239
240=item l or lib
241
242Load a different math lib, see L<MATH LIBRARY>.
243
244 perl -Mbigint=l,GMP -e 'print 2 ** 512'
245
246Currently there is no way to specify more than one library on the command
247line. This will be hopefully fixed soon ;)
248
249=item v or version
250
251This prints out the name and version of all modules used and then exits.
252
253 perl -Mbigint=v -e ''
254
255=head2 MATH LIBRARY
256
257Math with the numbers is done (by default) by a module called
258Math::BigInt::Calc. This is equivalent to saying:
259
260 use bigint lib => 'Calc';
261
262You can change this by using:
263
264 use bigint lib => 'BitVect';
265
266The following would first try to find Math::BigInt::Foo, then
267Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
268
269 use bigint lib => 'Foo,Math::BigInt::Bar';
270
271Please see respective module documentation for further details.
272
273=head2 INTERNAL FORMAT
274
275The numbers are stored as objects, and their internals might change at anytime,
276especially between math operations. The objects also might belong to different
277classes, like Math::BigInt, or Math::BigInt::Lite. Mixing them together, even
278with normal scalars is not extraordinary, but normal and expected.
279
280You should not depend on the internal format, all accesses must go through
281accessor methods. E.g. looking at $x->{sign} is not a bright idea since there
282is no guaranty that the object in question has such a hash key, nor is a hash
283underneath at all.
284
285=head2 SIGN
286
287The sign is either '+', '-', 'NaN', '+inf' or '-inf' and stored seperately.
288You can access it with the sign() method.
289
290A sign of 'NaN' is used to represent the result when input arguments are not
291numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
292minus infinity. You will get '+inf' when dividing a positive number by 0, and
293'-inf' when dividing any negative number by 0.
294
295=head2 METHODS
296
297Since all numbers are now objects, you can use all functions that are part of
298the BigInt API. You can only use the bxxx() notation, and not the fxxx()
299notation, though.
300
301=head1 MODULES USED
302
303C<bigint> is just a thin wrapper around various modules of the Math::BigInt
304family. Think of it as the head of the family, who runs the shop, and orders
305the others to do the work.
306
307The following modules are currently used by bigint:
308
309 Math::BigInt::Lite (for speed, and only if it is loadable)
310 Math::BigInt
311
312=head1 EXAMPLES
313
314Some cool command line examples to impress the Python crowd ;) You might want
315to compare them to the results under -Mbignum or -Mbigrat:
316
317 perl -Mbigint -le 'print sqrt(33)'
318 perl -Mbigint -le 'print 2*255'
319 perl -Mbigint -le 'print 4.5+2*255'
320 perl -Mbigint -le 'print 3/7 + 5/7 + 8/3'
321 perl -Mbigint -le 'print 123->is_odd()'
322 perl -Mbigint -le 'print log(2)'
323 perl -Mbigint -le 'print 2 ** 0.5'
324 perl -Mbigint=a,65 -le 'print 2 ** 0.2'
325
326=head1 LICENSE
327
328This program is free software; you may redistribute it and/or modify it under
329the same terms as Perl itself.
330
331=head1 SEE ALSO
332
333Especially L<bigrat> as in C<perl -Mbigrat -le 'print 1/3+1/4'> and
334L<bignum> as in C<perl -Mbignum -le 'print sqrt(2)'>.
335
336L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
337as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and L<Math::BigInt::GMP>.
338
339=head1 AUTHORS
340
341(C) by Tels L<http://bloodgate.com/> in early 2002.
342
343=cut