source: for-distributions/trunk/bin/windows/perl/lib/bigint.pm@ 14489

Last change on this file since 14489 was 14489, checked in by oranfry, 17 years ago

upgrading to perl 5.8

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