More PerlIO documentation.
[p5sagit/p5-mst-13.2.git] / lib / Math / BigRat.pm
1
2 #
3 # "Tax the rat farms." - Lord Vetinari
4 #
5
6 # The following hash values are used:
7 #   sign : +,-,NaN,+inf,-inf
8 #   _d   : denominator
9 #   _n   : numeraotr (value = _n/_d)
10 #   _a   : accuracy
11 #   _p   : precision
12 #   _f   : flags, used by MBR to flag parts of a rational as untouchable
13
14 package Math::BigRat;
15
16 require 5.005_03;
17 use strict;
18
19 use Exporter;
20 use Math::BigFloat;
21 use vars qw($VERSION @ISA $PACKAGE @EXPORT_OK $upgrade $downgrade
22             $accuracy $precision $round_mode $div_scale $_trap_nan $_trap_inf);
23
24 @ISA = qw(Exporter Math::BigFloat);
25 @EXPORT_OK = qw();
26
27 $VERSION = '0.10';
28
29 use overload;                   # inherit from Math::BigFloat
30
31 ##############################################################################
32 # global constants, flags and accessory
33
34 $accuracy = $precision = undef;
35 $round_mode = 'even';
36 $div_scale = 40;
37 $upgrade = undef;
38 $downgrade = undef;
39
40 # these are internally, and not to be used from the outside
41
42 use constant MB_NEVER_ROUND => 0x0001;
43
44 $_trap_nan = 0;                         # are NaNs ok? set w/ config()
45 $_trap_inf = 0;                         # are infs ok? set w/ config()
46
47 my $nan = 'NaN';
48 my $class = 'Math::BigRat';
49 my $MBI = 'Math::BigInt';
50
51 sub isa
52   {
53   return 0 if $_[1] =~ /^Math::Big(Int|Float)/;         # we aren't
54   UNIVERSAL::isa(@_);
55   }
56
57 sub _new_from_float
58   {
59   # turn a single float input into a rational (like '0.1')
60   my ($self,$f) = @_;
61
62   return $self->bnan() if $f->is_nan();
63   return $self->binf('-inf') if $f->{sign} eq '-inf';
64   return $self->binf('+inf') if $f->{sign} eq '+inf';
65
66   $self->{_n} = $f->{_m}->copy();                       # mantissa
67   $self->{_d} = $MBI->bone();
68   $self->{sign} = $f->{sign} || '+'; $self->{_n}->{sign} = '+';
69   if ($f->{_e}->{sign} eq '-')
70     {
71     # something like Math::BigRat->new('0.1');
72     $self->{_d}->blsft($f->{_e}->copy()->babs(),10);    # 1 / 1 => 1/10
73     }
74   else
75     {
76     # something like Math::BigRat->new('10');
77     # 1 / 1 => 10/1
78     $self->{_n}->blsft($f->{_e},10) unless $f->{_e}->is_zero(); 
79     }
80   $self;
81   }
82
83 sub new
84   {
85   # create a Math::BigRat
86   my $class = shift;
87
88   my ($n,$d) = shift;
89
90   my $self = { }; bless $self,$class;
91  
92   # input like (BigInt,BigInt) or (BigFloat,BigFloat) not handled yet
93
94   if ((!defined $d) && (ref $n) && (!$n->isa('Math::BigRat')))
95     {
96     if ($n->isa('Math::BigFloat'))
97       {
98       return $self->_new_from_float($n)->bnorm();
99       }
100     if ($n->isa('Math::BigInt'))
101       {
102       # TODO: trap NaN, inf
103       $self->{_n} = $n->copy();                         # "mantissa" = $n
104       $self->{_d} = $MBI->bone();
105       $self->{sign} = $self->{_n}->{sign}; $self->{_n}->{sign} = '+';
106       return $self->bnorm();
107       }
108     if ($n->isa('Math::BigInt::Lite'))
109       {
110       # TODO: trap NaN, inf
111       $self->{sign} = '+'; $self->{sign} = '-' if $$n < 0;
112       $self->{_n} = $MBI->new(abs($$n),undef,undef);    # "mantissa" = $n
113       $self->{_d} = $MBI->bone();
114       return $self->bnorm();
115       }
116     }
117   return $n->copy() if ref $n;
118
119   if (!defined $n)
120     {
121     $self->{_n} = $MBI->bzero();                        # undef => 0
122     $self->{_d} = $MBI->bone();
123     $self->{sign} = '+';
124     return $self->bnorm();
125     }
126   # string input with / delimiter
127   if ($n =~ /\s*\/\s*/)
128     {
129     return $class->bnan() if $n =~ /\/.*\//;    # 1/2/3 isn't valid
130     return $class->bnan() if $n =~ /\/\s*$/;    # 1/ isn't valid
131     ($n,$d) = split (/\//,$n);
132     # try as BigFloats first
133     if (($n =~ /[\.eE]/) || ($d =~ /[\.eE]/))
134       {
135       # one of them looks like a float 
136       # Math::BigFloat($n,undef,undef) does not what it is supposed to do, so:
137       local $Math::BigFloat::accuracy = undef;
138       local $Math::BigFloat::precision = undef;
139       local $Math::BigInt::accuracy = undef;
140       local $Math::BigInt::precision = undef;
141       my $nf = Math::BigFloat->new($n);
142       $self->{sign} = '+';
143       return $self->bnan() if $nf->is_nan();
144       $self->{_n} = $nf->{_m};
145       # now correct $self->{_n} due to $n
146       my $f = Math::BigFloat->new($d,undef,undef);
147       $self->{_d} = $f->{_m};
148       return $self->bnan() if $f->is_nan();
149       #print "n=$nf e$nf->{_e} d=$f e$f->{_e}\n";
150       # calculate the difference between nE and dE
151       my $diff_e = $nf->{_e}->copy()->bsub ( $f->{_e} );
152       if ($diff_e->is_negative())
153         {
154         # < 0: mul d with it
155         $self->{_d}->blsft($diff_e->babs(),10);
156         }
157       elsif (!$diff_e->is_zero())
158         {
159         # > 0: mul n with it
160         $self->{_n}->blsft($diff_e,10);
161         }
162       }
163     else
164       {
165       # both d and n are (big)ints
166       $self->{_n} = $MBI->new($n,undef,undef);
167       $self->{_d} = $MBI->new($d,undef,undef);
168       $self->{sign} = '+';
169       return $self->bnan() if $self->{_n}->{sign} eq $nan ||
170                               $self->{_d}->{sign} eq $nan;
171       # handle inf and NAN cases:
172       if ($self->{_n}->is_inf() || $self->{_d}->is_inf())
173         {
174         # inf/inf => NaN
175         return $self->bnan() if
176           ($self->{_n}->is_inf() && $self->{_d}->is_inf());
177         # +-inf/123 => +-inf
178         return $self->binf($self->{sign}) if $self->{_n}->is_inf();
179         # 123/inf => 0
180         return $self->bzero();
181         }
182  
183       $self->{sign} = $self->{_n}->{sign}; $self->{_n}->babs();
184       # if $d is negative, flip sign
185       $self->{sign} =~ tr/+-/-+/ if $self->{_d}->{sign} eq '-';
186       $self->{_d}->babs();                              # normalize
187       }
188
189     return $self->bnorm();
190     }
191
192   # simple string input
193   if (($n =~ /[\.eE]/))
194     {
195     # looks like a float, quacks like a float, so probably is a float
196     # Math::BigFloat($n,undef,undef) does not what it is supposed to do, so:
197     local $Math::BigFloat::accuracy = undef;
198     local $Math::BigFloat::precision = undef;
199     local $Math::BigInt::accuracy = undef;
200     local $Math::BigInt::precision = undef;
201     $self->{sign} = 'NaN';
202     $self->_new_from_float(Math::BigFloat->new($n,undef,undef));
203     }
204   else
205     {
206     $self->{_n} = $MBI->new($n,undef,undef);
207     $self->{_d} = $MBI->bone();
208     $self->{sign} = $self->{_n}->{sign}; $self->{_n}->babs();
209     return $self->bnan() if $self->{sign} eq 'NaN';
210     return $self->binf($self->{sign}) if $self->{sign} =~ /^[+-]inf$/;
211     }
212   $self->bnorm();
213   }
214
215 ##############################################################################
216
217 sub config
218   {
219   # return (later set?) configuration data as hash ref
220   my $class = shift || 'Math::BigFloat';
221
222   my $cfg = $class->SUPER::config(@_);
223
224   # now we need only to override the ones that are different from our parent
225   $cfg->{class} = $class;
226   $cfg->{with} = $MBI;
227   $cfg;
228   }
229
230 ##############################################################################
231
232 sub bstr
233   {
234   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
235
236   if ($x->{sign} !~ /^[+-]$/)           # inf, NaN etc
237     {
238     my $s = $x->{sign}; $s =~ s/^\+//;  # +inf => inf
239     return $s;
240     }
241
242   my $s = ''; $s = $x->{sign} if $x->{sign} ne '+';     # +3 vs 3
243
244   return $s.$x->{_n}->bstr() if $x->{_d}->is_one(); 
245   return $s.$x->{_n}->bstr() . '/' . $x->{_d}->bstr(); 
246   }
247
248 sub bsstr
249   {
250   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
251
252   if ($x->{sign} !~ /^[+-]$/)           # inf, NaN etc
253     {
254     my $s = $x->{sign}; $s =~ s/^\+//;  # +inf => inf
255     return $s;
256     }
257   
258   my $s = ''; $s = $x->{sign} if $x->{sign} ne '+';     # +3 vs 3
259   return $s . $x->{_n}->bstr() . '/' . $x->{_d}->bstr(); 
260   }
261
262 sub bnorm
263   {
264   # reduce the number to the shortest form and remember this (so that we
265   # don't reduce again)
266   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
267
268   # both parts must be BigInt's (or whatever we are using today)
269   if (ref($x->{_n}) ne $MBI)
270     {
271     require Carp; Carp::croak ("n is not $MBI but (".ref($x->{_n}).')');
272     }
273   if (ref($x->{_d}) ne $MBI)
274     {
275     require Carp; Carp::croak ("d is not $MBI but (".ref($x->{_d}).')');
276     }
277
278   # this is to prevent automatically rounding when MBI's globals are set
279   $x->{_d}->{_f} = MB_NEVER_ROUND;
280   $x->{_n}->{_f} = MB_NEVER_ROUND;
281   # 'forget' that parts were rounded via MBI::bround() in MBF's bfround()
282   $x->{_d}->{_a} = undef; $x->{_n}->{_a} = undef;
283   $x->{_d}->{_p} = undef; $x->{_n}->{_p} = undef; 
284
285   # no normalize for NaN, inf etc.
286   return $x if $x->{sign} !~ /^[+-]$/;
287
288   # normalize zeros to 0/1
289   if (($x->{sign} =~ /^[+-]$/) &&
290       ($x->{_n}->is_zero()))
291     {
292     $x->{sign} = '+';                                   # never -0
293     $x->{_d} = $MBI->bone() unless $x->{_d}->is_one();
294     return $x;
295     }
296
297   return $x if $x->{_d}->is_one();                      # no need to reduce
298
299   # reduce other numbers
300   # disable upgrade in BigInt, otherwise deep recursion
301   local $Math::BigInt::upgrade = undef;
302   local $Math::BigInt::accuracy = undef;
303   local $Math::BigInt::precision = undef;
304   my $gcd = $x->{_n}->bgcd($x->{_d});
305
306   if (!$gcd->is_one())
307     {
308     $x->{_n}->bdiv($gcd);
309     $x->{_d}->bdiv($gcd);
310     }
311   $x;
312   }
313
314 ##############################################################################
315 # special values
316
317 sub _bnan
318   {
319   # used by parent class bnan() to initialize number to NaN
320   my $self = shift;
321
322   if ($_trap_nan)
323     {
324     require Carp;
325     my $class = ref($self);
326     Carp::croak ("Tried to set $self to NaN in $class\::_bnan()");
327     }
328   $self->{_n} = $MBI->bzero();
329   $self->{_d} = $MBI->bzero();
330   }
331
332 sub _binf
333   {
334   # used by parent class bone() to initialize number to +inf/-inf
335   my $self = shift;
336
337   if ($_trap_inf)
338     {
339     require Carp;
340     my $class = ref($self);
341     Carp::croak ("Tried to set $self to inf in $class\::_binf()");
342     }
343   $self->{_n} = $MBI->bzero();
344   $self->{_d} = $MBI->bzero();
345   }
346
347 sub _bone
348   {
349   # used by parent class bone() to initialize number to +1/-1
350   my $self = shift;
351   $self->{_n} = $MBI->bone();
352   $self->{_d} = $MBI->bone();
353   }
354
355 sub _bzero
356   {
357   # used by parent class bzero() to initialize number to 0
358   my $self = shift;
359   $self->{_n} = $MBI->bzero();
360   $self->{_d} = $MBI->bone();
361   }
362
363 ##############################################################################
364 # mul/add/div etc
365
366 sub badd
367   {
368   # add two rationals
369
370   # set up parameters
371   my ($self,$x,$y,@r) = (ref($_[0]),@_);
372   # objectify is costly, so avoid it
373   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
374     {
375     ($self,$x,$y,@r) = objectify(2,@_);
376     }
377
378   $x = $self->new($x) unless $x->isa($self);
379   $y = $self->new($y) unless $y->isa($self);
380
381   return $x->bnan() if ($x->{sign} eq 'NaN' || $y->{sign} eq 'NaN');
382   # TODO: inf handling
383
384   #  1   1    gcd(3,4) = 1    1*3 + 1*4    7
385   #  - + -                  = --------- = --                 
386   #  4   3                      4*3       12
387
388   # we do not compute the gcd() here, but simple do:
389   #  5   7    5*3 + 7*4   41
390   #  - + -  = --------- = --                 
391   #  4   3       4*3      12
392  
393   # the gcd() calculation and reducing is then done in bnorm()
394
395   local $Math::BigInt::accuracy = undef;
396   local $Math::BigInt::precision = undef;
397
398   $x->{_n}->bmul($y->{_d}); $x->{_n}->{sign} = $x->{sign};
399   my $m = $y->{_n}->copy()->bmul($x->{_d});
400   $m->{sign} = $y->{sign};                      # 2/1 - 2/1
401   $x->{_n}->badd($m);
402
403   $x->{_d}->bmul($y->{_d});
404
405   # calculate new sign
406   $x->{sign} = $x->{_n}->{sign}; $x->{_n}->{sign} = '+';
407
408   $x->bnorm()->round(@r);
409   }
410
411 sub bsub
412   {
413   # subtract two rationals
414
415   # set up parameters
416   my ($self,$x,$y,@r) = (ref($_[0]),@_);
417   # objectify is costly, so avoid it
418   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
419     {
420     ($self,$x,$y,@r) = objectify(2,@_);
421     }
422
423   # TODO: $self instead or $class??
424   $x = $class->new($x) unless $x->isa($class);
425   $y = $class->new($y) unless $y->isa($class);
426
427   return $x->bnan() if ($x->{sign} eq 'NaN' || $y->{sign} eq 'NaN');
428   # TODO: inf handling
429
430   #  1   1    gcd(3,4) = 1    1*3 - 1*4    7
431   #  - - -                  = --------- = --                 
432   #  4   3                      4*3       12
433   
434   # we do not compute the gcd() here, but simple do:
435   #  5   7    5*3 - 7*4     13
436   #  - - -  = --------- = - --
437   #  4   3       4*3        12
438
439   local $Math::BigInt::accuracy = undef;
440   local $Math::BigInt::precision = undef;
441
442   $x->{_n}->bmul($y->{_d}); $x->{_n}->{sign} = $x->{sign};
443   my $m = $y->{_n}->copy()->bmul($x->{_d});
444   $m->{sign} = $y->{sign};                      # 2/1 - 2/1
445   $x->{_n}->bsub($m);
446
447   $x->{_d}->bmul($y->{_d});
448   
449   # calculate new sign
450   $x->{sign} = $x->{_n}->{sign}; $x->{_n}->{sign} = '+';
451
452   $x->bnorm()->round(@r);
453   }
454
455 sub bmul
456   {
457   # multiply two rationals
458   
459   # set up parameters
460   my ($self,$x,$y,@r) = (ref($_[0]),@_);
461   # objectify is costly, so avoid it
462   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
463     {
464     ($self,$x,$y,@r) = objectify(2,@_);
465     }
466
467   # TODO: $self instead or $class??
468   $x = $class->new($x) unless $x->isa($class);
469   $y = $class->new($y) unless $y->isa($class);
470
471   return $x->bnan() if ($x->{sign} eq 'NaN' || $y->{sign} eq 'NaN');
472
473   # inf handling
474   if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/))
475     {
476     return $x->bnan() if $x->is_zero() || $y->is_zero();
477     # result will always be +-inf:
478     # +inf * +/+inf => +inf, -inf * -/-inf => +inf
479     # +inf * -/-inf => -inf, -inf * +/+inf => -inf
480     return $x->binf() if ($x->{sign} =~ /^\+/ && $y->{sign} =~ /^\+/);
481     return $x->binf() if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/);
482     return $x->binf('-');
483     }
484
485   # x== 0 # also: or y == 1 or y == -1
486   return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
487
488   # According to Knuth, this can be optimized by doingtwice gcd (for d and n)
489   # and reducing in one step)
490
491   #  1   1    2    1
492   #  - * - =  -  = -
493   #  4   3    12   6
494   
495   local $Math::BigInt::accuracy = undef;
496   local $Math::BigInt::precision = undef;
497   $x->{_n}->bmul($y->{_n});
498   $x->{_d}->bmul($y->{_d});
499
500   # compute new sign
501   $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
502
503   $x->bnorm()->round(@r);
504   }
505
506 sub bdiv
507   {
508   # (dividend: BRAT or num_str, divisor: BRAT or num_str) return
509   # (BRAT,BRAT) (quo,rem) or BRAT (only rem)
510
511   # set up parameters
512   my ($self,$x,$y,@r) = (ref($_[0]),@_);
513   # objectify is costly, so avoid it
514   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
515     {
516     ($self,$x,$y,@r) = objectify(2,@_);
517     }
518
519   # TODO: $self instead or $class??
520   $x = $class->new($x) unless $x->isa($class);
521   $y = $class->new($y) unless $y->isa($class);
522
523   return $self->_div_inf($x,$y)
524    if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
525
526   # x== 0 # also: or y == 1 or y == -1
527   return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
528
529   # TODO: list context, upgrade
530
531   # 1     1    1   3
532   # -  /  - == - * -
533   # 4     3    4   1
534   
535 #  local $Math::BigInt::accuracy = undef;
536 #  local $Math::BigInt::precision = undef;
537   $x->{_n}->bmul($y->{_d});
538   $x->{_d}->bmul($y->{_n});
539
540   # compute new sign 
541   $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
542
543   $x->bnorm()->round(@r);
544   $x;
545   }
546
547 sub bmod
548   {
549   # compute "remainder" (in Perl way) of $x / $y
550
551   # set up parameters
552   my ($self,$x,$y,@r) = (ref($_[0]),@_);
553   # objectify is costly, so avoid it
554   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
555     {
556     ($self,$x,$y,@r) = objectify(2,@_);
557     }
558
559   # TODO: $self instead or $class??
560   $x = $class->new($x) unless $x->isa($class);
561   $y = $class->new($y) unless $y->isa($class);
562
563   return $self->_div_inf($x,$y)
564    if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
565
566   return $self->_div_inf($x,$y)
567    if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
568
569   return $x if $x->is_zero();           # 0 / 7 = 0, mod 0
570
571   # compute $x - $y * floor($x/$y), keeping the sign of $x
572
573   # locally disable these, since they would interfere
574   local $Math::BigInt::upgrade = undef;
575   local $Math::BigInt::accuracy = undef;
576   local $Math::BigInt::precision = undef;
577
578   my $u = $x->copy()->babs();
579   # first, do a "normal" division ($x/$y)
580   $u->{_d}->bmul($y->{_n});
581   $u->{_n}->bmul($y->{_d});
582
583   # compute floor
584   if (!$u->{_d}->is_one())
585     {
586     $u->{_n}->bdiv($u->{_d});                   # 22/7 => 3/1 w/ truncate
587     # no need to set $u->{_d} to 1, since later we set it to $y->{_d}
588     #$x->{_n}->binc() if $x->{sign} eq '-';     # -22/7 => -4/1
589     }
590   
591   # compute $y * $u
592   $u->{_d} = $y->{_d};                  # 1 * $y->{_d}, see floor above
593   $u->{_n}->bmul($y->{_n});
594
595   my $xsign = $x->{sign}; $x->{sign} = '+';     # remember sign and make abs
596   # compute $x - $u
597   $x->bsub($u);
598   $x->{sign} = $xsign;                          # put sign back
599
600   $x->bnorm()->round(@r);
601   }
602
603 ##############################################################################
604 # bdec/binc
605
606 sub bdec
607   {
608   # decrement value (subtract 1)
609   my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
610
611   return $x if $x->{sign} !~ /^[+-]$/;  # NaN, inf, -inf
612
613   if ($x->{sign} eq '-')
614     {
615     $x->{_n}->badd($x->{_d});   # -5/2 => -7/2
616     }
617   else
618     {
619     if ($x->{_n}->bacmp($x->{_d}) < 0)
620       {
621       # 1/3 -- => -2/3
622       $x->{_n} = $x->{_d} - $x->{_n};
623       $x->{sign} = '-';
624       }
625     else
626       {
627       $x->{_n}->bsub($x->{_d});         # 5/2 => 3/2
628       }
629     }
630   $x->bnorm()->round(@r);
631   }
632
633 sub binc
634   {
635   # increment value (add 1)
636   my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
637   
638   return $x if $x->{sign} !~ /^[+-]$/;  # NaN, inf, -inf
639
640   if ($x->{sign} eq '-')
641     {
642     if ($x->{_n}->bacmp($x->{_d}) < 0)
643       {
644       # -1/3 ++ => 2/3 (overflow at 0)
645       $x->{_n} = $x->{_d} - $x->{_n};
646       $x->{sign} = '+';
647       }
648     else
649       {
650       $x->{_n}->bsub($x->{_d});         # -5/2 => -3/2
651       }
652     }
653   else
654     {
655     $x->{_n}->badd($x->{_d});   # 5/2 => 7/2
656     }
657   $x->bnorm()->round(@r);
658   }
659
660 ##############################################################################
661 # is_foo methods (the rest is inherited)
662
663 sub is_int
664   {
665   # return true if arg (BRAT or num_str) is an integer
666   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
667
668   return 1 if ($x->{sign} =~ /^[+-]$/) &&       # NaN and +-inf aren't
669     $x->{_d}->is_one();                         # x/y && y != 1 => no integer
670   0;
671   }
672
673 sub is_zero
674   {
675   # return true if arg (BRAT or num_str) is zero
676   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
677
678   return 1 if $x->{sign} eq '+' && $x->{_n}->is_zero();
679   0;
680   }
681
682 sub is_one
683   {
684   # return true if arg (BRAT or num_str) is +1 or -1 if signis given
685   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
686
687   my $sign = shift || ''; $sign = '+' if $sign ne '-';
688   return 1
689    if ($x->{sign} eq $sign && $x->{_n}->is_one() && $x->{_d}->is_one());
690   0;
691   }
692
693 sub is_odd
694   {
695   # return true if arg (BFLOAT or num_str) is odd or false if even
696   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
697
698   return 1 if ($x->{sign} =~ /^[+-]$/) &&               # NaN & +-inf aren't
699     ($x->{_d}->is_one() && $x->{_n}->is_odd());         # x/2 is not, but 3/1
700   0;
701   }
702
703 sub is_even
704   {
705   # return true if arg (BINT or num_str) is even or false if odd
706   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
707
708   return 0 if $x->{sign} !~ /^[+-]$/;                   # NaN & +-inf aren't
709   return 1 if ($x->{_d}->is_one()                       # x/3 is never
710      && $x->{_n}->is_even());                           # but 4/1 is
711   0;
712   }
713
714 BEGIN
715   {
716   *objectify = \&Math::BigInt::objectify;
717   }
718
719 ##############################################################################
720 # parts() and friends
721
722 sub numerator
723   {
724   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
725
726   return $MBI->new($x->{sign}) if ($x->{sign} !~ /^[+-]$/);
727
728   my $n = $x->{_n}->copy(); $n->{sign} = $x->{sign};
729   $n;
730   }
731
732 sub denominator
733   {
734   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
735
736   return $MBI->new($x->{sign}) if ($x->{sign} !~ /^[+-]$/);
737   $x->{_d}->copy(); 
738   }
739
740 sub parts
741   {
742   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
743
744   return ($self->bnan(),$self->bnan()) if $x->{sign} eq 'NaN';
745   return ($self->binf(),$self->binf()) if $x->{sign} eq '+inf';
746   return ($self->binf('-'),$self->binf()) if $x->{sign} eq '-inf';
747
748   my $n = $x->{_n}->copy();
749   $n->{sign} = $x->{sign};
750   return ($n,$x->{_d}->copy());
751   }
752
753 sub length
754   {
755   return 0;
756   }
757
758 sub digit
759   {
760   return 0;
761   }
762
763 ##############################################################################
764 # special calc routines
765
766 sub bceil
767   {
768   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
769
770   return $x unless $x->{sign} =~ /^[+-]$/;
771   return $x if $x->{_d}->is_one();              # 22/1 => 22, 0/1 => 0
772
773   local $Math::BigInt::upgrade = undef;
774   local $Math::BigInt::accuracy = undef;
775   local $Math::BigInt::precision = undef;
776   $x->{_n}->bdiv($x->{_d});                     # 22/7 => 3/1 w/ truncate
777   $x->{_d}->bone();
778   $x->{_n}->binc() if $x->{sign} eq '+';        # +22/7 => 4/1
779   $x->{sign} = '+' if $x->{_n}->is_zero();      # -0 => 0
780   $x;
781   }
782
783 sub bfloor
784   {
785   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
786
787   return $x unless $x->{sign} =~ /^[+-]$/;
788   return $x if $x->{_d}->is_one();              # 22/1 => 22, 0/1 => 0
789
790   local $Math::BigInt::upgrade = undef;
791   local $Math::BigInt::accuracy = undef;
792   local $Math::BigInt::precision = undef;
793   $x->{_n}->bdiv($x->{_d});                     # 22/7 => 3/1 w/ truncate
794   $x->{_d}->bone();
795   $x->{_n}->binc() if $x->{sign} eq '-';        # -22/7 => -4/1
796   $x;
797   }
798
799 sub bfac
800   {
801   my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
802
803   if (($x->{sign} eq '+') && ($x->{_d}->is_one()))
804     {
805     $x->{_n}->bfac();
806     return $x->round(@r);
807     }
808   $x->bnan();
809   }
810
811 sub bpow
812   {
813   # power ($x ** $y)
814
815   # set up parameters
816   my ($self,$x,$y,@r) = (ref($_[0]),@_);
817   # objectify is costly, so avoid it
818   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
819     {
820     ($self,$x,$y,@r) = objectify(2,@_);
821     }
822
823   return $x if $x->{sign} =~ /^[+-]inf$/;       # -inf/+inf ** x
824   return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;
825   return $x->bone(@r) if $y->is_zero();
826   return $x->round(@r) if $x->is_one() || $y->is_one();
827   if ($x->{sign} eq '-' && $x->{_n}->is_one() && $x->{_d}->is_one())
828     {
829     # if $x == -1 and odd/even y => +1/-1
830     return $y->is_odd() ? $x->round(@r) : $x->babs()->round(@r);
831     # my Casio FX-5500L has a bug here: -1 ** 2 is -1, but -1 * -1 is 1;
832     }
833   # 1 ** -y => 1 / (1 ** |y|)
834   # so do test for negative $y after above's clause
835  #  return $x->bnan() if $y->{sign} eq '-';
836   return $x->round(@r) if $x->is_zero();  # 0**y => 0 (if not y <= 0)
837
838   # shortcut y/1 (and/or x/1)
839   if ($y->{_d}->is_one())
840     {
841     # shortcut for x/1 and y/1
842     if ($x->{_d}->is_one())
843       {
844       $x->{_n}->bpow($y->{_n});         # x/1 ** y/1 => (x ** y)/1
845       if ($y->{sign} eq '-')
846         {
847         # 0.2 ** -3 => 1/(0.2 ** 3)
848         ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n});      # swap
849         }
850       # correct sign; + ** + => +
851       if ($x->{sign} eq '-')
852         {
853         # - * - => +, - * - * - => -
854         $x->{sign} = '+' if $y->{_n}->is_even();        
855         }
856       return $x->round(@r);
857       }
858     # x/z ** y/1
859     $x->{_n}->bpow($y->{_n});           # 5/2 ** y/1 => 5 ** y / 2 ** y
860     $x->{_d}->bpow($y->{_n});
861     if ($y->{sign} eq '-')
862       {
863       # 0.2 ** -3 => 1/(0.2 ** 3)
864       ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n});        # swap
865       }
866     # correct sign; + ** + => +
867     if ($x->{sign} eq '-')
868       {
869       # - * - => +, - * - * - => -
870       $x->{sign} = '+' if $y->{_n}->is_even();  
871       }
872     return $x->round(@r);
873     }
874
875   # regular calculation (this is wrong for d/e ** f/g)
876   my $pow2 = $self->__one();
877   my $y1 = $MBI->new($y->{_n}/$y->{_d})->babs();
878   my $two = $MBI->new(2);
879   while (!$y1->is_one())
880     {
881     $pow2->bmul($x) if $y1->is_odd();
882     $y1->bdiv($two);
883     $x->bmul($x);
884     }
885   $x->bmul($pow2) unless $pow2->is_one();
886   # n ** -x => 1/n ** x
887   ($x->{_d},$x->{_n}) = ($x->{_n},$x->{_d}) if $y->{sign} eq '-'; 
888   $x->bnorm()->round(@r);
889   }
890
891 sub blog
892   {
893   return Math::BigRat->bnan();
894   }
895
896 sub bsqrt
897   {
898   my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
899
900   return $x->bnan() if $x->{sign} !~ /^[+]/;    # NaN, -inf or < 0
901   return $x if $x->{sign} eq '+inf';            # sqrt(inf) == inf
902   return $x->round(@r) if $x->is_zero() || $x->is_one();
903
904   local $Math::BigFloat::upgrade = undef;
905   local $Math::BigFloat::downgrade = undef;
906   local $Math::BigFloat::precision = undef;
907   local $Math::BigFloat::accuracy = undef;
908   local $Math::BigInt::upgrade = undef;
909   local $Math::BigInt::precision = undef;
910   local $Math::BigInt::accuracy = undef;
911   $x->{_d} = Math::BigFloat->new($x->{_d})->bsqrt();
912   $x->{_n} = Math::BigFloat->new($x->{_n})->bsqrt();
913
914   # if sqrt(D) was not integer
915   if ($x->{_d}->{_e}->{sign} ne '+')
916     {
917     $x->{_n}->blsft($x->{_d}->{_e}->babs(),10);         # 7.1/4.51 => 7.1/45.1
918     $x->{_d} = $x->{_d}->{_m};                          # 7.1/45.1 => 71/45.1
919     }
920   # if sqrt(N) was not integer
921   if ($x->{_n}->{_e}->{sign} ne '+')
922     {
923     $x->{_d}->blsft($x->{_n}->{_e}->babs(),10);         # 71/45.1 => 710/45.1
924     $x->{_n} = $x->{_n}->{_m};                          # 710/45.1 => 710/451
925     }
926  
927   # convert parts to $MBI again 
928   $x->{_n} = $x->{_n}->as_number();
929   $x->{_d} = $x->{_d}->as_number();
930   $x->bnorm()->round(@r);
931   }
932
933 sub blsft
934   {
935   my ($self,$x,$y,$b,$a,$p,$r) = objectify(3,@_);
936  
937   $x->bmul( $b->copy()->bpow($y), $a,$p,$r);
938   $x;
939   }
940
941 sub brsft
942   {
943   my ($self,$x,$y,$b,$a,$p,$r) = objectify(2,@_);
944
945   $x->bdiv( $b->copy()->bpow($y), $a,$p,$r);
946   $x;
947   }
948
949 ##############################################################################
950 # round
951
952 sub round
953   {
954   $_[0];
955   }
956
957 sub bround
958   {
959   $_[0];
960   }
961
962 sub bfround
963   {
964   $_[0];
965   }
966
967 ##############################################################################
968 # comparing
969
970 sub bcmp
971   {
972   my ($self,$x,$y) = objectify(2,@_);
973
974   if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
975     {
976     # handle +-inf and NaN
977     return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
978     return 0 if $x->{sign} eq $y->{sign} && $x->{sign} =~ /^[+-]inf$/;
979     return +1 if $x->{sign} eq '+inf';
980     return -1 if $x->{sign} eq '-inf';
981     return -1 if $y->{sign} eq '+inf';
982     return +1;
983     }
984   # check sign for speed first
985   return 1 if $x->{sign} eq '+' && $y->{sign} eq '-';   # does also 0 <=> -y
986   return -1 if $x->{sign} eq '-' && $y->{sign} eq '+';  # does also -x <=> 0
987
988   # shortcut
989   my $xz = $x->{_n}->is_zero();
990   my $yz = $y->{_n}->is_zero();
991   return 0 if $xz && $yz;                               # 0 <=> 0
992   return -1 if $xz && $y->{sign} eq '+';                # 0 <=> +y
993   return 1 if $yz && $x->{sign} eq '+';                 # +x <=> 0
994  
995   my $t = $x->{_n} * $y->{_d}; $t->{sign} = $x->{sign};
996   my $u = $y->{_n} * $x->{_d}; $u->{sign} = $y->{sign};
997   $t->bcmp($u);
998   }
999
1000 sub bacmp
1001   {
1002   my ($self,$x,$y) = objectify(2,@_);
1003
1004   if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
1005     {
1006     # handle +-inf and NaN
1007     return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1008     return 0 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} =~ /^[+-]inf$/;
1009     return +1;  # inf is always bigger
1010     }
1011
1012   my $t = $x->{_n} * $y->{_d};
1013   my $u = $y->{_n} * $x->{_d};
1014   $t->bacmp($u);
1015   }
1016
1017 ##############################################################################
1018 # output conversation
1019
1020 sub numify
1021   {
1022   # convert 17/8 => float (aka 2.125)
1023   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
1024  
1025   return $x->bstr() if $x->{sign} !~ /^[+-]$/;  # inf, NaN, etc
1026
1027   # N/1 => N
1028   return $x->{_n}->numify() if $x->{_d}->is_one();
1029
1030   # N/D
1031   my $neg = 1; $neg = -1 if $x->{sign} ne '+';
1032   $neg * $x->{_n}->numify() / $x->{_d}->numify();       # return sign * N/D
1033   }
1034
1035 sub as_number
1036   {
1037   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
1038
1039   return $x if $x->{sign} !~ /^[+-]$/;                  # NaN, inf etc
1040  
1041   # need to disable these, otherwise bdiv() gives BigRat again
1042   local $Math::BigInt::upgrade = undef;
1043   local $Math::BigInt::accuracy = undef;
1044   local $Math::BigInt::precision = undef;
1045   my $t = $x->{_n}->copy()->bdiv($x->{_d});             # 22/7 => 3
1046   $t->{sign} = $x->{sign};
1047   $t;
1048   }
1049
1050 sub import
1051   {
1052   my $self = shift;
1053   my $l = scalar @_;
1054   my $lib = ''; my @a;
1055   for ( my $i = 0; $i < $l ; $i++)
1056     {
1057 #    print "at $_[$i] (",$_[$i+1]||'undef',")\n";
1058     if ( $_[$i] eq ':constant' )
1059       {
1060       # this rest causes overlord er load to step in
1061       # print "overload @_\n";
1062       overload::constant float => sub { $self->new(shift); };
1063       }
1064 #    elsif ($_[$i] eq 'upgrade')
1065 #      {
1066 #     # this causes upgrading
1067 #      $upgrade = $_[$i+1];              # or undef to disable
1068 #      $i++;
1069 #      }
1070     elsif ($_[$i] eq 'downgrade')
1071       {
1072       # this causes downgrading
1073       $downgrade = $_[$i+1];            # or undef to disable
1074       $i++;
1075       }
1076     elsif ($_[$i] eq 'lib')
1077       {
1078       $lib = $_[$i+1] || '';            # default Calc
1079       $i++;
1080       }
1081     elsif ($_[$i] eq 'with')
1082       {
1083       $MBI = $_[$i+1] || 'Math::BigInt';        # default Math::BigInt
1084       $i++;
1085       }
1086     else
1087       {
1088       push @a, $_[$i];
1089       }
1090     }
1091   # let use Math::BigInt lib => 'GMP'; use Math::BigFloat; still work
1092   my $mbilib = eval { Math::BigInt->config()->{lib} };
1093   if ((defined $mbilib) && ($MBI eq 'Math::BigInt'))
1094     {
1095     # MBI already loaded
1096     $MBI->import('lib',"$lib,$mbilib", 'objectify');
1097     }
1098   else
1099     {
1100     # MBI not loaded, or not with "Math::BigInt"
1101     $lib .= ",$mbilib" if defined $mbilib;
1102
1103     if ($] < 5.006)
1104       {
1105       # Perl < 5.6.0 dies with "out of memory!" when eval() and ':constant' is
1106       # used in the same script, or eval inside import().
1107       my @parts = split /::/, $MBI;             # Math::BigInt => Math BigInt
1108       my $file = pop @parts; $file .= '.pm';    # BigInt => BigInt.pm
1109       $file = File::Spec->catfile (@parts, $file);
1110       eval { require $file; $MBI->import( lib => '$lib', 'objectify' ); }
1111       }
1112     else
1113       {
1114       my $rc = "use $MBI lib => '$lib', 'objectify';";
1115       eval $rc;
1116       }
1117     }
1118   if ($@)
1119     {
1120     require Carp; Carp::croak ("Couldn't load $MBI: $! $@");
1121     }
1122
1123   # any non :constant stuff is handled by our parent, Exporter
1124   # even if @_ is empty, to give it a chance
1125   $self->SUPER::import(@a);             # for subclasses
1126   $self->export_to_level(1,$self,@a);   # need this, too
1127   }
1128
1129 1;
1130
1131 __END__
1132
1133 =head1 NAME
1134
1135 Math::BigRat - arbitrarily big rationals
1136
1137 =head1 SYNOPSIS
1138
1139         use Math::BigRat;
1140
1141         $x = Math::BigRat->new('3/7'); $x += '5/9';
1142
1143         print $x->bstr(),"\n";
1144         print $x ** 2,"\n";
1145
1146 =head1 DESCRIPTION
1147
1148 Math::BigRat complements Math::BigInt and Math::BigFloat by providing support
1149 for arbitrarily big rationals.
1150
1151 =head2 MATH LIBRARY
1152
1153 Math with the numbers is done (by default) by a module called
1154 Math::BigInt::Calc. This is equivalent to saying:
1155
1156         use Math::BigRat lib => 'Calc';
1157
1158 You can change this by using:
1159
1160         use Math::BigRat lib => 'BitVect';
1161
1162 The following would first try to find Math::BigInt::Foo, then
1163 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
1164
1165         use Math::BigRat lib => 'Foo,Math::BigInt::Bar';
1166
1167 Calc.pm uses as internal format an array of elements of some decimal base
1168 (usually 1e7, but this might be different for some systems) with the least
1169 significant digit first, while BitVect.pm uses a bit vector of base 2, most
1170 significant bit first. Other modules might use even different means of
1171 representing the numbers. See the respective module documentation for further
1172 details.
1173
1174 Currently the following replacement libraries exist, search for them at CPAN:
1175
1176         Math::BigInt::BitVect
1177         Math::BigInt::GMP
1178         Math::BigInt::Pari
1179         Math::BigInt::FastCalc
1180
1181 =head1 METHODS
1182
1183 Any methods not listed here are dervied from Math::BigFloat (or
1184 Math::BigInt), so make sure you check these two modules for further
1185 information.
1186
1187 =head2 new()
1188
1189         $x = Math::BigRat->new('1/3');
1190
1191 Create a new Math::BigRat object. Input can come in various forms:
1192
1193         $x = Math::BigRat->new(123);                            # scalars
1194         $x = Math::BigRat->new('123.3');                        # float
1195         $x = Math::BigRat->new('1/3');                          # simple string
1196         $x = Math::BigRat->new('1 / 3');                        # spaced
1197         $x = Math::BigRat->new('1 / 0.1');                      # w/ floats
1198         $x = Math::BigRat->new(Math::BigInt->new(3));           # BigInt
1199         $x = Math::BigRat->new(Math::BigFloat->new('3.1'));     # BigFloat
1200         $x = Math::BigRat->new(Math::BigInt::Lite->new('2'));   # BigLite
1201
1202 =head2 numerator()
1203
1204         $n = $x->numerator();
1205
1206 Returns a copy of the numerator (the part above the line) as signed BigInt.
1207
1208 =head2 denominator()
1209         
1210         $d = $x->denominator();
1211
1212 Returns a copy of the denominator (the part under the line) as positive BigInt.
1213
1214 =head2 parts()
1215
1216         ($n,$d) = $x->parts();
1217
1218 Return a list consisting of (signed) numerator and (unsigned) denominator as
1219 BigInts.
1220
1221 =head2 as_number()
1222
1223         $x = Math::BigRat->new('13/7');
1224         print $x->as_number(),"\n";             # '1'
1225
1226 Returns a copy of the object as BigInt trunced it to integer.
1227
1228 =head2 bfac()
1229
1230         $x->bfac();
1231
1232 Calculates the factorial of $x. For instance:
1233
1234         print Math::BigRat->new('3/1')->bfac(),"\n";    # 1*2*3
1235         print Math::BigRat->new('5/1')->bfac(),"\n";    # 1*2*3*4*5
1236
1237 Works currently only for integers.
1238
1239 =head2 blog()
1240
1241 Is not yet implemented.
1242
1243 =head2 bround()/round()/bfround()
1244
1245 Are not yet implemented.
1246
1247 =head2 bmod()
1248
1249         use Math::BigRat;
1250         my $x = Math::BigRat->new('7/4');
1251         my $y = Math::BigRat->new('4/3');
1252         print $x->bmod($y);
1253
1254 Set $x to the remainder of the division of $x by $y.
1255
1256 =head2 is_one()
1257
1258         print "$x is 1\n" if $x->is_one();
1259
1260 Return true if $x is exactly one, otherwise false.
1261
1262 =head2 is_zero()
1263
1264         print "$x is 0\n" if $x->is_zero();
1265
1266 Return true if $x is exactly zero, otherwise false.
1267
1268 =head2 is_positive()
1269
1270         print "$x is >= 0\n" if $x->is_positive();
1271
1272 Return true if $x is positive (greater than or equal to zero), otherwise
1273 false. Please note that '+inf' is also positive, while 'NaN' and '-inf' aren't.
1274
1275 =head2 is_negative()
1276
1277         print "$x is < 0\n" if $x->is_negative();
1278
1279 Return true if $x is negative (smaller than zero), otherwise false. Please
1280 note that '-inf' is also negative, while 'NaN' and '+inf' aren't.
1281
1282 =head2 is_int()
1283
1284         print "$x is an integer\n" if $x->is_int();
1285
1286 Return true if $x has a denominator of 1 (e.g. no fraction parts), otherwise
1287 false. Please note that '-inf', 'inf' and 'NaN' aren't integer.
1288
1289 =head2 is_odd()
1290
1291         print "$x is odd\n" if $x->is_odd();
1292
1293 Return true if $x is odd, otherwise false.
1294
1295 =head2 is_even()
1296
1297         print "$x is even\n" if $x->is_even();
1298
1299 Return true if $x is even, otherwise false.
1300
1301 =head2 bceil()
1302
1303         $x->bceil();
1304
1305 Set $x to the next bigger integer value (e.g. truncate the number to integer
1306 and then increment it by one).
1307
1308 =head2 bfloor()
1309         
1310         $x->bfloor();
1311
1312 Truncate $x to an integer value.
1313
1314 =head2 config
1315
1316         use Data::Dumper;
1317
1318         print Dumper ( Math::BigRat->config() );
1319         print Math::BigRat->config()->{lib},"\n";
1320
1321 Returns a hash containing the configuration, e.g. the version number, lib
1322 loaded etc. The following hash keys are currently filled in with the
1323 appropriate information.
1324
1325         key             RO/RW   Description
1326                                 Example
1327         ============================================================
1328         lib             RO      Name of the Math library
1329                                 Math::BigInt::Calc
1330         lib_version     RO      Version of 'lib'
1331                                 0.30
1332         class           RO      The class of config you just called
1333                                 Math::BigRat
1334         version         RO      version number of the class you used
1335                                 0.10
1336         upgrade         RW      To which class numbers are upgraded
1337                                 undef
1338         downgrade       RW      To which class numbers are downgraded
1339                                 undef
1340         precision       RW      Global precision
1341                                 undef
1342         accuracy        RW      Global accuracy
1343                                 undef
1344         round_mode      RW      Global round mode
1345                                 even
1346         div_scale       RW      Fallback acccuracy for div
1347                                 40
1348         trap_nan        RW      Trap creation of NaN (undef = no)
1349                                 undef
1350         trap_inf        RW      Trap creation of +inf/-inf (undef = no)
1351                                 undef
1352
1353 By passing a reference to a hash you may set the configuration values. This
1354 works only for values that a marked with a C<RW> above, anything else is
1355 read-only.
1356
1357 =head1 BUGS
1358
1359 Some things are not yet implemented, or only implemented half-way:
1360
1361 =over 2
1362
1363 =item inf handling (partial)
1364
1365 =item NaN handling (partial)
1366
1367 =item rounding (not implemented except for bceil/bfloor)
1368
1369 =item $x ** $y where $y is not an integer
1370
1371 =back
1372
1373 =head1 LICENSE
1374
1375 This program is free software; you may redistribute it and/or modify it under
1376 the same terms as Perl itself.
1377
1378 =head1 SEE ALSO
1379
1380 L<Math::BigFloat> and L<Math::Big> as well as L<Math::BigInt::BitVect>,
1381 L<Math::BigInt::Pari> and  L<Math::BigInt::GMP>.
1382
1383 See L<http://search.cpan.org/search?dist=bignum> for a way to use
1384 Math::BigRat.
1385
1386 The package at L<http://search.cpan.org/search?dist=Math%3A%3ABigRat>
1387 may contain more documentation and examples as well as testcases.
1388
1389 =head1 AUTHORS
1390
1391 (C) by Tels L<http://bloodgate.com/> 2001-2002. 
1392
1393 =cut