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 if y == 1/N (is then sqrt() respective broot())
941 if ($MBI->_is_one($y->{_n}))
943 return $x->bsqrt(@r) if $MBI->_is_two($y->{_d}); # 1/2 => sqrt
944 return $x->broot($MBI->_str($y->{_d}),@r); # 1/N => root(N)
947 # shortcut y/1 (and/or x/1)
948 if ($MBI->_is_one($y->{_d}))
950 # shortcut for x/1 and y/1
951 if ($MBI->_is_one($x->{_d}))
953 $x->{_n} = $MBI->_pow($x->{_n},$y->{_n}); # x/1 ** y/1 => (x ** y)/1
954 if ($y->{sign} eq '-')
956 # 0.2 ** -3 => 1/(0.2 ** 3)
957 ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n}); # swap
959 # correct sign; + ** + => +
960 if ($x->{sign} eq '-')
962 # - * - => +, - * - * - => -
963 $x->{sign} = '+' if $MBI->_is_even($y->{_n});
965 return $x->round(@r);
968 $x->{_n} = $MBI->_pow($x->{_n},$y->{_n}); # 5/2 ** y/1 => 5 ** y / 2 ** y
969 $x->{_d} = $MBI->_pow($x->{_d},$y->{_n});
970 if ($y->{sign} eq '-')
972 # 0.2 ** -3 => 1/(0.2 ** 3)
973 ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n}); # swap
975 # correct sign; + ** + => +
976 if ($x->{sign} eq '-')
978 # - * - => +, - * - * - => -
979 $x->{sign} = '+' if $MBI->_is_even($y->{_n});
981 return $x->round(@r);
984 # print STDERR "# $x $y\n";
988 # n/d n ______________
989 # a/b = -\/ (a/b) ** d
991 # (a/b) ** n == (a ** n) / (b ** n)
992 $MBI->_pow($x->{_n}, $y->{_n} );
993 $MBI->_pow($x->{_d}, $y->{_n} );
995 return $x->broot($MBI->_str($y->{_d}),@r); # n/d => root(n)
1001 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1003 # objectify is costly, so avoid it
1004 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1006 ($self,$x,$y,@r) = objectify(2,$class,@_);
1010 return $x->bzero() if $x->is_one() && $y->{sign} eq '+';
1013 return $x->bnan() if $x->is_zero() || $x->{sign} ne '+' || $y->{sign} ne '+';
1015 if ($x->is_int() && $y->is_int())
1017 return $self->new($x->as_number()->blog($y->as_number(),@r));
1021 $x->_new_from_float( $x->_as_float()->blog(Math::BigFloat->new("$y"),@r) );
1027 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1029 # objectify is costly, so avoid it
1030 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1032 ($self,$x,$y,@r) = objectify(2,$class,@_);
1035 return $x->binf(@r) if $x->{sign} eq '+inf';
1036 return $x->bzero(@r) if $x->{sign} eq '-inf';
1038 # we need to limit the accuracy to protect against overflow
1040 my ($scale,@params);
1041 ($x,@params) = $x->_find_round_parameters(@r);
1043 # also takes care of the "error in _find_round_parameters?" case
1044 return $x if $x->{sign} eq 'NaN';
1046 # no rounding at all, so must use fallback
1047 if (scalar @params == 0)
1049 # simulate old behaviour
1050 $params[0] = $self->div_scale(); # and round to it as accuracy
1051 $params[1] = undef; # P = undef
1052 $scale = $params[0]+4; # at least four more for proper round
1053 $params[2] = $r[2]; # round mode by caller or undef
1054 $fallback = 1; # to clear a/p afterwards
1058 # the 4 below is empirical, and there might be cases where it's not enough...
1059 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined
1062 return $x->bone(@params) if $x->is_zero();
1064 # See the comments in Math::BigFloat on how this algorithm works.
1065 # Basically we calculate A and B (where B is faculty(N)) so that A/B = e
1067 my $x_org = $x->copy();
1070 # set $x directly from a cached string form
1071 $x->{_n} = $MBI->_new("90933395208605785401971970164779391644753259799242");
1072 $x->{_d} = $MBI->_new("33452526613163807108170062053440751665152000000000");
1077 # compute A and B so that e = A / B.
1079 # After some terms we end up with this, so we use it as a starting point:
1080 my $A = $MBI->_new("90933395208605785401971970164779391644753259799242");
1081 my $F = $MBI->_new(42); my $step = 42;
1083 # Compute how many steps we need to take to get $A and $B sufficiently big
1084 my $steps = Math::BigFloat::_len_to_steps($scale - 4);
1085 # print STDERR "# Doing $steps steps for ", $scale-4, " digits\n";
1086 while ($step++ <= $steps)
1088 # calculate $a * $f + 1
1089 $A = $MBI->_mul($A, $F);
1090 $A = $MBI->_inc($A);
1092 $F = $MBI->_inc($F);
1094 # compute $B as factorial of $steps (this is faster than doing it manually)
1095 my $B = $MBI->_fac($MBI->_new($steps));
1097 # print "A ", $MBI->_str($A), "\nB ", $MBI->_str($B), "\n";
1104 # $x contains now an estimate of e, with some surplus digits, so we can round
1105 if (!$x_org->is_one())
1107 # raise $x to the wanted power and round it in one step:
1108 $x->bpow($x_org, @params);
1112 # else just round the already computed result
1113 delete $x->{_a}; delete $x->{_p};
1114 # shortcut to not run through _find_round_parameters again
1115 if (defined $params[0])
1117 $x->bround($params[0],$params[2]); # then round accordingly
1121 $x->bfround($params[1],$params[2]); # then round accordingly
1126 # clear a/p after round, since user did not request it
1127 delete $x->{_a}; delete $x->{_p};
1136 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1138 # objectify is costly, so avoid it
1139 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1141 ($self,$x,$y,@r) = objectify(2,$class,@_);
1145 $x->_new_from_float( $x->_as_float()->bnok(Math::BigFloat->new("$y"),@r) );
1148 sub _float_from_part
1152 my $f = Math::BigFloat->bzero();
1153 $f->{_m} = $MBI->_copy($x);
1154 $f->{_e} = $MBI->_zero();
1163 local $Math::BigFloat::upgrade = undef;
1164 local $Math::BigFloat::accuracy = undef;
1165 local $Math::BigFloat::precision = undef;
1166 # 22/7 => 3.142857143..
1168 my $a = $x->accuracy() || 0;
1169 if ($a != 0 || !$MBI->_is_one($x->{_d}))
1172 return scalar Math::BigFloat->new($x->{sign} . $MBI->_str($x->{_n}))->bdiv( $MBI->_str($x->{_d}), $x->accuracy());
1175 Math::BigFloat->new($x->{sign} . $MBI->_str($x->{_n}));
1181 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1182 # objectify is costly, so avoid it
1183 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1185 ($self,$x,$y,@r) = objectify(2,@_);
1188 if ($x->is_int() && $y->is_int())
1190 return $self->new($x->as_number()->broot($y->as_number(),@r));
1194 $x->_new_from_float( $x->_as_float()->broot($y->_as_float(),@r) )->bnorm()->bround(@r);
1200 my ($self,$x,$y,$m,@r) = (ref($_[0]),@_);
1201 # objectify is costly, so avoid it
1202 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1204 ($self,$x,$y,$m,@r) = objectify(3,@_);
1207 # $x or $y or $m are NaN or +-inf => NaN
1209 if $x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/ ||
1210 $m->{sign} !~ /^[+-]$/;
1212 if ($x->is_int() && $y->is_int() && $m->is_int())
1214 return $self->new($x->as_number()->bmodpow($y->as_number(),$m,@r));
1217 warn ("bmodpow() not fully implemented");
1224 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1225 # objectify is costly, so avoid it
1226 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1228 ($self,$x,$y,@r) = objectify(2,@_);
1231 # $x or $y are NaN or +-inf => NaN
1233 if $x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/;
1235 if ($x->is_int() && $y->is_int())
1237 return $self->new($x->as_number()->bmodinv($y->as_number(),@r));
1240 warn ("bmodinv() not fully implemented");
1246 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
1248 return $x->bnan() if $x->{sign} !~ /^[+]/; # NaN, -inf or < 0
1249 return $x if $x->{sign} eq '+inf'; # sqrt(inf) == inf
1250 return $x->round(@r) if $x->is_zero() || $x->is_one();
1252 local $Math::BigFloat::upgrade = undef;
1253 local $Math::BigFloat::downgrade = undef;
1254 local $Math::BigFloat::precision = undef;
1255 local $Math::BigFloat::accuracy = undef;
1256 local $Math::BigInt::upgrade = undef;
1257 local $Math::BigInt::precision = undef;
1258 local $Math::BigInt::accuracy = undef;
1260 $x->{_n} = _float_from_part( $x->{_n} )->bsqrt();
1261 $x->{_d} = _float_from_part( $x->{_d} )->bsqrt();
1263 # XXX TODO: we probably can optimze this:
1265 # if sqrt(D) was not integer
1266 if ($x->{_d}->{_es} ne '+')
1268 $x->{_n}->blsft($x->{_d}->exponent()->babs(),10); # 7.1/4.51 => 7.1/45.1
1269 $x->{_d} = $MBI->_copy( $x->{_d}->{_m} ); # 7.1/45.1 => 71/45.1
1271 # if sqrt(N) was not integer
1272 if ($x->{_n}->{_es} ne '+')
1274 $x->{_d}->blsft($x->{_n}->exponent()->babs(),10); # 71/45.1 => 710/45.1
1275 $x->{_n} = $MBI->_copy( $x->{_n}->{_m} ); # 710/45.1 => 710/451
1278 # convert parts to $MBI again
1279 $x->{_n} = $MBI->_lsft( $MBI->_copy( $x->{_n}->{_m} ), $x->{_n}->{_e}, 10)
1280 if ref($x->{_n}) ne $MBI && ref($x->{_n}) ne 'ARRAY';
1281 $x->{_d} = $MBI->_lsft( $MBI->_copy( $x->{_d}->{_m} ), $x->{_d}->{_e}, 10)
1282 if ref($x->{_d}) ne $MBI && ref($x->{_d}) ne 'ARRAY';
1284 $x->bnorm()->round(@r);
1289 my ($self,$x,$y,$b,@r) = objectify(3,@_);
1291 $b = 2 unless defined $b;
1292 $b = $self->new($b) unless ref ($b);
1293 $x->bmul( $b->copy()->bpow($y), @r);
1299 my ($self,$x,$y,$b,@r) = objectify(3,@_);
1301 $b = 2 unless defined $b;
1302 $b = $self->new($b) unless ref ($b);
1303 $x->bdiv( $b->copy()->bpow($y), @r);
1307 ##############################################################################
1325 ##############################################################################
1330 # compare two signed numbers
1333 my ($self,$x,$y) = (ref($_[0]),@_);
1334 # objectify is costly, so avoid it
1335 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1337 ($self,$x,$y) = objectify(2,@_);
1340 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
1342 # handle +-inf and NaN
1343 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1344 return 0 if $x->{sign} eq $y->{sign} && $x->{sign} =~ /^[+-]inf$/;
1345 return +1 if $x->{sign} eq '+inf';
1346 return -1 if $x->{sign} eq '-inf';
1347 return -1 if $y->{sign} eq '+inf';
1350 # check sign for speed first
1351 return 1 if $x->{sign} eq '+' && $y->{sign} eq '-'; # does also 0 <=> -y
1352 return -1 if $x->{sign} eq '-' && $y->{sign} eq '+'; # does also -x <=> 0
1355 my $xz = $MBI->_is_zero($x->{_n});
1356 my $yz = $MBI->_is_zero($y->{_n});
1357 return 0 if $xz && $yz; # 0 <=> 0
1358 return -1 if $xz && $y->{sign} eq '+'; # 0 <=> +y
1359 return 1 if $yz && $x->{sign} eq '+'; # +x <=> 0
1361 my $t = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d});
1362 my $u = $MBI->_mul( $MBI->_copy($y->{_n}), $x->{_d});
1364 my $cmp = $MBI->_acmp($t,$u); # signs are equal
1365 $cmp = -$cmp if $x->{sign} eq '-'; # both are '-' => reverse
1371 # compare two numbers (as unsigned)
1374 my ($self,$x,$y) = (ref($_[0]),@_);
1375 # objectify is costly, so avoid it
1376 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1378 ($self,$x,$y) = objectify(2,$class,@_);
1381 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
1383 # handle +-inf and NaN
1384 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1385 return 0 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} =~ /^[+-]inf$/;
1386 return 1 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} !~ /^[+-]inf$/;
1390 my $t = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d});
1391 my $u = $MBI->_mul( $MBI->_copy($y->{_n}), $x->{_d});
1392 $MBI->_acmp($t,$u); # ignore signs
1395 ##############################################################################
1396 # output conversation
1400 # convert 17/8 => float (aka 2.125)
1401 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1403 return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, NaN, etc
1406 my $neg = ''; $neg = '-' if $x->{sign} eq '-';
1407 return $neg . $MBI->_num($x->{_n}) if $MBI->_is_one($x->{_d});
1409 $x->_as_float()->numify() + 0.0;
1414 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1417 return Math::BigInt->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
1419 my $u = Math::BigInt->bzero();
1420 $u->{sign} = $x->{sign};
1421 $u->{value} = $MBI->_div( $MBI->_copy($x->{_n}), $x->{_d}); # 22/7 => 3
1427 # return N/D as Math::BigFloat
1430 my ($self,$x,@r) = (ref($_[0]),@_);
1431 # objectify is costly, so avoid it
1432 ($self,$x,@r) = objectify(1,$class,@_) unless ref $_[0];
1435 return Math::BigFloat->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
1437 my $u = Math::BigFloat->bzero();
1438 $u->{sign} = $x->{sign};
1440 $u->{_m} = $MBI->_copy($x->{_n});
1441 $u->{_e} = $MBI->_zero();
1442 $u->bdiv( $MBI->_str($x->{_d}), @r);
1449 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1451 return $x unless $x->is_int();
1453 my $s = $x->{sign}; $s = '' if $s eq '+';
1454 $s . $MBI->_as_bin($x->{_n});
1459 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1461 return $x unless $x->is_int();
1463 my $s = $x->{sign}; $s = '' if $s eq '+';
1464 $s . $MBI->_as_hex($x->{_n});
1469 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1471 return $x unless $x->is_int();
1473 my $s = $x->{sign}; $s = '' if $s eq '+';
1474 $s . $MBI->_as_oct($x->{_n});
1477 ##############################################################################
1500 push @parts, Math::BigInt->from_oct($c);
1502 $class->new ( @parts );
1505 ##############################################################################
1512 my $lib = ''; my @a;
1515 for ( my $i = 0; $i < $l ; $i++)
1517 if ( $_[$i] eq ':constant' )
1519 # this rest causes overlord er load to step in
1520 overload::constant float => sub { $self->new(shift); };
1522 # elsif ($_[$i] eq 'upgrade')
1524 # # this causes upgrading
1525 # $upgrade = $_[$i+1]; # or undef to disable
1528 elsif ($_[$i] eq 'downgrade')
1530 # this causes downgrading
1531 $downgrade = $_[$i+1]; # or undef to disable
1534 elsif ($_[$i] =~ /^(lib|try|only)\z/)
1536 $lib = $_[$i+1] || ''; # default Calc
1537 $try = $1; # lib, try or only
1540 elsif ($_[$i] eq 'with')
1542 # this argument is no longer used
1543 #$MBI = $_[$i+1] || 'Math::BigInt::Calc'; # default Math::BigInt::Calc
1551 require Math::BigInt;
1553 # let use Math::BigInt lib => 'GMP'; use Math::BigRat; still have GMP
1556 my @c = split /\s*,\s*/, $lib;
1559 $_ =~ tr/a-zA-Z0-9://cd; # limit to sane characters
1561 $lib = join(",", @c);
1563 my @import = ('objectify');
1564 push @import, $try => $lib if $lib ne '';
1566 # MBI already loaded, so feed it our lib arguments
1567 Math::BigInt->import( @import );
1569 $MBI = Math::BigFloat->config()->{lib};
1571 # register us with MBI to get notified of future lib changes
1572 Math::BigInt::_register_callback( $self, sub { $MBI = $_[0]; } );
1574 # any non :constant stuff is handled by our parent, Exporter (loaded
1575 # by Math::BigFloat, even if @_ is empty, to give it a chance
1576 $self->SUPER::import(@a); # for subclasses
1577 $self->export_to_level(1,$self,@a); # need this, too
1586 Math::BigRat - Arbitrary big rational numbers
1592 my $x = Math::BigRat->new('3/7'); $x += '5/9';
1594 print $x->bstr(),"\n";
1597 my $y = Math::BigRat->new('inf');
1598 print "$y ", ($y->is_inf ? 'is' : 'is not') , " infinity\n";
1600 my $z = Math::BigRat->new(144); $z->bsqrt();
1604 Math::BigRat complements Math::BigInt and Math::BigFloat by providing support
1605 for arbitrary big rational numbers.
1609 You can change the underlying module that does the low-level
1610 math operations by using:
1612 use Math::BigRat try => 'GMP';
1614 Note: This needs Math::BigInt::GMP installed.
1616 The following would first try to find Math::BigInt::Foo, then
1617 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
1619 use Math::BigRat try => 'Foo,Math::BigInt::Bar';
1621 If you want to get warned when the fallback occurs, replace "try" with
1624 use Math::BigRat lib => 'Foo,Math::BigInt::Bar';
1626 If you want the code to die instead, replace "try" with
1629 use Math::BigRat only => 'Foo,Math::BigInt::Bar';
1633 Any methods not listed here are derived from Math::BigFloat (or
1634 Math::BigInt), so make sure you check these two modules for further
1639 $x = Math::BigRat->new('1/3');
1641 Create a new Math::BigRat object. Input can come in various forms:
1643 $x = Math::BigRat->new(123); # scalars
1644 $x = Math::BigRat->new('inf'); # infinity
1645 $x = Math::BigRat->new('123.3'); # float
1646 $x = Math::BigRat->new('1/3'); # simple string
1647 $x = Math::BigRat->new('1 / 3'); # spaced
1648 $x = Math::BigRat->new('1 / 0.1'); # w/ floats
1649 $x = Math::BigRat->new(Math::BigInt->new(3)); # BigInt
1650 $x = Math::BigRat->new(Math::BigFloat->new('3.1')); # BigFloat
1651 $x = Math::BigRat->new(Math::BigInt::Lite->new('2')); # BigLite
1653 # You can also give D and N as different objects:
1654 $x = Math::BigRat->new(
1655 Math::BigInt->new(-123),
1656 Math::BigInt->new(7),
1661 $n = $x->numerator();
1663 Returns a copy of the numerator (the part above the line) as signed BigInt.
1665 =head2 denominator()
1667 $d = $x->denominator();
1669 Returns a copy of the denominator (the part under the line) as positive BigInt.
1673 ($n,$d) = $x->parts();
1675 Return a list consisting of (signed) numerator and (unsigned) denominator as
1680 my $y = $x->numify();
1682 Returns the object as a scalar. This will lose some data if the object
1683 cannot be represented by a normal Perl scalar (integer or float), so
1684 use L<as_int()> or L<as_float()> instead.
1686 This routine is automatically used whenever a scalar is required:
1688 my $x = Math::BigRat->new('3/1');
1690 $y = $array[$x]; # set $y to 3
1692 =head2 as_int()/as_number()
1694 $x = Math::BigRat->new('13/7');
1695 print $x->as_int(),"\n"; # '1'
1697 Returns a copy of the object as BigInt, truncated to an integer.
1699 C<as_number()> is an alias for C<as_int()>.
1703 $x = Math::BigRat->new('13/7');
1704 print $x->as_float(),"\n"; # '1'
1706 $x = Math::BigRat->new('2/3');
1707 print $x->as_float(5),"\n"; # '0.66667'
1709 Returns a copy of the object as BigFloat, preserving the
1710 accuracy as wanted, or the default of 40 digits.
1712 This method was added in v0.22 of Math::BigRat (April 2008).
1716 $x = Math::BigRat->new('13');
1717 print $x->as_hex(),"\n"; # '0xd'
1719 Returns the BigRat as hexadecimal string. Works only for integers.
1723 $x = Math::BigRat->new('13');
1724 print $x->as_bin(),"\n"; # '0x1101'
1726 Returns the BigRat as binary string. Works only for integers.
1730 $x = Math::BigRat->new('13');
1731 print $x->as_oct(),"\n"; # '015'
1733 Returns the BigRat as octal string. Works only for integers.
1735 =head2 from_hex()/from_bin()/from_oct()
1737 my $h = Math::BigRat->from_hex('0x10');
1738 my $b = Math::BigRat->from_bin('0b10000000');
1739 my $o = Math::BigRat->from_oct('020');
1741 Create a BigRat from an hexadecimal, binary or octal number
1746 $len = $x->length();
1748 Return the length of $x in digitis for integer values.
1752 print Math::BigRat->new('123/1')->digit(1); # 1
1753 print Math::BigRat->new('123/1')->digit(-1); # 3
1755 Return the N'ths digit from X when X is an integer value.
1761 Reduce the number to the shortest form. This routine is called
1762 automatically whenever it is needed.
1768 Calculates the factorial of $x. For instance:
1770 print Math::BigRat->new('3/1')->bfac(),"\n"; # 1*2*3
1771 print Math::BigRat->new('5/1')->bfac(),"\n"; # 1*2*3*4*5
1773 Works currently only for integers.
1775 =head2 bround()/round()/bfround()
1777 Are not yet implemented.
1782 my $x = Math::BigRat->new('7/4');
1783 my $y = Math::BigRat->new('4/3');
1786 Set $x to the remainder of the division of $x by $y.
1792 Used to negate the object in-place.
1796 print "$x is 1\n" if $x->is_one();
1798 Return true if $x is exactly one, otherwise false.
1802 print "$x is 0\n" if $x->is_zero();
1804 Return true if $x is exactly zero, otherwise false.
1806 =head2 is_pos()/is_positive()
1808 print "$x is >= 0\n" if $x->is_positive();
1810 Return true if $x is positive (greater than or equal to zero), otherwise
1811 false. Please note that '+inf' is also positive, while 'NaN' and '-inf' aren't.
1813 C<is_positive()> is an alias for C<is_pos()>.
1815 =head2 is_neg()/is_negative()
1817 print "$x is < 0\n" if $x->is_negative();
1819 Return true if $x is negative (smaller than zero), otherwise false. Please
1820 note that '-inf' is also negative, while 'NaN' and '+inf' aren't.
1822 C<is_negative()> is an alias for C<is_neg()>.
1826 print "$x is an integer\n" if $x->is_int();
1828 Return true if $x has a denominator of 1 (e.g. no fraction parts), otherwise
1829 false. Please note that '-inf', 'inf' and 'NaN' aren't integer.
1833 print "$x is odd\n" if $x->is_odd();
1835 Return true if $x is odd, otherwise false.
1839 print "$x is even\n" if $x->is_even();
1841 Return true if $x is even, otherwise false.
1847 Set $x to the next bigger integer value (e.g. truncate the number to integer
1848 and then increment it by one).
1854 Truncate $x to an integer value.
1860 Calculate the square root of $x.
1866 Calculate the N'th root of $x.
1868 =head2 badd()/bmul()/bsub()/bdiv()/bdec()/binc()
1870 Please see the documentation in L<Math::BigInt>.
1876 Makes a deep copy of the object.
1878 Please see the documentation in L<Math::BigInt> for further details.
1880 =head2 bstr()/bsstr()
1882 my $x = Math::BigInt->new('8/4');
1883 print $x->bstr(),"\n"; # prints 1/2
1884 print $x->bsstr(),"\n"; # prints 1/2
1886 Return a string representating this object.
1888 =head2 bacmp()/bcmp()
1890 Used to compare numbers.
1892 Please see the documentation in L<Math::BigInt> for further details.
1894 =head2 blsft()/brsft()
1896 Used to shift numbers left/right.
1898 Please see the documentation in L<Math::BigInt> for further details.
1906 Please see the documentation in L<Math::BigInt> for further details.
1910 $x->bexp($accuracy); # calculate e ** X
1912 Calculates two integers A and B so that A/B is equal to C<e ** $x>, where C<e> is
1915 This method was added in v0.20 of Math::BigRat (May 2007).
1921 $x->bnok($y); # x over y (binomial coefficient n over k)
1923 Calculates the binomial coefficient n over k, also called the "choose"
1924 function. The result is equivalent to:
1930 This method was added in v0.20 of Math::BigRat (May 2007).
1936 print Dumper ( Math::BigRat->config() );
1937 print Math::BigRat->config()->{lib},"\n";
1939 Returns a hash containing the configuration, e.g. the version number, lib
1940 loaded etc. The following hash keys are currently filled in with the
1941 appropriate information.
1943 key RO/RW Description
1945 ============================================================
1946 lib RO Name of the Math library
1948 lib_version RO Version of 'lib'
1950 class RO The class of config you just called
1952 version RO version number of the class you used
1954 upgrade RW To which class numbers are upgraded
1956 downgrade RW To which class numbers are downgraded
1958 precision RW Global precision
1960 accuracy RW Global accuracy
1962 round_mode RW Global round mode
1964 div_scale RW Fallback accuracy for div
1966 trap_nan RW Trap creation of NaN (undef = no)
1968 trap_inf RW Trap creation of +inf/-inf (undef = no)
1971 By passing a reference to a hash you may set the configuration values. This
1972 works only for values that a marked with a C<RW> above, anything else is
1977 This is an internal routine that turns scalars into objects.
1981 Some things are not yet implemented, or only implemented half-way:
1985 =item inf handling (partial)
1987 =item NaN handling (partial)
1989 =item rounding (not implemented except for bceil/bfloor)
1991 =item $x ** $y where $y is not an integer
1993 =item bmod(), blog(), bmodinv() and bmodpow() (partial)
1999 This program is free software; you may redistribute it and/or modify it under
2000 the same terms as Perl itself.
2004 L<Math::BigFloat> and L<Math::Big> as well as L<Math::BigInt::BitVect>,
2005 L<Math::BigInt::Pari> and L<Math::BigInt::GMP>.
2007 See L<http://search.cpan.org/search?dist=bignum> for a way to use
2010 The package at L<http://search.cpan.org/search?dist=Math%3A%3ABigRat>
2011 may contain more documentation and examples as well as testcases.
2015 (C) by Tels L<http://bloodgate.com/> 2001 - 2008.