This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Rebreak lines to achieve <80 recommended line length.
[perl5.git] / dist / Math-BigRat / 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   : numerator (value = _n/_d)
10 #   _a   : accuracy
11 #   _p   : precision
12 # You should not look at the innards of a BigRat - use the methods for this.
13
14 package Math::BigRat;
15
16 # anything older is untested, and unlikely to work
17 use 5.006;
18 use strict;
19 use Carp ();
20
21 use Math::BigFloat;
22 use vars qw($VERSION @ISA $upgrade $downgrade
23             $accuracy $precision $round_mode $div_scale $_trap_nan $_trap_inf);
24
25 @ISA = qw(Math::BigFloat);
26
27 $VERSION = '0.2608';
28 $VERSION = eval $VERSION;
29
30 # inherit overload from Math::BigFloat, but disable the bitwise ops that don't
31 # make much sense for rationals unless they're truncated or something first
32
33 use overload
34     map {
35         my $op = $_;
36         ($op => sub {
37             Carp::croak("bitwise operation $op not supported in Math::BigRat");
38         });
39     } qw(& | ^ ~ << >> &= |= ^= <<= >>=);
40
41 BEGIN
42   {
43   *objectify = \&Math::BigInt::objectify;       # inherit this from BigInt
44   *AUTOLOAD = \&Math::BigFloat::AUTOLOAD;       # can't inherit AUTOLOAD
45   # we inherit these from BigFloat because currently it is not possible
46   # that MBF has a different $MBI variable than we, because MBF also uses
47   # Math::BigInt::config->('lib'); (there is always only one library loaded)
48   *_e_add = \&Math::BigFloat::_e_add;
49   *_e_sub = \&Math::BigFloat::_e_sub;
50   *as_int = \&as_number;
51   *is_pos = \&is_positive;
52   *is_neg = \&is_negative;
53   }
54
55 ##############################################################################
56 # Global constants and flags. Access these only via the accessor methods!
57
58 $accuracy = $precision = undef;
59 $round_mode = 'even';
60 $div_scale = 40;
61 $upgrade = undef;
62 $downgrade = undef;
63
64 # These are internally, and not to be used from the outside at all!
65
66 $_trap_nan = 0;                         # are NaNs ok? set w/ config()
67 $_trap_inf = 0;                         # are infs ok? set w/ config()
68
69 # the package we are using for our private parts, defaults to:
70 # Math::BigInt->config()->{lib}
71 my $MBI = 'Math::BigInt::Calc';
72
73 my $nan = 'NaN';
74 my $class = 'Math::BigRat';
75
76 sub isa
77   {
78   return 0 if $_[1] =~ /^Math::Big(Int|Float)/;         # we aren't
79   UNIVERSAL::isa(@_);
80   }
81
82 ##############################################################################
83
84 sub _new_from_float
85   {
86   # turn a single float input into a rational number (like '0.1')
87   my ($self,$f) = @_;
88
89   return $self->bnan() if $f->is_nan();
90   return $self->binf($f->{sign}) if $f->{sign} =~ /^[+-]inf$/;
91
92   $self->{_n} = $MBI->_copy( $f->{_m} );        # mantissa
93   $self->{_d} = $MBI->_one();
94   $self->{sign} = $f->{sign} || '+';
95   if ($f->{_es} eq '-')
96     {
97     # something like Math::BigRat->new('0.1');
98     # 1 / 1 => 1/10
99     $MBI->_lsft ( $self->{_d}, $f->{_e} ,10);
100     }
101   else
102     {
103     # something like Math::BigRat->new('10');
104     # 1 / 1 => 10/1
105     $MBI->_lsft ( $self->{_n}, $f->{_e} ,10) unless
106       $MBI->_is_zero($f->{_e});
107     }
108   $self;
109   }
110
111 sub new
112   {
113   # create a Math::BigRat
114   my $class = shift;
115
116   my ($n,$d) = @_;
117
118   my $self = { }; bless $self,$class;
119
120   # input like (BigInt) or (BigFloat):
121   if ((!defined $d) && (ref $n) && (!$n->isa('Math::BigRat')))
122     {
123     if ($n->isa('Math::BigFloat'))
124       {
125       $self->_new_from_float($n);
126       }
127     if ($n->isa('Math::BigInt'))
128       {
129       # TODO: trap NaN, inf
130       $self->{_n} = $MBI->_copy($n->{value});           # "mantissa" = N
131       $self->{_d} = $MBI->_one();                       # d => 1
132       $self->{sign} = $n->{sign};
133       }
134     if ($n->isa('Math::BigInt::Lite'))
135       {
136       # TODO: trap NaN, inf
137       $self->{sign} = '+'; $self->{sign} = '-' if $$n < 0;
138       $self->{_n} = $MBI->_new(abs($$n));               # "mantissa" = N
139       $self->{_d} = $MBI->_one();                       # d => 1
140       }
141     return $self->bnorm();                              # normalize (120/1 => 12/10)
142     }
143
144   # input like (BigInt,BigInt) or (BigLite,BigLite):
145   if (ref($d) && ref($n))
146     {
147     # do N first (for $self->{sign}):
148     if ($n->isa('Math::BigInt'))
149       {
150       # TODO: trap NaN, inf
151       $self->{_n} = $MBI->_copy($n->{value});           # "mantissa" = N
152       $self->{sign} = $n->{sign};
153       }
154     elsif ($n->isa('Math::BigInt::Lite'))
155       {
156       # TODO: trap NaN, inf
157       $self->{sign} = '+'; $self->{sign} = '-' if $$n < 0;
158       $self->{_n} = $MBI->_new(abs($$n));               # "mantissa" = $n
159       }
160     else
161       {
162       require Carp;
163       Carp::croak(ref($n) . " is not a recognized object format for Math::BigRat->new");
164       }
165     # now D:
166     if ($d->isa('Math::BigInt'))
167       {
168       # TODO: trap NaN, inf
169       $self->{_d} = $MBI->_copy($d->{value});           # "mantissa" = D
170       # +/+ or -/- => +, +/- or -/+ => -
171       $self->{sign} = $d->{sign} ne $self->{sign} ? '-' : '+';
172       }
173     elsif ($d->isa('Math::BigInt::Lite'))
174       {
175       # TODO: trap NaN, inf
176       $self->{_d} = $MBI->_new(abs($$d));               # "mantissa" = D
177       my $ds = '+'; $ds = '-' if $$d < 0;
178       # +/+ or -/- => +, +/- or -/+ => -
179       $self->{sign} = $ds ne $self->{sign} ? '-' : '+';
180       }
181     else
182       {
183       require Carp;
184       Carp::croak(ref($d) . " is not a recognized object format for Math::BigRat->new");
185       }
186     return $self->bnorm();                              # normalize (120/1 => 12/10)
187     }
188   return $n->copy() if ref $n;                          # already a BigRat
189
190   if (!defined $n)
191     {
192     $self->{_n} = $MBI->_zero();                        # undef => 0
193     $self->{_d} = $MBI->_one();
194     $self->{sign} = '+';
195     return $self;
196     }
197
198   # string input with / delimiter
199   if ($n =~ /\s*\/\s*/)
200     {
201     return $class->bnan() if $n =~ /\/.*\//;    # 1/2/3 isn't valid
202     return $class->bnan() if $n =~ /\/\s*$/;    # 1/ isn't valid
203     ($n,$d) = split (/\//,$n);
204     # try as BigFloats first
205     if (($n =~ /[\.eE]/) || ($d =~ /[\.eE]/))
206       {
207       local $Math::BigFloat::accuracy = undef;
208       local $Math::BigFloat::precision = undef;
209
210       # one of them looks like a float
211       my $nf = Math::BigFloat->new($n,undef,undef);
212       $self->{sign} = '+';
213       return $self->bnan() if $nf->is_nan();
214
215       $self->{_n} = $MBI->_copy( $nf->{_m} );   # get mantissa
216
217       # now correct $self->{_n} due to $n
218       my $f = Math::BigFloat->new($d,undef,undef);
219       return $self->bnan() if $f->is_nan();
220       $self->{_d} = $MBI->_copy( $f->{_m} );
221
222       # calculate the difference between nE and dE
223       my $diff_e = $nf->exponent()->bsub( $f->exponent);
224       if ($diff_e->is_negative())
225         {
226         # < 0: mul d with it
227         $MBI->_lsft( $self->{_d}, $MBI->_new( $diff_e->babs()), 10);
228         }
229       elsif (!$diff_e->is_zero())
230         {
231         # > 0: mul n with it
232         $MBI->_lsft( $self->{_n}, $MBI->_new( $diff_e), 10);
233         }
234       }
235     else
236       {
237       # both d and n look like (big)ints
238
239       $self->{sign} = '+';                                      # no sign => '+'
240       $self->{_n} = undef;
241       $self->{_d} = undef;
242       if ($n =~ /^([+-]?)0*([0-9]+)\z/)                         # first part ok?
243         {
244         $self->{sign} = $1 || '+';                              # no sign => '+'
245         $self->{_n} = $MBI->_new($2 || 0);
246         }
247
248       if ($d =~ /^([+-]?)0*([0-9]+)\z/)                         # second part ok?
249         {
250         $self->{sign} =~ tr/+-/-+/ if ($1 || '') eq '-';        # negate if second part neg.
251         $self->{_d} = $MBI->_new($2 || 0);
252         }
253
254       if (!defined $self->{_n} || !defined $self->{_d})
255         {
256         $d = Math::BigInt->new($d,undef,undef) unless ref $d;
257         $n = Math::BigInt->new($n,undef,undef) unless ref $n;
258
259         if ($n->{sign} =~ /^[+-]$/ && $d->{sign} =~ /^[+-]$/)
260           {
261           # both parts are ok as integers (weird things like ' 1e0'
262           $self->{_n} = $MBI->_copy($n->{value});
263           $self->{_d} = $MBI->_copy($d->{value});
264           $self->{sign} = $n->{sign};
265           $self->{sign} =~ tr/+-/-+/ if $d->{sign} eq '-';      # -1/-2 => 1/2
266           return $self->bnorm();
267           }
268
269         $self->{sign} = '+';                                    # a default sign
270         return $self->bnan() if $n->is_nan() || $d->is_nan();
271
272         # handle inf cases:
273         if ($n->is_inf() || $d->is_inf())
274           {
275           if ($n->is_inf())
276             {
277             return $self->bnan() if $d->is_inf();               # both are inf => NaN
278             my $s = '+';                # '+inf/+123' or '-inf/-123'
279             $s = '-' if substr($n->{sign},0,1) ne $d->{sign};
280             # +-inf/123 => +-inf
281             return $self->binf($s);
282             }
283           # 123/inf => 0
284           return $self->bzero();
285           }
286         }
287       }
288
289     return $self->bnorm();
290     }
291
292   # simple string input
293   if (($n =~ /[\.eE]/) && $n !~ /^0x/)
294     {
295     # looks like a float, quacks like a float, so probably is a float
296     $self->{sign} = 'NaN';
297     local $Math::BigFloat::accuracy = undef;
298     local $Math::BigFloat::precision = undef;
299     $self->_new_from_float(Math::BigFloat->new($n,undef,undef));
300     }
301   else
302     {
303     # for simple forms, use $MBI directly
304     if ($n =~ /^([+-]?)0*([0-9]+)\z/)
305       {
306       $self->{sign} = $1 || '+';
307       $self->{_n} = $MBI->_new($2 || 0);
308       $self->{_d} = $MBI->_one();
309       }
310     else
311       {
312       my $n = Math::BigInt->new($n,undef,undef);
313       $self->{_n} = $MBI->_copy($n->{value});
314       $self->{_d} = $MBI->_one();
315       $self->{sign} = $n->{sign};
316       return $self->bnan() if $self->{sign} eq 'NaN';
317       return $self->binf($self->{sign}) if $self->{sign} =~ /^[+-]inf$/;
318       }
319     }
320   $self->bnorm();
321   }
322
323 sub copy
324   {
325   # if two arguments, the first one is the class to "swallow" subclasses
326   my ($c,$x) = @_;
327
328   if (scalar @_ == 1)
329     {
330     $x = $_[0];
331     $c = ref($x);
332     }
333   return unless ref($x); # only for objects
334
335   my $self = bless {}, $c;
336
337   $self->{sign} = $x->{sign};
338   $self->{_d} = $MBI->_copy($x->{_d});
339   $self->{_n} = $MBI->_copy($x->{_n});
340   $self->{_a} = $x->{_a} if defined $x->{_a};
341   $self->{_p} = $x->{_p} if defined $x->{_p};
342   $self;
343   }
344
345 ##############################################################################
346
347 sub config
348   {
349   # return (later set?) configuration data as hash ref
350   my $class = shift || 'Math::BigRat';
351
352   if (@_ == 1 && ref($_[0]) ne 'HASH')
353     {
354     my $cfg = $class->SUPER::config();
355     return $cfg->{$_[0]};
356     }
357
358   my $cfg = $class->SUPER::config(@_);
359
360   # now we need only to override the ones that are different from our parent
361   $cfg->{class} = $class;
362   $cfg->{with} = $MBI;
363   $cfg;
364   }
365
366 ##############################################################################
367
368 sub bstr
369   {
370   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
371
372   if ($x->{sign} !~ /^[+-]$/)           # inf, NaN etc
373     {
374     my $s = $x->{sign}; $s =~ s/^\+//;  # +inf => inf
375     return $s;
376     }
377
378   my $s = ''; $s = $x->{sign} if $x->{sign} ne '+';     # '+3/2' => '3/2'
379
380   return $s . $MBI->_str($x->{_n}) if $MBI->_is_one($x->{_d});
381   $s . $MBI->_str($x->{_n}) . '/' . $MBI->_str($x->{_d});
382   }
383
384 sub bsstr
385   {
386   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
387
388   if ($x->{sign} !~ /^[+-]$/)           # inf, NaN etc
389     {
390     my $s = $x->{sign}; $s =~ s/^\+//;  # +inf => inf
391     return $s;
392     }
393
394   my $s = ''; $s = $x->{sign} if $x->{sign} ne '+';     # +3 vs 3
395   $s . $MBI->_str($x->{_n}) . '/' . $MBI->_str($x->{_d});
396   }
397
398 sub bnorm
399   {
400   # reduce the number to the shortest form
401   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
402
403   # Both parts must be objects of whatever we are using today.
404   if ( my $c = $MBI->_check($x->{_n}) )
405     {
406     require Carp; Carp::croak(
407         "n did not pass the self-check ($c) in bnorm()");
408     }
409   if ( my $c = $MBI->_check($x->{_d}) )
410     {
411     require Carp; Carp::croak(
412         "d did not pass the self-check ($c) in bnorm()");
413     }
414
415   # no normalize for NaN, inf etc.
416   return $x if $x->{sign} !~ /^[+-]$/;
417
418   # normalize zeros to 0/1
419   if ($MBI->_is_zero($x->{_n}))
420     {
421     $x->{sign} = '+';                                   # never leave a -0
422     $x->{_d} = $MBI->_one() unless $MBI->_is_one($x->{_d});
423     return $x;
424     }
425
426   return $x if $MBI->_is_one($x->{_d});                 # no need to reduce
427
428   # reduce other numbers
429   my $gcd = $MBI->_copy($x->{_n});
430   $gcd = $MBI->_gcd($gcd,$x->{_d});
431
432   if (!$MBI->_is_one($gcd))
433     {
434     $x->{_n} = $MBI->_div($x->{_n},$gcd);
435     $x->{_d} = $MBI->_div($x->{_d},$gcd);
436     }
437   $x;
438   }
439
440 ##############################################################################
441 # sign manipulation
442
443 sub bneg
444   {
445   # (BRAT or num_str) return BRAT
446   # negate number or make a negated number from string
447   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
448
449   return $x if $x->modify('bneg');
450
451   # for +0 do not negate (to have always normalized +0). Does nothing for 'NaN'
452   $x->{sign} =~ tr/+-/-+/
453     unless ($x->{sign} eq '+' && $MBI->_is_zero($x->{_n}));
454   $x;
455   }
456
457 ##############################################################################
458 # special values
459
460 sub _bnan
461   {
462   # used by parent class bnan() to initialize number to NaN
463   my $self = shift;
464
465   if ($_trap_nan)
466     {
467     require Carp;
468     my $class = ref($self);
469     # "$self" below will stringify the object, this blows up if $self is a
470     # partial object (happens under trap_nan), so fix it beforehand
471     $self->{_d} = $MBI->_zero() unless defined $self->{_d};
472     $self->{_n} = $MBI->_zero() unless defined $self->{_n};
473     Carp::croak ("Tried to set $self to NaN in $class\::_bnan()");
474     }
475   $self->{_n} = $MBI->_zero();
476   $self->{_d} = $MBI->_zero();
477   }
478
479 sub _binf
480   {
481   # used by parent class bone() to initialize number to +inf/-inf
482   my $self = shift;
483
484   if ($_trap_inf)
485     {
486     require Carp;
487     my $class = ref($self);
488     # "$self" below will stringify the object, this blows up if $self is a
489     # partial object (happens under trap_nan), so fix it beforehand
490     $self->{_d} = $MBI->_zero() unless defined $self->{_d};
491     $self->{_n} = $MBI->_zero() unless defined $self->{_n};
492     Carp::croak ("Tried to set $self to inf in $class\::_binf()");
493     }
494   $self->{_n} = $MBI->_zero();
495   $self->{_d} = $MBI->_zero();
496   }
497
498 sub _bone
499   {
500   # used by parent class bone() to initialize number to +1/-1
501   my $self = shift;
502   $self->{_n} = $MBI->_one();
503   $self->{_d} = $MBI->_one();
504   }
505
506 sub _bzero
507   {
508   # used by parent class bzero() to initialize number to 0
509   my $self = shift;
510   $self->{_n} = $MBI->_zero();
511   $self->{_d} = $MBI->_one();
512   }
513
514 ##############################################################################
515 # mul/add/div etc
516
517 sub badd
518   {
519   # add two rational numbers
520
521   # set up parameters
522   my ($self,$x,$y,@r) = (ref($_[0]),@_);
523   # objectify is costly, so avoid it
524   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
525     {
526     ($self,$x,$y,@r) = objectify(2,@_);
527     }
528
529   # +inf + +inf => +inf,  -inf + -inf => -inf
530   return $x->binf(substr($x->{sign},0,1))
531     if $x->{sign} eq $y->{sign} && $x->{sign} =~ /^[+-]inf$/;
532
533   # +inf + -inf or -inf + +inf => NaN
534   return $x->bnan() if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/);
535
536   #  1   1    gcd(3,4) = 1    1*3 + 1*4    7
537   #  - + -                  = --------- = --
538   #  4   3                      4*3       12
539
540   # we do not compute the gcd() here, but simple do:
541   #  5   7    5*3 + 7*4   43
542   #  - + -  = --------- = --
543   #  4   3       4*3      12
544
545   # and bnorm() will then take care of the rest
546
547   # 5 * 3
548   $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_d});
549
550   # 7 * 4
551   my $m = $MBI->_mul( $MBI->_copy( $y->{_n} ), $x->{_d} );
552
553   # 5 * 3 + 7 * 4
554   ($x->{_n}, $x->{sign}) = _e_add( $x->{_n}, $m, $x->{sign}, $y->{sign});
555
556   # 4 * 3
557   $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_d});
558
559   # normalize result, and possible round
560   $x->bnorm()->round(@r);
561   }
562
563 sub bsub
564   {
565   # subtract two rational numbers
566
567   # set up parameters
568   my ($self,$x,$y,@r) = (ref($_[0]),@_);
569   # objectify is costly, so avoid it
570   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
571     {
572     ($self,$x,$y,@r) = objectify(2,@_);
573     }
574
575   # flip sign of $x, call badd(), then flip sign of result
576   $x->{sign} =~ tr/+-/-+/
577     unless $x->{sign} eq '+' && $MBI->_is_zero($x->{_n});       # not -0
578   $x->badd($y,@r);                              # does norm and round
579   $x->{sign} =~ tr/+-/-+/
580     unless $x->{sign} eq '+' && $MBI->_is_zero($x->{_n});       # not -0
581   $x;
582   }
583
584 sub bmul
585   {
586   # multiply two rational numbers
587
588   # set up parameters
589   my ($self,$x,$y,@r) = (ref($_[0]),@_);
590   # objectify is costly, so avoid it
591   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
592     {
593     ($self,$x,$y,@r) = objectify(2,@_);
594     }
595
596   return $x->bnan() if ($x->{sign} eq 'NaN' || $y->{sign} eq 'NaN');
597
598   # inf handling
599   if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/))
600     {
601     return $x->bnan() if $x->is_zero() || $y->is_zero();
602     # result will always be +-inf:
603     # +inf * +/+inf => +inf, -inf * -/-inf => +inf
604     # +inf * -/-inf => -inf, -inf * +/+inf => -inf
605     return $x->binf() if ($x->{sign} =~ /^\+/ && $y->{sign} =~ /^\+/);
606     return $x->binf() if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/);
607     return $x->binf('-');
608     }
609
610   # x== 0 # also: or y == 1 or y == -1
611   return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
612
613   # XXX TODO:
614   # According to Knuth, this can be optimized by doing gcd twice (for d and n)
615   # and reducing in one step. This would save us the bnorm() at the end.
616
617   #  1   2    1 * 2    2    1
618   #  - * - =  -----  = -  = -
619   #  4   3    4 * 3    12   6
620
621   $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_n});
622   $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_d});
623
624   # compute new sign
625   $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
626
627   $x->bnorm()->round(@r);
628   }
629
630 sub bdiv
631   {
632   # (dividend: BRAT or num_str, divisor: BRAT or num_str) return
633   # (BRAT,BRAT) (quo,rem) or BRAT (only rem)
634
635   # set up parameters
636   my ($self,$x,$y,@r) = (ref($_[0]),@_);
637   # objectify is costly, so avoid it
638   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
639     {
640     ($self,$x,$y,@r) = objectify(2,@_);
641     }
642
643   return $self->_div_inf($x,$y)
644    if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
645
646   # x== 0 # also: or y == 1 or y == -1
647   return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
648
649   # XXX TODO: list context, upgrade
650   # According to Knuth, this can be optimized by doing gcd twice (for d and n)
651   # and reducing in one step. This would save us the bnorm() at the end.
652
653   # 1     1    1   3
654   # -  /  - == - * -
655   # 4     3    4   1
656
657   $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_d});
658   $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_n});
659
660   # compute new sign
661   $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
662
663   $x->bnorm()->round(@r);
664   $x;
665   }
666
667 sub bmod
668   {
669   # compute "remainder" (in Perl way) of $x / $y
670
671   # set up parameters
672   my ($self,$x,$y,@r) = (ref($_[0]),@_);
673   # objectify is costly, so avoid it
674   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
675     {
676     ($self,$x,$y,@r) = objectify(2,@_);
677     }
678
679   return $self->_div_inf($x,$y)
680    if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
681
682   return $x if $x->is_zero();           # 0 / 7 = 0, mod 0
683
684   # compute $x - $y * floor($x/$y), keeping the sign of $x
685
686   # copy x to u, make it positive and then do a normal division ($u/$y)
687   my $u = bless { sign => '+' }, $self;
688   $u->{_n} = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d} );
689   $u->{_d} = $MBI->_mul( $MBI->_copy($x->{_d}), $y->{_n} );
690
691   # compute floor(u)
692   if (! $MBI->_is_one($u->{_d}))
693     {
694     $u->{_n} = $MBI->_div($u->{_n},$u->{_d});   # 22/7 => 3/1 w/ truncate
695     # no need to set $u->{_d} to 1, since below we set it to $y->{_d} anyway
696     }
697
698   # now compute $y * $u
699   $u->{_d} = $MBI->_copy($y->{_d});             # 1 * $y->{_d}, see floor above
700   $u->{_n} = $MBI->_mul($u->{_n},$y->{_n});
701
702   my $xsign = $x->{sign}; $x->{sign} = '+';     # remember sign and make x positive
703   # compute $x - $u
704   $x->bsub($u);
705   $x->{sign} = $xsign;                          # put sign back
706
707   $x->bnorm()->round(@r);
708   }
709
710 ##############################################################################
711 # bdec/binc
712
713 sub bdec
714   {
715   # decrement value (subtract 1)
716   my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
717
718   return $x if $x->{sign} !~ /^[+-]$/;  # NaN, inf, -inf
719
720   if ($x->{sign} eq '-')
721     {
722     $x->{_n} = $MBI->_add( $x->{_n}, $x->{_d});         # -5/2 => -7/2
723     }
724   else
725     {
726     if ($MBI->_acmp($x->{_n},$x->{_d}) < 0)             # n < d?
727       {
728       # 1/3 -- => -2/3
729       $x->{_n} = $MBI->_sub( $MBI->_copy($x->{_d}), $x->{_n});
730       $x->{sign} = '-';
731       }
732     else
733       {
734       $x->{_n} = $MBI->_sub($x->{_n}, $x->{_d});        # 5/2 => 3/2
735       }
736     }
737   $x->bnorm()->round(@r);
738   }
739
740 sub binc
741   {
742   # increment value (add 1)
743   my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
744
745   return $x if $x->{sign} !~ /^[+-]$/;  # NaN, inf, -inf
746
747   if ($x->{sign} eq '-')
748     {
749     if ($MBI->_acmp($x->{_n},$x->{_d}) < 0)
750       {
751       # -1/3 ++ => 2/3 (overflow at 0)
752       $x->{_n} = $MBI->_sub( $MBI->_copy($x->{_d}), $x->{_n});
753       $x->{sign} = '+';
754       }
755     else
756       {
757       $x->{_n} = $MBI->_sub($x->{_n}, $x->{_d});        # -5/2 => -3/2
758       }
759     }
760   else
761     {
762     $x->{_n} = $MBI->_add($x->{_n},$x->{_d});           # 5/2 => 7/2
763     }
764   $x->bnorm()->round(@r);
765   }
766
767 ##############################################################################
768 # is_foo methods (the rest is inherited)
769
770 sub is_int
771   {
772   # return true if arg (BRAT or num_str) is an integer
773   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
774
775   return 1 if ($x->{sign} =~ /^[+-]$/) &&       # NaN and +-inf aren't
776     $MBI->_is_one($x->{_d});                    # x/y && y != 1 => no integer
777   0;
778   }
779
780 sub is_zero
781   {
782   # return true if arg (BRAT or num_str) is zero
783   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
784
785   return 1 if $x->{sign} eq '+' && $MBI->_is_zero($x->{_n});
786   0;
787   }
788
789 sub is_one
790   {
791   # return true if arg (BRAT or num_str) is +1 or -1 if signis given
792   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
793
794   my $sign = $_[2] || ''; $sign = '+' if $sign ne '-';
795   return 1
796    if ($x->{sign} eq $sign && $MBI->_is_one($x->{_n}) && $MBI->_is_one($x->{_d}));
797   0;
798   }
799
800 sub is_odd
801   {
802   # return true if arg (BFLOAT or num_str) is odd or false if even
803   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
804
805   return 1 if ($x->{sign} =~ /^[+-]$/) &&               # NaN & +-inf aren't
806     ($MBI->_is_one($x->{_d}) && $MBI->_is_odd($x->{_n})); # x/2 is not, but 3/1
807   0;
808   }
809
810 sub is_even
811   {
812   # return true if arg (BINT or num_str) is even or false if odd
813   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
814
815   return 0 if $x->{sign} !~ /^[+-]$/;                   # NaN & +-inf aren't
816   return 1 if ($MBI->_is_one($x->{_d})                  # x/3 is never
817      && $MBI->_is_even($x->{_n}));                      # but 4/1 is
818   0;
819   }
820
821 ##############################################################################
822 # parts() and friends
823
824 sub numerator
825   {
826   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
827
828   # NaN, inf, -inf
829   return Math::BigInt->new($x->{sign}) if ($x->{sign} !~ /^[+-]$/);
830
831   my $n = Math::BigInt->new($MBI->_str($x->{_n})); $n->{sign} = $x->{sign};
832   $n;
833   }
834
835 sub denominator
836   {
837   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
838
839   # NaN
840   return Math::BigInt->new($x->{sign}) if $x->{sign} eq 'NaN';
841   # inf, -inf
842   return Math::BigInt->bone() if $x->{sign} !~ /^[+-]$/;
843
844   Math::BigInt->new($MBI->_str($x->{_d}));
845   }
846
847 sub parts
848   {
849   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
850
851   my $c = 'Math::BigInt';
852
853   return ($c->bnan(),$c->bnan()) if $x->{sign} eq 'NaN';
854   return ($c->binf(),$c->binf()) if $x->{sign} eq '+inf';
855   return ($c->binf('-'),$c->binf()) if $x->{sign} eq '-inf';
856
857   my $n = $c->new( $MBI->_str($x->{_n}));
858   $n->{sign} = $x->{sign};
859   my $d = $c->new( $MBI->_str($x->{_d}));
860   ($n,$d);
861   }
862
863 sub length
864   {
865   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
866
867   return $nan unless $x->is_int();
868   $MBI->_len($x->{_n});                         # length(-123/1) => length(123)
869   }
870
871 sub digit
872   {
873   my ($self,$x,$n) = ref($_[0]) ? (undef,$_[0],$_[1]) : objectify(1,@_);
874
875   return $nan unless $x->is_int();
876   $MBI->_digit($x->{_n},$n || 0);               # digit(-123/1,2) => digit(123,2)
877   }
878
879 ##############################################################################
880 # special calc routines
881
882 sub bceil
883   {
884   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
885
886   return $x if $x->{sign} !~ /^[+-]$/ ||        # not for NaN, inf
887             $MBI->_is_one($x->{_d});            # 22/1 => 22, 0/1 => 0
888
889   $x->{_n} = $MBI->_div($x->{_n},$x->{_d});     # 22/7 => 3/1 w/ truncate
890   $x->{_d} = $MBI->_one();                      # d => 1
891   $x->{_n} = $MBI->_inc($x->{_n})
892     if $x->{sign} eq '+';                       # +22/7 => 4/1
893   $x->{sign} = '+' if $MBI->_is_zero($x->{_n}); # -0 => 0
894   $x;
895   }
896
897 sub bfloor
898   {
899   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
900
901   return $x if $x->{sign} !~ /^[+-]$/ ||        # not for NaN, inf
902             $MBI->_is_one($x->{_d});            # 22/1 => 22, 0/1 => 0
903
904   $x->{_n} = $MBI->_div($x->{_n},$x->{_d});     # 22/7 => 3/1 w/ truncate
905   $x->{_d} = $MBI->_one();                      # d => 1
906   $x->{_n} = $MBI->_inc($x->{_n})
907     if $x->{sign} eq '-';                       # -22/7 => -4/1
908   $x;
909   }
910
911 sub bfac
912   {
913   my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
914
915   # if $x is not an integer
916   if (($x->{sign} ne '+') || (!$MBI->_is_one($x->{_d})))
917     {
918     return $x->bnan();
919     }
920
921   $x->{_n} = $MBI->_fac($x->{_n});
922   # since _d is 1, we don't need to reduce/norm the result
923   $x->round(@r);
924   }
925
926 sub bpow
927   {
928   # power ($x ** $y)
929
930   # set up parameters
931   my ($self,$x,$y,@r) = (ref($_[0]),@_);
932   # objectify is costly, so avoid it
933   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
934     {
935     ($self,$x,$y,@r) = objectify(2,@_);
936     }
937
938   return $x if $x->{sign} =~ /^[+-]inf$/;       # -inf/+inf ** x
939   return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;
940   return $x->bone(@r) if $y->is_zero();
941   return $x->round(@r) if $x->is_one() || $y->is_one();
942
943   if ($x->{sign} eq '-' && $MBI->_is_one($x->{_n}) && $MBI->_is_one($x->{_d}))
944     {
945     # if $x == -1 and odd/even y => +1/-1
946     return $y->is_odd() ? $x->round(@r) : $x->babs()->round(@r);
947     # my Casio FX-5500L has a bug here: -1 ** 2 is -1, but -1 * -1 is 1;
948     }
949   # 1 ** -y => 1 / (1 ** |y|)
950   # so do test for negative $y after above's clause
951
952   return $x->round(@r) if $x->is_zero();  # 0**y => 0 (if not y <= 0)
953
954   # shortcut if y == 1/N (is then sqrt() respective broot())
955   if ($MBI->_is_one($y->{_n}))
956     {
957     return $x->bsqrt(@r) if $MBI->_is_two($y->{_d});    # 1/2 => sqrt
958     return $x->broot($MBI->_str($y->{_d}),@r);          # 1/N => root(N)
959     }
960
961   # shortcut y/1 (and/or x/1)
962   if ($MBI->_is_one($y->{_d}))
963     {
964     # shortcut for x/1 and y/1
965     if ($MBI->_is_one($x->{_d}))
966       {
967       $x->{_n} = $MBI->_pow($x->{_n},$y->{_n});         # x/1 ** y/1 => (x ** y)/1
968       if ($y->{sign} eq '-')
969         {
970         # 0.2 ** -3 => 1/(0.2 ** 3)
971         ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n});      # swap
972         }
973       # correct sign; + ** + => +
974       if ($x->{sign} eq '-')
975         {
976         # - * - => +, - * - * - => -
977         $x->{sign} = '+' if $MBI->_is_even($y->{_n});
978         }
979       return $x->round(@r);
980       }
981     # x/z ** y/1
982     $x->{_n} = $MBI->_pow($x->{_n},$y->{_n});           # 5/2 ** y/1 => 5 ** y / 2 ** y
983     $x->{_d} = $MBI->_pow($x->{_d},$y->{_n});
984     if ($y->{sign} eq '-')
985       {
986       # 0.2 ** -3 => 1/(0.2 ** 3)
987       ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n});        # swap
988       }
989     # correct sign; + ** + => +
990     if ($x->{sign} eq '-')
991       {
992       # - * - => +, - * - * - => -
993       $x->{sign} = '+' if $MBI->_is_even($y->{_n});
994       }
995     return $x->round(@r);
996     }
997
998 #  print STDERR "# $x $y\n";
999
1000   # otherwise:
1001
1002   #      n/d     n  ______________
1003   # a/b       =  -\/  (a/b) ** d
1004
1005   # (a/b) ** n == (a ** n) / (b ** n)
1006   $MBI->_pow($x->{_n}, $y->{_n} );
1007   $MBI->_pow($x->{_d}, $y->{_n} );
1008
1009   return $x->broot($MBI->_str($y->{_d}),@r);            # n/d => root(n)
1010   }
1011
1012 sub blog
1013   {
1014   # set up parameters
1015   my ($self,$x,$y,@r) = (ref($_[0]),@_);
1016
1017   # objectify is costly, so avoid it
1018   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1019     {
1020     ($self,$x,$y,@r) = objectify(2,$class,@_);
1021     }
1022
1023   # blog(1,Y) => 0
1024   return $x->bzero() if $x->is_one() && $y->{sign} eq '+';
1025
1026   # $x <= 0 => NaN
1027   return $x->bnan() if $x->is_zero() || $x->{sign} ne '+' || $y->{sign} ne '+';
1028
1029   if ($x->is_int() && $y->is_int())
1030     {
1031     return $self->new($x->as_number()->blog($y->as_number(),@r));
1032     }
1033
1034   # do it with floats
1035   $x->_new_from_float( $x->_as_float()->blog(Math::BigFloat->new("$y"),@r) );
1036   }
1037
1038 sub bexp
1039   {
1040   # set up parameters
1041   my ($self,$x,$y,@r) = (ref($_[0]),@_);
1042
1043   # objectify is costly, so avoid it
1044   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1045     {
1046     ($self,$x,$y,@r) = objectify(2,$class,@_);
1047     }
1048
1049   return $x->binf(@r) if $x->{sign} eq '+inf';
1050   return $x->bzero(@r) if $x->{sign} eq '-inf';
1051
1052   # we need to limit the accuracy to protect against overflow
1053   my $fallback = 0;
1054   my ($scale,@params);
1055   ($x,@params) = $x->_find_round_parameters(@r);
1056
1057   # also takes care of the "error in _find_round_parameters?" case
1058   return $x if $x->{sign} eq 'NaN';
1059
1060   # no rounding at all, so must use fallback
1061   if (scalar @params == 0)
1062     {
1063     # simulate old behaviour
1064     $params[0] = $self->div_scale();    # and round to it as accuracy
1065     $params[1] = undef;                 # P = undef
1066     $scale = $params[0]+4;              # at least four more for proper round
1067     $params[2] = $r[2];                 # round mode by caller or undef
1068     $fallback = 1;                      # to clear a/p afterwards
1069     }
1070   else
1071     {
1072     # the 4 below is empirical, and there might be cases where it's not enough...
1073     $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined
1074     }
1075
1076   return $x->bone(@params) if $x->is_zero();
1077
1078   # See the comments in Math::BigFloat on how this algorithm works.
1079   # Basically we calculate A and B (where B is faculty(N)) so that A/B = e
1080
1081   my $x_org = $x->copy();
1082   if ($scale <= 75)
1083     {
1084     # set $x directly from a cached string form
1085     $x->{_n} =
1086         $MBI->_new("90933395208605785401971970164779391644753259799242");
1087     $x->{_d} =
1088         $MBI->_new("33452526613163807108170062053440751665152000000000");
1089     $x->{sign} = '+';
1090     }
1091   else
1092     {
1093     # compute A and B so that e = A / B.
1094
1095     # After some terms we end up with this, so we use it as a starting point:
1096     my $A = $MBI->_new("90933395208605785401971970164779391644753259799242");
1097     my $F = $MBI->_new(42); my $step = 42;
1098
1099     # Compute how many steps we need to take to get $A and $B sufficiently big
1100     my $steps = Math::BigFloat::_len_to_steps($scale - 4);
1101 #    print STDERR "# Doing $steps steps for ", $scale-4, " digits\n";
1102     while ($step++ <= $steps)
1103       {
1104       # calculate $a * $f + 1
1105       $A = $MBI->_mul($A, $F);
1106       $A = $MBI->_inc($A);
1107       # increment f
1108       $F = $MBI->_inc($F);
1109       }
1110     # compute $B as factorial of $steps (this is faster than doing it manually)
1111     my $B = $MBI->_fac($MBI->_new($steps));
1112
1113 #  print "A ", $MBI->_str($A), "\nB ", $MBI->_str($B), "\n";
1114
1115     $x->{_n} = $A;
1116     $x->{_d} = $B;
1117     $x->{sign} = '+';
1118     }
1119
1120   # $x contains now an estimate of e, with some surplus digits, so we can round
1121   if (!$x_org->is_one())
1122     {
1123     # raise $x to the wanted power and round it in one step:
1124     $x->bpow($x_org, @params);
1125     }
1126   else
1127     {
1128     # else just round the already computed result
1129     delete $x->{_a}; delete $x->{_p};
1130     # shortcut to not run through _find_round_parameters again
1131     if (defined $params[0])
1132       {
1133       $x->bround($params[0],$params[2]);                # then round accordingly
1134       }
1135     else
1136       {
1137       $x->bfround($params[1],$params[2]);               # then round accordingly
1138       }
1139     }
1140   if ($fallback)
1141     {
1142     # clear a/p after round, since user did not request it
1143     delete $x->{_a}; delete $x->{_p};
1144     }
1145
1146   $x;
1147   }
1148
1149 sub bnok
1150   {
1151   # set up parameters
1152   my ($self,$x,$y,@r) = (ref($_[0]),@_);
1153
1154   # objectify is costly, so avoid it
1155   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1156     {
1157     ($self,$x,$y,@r) = objectify(2,$class,@_);
1158     }
1159
1160   # do it with floats
1161   $x->_new_from_float( $x->_as_float()->bnok(Math::BigFloat->new("$y"),@r) );
1162   }
1163
1164 sub _float_from_part
1165   {
1166   my $x = shift;
1167
1168   my $f = Math::BigFloat->bzero();
1169   $f->{_m} = $MBI->_copy($x);
1170   $f->{_e} = $MBI->_zero();
1171
1172   $f;
1173   }
1174
1175 sub _as_float
1176   {
1177   my $x = shift;
1178
1179   local $Math::BigFloat::upgrade = undef;
1180   local $Math::BigFloat::accuracy = undef;
1181   local $Math::BigFloat::precision = undef;
1182   # 22/7 => 3.142857143..
1183
1184   my $a = $x->accuracy() || 0;
1185   if ($a != 0 || !$MBI->_is_one($x->{_d}))
1186     {
1187     # n/d
1188     return scalar Math::BigFloat->new($x->{sign} . $MBI->_str($x->{_n}))->bdiv( $MBI->_str($x->{_d}), $x->accuracy());
1189     }
1190   # just n
1191   Math::BigFloat->new($x->{sign} . $MBI->_str($x->{_n}));
1192   }
1193
1194 sub broot
1195   {
1196   # set up parameters
1197   my ($self,$x,$y,@r) = (ref($_[0]),@_);
1198   # objectify is costly, so avoid it
1199   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1200     {
1201     ($self,$x,$y,@r) = objectify(2,@_);
1202     }
1203
1204   if ($x->is_int() && $y->is_int())
1205     {
1206     return $self->new($x->as_number()->broot($y->as_number(),@r));
1207     }
1208
1209   # do it with floats
1210   $x->_new_from_float( $x->_as_float()->broot($y->_as_float(),@r) )->bnorm()->bround(@r);
1211   }
1212
1213 sub bmodpow
1214   {
1215   # set up parameters
1216   my ($self,$x,$y,$m,@r) = (ref($_[0]),@_);
1217   # objectify is costly, so avoid it
1218   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1219     {
1220     ($self,$x,$y,$m,@r) = objectify(3,@_);
1221     }
1222
1223   # $x or $y or $m are NaN or +-inf => NaN
1224   return $x->bnan()
1225    if $x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/ ||
1226    $m->{sign} !~ /^[+-]$/;
1227
1228   if ($x->is_int() && $y->is_int() && $m->is_int())
1229     {
1230     return $self->new($x->as_number()->bmodpow($y->as_number(),$m,@r));
1231     }
1232
1233   warn ("bmodpow() not fully implemented");
1234   $x->bnan();
1235   }
1236
1237 sub bmodinv
1238   {
1239   # set up parameters
1240   my ($self,$x,$y,@r) = (ref($_[0]),@_);
1241   # objectify is costly, so avoid it
1242   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1243     {
1244     ($self,$x,$y,@r) = objectify(2,@_);
1245     }
1246
1247   # $x or $y are NaN or +-inf => NaN
1248   return $x->bnan()
1249    if $x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/;
1250
1251   if ($x->is_int() && $y->is_int())
1252     {
1253     return $self->new($x->as_number()->bmodinv($y->as_number(),@r));
1254     }
1255
1256   warn ("bmodinv() not fully implemented");
1257   $x->bnan();
1258   }
1259
1260 sub bsqrt
1261   {
1262   my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
1263
1264   return $x->bnan() if $x->{sign} !~ /^[+]/;    # NaN, -inf or < 0
1265   return $x if $x->{sign} eq '+inf';            # sqrt(inf) == inf
1266   return $x->round(@r) if $x->is_zero() || $x->is_one();
1267
1268   local $Math::BigFloat::upgrade = undef;
1269   local $Math::BigFloat::downgrade = undef;
1270   local $Math::BigFloat::precision = undef;
1271   local $Math::BigFloat::accuracy = undef;
1272   local $Math::BigInt::upgrade = undef;
1273   local $Math::BigInt::precision = undef;
1274   local $Math::BigInt::accuracy = undef;
1275
1276   $x->{_n} = _float_from_part( $x->{_n} )->bsqrt();
1277   $x->{_d} = _float_from_part( $x->{_d} )->bsqrt();
1278
1279   # XXX TODO: we probably can optimize this:
1280
1281   # if sqrt(D) was not integer
1282   if ($x->{_d}->{_es} ne '+')
1283     {
1284     $x->{_n}->blsft($x->{_d}->exponent()->babs(),10);   # 7.1/4.51 => 7.1/45.1
1285     $x->{_d} = $MBI->_copy( $x->{_d}->{_m} );           # 7.1/45.1 => 71/45.1
1286     }
1287   # if sqrt(N) was not integer
1288   if ($x->{_n}->{_es} ne '+')
1289     {
1290     $x->{_d}->blsft($x->{_n}->exponent()->babs(),10);   # 71/45.1 => 710/45.1
1291     $x->{_n} = $MBI->_copy( $x->{_n}->{_m} );           # 710/45.1 => 710/451
1292     }
1293
1294   # convert parts to $MBI again
1295   $x->{_n} = $MBI->_lsft( $MBI->_copy( $x->{_n}->{_m} ), $x->{_n}->{_e}, 10)
1296     if ref($x->{_n}) ne $MBI && ref($x->{_n}) ne 'ARRAY';
1297   $x->{_d} = $MBI->_lsft( $MBI->_copy( $x->{_d}->{_m} ), $x->{_d}->{_e}, 10)
1298     if ref($x->{_d}) ne $MBI && ref($x->{_d}) ne 'ARRAY';
1299
1300   $x->bnorm()->round(@r);
1301   }
1302
1303 sub blsft
1304   {
1305   my ($self,$x,$y,$b,@r) = objectify(3,@_);
1306
1307   $b = 2 unless defined $b;
1308   $b = $self->new($b) unless ref ($b);
1309   $x->bmul( $b->copy()->bpow($y), @r);
1310   $x;
1311   }
1312
1313 sub brsft
1314   {
1315   my ($self,$x,$y,$b,@r) = objectify(3,@_);
1316
1317   $b = 2 unless defined $b;
1318   $b = $self->new($b) unless ref ($b);
1319   $x->bdiv( $b->copy()->bpow($y), @r);
1320   $x;
1321   }
1322
1323 ##############################################################################
1324 # round
1325
1326 sub round
1327   {
1328   $_[0];
1329   }
1330
1331 sub bround
1332   {
1333   $_[0];
1334   }
1335
1336 sub bfround
1337   {
1338   $_[0];
1339   }
1340
1341 ##############################################################################
1342 # comparing
1343
1344 sub bcmp
1345   {
1346   # compare two signed numbers
1347
1348   # set up parameters
1349   my ($self,$x,$y) = (ref($_[0]),@_);
1350   # objectify is costly, so avoid it
1351   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1352     {
1353     ($self,$x,$y) = objectify(2,@_);
1354     }
1355
1356   if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
1357     {
1358     # handle +-inf and NaN
1359     return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1360     return 0 if $x->{sign} eq $y->{sign} && $x->{sign} =~ /^[+-]inf$/;
1361     return +1 if $x->{sign} eq '+inf';
1362     return -1 if $x->{sign} eq '-inf';
1363     return -1 if $y->{sign} eq '+inf';
1364     return +1;
1365     }
1366   # check sign for speed first
1367   return 1 if $x->{sign} eq '+' && $y->{sign} eq '-';   # does also 0 <=> -y
1368   return -1 if $x->{sign} eq '-' && $y->{sign} eq '+';  # does also -x <=> 0
1369
1370   # shortcut
1371   my $xz = $MBI->_is_zero($x->{_n});
1372   my $yz = $MBI->_is_zero($y->{_n});
1373   return 0 if $xz && $yz;                               # 0 <=> 0
1374   return -1 if $xz && $y->{sign} eq '+';                # 0 <=> +y
1375   return 1 if $yz && $x->{sign} eq '+';                 # +x <=> 0
1376
1377   my $t = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d});
1378   my $u = $MBI->_mul( $MBI->_copy($y->{_n}), $x->{_d});
1379
1380   my $cmp = $MBI->_acmp($t,$u);                         # signs are equal
1381   $cmp = -$cmp if $x->{sign} eq '-';                    # both are '-' => reverse
1382   $cmp;
1383   }
1384
1385 sub bacmp
1386   {
1387   # compare two numbers (as unsigned)
1388
1389   # set up parameters
1390   my ($self,$x,$y) = (ref($_[0]),@_);
1391   # objectify is costly, so avoid it
1392   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1393     {
1394     ($self,$x,$y) = objectify(2,$class,@_);
1395     }
1396
1397   if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
1398     {
1399     # handle +-inf and NaN
1400     return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1401     return 0 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} =~ /^[+-]inf$/;
1402     return 1 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} !~ /^[+-]inf$/;
1403     return -1;
1404     }
1405
1406   my $t = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d});
1407   my $u = $MBI->_mul( $MBI->_copy($y->{_n}), $x->{_d});
1408   $MBI->_acmp($t,$u);                                   # ignore signs
1409   }
1410
1411 ##############################################################################
1412 # output conversation
1413
1414 sub numify
1415   {
1416   # convert 17/8 => float (aka 2.125)
1417   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1418
1419   return $x->bstr() if $x->{sign} !~ /^[+-]$/;  # inf, NaN, etc
1420
1421   # N/1 => N
1422   my $neg = ''; $neg = '-' if $x->{sign} eq '-';
1423   return $neg . $MBI->_num($x->{_n}) if $MBI->_is_one($x->{_d});
1424
1425   $x->_as_float()->numify() + 0.0;
1426   }
1427
1428 sub as_number
1429   {
1430   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1431
1432   # NaN, inf etc
1433   return Math::BigInt->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
1434
1435   my $u = Math::BigInt->bzero();
1436   $u->{value} = $MBI->_div( $MBI->_copy($x->{_n}), $x->{_d});   # 22/7 => 3
1437   $u->bneg if $x->{sign} eq '-'; # no negative zero
1438   $u;
1439   }
1440
1441 sub as_float
1442   {
1443   # return N/D as Math::BigFloat
1444
1445   # set up parameters
1446   my ($self,$x,@r) = (ref($_[0]),@_);
1447   # objectify is costly, so avoid it
1448   ($self,$x,@r) = objectify(1,$class,@_) unless ref $_[0];
1449
1450   # NaN, inf etc
1451   return Math::BigFloat->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
1452
1453   my $u = Math::BigFloat->bzero();
1454   $u->{sign} = $x->{sign};
1455   # n
1456   $u->{_m} = $MBI->_copy($x->{_n});
1457   $u->{_e} = $MBI->_zero();
1458   $u->bdiv( $MBI->_str($x->{_d}), @r);
1459   # return $u
1460   $u;
1461   }
1462
1463 sub as_bin
1464   {
1465   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1466
1467   return $x unless $x->is_int();
1468
1469   my $s = $x->{sign}; $s = '' if $s eq '+';
1470   $s . $MBI->_as_bin($x->{_n});
1471   }
1472
1473 sub as_hex
1474   {
1475   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1476
1477   return $x unless $x->is_int();
1478
1479   my $s = $x->{sign}; $s = '' if $s eq '+';
1480   $s . $MBI->_as_hex($x->{_n});
1481   }
1482
1483 sub as_oct
1484   {
1485   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1486
1487   return $x unless $x->is_int();
1488
1489   my $s = $x->{sign}; $s = '' if $s eq '+';
1490   $s . $MBI->_as_oct($x->{_n});
1491   }
1492
1493 ##############################################################################
1494
1495 sub from_hex
1496   {
1497   my $class = shift;
1498
1499   $class->new(@_);
1500   }
1501
1502 sub from_bin
1503   {
1504   my $class = shift;
1505
1506   $class->new(@_);
1507   }
1508
1509 sub from_oct
1510   {
1511   my $class = shift;
1512
1513   my @parts;
1514   for my $c (@_)
1515     {
1516     push @parts, Math::BigInt->from_oct($c);
1517     }
1518   $class->new ( @parts );
1519   }
1520
1521 ##############################################################################
1522 # import
1523
1524 sub import
1525   {
1526   my $self = shift;
1527   my $l = scalar @_;
1528   my $lib = ''; my @a;
1529   my $try = 'try';
1530
1531   for ( my $i = 0; $i < $l ; $i++)
1532     {
1533     if ( $_[$i] eq ':constant' )
1534       {
1535       # this rest causes overlord er load to step in
1536       overload::constant float => sub { $self->new(shift); };
1537       }
1538 #    elsif ($_[$i] eq 'upgrade')
1539 #      {
1540 #     # this causes upgrading
1541 #      $upgrade = $_[$i+1];             # or undef to disable
1542 #      $i++;
1543 #      }
1544     elsif ($_[$i] eq 'downgrade')
1545       {
1546       # this causes downgrading
1547       $downgrade = $_[$i+1];            # or undef to disable
1548       $i++;
1549       }
1550     elsif ($_[$i] =~ /^(lib|try|only)\z/)
1551       {
1552       $lib = $_[$i+1] || '';            # default Calc
1553       $try = $1;                        # lib, try or only
1554       $i++;
1555       }
1556     elsif ($_[$i] eq 'with')
1557       {
1558       # this argument is no longer used
1559       #$MBI = $_[$i+1] || 'Math::BigInt::Calc'; # default Math::BigInt::Calc
1560       $i++;
1561       }
1562     else
1563       {
1564       push @a, $_[$i];
1565       }
1566     }
1567   require Math::BigInt;
1568
1569   # let use Math::BigInt lib => 'GMP'; use Math::BigRat; still have GMP
1570   if ($lib ne '')
1571     {
1572     my @c = split /\s*,\s*/, $lib;
1573     foreach (@c)
1574       {
1575       $_ =~ tr/a-zA-Z0-9://cd;                    # limit to sane characters
1576       }
1577     $lib = join(",", @c);
1578     }
1579   my @import = ('objectify');
1580   push @import, $try => $lib if $lib ne '';
1581
1582   # MBI already loaded, so feed it our lib arguments
1583   Math::BigInt->import( @import );
1584
1585   $MBI = Math::BigFloat->config()->{lib};
1586
1587   # register us with MBI to get notified of future lib changes
1588   Math::BigInt::_register_callback( $self, sub { $MBI = $_[0]; } );
1589
1590   # any non :constant stuff is handled by our parent, Exporter (loaded
1591   # by Math::BigFloat, even if @_ is empty, to give it a chance
1592   $self->SUPER::import(@a);             # for subclasses
1593   $self->export_to_level(1,$self,@a);   # need this, too
1594   }
1595
1596 1;
1597
1598 __END__
1599
1600 =pod
1601
1602 =head1 NAME
1603
1604 Math::BigRat - Arbitrary big rational numbers
1605
1606 =head1 SYNOPSIS
1607
1608         use Math::BigRat;
1609
1610         my $x = Math::BigRat->new('3/7'); $x += '5/9';
1611
1612         print $x->bstr(),"\n";
1613         print $x ** 2,"\n";
1614
1615         my $y = Math::BigRat->new('inf');
1616         print "$y ", ($y->is_inf ? 'is' : 'is not') , " infinity\n";
1617
1618         my $z = Math::BigRat->new(144); $z->bsqrt();
1619
1620 =head1 DESCRIPTION
1621
1622 Math::BigRat complements Math::BigInt and Math::BigFloat by providing support
1623 for arbitrary big rational numbers.
1624
1625 =head2 MATH LIBRARY
1626
1627 You can change the underlying module that does the low-level
1628 math operations by using:
1629
1630         use Math::BigRat try => 'GMP';
1631
1632 Note: This needs Math::BigInt::GMP installed.
1633
1634 The following would first try to find Math::BigInt::Foo, then
1635 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
1636
1637         use Math::BigRat try => 'Foo,Math::BigInt::Bar';
1638
1639 If you want to get warned when the fallback occurs, replace "try" with
1640 "lib":
1641
1642         use Math::BigRat lib => 'Foo,Math::BigInt::Bar';
1643
1644 If you want the code to die instead, replace "try" with
1645 "only":
1646
1647         use Math::BigRat only => 'Foo,Math::BigInt::Bar';
1648
1649 =head1 METHODS
1650
1651 Any methods not listed here are derived from Math::BigFloat (or
1652 Math::BigInt), so make sure you check these two modules for further
1653 information.
1654
1655 =head2 new()
1656
1657         $x = Math::BigRat->new('1/3');
1658
1659 Create a new Math::BigRat object. Input can come in various forms:
1660
1661         $x = Math::BigRat->new(123);                            # scalars
1662         $x = Math::BigRat->new('inf');                          # infinity
1663         $x = Math::BigRat->new('123.3');                        # float
1664         $x = Math::BigRat->new('1/3');                          # simple string
1665         $x = Math::BigRat->new('1 / 3');                        # spaced
1666         $x = Math::BigRat->new('1 / 0.1');                      # w/ floats
1667         $x = Math::BigRat->new(Math::BigInt->new(3));           # BigInt
1668         $x = Math::BigRat->new(Math::BigFloat->new('3.1'));     # BigFloat
1669         $x = Math::BigRat->new(Math::BigInt::Lite->new('2'));   # BigLite
1670
1671         # You can also give D and N as different objects:
1672         $x = Math::BigRat->new(
1673                 Math::BigInt->new(-123),
1674                 Math::BigInt->new(7),
1675                 );                      # => -123/7
1676
1677 =head2 numerator()
1678
1679         $n = $x->numerator();
1680
1681 Returns a copy of the numerator (the part above the line) as signed BigInt.
1682
1683 =head2 denominator()
1684
1685         $d = $x->denominator();
1686
1687 Returns a copy of the denominator (the part under the line) as positive BigInt.
1688
1689 =head2 parts()
1690
1691         ($n,$d) = $x->parts();
1692
1693 Return a list consisting of (signed) numerator and (unsigned) denominator as
1694 BigInts.
1695
1696 =head2 numify()
1697
1698         my $y = $x->numify();
1699
1700 Returns the object as a scalar. This will lose some data if the object
1701 cannot be represented by a normal Perl scalar (integer or float), so
1702 use L<as_int()|/as_int()E<sol>as_number()> or L</as_float()> instead.
1703
1704 This routine is automatically used whenever a scalar is required:
1705
1706         my $x = Math::BigRat->new('3/1');
1707         @array = (0,1,2,3);
1708         $y = $array[$x];                # set $y to 3
1709
1710 =head2 as_int()/as_number()
1711
1712         $x = Math::BigRat->new('13/7');
1713         print $x->as_int(),"\n";                # '1'
1714
1715 Returns a copy of the object as BigInt, truncated to an integer.
1716
1717 C<as_number()> is an alias for C<as_int()>.
1718
1719 =head2 as_float()
1720
1721         $x = Math::BigRat->new('13/7');
1722         print $x->as_float(),"\n";              # '1'
1723
1724         $x = Math::BigRat->new('2/3');
1725         print $x->as_float(5),"\n";             # '0.66667'
1726
1727 Returns a copy of the object as BigFloat, preserving the
1728 accuracy as wanted, or the default of 40 digits.
1729
1730 This method was added in v0.22 of Math::BigRat (April 2008).
1731
1732 =head2 as_hex()
1733
1734         $x = Math::BigRat->new('13');
1735         print $x->as_hex(),"\n";                # '0xd'
1736
1737 Returns the BigRat as hexadecimal string. Works only for integers.
1738
1739 =head2 as_bin()
1740
1741         $x = Math::BigRat->new('13');
1742         print $x->as_bin(),"\n";                # '0x1101'
1743
1744 Returns the BigRat as binary string. Works only for integers.
1745
1746 =head2 as_oct()
1747
1748         $x = Math::BigRat->new('13');
1749         print $x->as_oct(),"\n";                # '015'
1750
1751 Returns the BigRat as octal string. Works only for integers.
1752
1753 =head2 from_hex()/from_bin()/from_oct()
1754
1755         my $h = Math::BigRat->from_hex('0x10');
1756         my $b = Math::BigRat->from_bin('0b10000000');
1757         my $o = Math::BigRat->from_oct('020');
1758
1759 Create a BigRat from an hexadecimal, binary or octal number
1760 in string form.
1761
1762 =head2 length()
1763
1764         $len = $x->length();
1765
1766 Return the length of $x in digits for integer values.
1767
1768 =head2 digit()
1769
1770         print Math::BigRat->new('123/1')->digit(1);     # 1
1771         print Math::BigRat->new('123/1')->digit(-1);    # 3
1772
1773 Return the N'ths digit from X when X is an integer value.
1774
1775 =head2 bnorm()
1776
1777         $x->bnorm();
1778
1779 Reduce the number to the shortest form. This routine is called
1780 automatically whenever it is needed.
1781
1782 =head2 bfac()
1783
1784         $x->bfac();
1785
1786 Calculates the factorial of $x. For instance:
1787
1788         print Math::BigRat->new('3/1')->bfac(),"\n";    # 1*2*3
1789         print Math::BigRat->new('5/1')->bfac(),"\n";    # 1*2*3*4*5
1790
1791 Works currently only for integers.
1792
1793 =head2 bround()/round()/bfround()
1794
1795 Are not yet implemented.
1796
1797 =head2 bmod()
1798
1799         use Math::BigRat;
1800         my $x = Math::BigRat->new('7/4');
1801         my $y = Math::BigRat->new('4/3');
1802         print $x->bmod($y);
1803
1804 Set $x to the remainder of the division of $x by $y.
1805
1806 =head2 bneg()
1807
1808         $x->bneg();
1809
1810 Used to negate the object in-place.
1811
1812 =head2 is_one()
1813
1814         print "$x is 1\n" if $x->is_one();
1815
1816 Return true if $x is exactly one, otherwise false.
1817
1818 =head2 is_zero()
1819
1820         print "$x is 0\n" if $x->is_zero();
1821
1822 Return true if $x is exactly zero, otherwise false.
1823
1824 =head2 is_pos()/is_positive()
1825
1826         print "$x is >= 0\n" if $x->is_positive();
1827
1828 Return true if $x is positive (greater than or equal to zero), otherwise
1829 false. Please note that '+inf' is also positive, while 'NaN' and '-inf' aren't.
1830
1831 C<is_positive()> is an alias for C<is_pos()>.
1832
1833 =head2 is_neg()/is_negative()
1834
1835         print "$x is < 0\n" if $x->is_negative();
1836
1837 Return true if $x is negative (smaller than zero), otherwise false. Please
1838 note that '-inf' is also negative, while 'NaN' and '+inf' aren't.
1839
1840 C<is_negative()> is an alias for C<is_neg()>.
1841
1842 =head2 is_int()
1843
1844         print "$x is an integer\n" if $x->is_int();
1845
1846 Return true if $x has a denominator of 1 (e.g. no fraction parts), otherwise
1847 false. Please note that '-inf', 'inf' and 'NaN' aren't integer.
1848
1849 =head2 is_odd()
1850
1851         print "$x is odd\n" if $x->is_odd();
1852
1853 Return true if $x is odd, otherwise false.
1854
1855 =head2 is_even()
1856
1857         print "$x is even\n" if $x->is_even();
1858
1859 Return true if $x is even, otherwise false.
1860
1861 =head2 bceil()
1862
1863         $x->bceil();
1864
1865 Set $x to the next bigger integer value (e.g. truncate the number to integer
1866 and then increment it by one).
1867
1868 =head2 bfloor()
1869
1870         $x->bfloor();
1871
1872 Truncate $x to an integer value.
1873
1874 =head2 bsqrt()
1875
1876         $x->bsqrt();
1877
1878 Calculate the square root of $x.
1879
1880 =head2 broot()
1881
1882         $x->broot($n);
1883
1884 Calculate the N'th root of $x.
1885
1886 =head2 badd()/bmul()/bsub()/bdiv()/bdec()/binc()
1887
1888 Please see the documentation in L<Math::BigInt>.
1889
1890 =head2 copy()
1891
1892         my $z = $x->copy();
1893
1894 Makes a deep copy of the object.
1895
1896 Please see the documentation in L<Math::BigInt> for further details.
1897
1898 =head2 bstr()/bsstr()
1899
1900         my $x = Math::BigInt->new('8/4');
1901         print $x->bstr(),"\n";                  # prints 1/2
1902         print $x->bsstr(),"\n";                 # prints 1/2
1903
1904 Return a string representing this object.
1905
1906 =head2 bacmp()/bcmp()
1907
1908 Used to compare numbers.
1909
1910 Please see the documentation in L<Math::BigInt> for further details.
1911
1912 =head2 blsft()/brsft()
1913
1914 Used to shift numbers left/right.
1915
1916 Please see the documentation in L<Math::BigInt> for further details.
1917
1918 =head2 bpow()
1919
1920         $x->bpow($y);
1921
1922 Compute $x ** $y.
1923
1924 Please see the documentation in L<Math::BigInt> for further details.
1925
1926 =head2 bexp()
1927
1928         $x->bexp($accuracy);            # calculate e ** X
1929
1930 Calculates two integers A and B so that A/B is equal to C<e ** $x>, where C<e> is
1931 Euler's number.
1932
1933 This method was added in v0.20 of Math::BigRat (May 2007).
1934
1935 See also C<blog()>.
1936
1937 =head2 bnok()
1938
1939         $x->bnok($y);              # x over y (binomial coefficient n over k)
1940
1941 Calculates the binomial coefficient n over k, also called the "choose"
1942 function. The result is equivalent to:
1943
1944         ( n )      n!
1945         | - |  = -------
1946         ( k )    k!(n-k)!
1947
1948 This method was added in v0.20 of Math::BigRat (May 2007).
1949
1950 =head2 config()
1951
1952         use Data::Dumper;
1953
1954         print Dumper ( Math::BigRat->config() );
1955         print Math::BigRat->config()->{lib},"\n";
1956
1957 Returns a hash containing the configuration, e.g. the version number, lib
1958 loaded etc. The following hash keys are currently filled in with the
1959 appropriate information.
1960
1961         key             RO/RW   Description
1962                                 Example
1963         ============================================================
1964         lib             RO      Name of the Math library
1965                                 Math::BigInt::Calc
1966         lib_version     RO      Version of 'lib'
1967                                 0.30
1968         class           RO      The class of config you just called
1969                                 Math::BigRat
1970         version         RO      version number of the class you used
1971                                 0.10
1972         upgrade         RW      To which class numbers are upgraded
1973                                 undef
1974         downgrade       RW      To which class numbers are downgraded
1975                                 undef
1976         precision       RW      Global precision
1977                                 undef
1978         accuracy        RW      Global accuracy
1979                                 undef
1980         round_mode      RW      Global round mode
1981                                 even
1982         div_scale       RW      Fallback accuracy for div
1983                                 40
1984         trap_nan        RW      Trap creation of NaN (undef = no)
1985                                 undef
1986         trap_inf        RW      Trap creation of +inf/-inf (undef = no)
1987                                 undef
1988
1989 By passing a reference to a hash you may set the configuration values. This
1990 works only for values that a marked with a C<RW> above, anything else is
1991 read-only.
1992
1993 =head2 objectify()
1994
1995 This is an internal routine that turns scalars into objects.
1996
1997 =head1 BUGS
1998
1999 Please report any bugs or feature requests to
2000 C<bug-math-bigrat at rt.cpan.org>, or through the web interface at
2001 L<https://rt.cpan.org/Ticket/Create.html?Queue=Math-BigRat>
2002 (requires login).
2003 We will be notified, and then you'll automatically be notified of progress on
2004 your bug as I make changes.
2005
2006 =head1 SUPPORT
2007
2008 You can find documentation for this module with the perldoc command.
2009
2010     perldoc Math::BigRat
2011
2012 You can also look for information at:
2013
2014 =over 4
2015
2016 =item * RT: CPAN's request tracker
2017
2018 L<https://rt.cpan.org/Public/Dist/Display.html?Name=Math-BigRat>
2019
2020 =item * AnnoCPAN: Annotated CPAN documentation
2021
2022 L<http://annocpan.org/dist/Math-BigRat>
2023
2024 =item * CPAN Ratings
2025
2026 L<http://cpanratings.perl.org/dist/Math-BigRat>
2027
2028 =item * Search CPAN
2029
2030 L<http://search.cpan.org/dist/Math-BigRat/>
2031
2032 =item * CPAN Testers Matrix
2033
2034 L<http://matrix.cpantesters.org/?dist=Math-BigRat>
2035
2036 =item * The Bignum mailing list
2037
2038 =over 4
2039
2040 =item * Post to mailing list
2041
2042 C<bignum at lists.scsys.co.uk>
2043
2044 =item * View mailing list
2045
2046 L<http://lists.scsys.co.uk/pipermail/bignum/>
2047
2048 =item * Subscribe/Unsubscribe
2049
2050 L<http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/bignum>
2051
2052 =back
2053
2054 =back
2055
2056 =head1 LICENSE
2057
2058 This program is free software; you may redistribute it and/or modify it under
2059 the same terms as Perl itself.
2060
2061 =head1 SEE ALSO
2062
2063 L<bigrat>, L<Math::BigFloat> and L<Math::BigInt> as well as the backends
2064 L<Math::BigInt::FastCalc>, L<Math::BigInt::GMP>, and L<Math::BigInt::Pari>.
2065
2066 =head1 AUTHORS
2067
2068 (C) by Tels L<http://bloodgate.com/> 2001 - 2009.
2069
2070 Currently maintained by Jonathan "Duke" Leto <jonathan@leto.net> L<http://leto.net>
2071
2072 =cut