3 # "Tax the rat farms." - Lord Vetinari
6 # The following hash values are used:
7 # sign : +,-,NaN,+inf,-inf
9 # _n : numeraotr (value = _n/_d)
12 # You should not look at the innards of a BigRat - use the methods for this.
16 # anythig older is untested, and unlikely to work
21 use vars qw($VERSION @ISA $upgrade $downgrade
22 $accuracy $precision $round_mode $div_scale $_trap_nan $_trap_inf);
24 @ISA = qw(Math::BigFloat);
28 use overload; # inherit overload from Math::BigFloat
32 *objectify = \&Math::BigInt::objectify; # inherit this from BigInt
33 *AUTOLOAD = \&Math::BigFloat::AUTOLOAD; # can't inherit AUTOLOAD
34 # we inherit these from BigFloat because currently it is not possible
35 # that MBF has a different $MBI variable than we, because MBF also uses
36 # Math::BigInt::config->('lib'); (there is always only one library loaded)
37 *_e_add = \&Math::BigFloat::_e_add;
38 *_e_sub = \&Math::BigFloat::_e_sub;
39 *as_int = \&as_number;
40 *is_pos = \&is_positive;
41 *is_neg = \&is_negative;
44 ##############################################################################
45 # Global constants and flags. Access these only via the accessor methods!
47 $accuracy = $precision = undef;
53 # These are internally, and not to be used from the outside at all!
55 $_trap_nan = 0; # are NaNs ok? set w/ config()
56 $_trap_inf = 0; # are infs ok? set w/ config()
58 # the package we are using for our private parts, defaults to:
59 # Math::BigInt->config()->{lib}
60 my $MBI = 'Math::BigInt::Calc';
63 my $class = 'Math::BigRat';
67 return 0 if $_[1] =~ /^Math::Big(Int|Float)/; # we aren't
71 ##############################################################################
75 # turn a single float input into a rational number (like '0.1')
78 return $self->bnan() if $f->is_nan();
79 return $self->binf($f->{sign}) if $f->{sign} =~ /^[+-]inf$/;
81 $self->{_n} = $MBI->_copy( $f->{_m} ); # mantissa
82 $self->{_d} = $MBI->_one();
83 $self->{sign} = $f->{sign} || '+';
86 # something like Math::BigRat->new('0.1');
88 $MBI->_lsft ( $self->{_d}, $f->{_e} ,10);
92 # something like Math::BigRat->new('10');
94 $MBI->_lsft ( $self->{_n}, $f->{_e} ,10) unless
95 $MBI->_is_zero($f->{_e});
102 # create a Math::BigRat
107 my $self = { }; bless $self,$class;
109 # input like (BigInt) or (BigFloat):
110 if ((!defined $d) && (ref $n) && (!$n->isa('Math::BigRat')))
112 if ($n->isa('Math::BigFloat'))
114 $self->_new_from_float($n);
116 if ($n->isa('Math::BigInt'))
118 # TODO: trap NaN, inf
119 $self->{_n} = $MBI->_copy($n->{value}); # "mantissa" = N
120 $self->{_d} = $MBI->_one(); # d => 1
121 $self->{sign} = $n->{sign};
123 if ($n->isa('Math::BigInt::Lite'))
125 # TODO: trap NaN, inf
126 $self->{sign} = '+'; $self->{sign} = '-' if $$n < 0;
127 $self->{_n} = $MBI->_new(abs($$n)); # "mantissa" = N
128 $self->{_d} = $MBI->_one(); # d => 1
130 return $self->bnorm(); # normalize (120/1 => 12/10)
133 # input like (BigInt,BigInt) or (BigLite,BigLite):
134 if (ref($d) && ref($n))
136 # do N first (for $self->{sign}):
137 if ($n->isa('Math::BigInt'))
139 # TODO: trap NaN, inf
140 $self->{_n} = $MBI->_copy($n->{value}); # "mantissa" = N
141 $self->{sign} = $n->{sign};
143 elsif ($n->isa('Math::BigInt::Lite'))
145 # TODO: trap NaN, inf
146 $self->{sign} = '+'; $self->{sign} = '-' if $$n < 0;
147 $self->{_n} = $MBI->_new(abs($$n)); # "mantissa" = $n
152 Carp::croak(ref($n) . " is not a recognized object format for Math::BigRat->new");
155 if ($d->isa('Math::BigInt'))
157 # TODO: trap NaN, inf
158 $self->{_d} = $MBI->_copy($d->{value}); # "mantissa" = D
159 # +/+ or -/- => +, +/- or -/+ => -
160 $self->{sign} = $d->{sign} ne $self->{sign} ? '-' : '+';
162 elsif ($d->isa('Math::BigInt::Lite'))
164 # TODO: trap NaN, inf
165 $self->{_d} = $MBI->_new(abs($$d)); # "mantissa" = D
166 my $ds = '+'; $ds = '-' if $$d < 0;
167 # +/+ or -/- => +, +/- or -/+ => -
168 $self->{sign} = $ds ne $self->{sign} ? '-' : '+';
173 Carp::croak(ref($d) . " is not a recognized object format for Math::BigRat->new");
175 return $self->bnorm(); # normalize (120/1 => 12/10)
177 return $n->copy() if ref $n; # already a BigRat
181 $self->{_n} = $MBI->_zero(); # undef => 0
182 $self->{_d} = $MBI->_one();
187 # string input with / delimiter
188 if ($n =~ /\s*\/\s*/)
190 return $class->bnan() if $n =~ /\/.*\//; # 1/2/3 isn't valid
191 return $class->bnan() if $n =~ /\/\s*$/; # 1/ isn't valid
192 ($n,$d) = split (/\//,$n);
193 # try as BigFloats first
194 if (($n =~ /[\.eE]/) || ($d =~ /[\.eE]/))
196 local $Math::BigFloat::accuracy = undef;
197 local $Math::BigFloat::precision = undef;
199 # one of them looks like a float
200 my $nf = Math::BigFloat->new($n,undef,undef);
202 return $self->bnan() if $nf->is_nan();
204 $self->{_n} = $MBI->_copy( $nf->{_m} ); # get mantissa
206 # now correct $self->{_n} due to $n
207 my $f = Math::BigFloat->new($d,undef,undef);
208 return $self->bnan() if $f->is_nan();
209 $self->{_d} = $MBI->_copy( $f->{_m} );
211 # calculate the difference between nE and dE
212 my $diff_e = $nf->exponent()->bsub( $f->exponent);
213 if ($diff_e->is_negative())
216 $MBI->_lsft( $self->{_d}, $MBI->_new( $diff_e->babs()), 10);
218 elsif (!$diff_e->is_zero())
221 $MBI->_lsft( $self->{_n}, $MBI->_new( $diff_e), 10);
226 # both d and n look like (big)ints
228 $self->{sign} = '+'; # no sign => '+'
231 if ($n =~ /^([+-]?)0*([0-9]+)\z/) # first part ok?
233 $self->{sign} = $1 || '+'; # no sign => '+'
234 $self->{_n} = $MBI->_new($2 || 0);
237 if ($d =~ /^([+-]?)0*([0-9]+)\z/) # second part ok?
239 $self->{sign} =~ tr/+-/-+/ if ($1 || '') eq '-'; # negate if second part neg.
240 $self->{_d} = $MBI->_new($2 || 0);
243 if (!defined $self->{_n} || !defined $self->{_d})
245 $d = Math::BigInt->new($d,undef,undef) unless ref $d;
246 $n = Math::BigInt->new($n,undef,undef) unless ref $n;
248 if ($n->{sign} =~ /^[+-]$/ && $d->{sign} =~ /^[+-]$/)
250 # both parts are ok as integers (wierd things like ' 1e0'
251 $self->{_n} = $MBI->_copy($n->{value});
252 $self->{_d} = $MBI->_copy($d->{value});
253 $self->{sign} = $n->{sign};
254 $self->{sign} =~ tr/+-/-+/ if $d->{sign} eq '-'; # -1/-2 => 1/2
255 return $self->bnorm();
258 $self->{sign} = '+'; # a default sign
259 return $self->bnan() if $n->is_nan() || $d->is_nan();
262 if ($n->is_inf() || $d->is_inf())
266 return $self->bnan() if $d->is_inf(); # both are inf => NaN
267 my $s = '+'; # '+inf/+123' or '-inf/-123'
268 $s = '-' if substr($n->{sign},0,1) ne $d->{sign};
270 return $self->binf($s);
273 return $self->bzero();
278 return $self->bnorm();
281 # simple string input
282 if (($n =~ /[\.eE]/))
284 # looks like a float, quacks like a float, so probably is a float
285 $self->{sign} = 'NaN';
286 local $Math::BigFloat::accuracy = undef;
287 local $Math::BigFloat::precision = undef;
288 $self->_new_from_float(Math::BigFloat->new($n,undef,undef));
292 # for simple forms, use $MBI directly
293 if ($n =~ /^([+-]?)0*([0-9]+)\z/)
295 $self->{sign} = $1 || '+';
296 $self->{_n} = $MBI->_new($2 || 0);
297 $self->{_d} = $MBI->_one();
301 my $n = Math::BigInt->new($n,undef,undef);
302 $self->{_n} = $MBI->_copy($n->{value});
303 $self->{_d} = $MBI->_one();
304 $self->{sign} = $n->{sign};
305 return $self->bnan() if $self->{sign} eq 'NaN';
306 return $self->binf($self->{sign}) if $self->{sign} =~ /^[+-]inf$/;
314 # if two arguments, the first one is the class to "swallow" subclasses
322 return unless ref($x); # only for objects
324 my $self = bless {}, $c;
326 $self->{sign} = $x->{sign};
327 $self->{_d} = $MBI->_copy($x->{_d});
328 $self->{_n} = $MBI->_copy($x->{_n});
329 $self->{_a} = $x->{_a} if defined $x->{_a};
330 $self->{_p} = $x->{_p} if defined $x->{_p};
334 ##############################################################################
338 # return (later set?) configuration data as hash ref
339 my $class = shift || 'Math::BigRat';
341 if (@_ == 1 && ref($_[0]) ne 'HASH')
343 my $cfg = $class->SUPER::config();
344 return $cfg->{$_[0]};
347 my $cfg = $class->SUPER::config(@_);
349 # now we need only to override the ones that are different from our parent
350 $cfg->{class} = $class;
355 ##############################################################################
359 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
361 if ($x->{sign} !~ /^[+-]$/) # inf, NaN etc
363 my $s = $x->{sign}; $s =~ s/^\+//; # +inf => inf
367 my $s = ''; $s = $x->{sign} if $x->{sign} ne '+'; # '+3/2' => '3/2'
369 return $s . $MBI->_str($x->{_n}) if $MBI->_is_one($x->{_d});
370 $s . $MBI->_str($x->{_n}) . '/' . $MBI->_str($x->{_d});
375 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
377 if ($x->{sign} !~ /^[+-]$/) # inf, NaN etc
379 my $s = $x->{sign}; $s =~ s/^\+//; # +inf => inf
383 my $s = ''; $s = $x->{sign} if $x->{sign} ne '+'; # +3 vs 3
384 $s . $MBI->_str($x->{_n}) . '/' . $MBI->_str($x->{_d});
389 # reduce the number to the shortest form
390 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
392 # Both parts must be objects of whatever we are using today.
393 if ( my $c = $MBI->_check($x->{_n}) )
395 require Carp; Carp::croak ("n did not pass the self-check ($c) in bnorm()");
397 if ( my $c = $MBI->_check($x->{_d}) )
399 require Carp; Carp::croak ("d did not pass the self-check ($c) in bnorm()");
402 # no normalize for NaN, inf etc.
403 return $x if $x->{sign} !~ /^[+-]$/;
405 # normalize zeros to 0/1
406 if ($MBI->_is_zero($x->{_n}))
408 $x->{sign} = '+'; # never leave a -0
409 $x->{_d} = $MBI->_one() unless $MBI->_is_one($x->{_d});
413 return $x if $MBI->_is_one($x->{_d}); # no need to reduce
415 # reduce other numbers
416 my $gcd = $MBI->_copy($x->{_n});
417 $gcd = $MBI->_gcd($gcd,$x->{_d});
419 if (!$MBI->_is_one($gcd))
421 $x->{_n} = $MBI->_div($x->{_n},$gcd);
422 $x->{_d} = $MBI->_div($x->{_d},$gcd);
427 ##############################################################################
432 # (BRAT or num_str) return BRAT
433 # negate number or make a negated number from string
434 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
436 return $x if $x->modify('bneg');
438 # for +0 dont negate (to have always normalized +0). Does nothing for 'NaN'
439 $x->{sign} =~ tr/+-/-+/ unless ($x->{sign} eq '+' && $MBI->_is_zero($x->{_n}));
443 ##############################################################################
448 # used by parent class bnan() to initialize number to NaN
454 my $class = ref($self);
455 # "$self" below will stringify the object, this blows up if $self is a
456 # partial object (happens under trap_nan), so fix it beforehand
457 $self->{_d} = $MBI->_zero() unless defined $self->{_d};
458 $self->{_n} = $MBI->_zero() unless defined $self->{_n};
459 Carp::croak ("Tried to set $self to NaN in $class\::_bnan()");
461 $self->{_n} = $MBI->_zero();
462 $self->{_d} = $MBI->_zero();
467 # used by parent class bone() to initialize number to +inf/-inf
473 my $class = ref($self);
474 # "$self" below will stringify the object, this blows up if $self is a
475 # partial object (happens under trap_nan), so fix it beforehand
476 $self->{_d} = $MBI->_zero() unless defined $self->{_d};
477 $self->{_n} = $MBI->_zero() unless defined $self->{_n};
478 Carp::croak ("Tried to set $self to inf in $class\::_binf()");
480 $self->{_n} = $MBI->_zero();
481 $self->{_d} = $MBI->_zero();
486 # used by parent class bone() to initialize number to +1/-1
488 $self->{_n} = $MBI->_one();
489 $self->{_d} = $MBI->_one();
494 # used by parent class bzero() to initialize number to 0
496 $self->{_n} = $MBI->_zero();
497 $self->{_d} = $MBI->_one();
500 ##############################################################################
505 # add two rational numbers
508 my ($self,$x,$y,@r) = (ref($_[0]),@_);
509 # objectify is costly, so avoid it
510 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
512 ($self,$x,$y,@r) = objectify(2,@_);
515 # +inf + +inf => +inf, -inf + -inf => -inf
516 return $x->binf(substr($x->{sign},0,1))
517 if $x->{sign} eq $y->{sign} && $x->{sign} =~ /^[+-]inf$/;
519 # +inf + -inf or -inf + +inf => NaN
520 return $x->bnan() if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/);
522 # 1 1 gcd(3,4) = 1 1*3 + 1*4 7
523 # - + - = --------- = --
526 # we do not compute the gcd() here, but simple do:
528 # - + - = --------- = --
531 # and bnorm() will then take care of the rest
534 $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_d});
537 my $m = $MBI->_mul( $MBI->_copy( $y->{_n} ), $x->{_d} );
540 ($x->{_n}, $x->{sign}) = _e_add( $x->{_n}, $m, $x->{sign}, $y->{sign});
543 $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_d});
545 # normalize result, and possible round
546 $x->bnorm()->round(@r);
551 # subtract two rational numbers
554 my ($self,$x,$y,@r) = (ref($_[0]),@_);
555 # objectify is costly, so avoid it
556 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
558 ($self,$x,$y,@r) = objectify(2,@_);
561 # flip sign of $x, call badd(), then flip sign of result
562 $x->{sign} =~ tr/+-/-+/
563 unless $x->{sign} eq '+' && $MBI->_is_zero($x->{_n}); # not -0
564 $x->badd($y,@r); # does norm and round
565 $x->{sign} =~ tr/+-/-+/
566 unless $x->{sign} eq '+' && $MBI->_is_zero($x->{_n}); # not -0
572 # multiply two rational numbers
575 my ($self,$x,$y,@r) = (ref($_[0]),@_);
576 # objectify is costly, so avoid it
577 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
579 ($self,$x,$y,@r) = objectify(2,@_);
582 return $x->bnan() if ($x->{sign} eq 'NaN' || $y->{sign} eq 'NaN');
585 if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/))
587 return $x->bnan() if $x->is_zero() || $y->is_zero();
588 # result will always be +-inf:
589 # +inf * +/+inf => +inf, -inf * -/-inf => +inf
590 # +inf * -/-inf => -inf, -inf * +/+inf => -inf
591 return $x->binf() if ($x->{sign} =~ /^\+/ && $y->{sign} =~ /^\+/);
592 return $x->binf() if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/);
593 return $x->binf('-');
596 # x== 0 # also: or y == 1 or y == -1
597 return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
600 # According to Knuth, this can be optimized by doing gcd twice (for d and n)
601 # and reducing in one step. This would save us the bnorm() at the end.
604 # - * - = ----- = - = -
607 $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_n});
608 $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_d});
611 $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
613 $x->bnorm()->round(@r);
618 # (dividend: BRAT or num_str, divisor: BRAT or num_str) return
619 # (BRAT,BRAT) (quo,rem) or BRAT (only rem)
622 my ($self,$x,$y,@r) = (ref($_[0]),@_);
623 # objectify is costly, so avoid it
624 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
626 ($self,$x,$y,@r) = objectify(2,@_);
629 return $self->_div_inf($x,$y)
630 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
632 # x== 0 # also: or y == 1 or y == -1
633 return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
635 # XXX TODO: list context, upgrade
636 # According to Knuth, this can be optimized by doing gcd twice (for d and n)
637 # and reducing in one step. This would save us the bnorm() at the end.
643 $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_d});
644 $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_n});
647 $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
649 $x->bnorm()->round(@r);
655 # compute "remainder" (in Perl way) of $x / $y
658 my ($self,$x,$y,@r) = (ref($_[0]),@_);
659 # objectify is costly, so avoid it
660 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
662 ($self,$x,$y,@r) = objectify(2,@_);
665 return $self->_div_inf($x,$y)
666 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
668 return $x if $x->is_zero(); # 0 / 7 = 0, mod 0
670 # compute $x - $y * floor($x/$y), keeping the sign of $x
672 # copy x to u, make it positive and then do a normal division ($u/$y)
673 my $u = bless { sign => '+' }, $self;
674 $u->{_n} = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d} );
675 $u->{_d} = $MBI->_mul( $MBI->_copy($x->{_d}), $y->{_n} );
678 if (! $MBI->_is_one($u->{_d}))
680 $u->{_n} = $MBI->_div($u->{_n},$u->{_d}); # 22/7 => 3/1 w/ truncate
681 # no need to set $u->{_d} to 1, since below we set it to $y->{_d} anyway
684 # now compute $y * $u
685 $u->{_d} = $MBI->_copy($y->{_d}); # 1 * $y->{_d}, see floor above
686 $u->{_n} = $MBI->_mul($u->{_n},$y->{_n});
688 my $xsign = $x->{sign}; $x->{sign} = '+'; # remember sign and make x positive
691 $x->{sign} = $xsign; # put sign back
693 $x->bnorm()->round(@r);
696 ##############################################################################
701 # decrement value (subtract 1)
702 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
704 return $x if $x->{sign} !~ /^[+-]$/; # NaN, inf, -inf
706 if ($x->{sign} eq '-')
708 $x->{_n} = $MBI->_add( $x->{_n}, $x->{_d}); # -5/2 => -7/2
712 if ($MBI->_acmp($x->{_n},$x->{_d}) < 0) # n < d?
715 $x->{_n} = $MBI->_sub( $MBI->_copy($x->{_d}), $x->{_n});
720 $x->{_n} = $MBI->_sub($x->{_n}, $x->{_d}); # 5/2 => 3/2
723 $x->bnorm()->round(@r);
728 # increment value (add 1)
729 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
731 return $x if $x->{sign} !~ /^[+-]$/; # NaN, inf, -inf
733 if ($x->{sign} eq '-')
735 if ($MBI->_acmp($x->{_n},$x->{_d}) < 0)
737 # -1/3 ++ => 2/3 (overflow at 0)
738 $x->{_n} = $MBI->_sub( $MBI->_copy($x->{_d}), $x->{_n});
743 $x->{_n} = $MBI->_sub($x->{_n}, $x->{_d}); # -5/2 => -3/2
748 $x->{_n} = $MBI->_add($x->{_n},$x->{_d}); # 5/2 => 7/2
750 $x->bnorm()->round(@r);
753 ##############################################################################
754 # is_foo methods (the rest is inherited)
758 # return true if arg (BRAT or num_str) is an integer
759 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
761 return 1 if ($x->{sign} =~ /^[+-]$/) && # NaN and +-inf aren't
762 $MBI->_is_one($x->{_d}); # x/y && y != 1 => no integer
768 # return true if arg (BRAT or num_str) is zero
769 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
771 return 1 if $x->{sign} eq '+' && $MBI->_is_zero($x->{_n});
777 # return true if arg (BRAT or num_str) is +1 or -1 if signis given
778 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
780 my $sign = $_[2] || ''; $sign = '+' if $sign ne '-';
782 if ($x->{sign} eq $sign && $MBI->_is_one($x->{_n}) && $MBI->_is_one($x->{_d}));
788 # return true if arg (BFLOAT or num_str) is odd or false if even
789 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
791 return 1 if ($x->{sign} =~ /^[+-]$/) && # NaN & +-inf aren't
792 ($MBI->_is_one($x->{_d}) && $MBI->_is_odd($x->{_n})); # x/2 is not, but 3/1
798 # return true if arg (BINT or num_str) is even or false if odd
799 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
801 return 0 if $x->{sign} !~ /^[+-]$/; # NaN & +-inf aren't
802 return 1 if ($MBI->_is_one($x->{_d}) # x/3 is never
803 && $MBI->_is_even($x->{_n})); # but 4/1 is
807 ##############################################################################
808 # parts() and friends
812 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
815 return Math::BigInt->new($x->{sign}) if ($x->{sign} !~ /^[+-]$/);
817 my $n = Math::BigInt->new($MBI->_str($x->{_n})); $n->{sign} = $x->{sign};
823 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
826 return Math::BigInt->new($x->{sign}) if $x->{sign} eq 'NaN';
828 return Math::BigInt->bone() if $x->{sign} !~ /^[+-]$/;
830 Math::BigInt->new($MBI->_str($x->{_d}));
835 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
837 my $c = 'Math::BigInt';
839 return ($c->bnan(),$c->bnan()) if $x->{sign} eq 'NaN';
840 return ($c->binf(),$c->binf()) if $x->{sign} eq '+inf';
841 return ($c->binf('-'),$c->binf()) if $x->{sign} eq '-inf';
843 my $n = $c->new( $MBI->_str($x->{_n}));
844 $n->{sign} = $x->{sign};
845 my $d = $c->new( $MBI->_str($x->{_d}));
851 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
853 return $nan unless $x->is_int();
854 $MBI->_len($x->{_n}); # length(-123/1) => length(123)
859 my ($self,$x,$n) = ref($_[0]) ? (undef,$_[0],$_[1]) : objectify(1,@_);
861 return $nan unless $x->is_int();
862 $MBI->_digit($x->{_n},$n || 0); # digit(-123/1,2) => digit(123,2)
865 ##############################################################################
866 # special calc routines
870 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
872 return $x if $x->{sign} !~ /^[+-]$/ || # not for NaN, inf
873 $MBI->_is_one($x->{_d}); # 22/1 => 22, 0/1 => 0
875 $x->{_n} = $MBI->_div($x->{_n},$x->{_d}); # 22/7 => 3/1 w/ truncate
876 $x->{_d} = $MBI->_one(); # d => 1
877 $x->{_n} = $MBI->_inc($x->{_n})
878 if $x->{sign} eq '+'; # +22/7 => 4/1
879 $x->{sign} = '+' if $MBI->_is_zero($x->{_n}); # -0 => 0
885 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
887 return $x if $x->{sign} !~ /^[+-]$/ || # not for NaN, inf
888 $MBI->_is_one($x->{_d}); # 22/1 => 22, 0/1 => 0
890 $x->{_n} = $MBI->_div($x->{_n},$x->{_d}); # 22/7 => 3/1 w/ truncate
891 $x->{_d} = $MBI->_one(); # d => 1
892 $x->{_n} = $MBI->_inc($x->{_n})
893 if $x->{sign} eq '-'; # -22/7 => -4/1
899 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
901 # if $x is not an integer
902 if (($x->{sign} ne '+') || (!$MBI->_is_one($x->{_d})))
907 $x->{_n} = $MBI->_fac($x->{_n});
908 # since _d is 1, we don't need to reduce/norm the result
917 my ($self,$x,$y,@r) = (ref($_[0]),@_);
918 # objectify is costly, so avoid it
919 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
921 ($self,$x,$y,@r) = objectify(2,@_);
924 return $x if $x->{sign} =~ /^[+-]inf$/; # -inf/+inf ** x
925 return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;
926 return $x->bone(@r) if $y->is_zero();
927 return $x->round(@r) if $x->is_one() || $y->is_one();
929 if ($x->{sign} eq '-' && $MBI->_is_one($x->{_n}) && $MBI->_is_one($x->{_d}))
931 # if $x == -1 and odd/even y => +1/-1
932 return $y->is_odd() ? $x->round(@r) : $x->babs()->round(@r);
933 # my Casio FX-5500L has a bug here: -1 ** 2 is -1, but -1 * -1 is 1;
935 # 1 ** -y => 1 / (1 ** |y|)
936 # so do test for negative $y after above's clause
938 return $x->round(@r) if $x->is_zero(); # 0**y => 0 (if not y <= 0)
940 # shortcut y/1 (and/or x/1)
941 if ($MBI->_is_one($y->{_d}))
943 # shortcut for x/1 and y/1
944 if ($MBI->_is_one($x->{_d}))
946 $x->{_n} = $MBI->_pow($x->{_n},$y->{_n}); # x/1 ** y/1 => (x ** y)/1
947 if ($y->{sign} eq '-')
949 # 0.2 ** -3 => 1/(0.2 ** 3)
950 ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n}); # swap
952 # correct sign; + ** + => +
953 if ($x->{sign} eq '-')
955 # - * - => +, - * - * - => -
956 $x->{sign} = '+' if $MBI->_is_even($y->{_n});
958 return $x->round(@r);
961 $x->{_n} = $MBI->_pow($x->{_n},$y->{_n}); # 5/2 ** y/1 => 5 ** y / 2 ** y
962 $x->{_d} = $MBI->_pow($x->{_d},$y->{_n});
963 if ($y->{sign} eq '-')
965 # 0.2 ** -3 => 1/(0.2 ** 3)
966 ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n}); # swap
968 # correct sign; + ** + => +
969 if ($x->{sign} eq '-')
971 # - * - => +, - * - * - => -
972 $x->{sign} = '+' if $MBI->_is_even($y->{_n});
974 return $x->round(@r);
977 # regular calculation (this is wrong for d/e ** f/g)
978 my $pow2 = $self->bone();
979 my $y1 = $MBI->_div ( $MBI->_copy($y->{_n}), $y->{_d});
980 my $two = $MBI->_two();
982 while (!$MBI->_is_one($y1))
984 $pow2->bmul($x) if $MBI->_is_odd($y1);
985 $MBI->_div($y1, $two);
988 $x->bmul($pow2) unless $pow2->is_one();
989 # n ** -x => 1/n ** x
990 ($x->{_d},$x->{_n}) = ($x->{_n},$x->{_d}) if $y->{sign} eq '-';
991 $x->bnorm()->round(@r);
997 my ($self,$x,$y,@r) = (ref($_[0]),@_);
999 # objectify is costly, so avoid it
1000 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1002 ($self,$x,$y,@r) = objectify(2,$class,@_);
1006 return $x->bzero() if $x->is_one() && $y->{sign} eq '+';
1009 return $x->bnan() if $x->is_zero() || $x->{sign} ne '+' || $y->{sign} ne '+';
1011 if ($x->is_int() && $y->is_int())
1013 return $self->new($x->as_number()->blog($y->as_number(),@r));
1017 $x->_new_from_float( $x->_as_float()->blog(Math::BigFloat->new("$y"),@r) );
1023 my ($self,$x,$y,$a,$p,$r) = (ref($_[0]),@_);
1025 # objectify is costly, so avoid it
1026 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1028 ($self,$x,$y,$a,$p,$r) = objectify(2,$class,@_);
1031 return $x->binf() if $x->{sign} eq '+inf';
1032 return $x->bzero() if $x->{sign} eq '-inf';
1034 # we need to limit the accuracy to protect against overflow
1036 my ($scale,@params);
1037 ($x,@params) = $x->_find_round_parameters($a,$p,$r);
1039 # also takes care of the "error in _find_round_parameters?" case
1040 return $x if $x->{sign} eq 'NaN';
1042 # no rounding at all, so must use fallback
1043 if (scalar @params == 0)
1045 # simulate old behaviour
1046 $params[0] = $self->div_scale(); # and round to it as accuracy
1047 $params[1] = undef; # P = undef
1048 $scale = $params[0]+4; # at least four more for proper round
1049 $params[2] = $r; # round mode by caller or undef
1050 $fallback = 1; # to clear a/p afterwards
1054 # the 4 below is empirical, and there might be cases where it's not enough...
1055 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined
1058 return $x->bone(@params) if $x->is_zero();
1060 # See the comments in Math::BigFloat on how this algorithm works.
1061 # Basically we calculate A and B (where B is faculty(N)) so that A/B = e
1063 my $x_org = $x->copy();
1066 # set $x directly from a cached string form
1067 $x->{_n} = $MBI->_new("90933395208605785401971970164779391644753259799242");
1068 $x->{_d} = $MBI->_new("33452526613163807108170062053440751665152000000000");
1073 # compute A and B so that e = A / B.
1075 # After some terms we end up with this, so we use it as a starting point:
1076 my $A = $MBI->_new("90933395208605785401971970164779391644753259799242");
1077 my $F = $MBI->_new(42); my $step = 42;
1079 # Compute how many steps we need to take to get $A and $B sufficiently big
1080 my $steps = Math::BigFloat::_len_to_steps($scale - 4);
1081 # print STDERR "# Doing $steps steps for ", $scale-4, " digits\n";
1082 while ($step++ <= $steps)
1084 # calculate $a * $f + 1
1085 $A = $MBI->_mul($A, $F);
1086 $A = $MBI->_inc($A);
1088 $F = $MBI->_inc($F);
1090 # compute $B as factorial of $steps (this is faster than doing it manually)
1091 my $B = $MBI->_fac($MBI->_new($steps));
1093 # print "A ", $MBI->_str($A), "\nB ", $MBI->_str($B), "\n";
1100 # $x contains now an estimate of e, with some surplus digits, so we can round
1101 if (!$x_org->is_one())
1103 # raise $x to the wanted power and round it in one step:
1104 $x->bpow($x_org, @params);
1108 # else just round the already computed result
1109 delete $x->{_a}; delete $x->{_p};
1110 # shortcut to not run through _find_round_parameters again
1111 if (defined $params[0])
1113 $x->bround($params[0],$params[2]); # then round accordingly
1117 $x->bfround($params[1],$params[2]); # then round accordingly
1122 # clear a/p after round, since user did not request it
1123 delete $x->{_a}; delete $x->{_p};
1132 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1134 # objectify is costly, so avoid it
1135 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1137 ($self,$x,$y,@r) = objectify(2,$class,@_);
1141 $x->_new_from_float( $x->_as_float()->bnok(Math::BigFloat->new("$y"),@r) );
1144 sub _float_from_part
1148 my $f = Math::BigFloat->bzero();
1149 $f->{_m} = $MBI->_copy($x);
1150 $f->{_e} = $MBI->_zero();
1159 local $Math::BigFloat::upgrade = undef;
1160 local $Math::BigFloat::accuracy = undef;
1161 local $Math::BigFloat::precision = undef;
1162 # 22/7 => 3.142857143..
1164 my $a = $x->accuracy() || 0;
1165 if ($a != 0 || !$MBI->_is_one($x->{_d}))
1168 return Math::BigFloat->new($x->{sign} . $MBI->_str($x->{_n}))->bdiv( $MBI->_str($x->{_d}), $x->accuracy());
1171 Math::BigFloat->new($x->{sign} . $MBI->_str($x->{_n}));
1177 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1178 # objectify is costly, so avoid it
1179 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1181 ($self,$x,$y,@r) = objectify(2,@_);
1184 if ($x->is_int() && $y->is_int())
1186 return $self->new($x->as_number()->broot($y->as_number(),@r));
1190 $x->_new_from_float( $x->_as_float()->broot($y,@r) );
1196 my ($self,$x,$y,$m,@r) = (ref($_[0]),@_);
1197 # objectify is costly, so avoid it
1198 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1200 ($self,$x,$y,$m,@r) = objectify(3,@_);
1203 # $x or $y or $m are NaN or +-inf => NaN
1205 if $x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/ ||
1206 $m->{sign} !~ /^[+-]$/;
1208 if ($x->is_int() && $y->is_int() && $m->is_int())
1210 return $self->new($x->as_number()->bmodpow($y->as_number(),$m,@r));
1213 warn ("bmodpow() not fully implemented");
1220 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1221 # objectify is costly, so avoid it
1222 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1224 ($self,$x,$y,@r) = objectify(2,@_);
1227 # $x or $y are NaN or +-inf => NaN
1229 if $x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/;
1231 if ($x->is_int() && $y->is_int())
1233 return $self->new($x->as_number()->bmodinv($y->as_number(),@r));
1236 warn ("bmodinv() not fully implemented");
1242 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
1244 return $x->bnan() if $x->{sign} !~ /^[+]/; # NaN, -inf or < 0
1245 return $x if $x->{sign} eq '+inf'; # sqrt(inf) == inf
1246 return $x->round(@r) if $x->is_zero() || $x->is_one();
1248 local $Math::BigFloat::upgrade = undef;
1249 local $Math::BigFloat::downgrade = undef;
1250 local $Math::BigFloat::precision = undef;
1251 local $Math::BigFloat::accuracy = undef;
1252 local $Math::BigInt::upgrade = undef;
1253 local $Math::BigInt::precision = undef;
1254 local $Math::BigInt::accuracy = undef;
1256 $x->{_n} = _float_from_part( $x->{_n} )->bsqrt();
1257 $x->{_d} = _float_from_part( $x->{_d} )->bsqrt();
1259 # XXX TODO: we probably can optimze this:
1261 # if sqrt(D) was not integer
1262 if ($x->{_d}->{_es} ne '+')
1264 $x->{_n}->blsft($x->{_d}->exponent()->babs(),10); # 7.1/4.51 => 7.1/45.1
1265 $x->{_d} = $MBI->_copy( $x->{_d}->{_m} ); # 7.1/45.1 => 71/45.1
1267 # if sqrt(N) was not integer
1268 if ($x->{_n}->{_es} ne '+')
1270 $x->{_d}->blsft($x->{_n}->exponent()->babs(),10); # 71/45.1 => 710/45.1
1271 $x->{_n} = $MBI->_copy( $x->{_n}->{_m} ); # 710/45.1 => 710/451
1274 # convert parts to $MBI again
1275 $x->{_n} = $MBI->_lsft( $MBI->_copy( $x->{_n}->{_m} ), $x->{_n}->{_e}, 10)
1276 if ref($x->{_n}) ne $MBI && ref($x->{_n}) ne 'ARRAY';
1277 $x->{_d} = $MBI->_lsft( $MBI->_copy( $x->{_d}->{_m} ), $x->{_d}->{_e}, 10)
1278 if ref($x->{_d}) ne $MBI && ref($x->{_d}) ne 'ARRAY';
1280 $x->bnorm()->round(@r);
1285 my ($self,$x,$y,$b,@r) = objectify(3,@_);
1287 $b = 2 unless defined $b;
1288 $b = $self->new($b) unless ref ($b);
1289 $x->bmul( $b->copy()->bpow($y), @r);
1295 my ($self,$x,$y,$b,@r) = objectify(3,@_);
1297 $b = 2 unless defined $b;
1298 $b = $self->new($b) unless ref ($b);
1299 $x->bdiv( $b->copy()->bpow($y), @r);
1303 ##############################################################################
1321 ##############################################################################
1326 # compare two signed numbers
1329 my ($self,$x,$y) = (ref($_[0]),@_);
1330 # objectify is costly, so avoid it
1331 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1333 ($self,$x,$y) = objectify(2,@_);
1336 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
1338 # handle +-inf and NaN
1339 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1340 return 0 if $x->{sign} eq $y->{sign} && $x->{sign} =~ /^[+-]inf$/;
1341 return +1 if $x->{sign} eq '+inf';
1342 return -1 if $x->{sign} eq '-inf';
1343 return -1 if $y->{sign} eq '+inf';
1346 # check sign for speed first
1347 return 1 if $x->{sign} eq '+' && $y->{sign} eq '-'; # does also 0 <=> -y
1348 return -1 if $x->{sign} eq '-' && $y->{sign} eq '+'; # does also -x <=> 0
1351 my $xz = $MBI->_is_zero($x->{_n});
1352 my $yz = $MBI->_is_zero($y->{_n});
1353 return 0 if $xz && $yz; # 0 <=> 0
1354 return -1 if $xz && $y->{sign} eq '+'; # 0 <=> +y
1355 return 1 if $yz && $x->{sign} eq '+'; # +x <=> 0
1357 my $t = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d});
1358 my $u = $MBI->_mul( $MBI->_copy($y->{_n}), $x->{_d});
1360 my $cmp = $MBI->_acmp($t,$u); # signs are equal
1361 $cmp = -$cmp if $x->{sign} eq '-'; # both are '-' => reverse
1367 # compare two numbers (as unsigned)
1370 my ($self,$x,$y) = (ref($_[0]),@_);
1371 # objectify is costly, so avoid it
1372 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1374 ($self,$x,$y) = objectify(2,$class,@_);
1377 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
1379 # handle +-inf and NaN
1380 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1381 return 0 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} =~ /^[+-]inf$/;
1382 return 1 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} !~ /^[+-]inf$/;
1386 my $t = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d});
1387 my $u = $MBI->_mul( $MBI->_copy($y->{_n}), $x->{_d});
1388 $MBI->_acmp($t,$u); # ignore signs
1391 ##############################################################################
1392 # output conversation
1396 # convert 17/8 => float (aka 2.125)
1397 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1399 return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, NaN, etc
1402 my $neg = ''; $neg = '-' if $x->{sign} eq '-';
1403 return $neg . $MBI->_num($x->{_n}) if $MBI->_is_one($x->{_d});
1405 $x->_as_float()->numify() + 0.0;
1410 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1413 return Math::BigInt->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
1415 my $u = Math::BigInt->bzero();
1416 $u->{sign} = $x->{sign};
1417 $u->{value} = $MBI->_div( $MBI->_copy($x->{_n}), $x->{_d}); # 22/7 => 3
1423 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1425 return $x unless $x->is_int();
1427 my $s = $x->{sign}; $s = '' if $s eq '+';
1428 $s . $MBI->_as_bin($x->{_n});
1433 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1435 return $x unless $x->is_int();
1437 my $s = $x->{sign}; $s = '' if $s eq '+';
1438 $s . $MBI->_as_hex($x->{_n});
1443 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1445 return $x unless $x->is_int();
1447 my $s = $x->{sign}; $s = '' if $s eq '+';
1448 $s . $MBI->_as_oct($x->{_n});
1451 ##############################################################################
1474 push @parts, Math::BigInt->from_oct($c);
1476 $class->new ( @parts );
1479 ##############################################################################
1486 my $lib = ''; my @a;
1489 for ( my $i = 0; $i < $l ; $i++)
1491 if ( $_[$i] eq ':constant' )
1493 # this rest causes overlord er load to step in
1494 overload::constant float => sub { $self->new(shift); };
1496 # elsif ($_[$i] eq 'upgrade')
1498 # # this causes upgrading
1499 # $upgrade = $_[$i+1]; # or undef to disable
1502 elsif ($_[$i] eq 'downgrade')
1504 # this causes downgrading
1505 $downgrade = $_[$i+1]; # or undef to disable
1508 elsif ($_[$i] =~ /^(lib|try|only)\z/)
1510 $lib = $_[$i+1] || ''; # default Calc
1511 $try = $1; # lib, try or only
1514 elsif ($_[$i] eq 'with')
1516 # this argument is no longer used
1517 #$MBI = $_[$i+1] || 'Math::BigInt::Calc'; # default Math::BigInt::Calc
1525 require Math::BigInt;
1527 # let use Math::BigInt lib => 'GMP'; use Math::BigRat; still have GMP
1530 my @c = split /\s*,\s*/, $lib;
1533 $_ =~ tr/a-zA-Z0-9://cd; # limit to sane characters
1535 $lib = join(",", @c);
1537 my @import = ('objectify');
1538 push @import, $try => $lib if $lib ne '';
1540 # MBI already loaded, so feed it our lib arguments
1541 Math::BigInt->import( @import );
1543 $MBI = Math::BigFloat->config()->{lib};
1545 # register us with MBI to get notified of future lib changes
1546 Math::BigInt::_register_callback( $self, sub { $MBI = $_[0]; } );
1548 # any non :constant stuff is handled by our parent, Exporter (loaded
1549 # by Math::BigFloat, even if @_ is empty, to give it a chance
1550 $self->SUPER::import(@a); # for subclasses
1551 $self->export_to_level(1,$self,@a); # need this, too
1560 Math::BigRat - Arbitrary big rational numbers
1566 my $x = Math::BigRat->new('3/7'); $x += '5/9';
1568 print $x->bstr(),"\n";
1571 my $y = Math::BigRat->new('inf');
1572 print "$y ", ($y->is_inf ? 'is' : 'is not') , " infinity\n";
1574 my $z = Math::BigRat->new(144); $z->bsqrt();
1578 Math::BigRat complements Math::BigInt and Math::BigFloat by providing support
1579 for arbitrary big rational numbers.
1583 You can change the underlying module that does the low-level
1584 math operations by using:
1586 use Math::BigRat try => 'GMP';
1588 Note: This needs Math::BigInt::GMP installed.
1590 The following would first try to find Math::BigInt::Foo, then
1591 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
1593 use Math::BigRat try => 'Foo,Math::BigInt::Bar';
1595 If you want to get warned when the fallback occurs, replace "try" with
1598 use Math::BigRat lib => 'Foo,Math::BigInt::Bar';
1600 If you want the code to die instead, replace "try" with
1603 use Math::BigRat only => 'Foo,Math::BigInt::Bar';
1607 Any methods not listed here are derived from Math::BigFloat (or
1608 Math::BigInt), so make sure you check these two modules for further
1613 $x = Math::BigRat->new('1/3');
1615 Create a new Math::BigRat object. Input can come in various forms:
1617 $x = Math::BigRat->new(123); # scalars
1618 $x = Math::BigRat->new('inf'); # infinity
1619 $x = Math::BigRat->new('123.3'); # float
1620 $x = Math::BigRat->new('1/3'); # simple string
1621 $x = Math::BigRat->new('1 / 3'); # spaced
1622 $x = Math::BigRat->new('1 / 0.1'); # w/ floats
1623 $x = Math::BigRat->new(Math::BigInt->new(3)); # BigInt
1624 $x = Math::BigRat->new(Math::BigFloat->new('3.1')); # BigFloat
1625 $x = Math::BigRat->new(Math::BigInt::Lite->new('2')); # BigLite
1627 # You can also give D and N as different objects:
1628 $x = Math::BigRat->new(
1629 Math::BigInt->new(-123),
1630 Math::BigInt->new(7),
1635 $n = $x->numerator();
1637 Returns a copy of the numerator (the part above the line) as signed BigInt.
1639 =head2 denominator()
1641 $d = $x->denominator();
1643 Returns a copy of the denominator (the part under the line) as positive BigInt.
1647 ($n,$d) = $x->parts();
1649 Return a list consisting of (signed) numerator and (unsigned) denominator as
1654 my $y = $x->numify();
1656 Returns the object as a scalar. This will lose some data if the object
1657 cannot be represented by a normal Perl scalar (integer or float), so
1658 use as_int() instead.
1660 This routine is automatically used whenever a scalar is required:
1662 my $x = Math::BigRat->new('3/1');
1664 $y = $array[$x]; # set $y to 3
1666 =head2 as_int()/as_number()
1668 $x = Math::BigRat->new('13/7');
1669 print $x->as_int(),"\n"; # '1'
1671 Returns a copy of the object as BigInt, truncated to an integer.
1673 C<as_number()> is an alias for C<as_int()>.
1677 $x = Math::BigRat->new('13');
1678 print $x->as_hex(),"\n"; # '0xd'
1680 Returns the BigRat as hexadecimal string. Works only for integers.
1684 $x = Math::BigRat->new('13');
1685 print $x->as_bin(),"\n"; # '0x1101'
1687 Returns the BigRat as binary string. Works only for integers.
1691 $x = Math::BigRat->new('13');
1692 print $x->as_oct(),"\n"; # '015'
1694 Returns the BigRat as octal string. Works only for integers.
1696 =head2 from_hex()/from_bin()/from_oct()
1698 my $h = Math::BigRat->from_hex('0x10');
1699 my $b = Math::BigRat->from_bin('0b10000000');
1700 my $o = Math::BigRat->from_oct('020');
1702 Create a BigRat from an hexadecimal, binary or octal number
1707 $len = $x->length();
1709 Return the length of $x in digitis for integer values.
1713 print Math::BigRat->new('123/1')->digit(1); # 1
1714 print Math::BigRat->new('123/1')->digit(-1); # 3
1716 Return the N'ths digit from X when X is an integer value.
1722 Reduce the number to the shortest form. This routine is called
1723 automatically whenever it is needed.
1729 Calculates the factorial of $x. For instance:
1731 print Math::BigRat->new('3/1')->bfac(),"\n"; # 1*2*3
1732 print Math::BigRat->new('5/1')->bfac(),"\n"; # 1*2*3*4*5
1734 Works currently only for integers.
1736 =head2 bround()/round()/bfround()
1738 Are not yet implemented.
1743 my $x = Math::BigRat->new('7/4');
1744 my $y = Math::BigRat->new('4/3');
1747 Set $x to the remainder of the division of $x by $y.
1753 Used to negate the object in-place.
1757 print "$x is 1\n" if $x->is_one();
1759 Return true if $x is exactly one, otherwise false.
1763 print "$x is 0\n" if $x->is_zero();
1765 Return true if $x is exactly zero, otherwise false.
1767 =head2 is_pos()/is_positive()
1769 print "$x is >= 0\n" if $x->is_positive();
1771 Return true if $x is positive (greater than or equal to zero), otherwise
1772 false. Please note that '+inf' is also positive, while 'NaN' and '-inf' aren't.
1774 C<is_positive()> is an alias for C<is_pos()>.
1776 =head2 is_neg()/is_negative()
1778 print "$x is < 0\n" if $x->is_negative();
1780 Return true if $x is negative (smaller than zero), otherwise false. Please
1781 note that '-inf' is also negative, while 'NaN' and '+inf' aren't.
1783 C<is_negative()> is an alias for C<is_neg()>.
1787 print "$x is an integer\n" if $x->is_int();
1789 Return true if $x has a denominator of 1 (e.g. no fraction parts), otherwise
1790 false. Please note that '-inf', 'inf' and 'NaN' aren't integer.
1794 print "$x is odd\n" if $x->is_odd();
1796 Return true if $x is odd, otherwise false.
1800 print "$x is even\n" if $x->is_even();
1802 Return true if $x is even, otherwise false.
1808 Set $x to the next bigger integer value (e.g. truncate the number to integer
1809 and then increment it by one).
1815 Truncate $x to an integer value.
1821 Calculate the square root of $x.
1827 Calculate the N'th root of $x.
1829 =head2 badd()/bmul()/bsub()/bdiv()/bdec()/binc()
1831 Please see the documentation in L<Math::BigInt>.
1837 Makes a deep copy of the object.
1839 Please see the documentation in L<Math::BigInt> for further details.
1841 =head2 bstr()/bsstr()
1843 my $x = Math::BigInt->new('8/4');
1844 print $x->bstr(),"\n"; # prints 1/2
1845 print $x->bsstr(),"\n"; # prints 1/2
1847 Return a string representating this object.
1849 =head2 bacmp()/bcmp()
1851 Used to compare numbers.
1853 Please see the documentation in L<Math::BigInt> for further details.
1855 =head2 blsft()/brsft()
1857 Used to shift numbers left/right.
1859 Please see the documentation in L<Math::BigInt> for further details.
1867 Please see the documentation in L<Math::BigInt> for further details.
1871 $x->bexp($accuracy); # calculate e ** X
1873 Calculates two integers A and B so that A/B is equal to C<e ** $x>, where C<e> is
1876 This method was added in v0.20 of Math::BigRat (May 2007).
1882 $x->bnok($y); # x over y (binomial coefficient n over k)
1884 Calculates the binomial coefficient n over k, also called the "choose"
1885 function. The result is equivalent to:
1891 This method was added in v0.20 of Math::BigRat (May 2007).
1897 print Dumper ( Math::BigRat->config() );
1898 print Math::BigRat->config()->{lib},"\n";
1900 Returns a hash containing the configuration, e.g. the version number, lib
1901 loaded etc. The following hash keys are currently filled in with the
1902 appropriate information.
1904 key RO/RW Description
1906 ============================================================
1907 lib RO Name of the Math library
1909 lib_version RO Version of 'lib'
1911 class RO The class of config you just called
1913 version RO version number of the class you used
1915 upgrade RW To which class numbers are upgraded
1917 downgrade RW To which class numbers are downgraded
1919 precision RW Global precision
1921 accuracy RW Global accuracy
1923 round_mode RW Global round mode
1925 div_scale RW Fallback accuracy for div
1927 trap_nan RW Trap creation of NaN (undef = no)
1929 trap_inf RW Trap creation of +inf/-inf (undef = no)
1932 By passing a reference to a hash you may set the configuration values. This
1933 works only for values that a marked with a C<RW> above, anything else is
1938 Some things are not yet implemented, or only implemented half-way:
1942 =item inf handling (partial)
1944 =item NaN handling (partial)
1946 =item rounding (not implemented except for bceil/bfloor)
1948 =item $x ** $y where $y is not an integer
1950 =item bmod(), blog(), bmodinv() and bmodpow() (partial)
1956 This program is free software; you may redistribute it and/or modify it under
1957 the same terms as Perl itself.
1961 L<Math::BigFloat> and L<Math::Big> as well as L<Math::BigInt::BitVect>,
1962 L<Math::BigInt::Pari> and L<Math::BigInt::GMP>.
1964 See L<http://search.cpan.org/search?dist=bignum> for a way to use
1967 The package at L<http://search.cpan.org/search?dist=Math%3A%3ABigRat>
1968 may contain more documentation and examples as well as testcases.
1972 (C) by Tels L<http://bloodgate.com/> 2001 - 2007.