xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/lib/bigrat.pm (revision 0:68f95e015346)
1package bigrat;
2require 5.005;
3
4$VERSION = '0.06';
5use Exporter;
6@ISA		= qw( Exporter );
7@EXPORT_OK	= qw( );
8@EXPORT		= qw( inf NaN );
9
10use strict;
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      *{"bigrat::$name"} = sub
30        {
31        my $self = shift;
32        no strict 'refs';
33        if (defined $_[0])
34          {
35          Math::BigInt->$name($_[0]);
36          Math::BigFloat->$name($_[0]);
37          return Math::BigRat->$name($_[0]);
38          }
39        return Math::BigInt->$name();
40        };
41      return &$name;
42      }
43    }
44
45  # delayed load of Carp and avoid recursion
46  require Carp;
47  Carp::croak ("Can't call bigrat\-\>$name, not a valid method");
48  }
49
50sub upgrade
51  {
52  my $self = shift;
53  no strict 'refs';
54#  if (defined $_[0])
55#    {
56#    $Math::BigInt::upgrade = $_[0];
57#    $Math::BigFloat::upgrade = $_[0];
58#    }
59  return $Math::BigInt::upgrade;
60  }
61
62sub import
63  {
64  my $self = shift;
65
66  # see also bignum->import() for additional comments
67
68  # some defaults
69  my $lib = 'Calc'; my $upgrade = 'Math::BigFloat';
70
71  my @import = ( ':constant' );				# drive it w/ constant
72  my @a = @_; my $l = scalar @_; my $j = 0;
73  my ($a,$p);
74  my ($ver,$trace);					# version? trace?
75  for ( my $i = 0; $i < $l ; $i++,$j++ )
76    {
77    if ($_[$i] eq 'upgrade')
78      {
79      # this causes upgrading
80      $upgrade = $_[$i+1];		# or undef to disable
81      my $s = 2; $s = 1 if @a-$j < 2;	# avoid "can not modify non-existant..."
82      splice @a, $j, $s; $j -= $s;
83      }
84    elsif ($_[$i] =~ /^(l|lib)$/)
85      {
86      # this causes a different low lib to take care...
87      $lib = $_[$i+1] || '';
88      my $s = 2; $s = 1 if @a-$j < 2;	# avoid "can not modify non-existant..."
89      splice @a, $j, $s; $j -= $s;
90      }
91    elsif ($_[$i] =~ /^(v|version)$/)
92      {
93      $ver = 1;
94      splice @a, $j, 1; $j --;
95      }
96    elsif ($_[$i] =~ /^(t|trace)$/)
97      {
98      $trace = 1;
99      splice @a, $j, 1; $j --;
100      }
101    else
102      {
103      die ("unknown option $_[$i]");
104      }
105    }
106  my $class;
107  $_lite = 0;                                   # using M::BI::L ?
108  if ($trace)
109    {
110    require Math::BigInt::Trace; $class = 'Math::BigInt::Trace';
111    $upgrade = 'Math::BigFloat::Trace';
112    }
113  else
114    {
115    # see if we can find Math::BigInt::Lite
116    if (!defined $a && !defined $p)             # rounding won't work to well
117      {
118      eval 'require Math::BigInt::Lite;';
119      if ($@ eq '')
120        {
121        @import = ( );                          # :constant in Lite, not MBI
122        Math::BigInt::Lite->import( ':constant' );
123        $_lite= 1;                              # signal okay
124        }
125      }
126    require Math::BigInt if $_lite == 0;        # not already loaded?
127    $class = 'Math::BigInt';                    # regardless of MBIL or not
128    }
129  # Math::BigInt::Trace or plain Math::BigInt
130  $class->import(@import, upgrade => $upgrade, lib => $lib);
131
132  require Math::BigFloat;
133  Math::BigFloat->import( upgrade => 'Math::BigRat', ':constant' );
134  require Math::BigRat;
135  if ($ver)
136    {
137    print "bigrat\t\t\t v$VERSION\n";
138    print "Math::BigInt::Lite\t v$Math::BigInt::Lite::VERSION\n" if $_lite;
139    print "Math::BigInt\t\t v$Math::BigInt::VERSION";
140    my $config = Math::BigInt->config();
141    print " lib => $config->{lib} v$config->{lib_version}\n";
142    print "Math::BigFloat\t\t v$Math::BigFloat::VERSION\n";
143    print "Math::BigRat\t\t v$Math::BigRat::VERSION\n";
144    exit;
145    }
146  $self->export_to_level(1,$self,@a);           # export inf and NaN
147  }
148
149sub inf () { Math::BigInt->binf(); }
150sub NaN () { Math::BigInt->bnan(); }
151
1521;
153
154__END__
155
156=head1 NAME
157
158bigrat - Transparent BigNumber/BigRational support for Perl
159
160=head1 SYNOPSIS
161
162  use bigrat;
163
164  $x = 2 + 4.5,"\n";			# BigFloat 6.5
165  print 1/3 + 1/4,"\n";			# produces 7/12
166
167=head1 DESCRIPTION
168
169All operators (inlcuding basic math operations) are overloaded. Integer and
170floating-point constants are created as proper BigInts or BigFloats,
171respectively.
172
173Other than L<bignum>, this module upgrades to Math::BigRat, meaning that
174instead of 2.5 you will get 2+1/2 as output.
175
176=head2 MODULES USED
177
178C<bigrat> is just a thin wrapper around various modules of the Math::BigInt
179family. Think of it as the head of the family, who runs the shop, and orders
180the others to do the work.
181
182The following modules are currently used by bignum:
183
184        Math::BigInt::Lite      (for speed, and only if it is loadable)
185        Math::BigInt
186        Math::BigFloat
187        Math::BigRat
188
189=head2 MATH LIBRARY
190
191Math with the numbers is done (by default) by a module called
192Math::BigInt::Calc. This is equivalent to saying:
193
194	use bigrat lib => 'Calc';
195
196You can change this by using:
197
198	use bigrat lib => 'BitVect';
199
200The following would first try to find Math::BigInt::Foo, then
201Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
202
203	use bigrat lib => 'Foo,Math::BigInt::Bar';
204
205Please see respective module documentation for further details.
206
207=head2 SIGN
208
209The sign is either '+', '-', 'NaN', '+inf' or '-inf' and stored seperately.
210
211A sign of 'NaN' is used to represent the result when input arguments are not
212numbers or as a result of 0/0. '+inf' and '-inf' represent plus respectively
213minus infinity. You will get '+inf' when dividing a positive number by 0, and
214'-inf' when dividing any negative number by 0.
215
216=head2 METHODS
217
218Since all numbers are not objects, you can use all functions that are part of
219the BigInt or BigFloat API. It is wise to use only the bxxx() notation, and not
220the fxxx() notation, though. This makes you independed on the fact that the
221underlying object might morph into a different class than BigFloat.
222
223=head2 CAVEAT
224
225But a warning is in order. When using the following to make a copy of a number,
226only a shallow copy will be made.
227
228        $x = 9; $y = $x;
229        $x = $y = 7;
230
231Using the copy or the original with overloaded math is okay, e.g. the
232following work:
233
234        $x = 9; $y = $x;
235        print $x + 1, " ", $y,"\n";     # prints 10 9
236
237but calling any method that modifies the number directly will result in
238B<both> the original and the copy beeing destroyed:
239
240        $x = 9; $y = $x;
241        print $x->badd(1), " ", $y,"\n";        # prints 10 10
242
243        $x = 9; $y = $x;
244        print $x->binc(1), " ", $y,"\n";        # prints 10 10
245
246        $x = 9; $y = $x;
247        print $x->bmul(2), " ", $y,"\n";        # prints 18 18
248
249Using methods that do not modify, but testthe contents works:
250
251        $x = 9; $y = $x;
252        $z = 9 if $x->is_zero();                # works fine
253
254See the documentation about the copy constructor and C<=> in overload, as
255well as the documentation in BigInt for further details.
256
257=head1 EXAMPLES
258
259	perl -Mbigrat -le 'print sqrt(33)'
260	perl -Mbigrat -le 'print 2*255'
261	perl -Mbigrat -le 'print 4.5+2*255'
262	perl -Mbigrat -le 'print 3/7 + 5/7 + 8/3'
263	perl -Mbigrat -le 'print 12->is_odd()';
264
265=head1 LICENSE
266
267This program is free software; you may redistribute it and/or modify it under
268the same terms as Perl itself.
269
270=head1 SEE ALSO
271
272Especially L<bignum>.
273
274L<Math::BigFloat>, L<Math::BigInt>, L<Math::BigRat> and L<Math::Big> as well
275as L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and  L<Math::BigInt::GMP>.
276
277=head1 AUTHORS
278
279(C) by Tels L<http://bloodgate.com/> in early 2002.
280
281=cut
282