[ PATCH ] mymalloc on HP-UX
[p5sagit/p5-mst-13.2.git] / lib / bigrat.pm
1 package bigrat;
2 require 5.005;
3
4 $VERSION = '0.04';
5 use Exporter;
6 @ISA =       qw( Exporter );
7 @EXPORT_OK = qw( ); 
8
9 use strict;
10
11 ############################################################################## 
12
13 # These are all alike, and thus faked by AUTOLOAD
14
15 my @faked = qw/round_mode accuracy precision div_scale/;
16 use vars qw/$VERSION $AUTOLOAD $_lite/;         # _lite for testsuite
17
18 sub AUTOLOAD
19   {
20   my $name = $AUTOLOAD;
21
22   $name =~ s/.*:://;    # split package
23   no strict 'refs';
24   foreach my $n (@faked)
25     {
26     if ($n eq $name)
27       {
28       *{"bigrat::$name"} = sub 
29         {
30         my $self = shift;
31         no strict 'refs';
32         if (defined $_[0])
33           {
34           Math::BigInt->$name($_[0]);
35           Math::BigFloat->$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 bigrat\-\>$name, not a valid method");
46   }
47
48 sub upgrade
49   {
50   my $self = shift;
51   no strict 'refs';
52 #  if (defined $_[0])
53 #    {
54 #    $Math::BigInt::upgrade = $_[0];
55 #    $Math::BigFloat::upgrade = $_[0];
56 #    }
57   return $Math::BigInt::upgrade;
58   }
59
60 sub import 
61   {
62   my $self = shift;
63
64   # see also bignum->import() for additional comments
65
66   # some defaults
67   my $lib = 'Calc'; my $upgrade = 'Math::BigFloat';
68
69   my @import = ( ':constant' );                         # drive it w/ constant
70   my @a = @_; my $l = scalar @_; my $j = 0;
71   my ($a,$p);
72   my ($ver,$trace);                                     # version? trace?
73   for ( my $i = 0; $i < $l ; $i++,$j++ )
74     {
75     if ($_[$i] eq 'upgrade')
76       {
77       # this causes upgrading
78       $upgrade = $_[$i+1];              # or undef to disable
79       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
80       splice @a, $j, $s; $j -= $s;
81       }
82     elsif ($_[$i] =~ /^(l|lib)$/)
83       {
84       # this causes a different low lib to take care...
85       $lib = $_[$i+1] || '';
86       my $s = 2; $s = 1 if @a-$j < 2;   # avoid "can not modify non-existant..."
87       splice @a, $j, $s; $j -= $s;
88       }
89     elsif ($_[$i] =~ /^(v|version)$/)
90       {
91       $ver = 1;
92       splice @a, $j, 1; $j --;
93       }
94     elsif ($_[$i] =~ /^(t|trace)$/)
95       {
96       $trace = 1;
97       splice @a, $j, 1; $j --;
98       }
99     else
100       {
101       die ("unknown option $_[$i]");
102       }
103     }
104   my $class;
105   $_lite = 0;                                   # using M::BI::L ?
106   if ($trace)
107     {
108     require Math::BigInt::Trace; $class = 'Math::BigInt::Trace';
109     $upgrade = 'Math::BigFloat::Trace';
110     }
111   else
112     {
113     # see if we can find Math::BigInt::Lite
114     if (!defined $a && !defined $p)             # rounding won't work to well
115       {
116       eval 'require Math::BigInt::Lite;';
117       if ($@ eq '')
118         {
119         @import = ( );                          # :constant in Lite, not MBI
120         Math::BigInt::Lite->import( ':constant' );
121         $_lite= 1;                              # signal okay
122         }
123       }
124     require Math::BigInt if $_lite == 0;        # not already loaded?
125     $class = 'Math::BigInt';                    # regardless of MBIL or not
126     }
127   # Math::BigInt::Trace or plain Math::BigInt
128   $class->import(@import, upgrade => $upgrade, lib => $lib);
129
130   require Math::BigFloat;
131   Math::BigFloat->import( upgrade => 'Math::BigRat', ':constant' );
132   require Math::BigRat;
133   if ($ver)
134     {
135     print "bigrat\t\t\t v$VERSION\n";
136     print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite;  
137     print "Math::BigInt\t\t v$Math::BigInt::VERSION";
138     my $config = Math::BigInt->config();
139     print " lib => $config->{lib} v$config->{lib_version}\n";
140     print "Math::BigFloat\t\t v$Math::BigFloat::VERSION\n";
141     print "Math::BigRat\t\t v$Math::BigRat::VERSION\n";
142     exit;
143     }
144   }
145
146 1;
147
148 __END__
149
150 =head1 NAME
151
152 bigrat - Transparent BigNumber/BigRational support for Perl
153
154 =head1 SYNOPSIS
155
156   use bigrat;
157
158   $x = 2 + 4.5,"\n";                    # BigFloat 6.5
159   print 1/3 + 1/4,"\n";                 # produces 7/12
160
161 =head1 DESCRIPTION
162
163 All operators (inlcuding basic math operations) are overloaded. Integer and
164 floating-point constants are created as proper BigInts or BigFloats,
165 respectively.
166
167 Other than L<bignum>, this module upgrades to Math::BigRat, meaning that
168 instead of 2.5 you will get 2+1/2 as output.
169
170 =head2 MODULES USED
171
172 C<bigrat> is just a thin wrapper around various modules of the Math::BigInt
173 family. Think of it as the head of the family, who runs the shop, and orders
174 the others to do the work.
175
176 The following modules are currently used by bignum:
177
178         Math::BigInt::Lite      (for speed, and only if it is loadable)
179         Math::BigInt
180         Math::BigFloat
181         Math::BigRat
182
183 =head2 MATH LIBRARY
184
185 Math with the numbers is done (by default) by a module called
186 Math::BigInt::Calc. This is equivalent to saying:
187
188         use bigrat lib => 'Calc';
189
190 You can change this by using:
191
192         use bigrat lib => 'BitVect';
193
194 The following would first try to find Math::BigInt::Foo, then
195 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
196
197         use bigrat lib => 'Foo,Math::BigInt::Bar';
198
199 Please see respective module documentation for further details.
200
201 =head2 SIGN
202
203 The sign is either '+', '-', 'NaN', '+inf' or '-inf' and stored seperately.
204
205 A sign of 'NaN' is used to represent the result when input arguments are not
206 numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
207 minus infinity. You will get '+inf' when dividing a positive number by 0, and
208 '-inf' when dividing any negative number by 0.
209
210 =head2 METHODS
211
212 Since all numbers are not objects, you can use all functions that are part of
213 the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not
214 the fxxx() notation, though. This makes you independed on the fact that the
215 underlying object might morph into a different class than BigFloat.
216
217 =head1 EXAMPLES
218  
219         perl -Mbigrat -le 'print sqrt(33)'
220         perl -Mbigrat -le 'print 2*255'
221         perl -Mbigrat -le 'print 4.5+2*255'
222         perl -Mbigrat -le 'print 3/7 + 5/7 + 8/3'       
223         perl -Mbigrat -le 'print 12->is_odd()';
224
225 =head1 LICENSE
226
227 This program is free software; you may redistribute it and/or modify it under
228 the same terms as Perl itself.
229
230 =head1 SEE ALSO
231
232 Especially L<bignum>.
233
234 L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
235 as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and  L<Math::BigInt::GMP>.
236
237 =head1 AUTHORS
238
239 (C) by Tels L<http://bloodgate.com/> in early 2002.
240
241 =cut