A more general fix to non-threaded static extension build problems
[p5sagit/p5-mst-13.2.git] / lib / bigrat.pm
CommitLineData
126f3c5f 1package bigrat;
95a2d02c 2use 5.006002;
126f3c5f 3
bd49aa09 4$VERSION = '0.10';
b68b7ab1 5require Exporter;
b4bc5691 6@ISA = qw( Exporter );
7@EXPORT_OK = qw( );
8@EXPORT = qw( inf NaN );
126f3c5f 9
10use strict;
95a2d02c 11use overload;
126f3c5f 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 *{"bigrat::$name"} = sub
31 {
32 my $self = shift;
33 no strict 'refs';
34 if (defined $_[0])
35 {
36 Math::BigInt->$name($_[0]);
37 Math::BigFloat->$name($_[0]);
990fb837 38 return Math::BigRat->$name($_[0]);
126f3c5f 39 }
40 return Math::BigInt->$name();
41 };
42 return &$name;
43 }
44 }
45
46 # delayed load of Carp and avoid recursion
47 require Carp;
48 Carp::croak ("Can't call bigrat\-\>$name, not a valid method");
49 }
50
51sub upgrade
52 {
53 my $self = shift;
54 no strict 'refs';
55# if (defined $_[0])
56# {
57# $Math::BigInt::upgrade = $_[0];
58# $Math::BigFloat::upgrade = $_[0];
59# }
95a2d02c 60 $Math::BigInt::upgrade;
61 }
62
63sub _binary_constant
64 {
65 # this takes a binary/hexadecimal/octal constant string and returns it
66 # as string suitable for new. Basically it converts octal to decimal, and
67 # passes every thing else unmodified back.
68 my $string = shift;
69
70 return Math::BigInt->new($string) if $string =~ /^0[bx]/;
71
72 # so it must be an octal constant
73 Math::BigInt->from_oct($string);
126f3c5f 74 }
75
76sub import
77 {
78 my $self = shift;
79
80 # see also bignum->import() for additional comments
81
82 # some defaults
bd49aa09 83 my $lib = ''; my $lib_kind = 'try'; my $upgrade = 'Math::BigFloat';
126f3c5f 84
85 my @import = ( ':constant' ); # drive it w/ constant
86 my @a = @_; my $l = scalar @_; my $j = 0;
87 my ($a,$p);
88 my ($ver,$trace); # version? trace?
89 for ( my $i = 0; $i < $l ; $i++,$j++ )
90 {
91 if ($_[$i] eq 'upgrade')
92 {
93 # this causes upgrading
94 $upgrade = $_[$i+1]; # or undef to disable
95 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
96 splice @a, $j, $s; $j -= $s;
97 }
bd49aa09 98 elsif ($_[$i] =~ /^(l|lib|try|only)$/)
126f3c5f 99 {
100 # this causes a different low lib to take care...
bd49aa09 101 $lib_kind = $1; $lib_kind = 'lib' if $lib_kind eq 'l';
126f3c5f 102 $lib = $_[$i+1] || '';
103 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
b68b7ab1 104 splice @a, $j, $s; $j -= $s; $i++;
105 }
106 elsif ($_[$i] =~ /^(a|accuracy)$/)
107 {
108 $a = $_[$i+1];
109 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
110 splice @a, $j, $s; $j -= $s; $i++;
111 }
112 elsif ($_[$i] =~ /^(p|precision)$/)
113 {
114 $p = $_[$i+1];
115 my $s = 2; $s = 1 if @a-$j < 2; # avoid "can not modify non-existant..."
116 splice @a, $j, $s; $j -= $s; $i++;
126f3c5f 117 }
118 elsif ($_[$i] =~ /^(v|version)$/)
119 {
120 $ver = 1;
121 splice @a, $j, 1; $j --;
122 }
123 elsif ($_[$i] =~ /^(t|trace)$/)
124 {
125 $trace = 1;
126 splice @a, $j, 1; $j --;
127 }
128 else
129 {
130 die ("unknown option $_[$i]");
131 }
132 }
133 my $class;
134 $_lite = 0; # using M::BI::L ?
135 if ($trace)
136 {
137 require Math::BigInt::Trace; $class = 'Math::BigInt::Trace';
138 $upgrade = 'Math::BigFloat::Trace';
126f3c5f 139 }
140 else
141 {
142 # see if we can find Math::BigInt::Lite
143 if (!defined $a && !defined $p) # rounding won't work to well
144 {
145 eval 'require Math::BigInt::Lite;';
146 if ($@ eq '')
147 {
148 @import = ( ); # :constant in Lite, not MBI
149 Math::BigInt::Lite->import( ':constant' );
150 $_lite= 1; # signal okay
151 }
152 }
153 require Math::BigInt if $_lite == 0; # not already loaded?
154 $class = 'Math::BigInt'; # regardless of MBIL or not
155 }
bd49aa09 156 push @import, $lib_kind => $lib if $lib ne '';
126f3c5f 157 # Math::BigInt::Trace or plain Math::BigInt
233f7bc0 158 $class->import(@import, upgrade => $upgrade);
126f3c5f 159
160 require Math::BigFloat;
161 Math::BigFloat->import( upgrade => 'Math::BigRat', ':constant' );
162 require Math::BigRat;
b68b7ab1 163
164 bigrat->accuracy($a) if defined $a;
165 bigrat->precision($p) if defined $p;
126f3c5f 166 if ($ver)
167 {
168 print "bigrat\t\t\t v$VERSION\n";
169 print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite;
170 print "Math::BigInt\t\t v$Math::BigInt::VERSION";
171 my $config = Math::BigInt->config();
172 print " lib => $config->{lib} v$config->{lib_version}\n";
173 print "Math::BigFloat\t\t v$Math::BigFloat::VERSION\n";
174 print "Math::BigRat\t\t v$Math::BigRat::VERSION\n";
175 exit;
176 }
95a2d02c 177
178 # Take care of octal/hexadecimal constants
179 overload::constant binary => sub { _binary_constant(shift) };
180
b4bc5691 181 $self->export_to_level(1,$self,@a); # export inf and NaN
126f3c5f 182 }
183
b4bc5691 184sub inf () { Math::BigInt->binf(); }
185sub NaN () { Math::BigInt->bnan(); }
186
126f3c5f 1871;
188
189__END__
190
191=head1 NAME
192
b1f79218 193bigrat - Transparent BigNumber/BigRational support for Perl
126f3c5f 194
195=head1 SYNOPSIS
196
197 use bigrat;
198
199 $x = 2 + 4.5,"\n"; # BigFloat 6.5
200 print 1/3 + 1/4,"\n"; # produces 7/12
201
202=head1 DESCRIPTION
203
3c4b39be 204All operators (including basic math operations) are overloaded. Integer and
126f3c5f 205floating-point constants are created as proper BigInts or BigFloats,
206respectively.
207
208Other than L<bignum>, this module upgrades to Math::BigRat, meaning that
209instead of 2.5 you will get 2+1/2 as output.
210
b68b7ab1 211=head2 Modules Used
126f3c5f 212
213C<bigrat> is just a thin wrapper around various modules of the Math::BigInt
214family. Think of it as the head of the family, who runs the shop, and orders
215the others to do the work.
216
217The following modules are currently used by bignum:
218
219 Math::BigInt::Lite (for speed, and only if it is loadable)
220 Math::BigInt
221 Math::BigFloat
222 Math::BigRat
223
b68b7ab1 224=head2 Math Library
126f3c5f 225
226Math with the numbers is done (by default) by a module called
227Math::BigInt::Calc. This is equivalent to saying:
228
229 use bigrat lib => 'Calc';
230
231You can change this by using:
232
bd49aa09 233 use bignum lib => 'GMP';
126f3c5f 234
235The following would first try to find Math::BigInt::Foo, then
236Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
237
238 use bigrat lib => 'Foo,Math::BigInt::Bar';
239
bd49aa09 240Using C<lib> warns if none of the specified libraries can be found and
241L<Math::BigInt> did fall back to one of the default libraries.
242To supress this warning, use C<try> instead:
243
244 use bignum try => 'GMP';
245
246If you want the code to die instead of falling back, use C<only> instead:
247
248 use bignum only => 'GMP';
249
126f3c5f 250Please see respective module documentation for further details.
251
b68b7ab1 252=head2 Sign
126f3c5f 253
b68b7ab1 254The sign is either '+', '-', 'NaN', '+inf' or '-inf'.
126f3c5f 255
256A sign of 'NaN' is used to represent the result when input arguments are not
257numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
258minus infinity. You will get '+inf' when dividing a positive number by 0, and
259'-inf' when dividing any negative number by 0.
260
b68b7ab1 261=head2 Methods
126f3c5f 262
263Since all numbers are not objects, you can use all functions that are part of
264the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not
265the fxxx() notation, though. This makes you independed on the fact that the
266underlying object might morph into a different class than BigFloat.
267
95a2d02c 268=over 2
269
270=item inf()
271
272A shortcut to return Math::BigInt->binf(). Useful because Perl does not always
273handle bareword C<inf> properly.
274
275=item NaN()
276
277A shortcut to return Math::BigInt->bnan(). Useful because Perl does not always
278handle bareword C<NaN> properly.
279
280=item upgrade()
281
282Return the class that numbers are upgraded to, is in fact returning
283C<$Math::BigInt::upgrade>.
284
285=back
286
287=head2 MATH LIBRARY
288
289Math with the numbers is done (by default) by a module called
290
291=head2 Cavaet
990fb837 292
293But a warning is in order. When using the following to make a copy of a number,
294only a shallow copy will be made.
295
296 $x = 9; $y = $x;
297 $x = $y = 7;
298
b68b7ab1 299If you want to make a real copy, use the following:
300
301 $y = $x->copy();
302
990fb837 303Using the copy or the original with overloaded math is okay, e.g. the
304following work:
305
306 $x = 9; $y = $x;
307 print $x + 1, " ", $y,"\n"; # prints 10 9
308
309but calling any method that modifies the number directly will result in
3c4b39be 310B<both> the original and the copy being destroyed:
990fb837 311
312 $x = 9; $y = $x;
313 print $x->badd(1), " ", $y,"\n"; # prints 10 10
314
315 $x = 9; $y = $x;
316 print $x->binc(1), " ", $y,"\n"; # prints 10 10
317
318 $x = 9; $y = $x;
319 print $x->bmul(2), " ", $y,"\n"; # prints 18 18
320
321Using methods that do not modify, but testthe contents works:
322
323 $x = 9; $y = $x;
324 $z = 9 if $x->is_zero(); # works fine
325
326See the documentation about the copy constructor and C<=> in overload, as
327well as the documentation in BigInt for further details.
328
b68b7ab1 329=head2 Options
330
331bignum recognizes some options that can be passed while loading it via use.
332The options can (currently) be either a single letter form, or the long form.
333The following options exist:
334
335=over 2
336
337=item a or accuracy
338
339This sets the accuracy for all math operations. The argument must be greater
340than or equal to zero. See Math::BigInt's bround() function for details.
341
342 perl -Mbigrat=a,50 -le 'print sqrt(20)'
343
95a2d02c 344Note that setting precision and accurary at the same time is not possible.
345
b68b7ab1 346=item p or precision
347
348This sets the precision for all math operations. The argument can be any
349integer. Negative values mean a fixed number of digits after the dot, while
350a positive value rounds to this digit left from the dot. 0 or 1 mean round to
351integer. See Math::BigInt's bfround() function for details.
352
353 perl -Mbigrat=p,-50 -le 'print sqrt(20)'
354
95a2d02c 355Note that setting precision and accurary at the same time is not possible.
356
b68b7ab1 357=item t or trace
358
359This enables a trace mode and is primarily for debugging bignum or
360Math::BigInt/Math::BigFloat.
361
362=item l or lib
363
364Load a different math lib, see L<MATH LIBRARY>.
365
366 perl -Mbigrat=l,GMP -e 'print 2 ** 512'
367
368Currently there is no way to specify more than one library on the command
95a2d02c 369line. This means the following does not work:
370
371 perl -Mbignum=l,GMP,Pari -e 'print 2 ** 512'
372
373This will be hopefully fixed soon ;)
b68b7ab1 374
375=item v or version
376
377This prints out the name and version of all modules used and then exits.
378
379 perl -Mbigrat=v
380
95a2d02c 381=back
382
126f3c5f 383=head1 EXAMPLES
384
385 perl -Mbigrat -le 'print sqrt(33)'
386 perl -Mbigrat -le 'print 2*255'
387 perl -Mbigrat -le 'print 4.5+2*255'
388 perl -Mbigrat -le 'print 3/7 + 5/7 + 8/3'
389 perl -Mbigrat -le 'print 12->is_odd()';
95a2d02c 390 perl -Mbignum=l,GMP -le 'print 7 ** 7777'
126f3c5f 391
392=head1 LICENSE
393
394This program is free software; you may redistribute it and/or modify it under
395the same terms as Perl itself.
396
397=head1 SEE ALSO
398
399Especially L<bignum>.
400
401L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
402as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and L<Math::BigInt::GMP>.
403
404=head1 AUTHORS
405
95a2d02c 406(C) by Tels L<http://bloodgate.com/> in early 2002 - 2007.
126f3c5f 407
408=cut