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
22 use vars qw($VERSION @ISA $upgrade $downgrade
23 $accuracy $precision $round_mode $div_scale $_trap_nan $_trap_inf);
25 @ISA = qw(Math::BigFloat);
28 $VERSION = eval $VERSION;
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
37 Carp::croak("bitwise operation $op not supported in Math::BigRat");
39 } qw(& | ^ ~ << >> &= |= ^= <<= >>=);
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;
55 ##############################################################################
56 # Global constants and flags. Access these only via the accessor methods!
58 $accuracy = $precision = undef;
64 # These are internally, and not to be used from the outside at all!
66 $_trap_nan = 0; # are NaNs ok? set w/ config()
67 $_trap_inf = 0; # are infs ok? set w/ config()
69 # the package we are using for our private parts, defaults to:
70 # Math::BigInt->config()->{lib}
71 my $MBI = 'Math::BigInt::Calc';
74 my $class = 'Math::BigRat';
78 return 0 if $_[1] =~ /^Math::Big(Int|Float)/; # we aren't
82 ##############################################################################
86 # turn a single float input into a rational number (like '0.1')
89 return $self->bnan() if $f->is_nan();
90 return $self->binf($f->{sign}) if $f->{sign} =~ /^[+-]inf$/;
92 $self->{_n} = $MBI->_copy( $f->{_m} ); # mantissa
93 $self->{_d} = $MBI->_one();
94 $self->{sign} = $f->{sign} || '+';
97 # something like Math::BigRat->new('0.1');
99 $MBI->_lsft ( $self->{_d}, $f->{_e} ,10);
103 # something like Math::BigRat->new('10');
105 $MBI->_lsft ( $self->{_n}, $f->{_e} ,10) unless
106 $MBI->_is_zero($f->{_e});
113 # create a Math::BigRat
118 my $self = { }; bless $self,$class;
120 # input like (BigInt) or (BigFloat):
121 if ((!defined $d) && (ref $n) && (!$n->isa('Math::BigRat')))
123 if ($n->isa('Math::BigFloat'))
125 $self->_new_from_float($n);
127 if ($n->isa('Math::BigInt'))
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};
134 if ($n->isa('Math::BigInt::Lite'))
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
141 return $self->bnorm(); # normalize (120/1 => 12/10)
144 # input like (BigInt,BigInt) or (BigLite,BigLite):
145 if (ref($d) && ref($n))
147 # do N first (for $self->{sign}):
148 if ($n->isa('Math::BigInt'))
150 # TODO: trap NaN, inf
151 $self->{_n} = $MBI->_copy($n->{value}); # "mantissa" = N
152 $self->{sign} = $n->{sign};
154 elsif ($n->isa('Math::BigInt::Lite'))
156 # TODO: trap NaN, inf
157 $self->{sign} = '+'; $self->{sign} = '-' if $$n < 0;
158 $self->{_n} = $MBI->_new(abs($$n)); # "mantissa" = $n
163 Carp::croak(ref($n) . " is not a recognized object format for Math::BigRat->new");
166 if ($d->isa('Math::BigInt'))
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} ? '-' : '+';
173 elsif ($d->isa('Math::BigInt::Lite'))
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} ? '-' : '+';
184 Carp::croak(ref($d) . " is not a recognized object format for Math::BigRat->new");
186 return $self->bnorm(); # normalize (120/1 => 12/10)
188 return $n->copy() if ref $n; # already a BigRat
192 $self->{_n} = $MBI->_zero(); # undef => 0
193 $self->{_d} = $MBI->_one();
198 # string input with / delimiter
199 if ($n =~ /\s*\/\s*/)
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]/))
207 local $Math::BigFloat::accuracy = undef;
208 local $Math::BigFloat::precision = undef;
210 # one of them looks like a float
211 my $nf = Math::BigFloat->new($n,undef,undef);
213 return $self->bnan() if $nf->is_nan();
215 $self->{_n} = $MBI->_copy( $nf->{_m} ); # get mantissa
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} );
222 # calculate the difference between nE and dE
223 my $diff_e = $nf->exponent()->bsub( $f->exponent);
224 if ($diff_e->is_negative())
227 $MBI->_lsft( $self->{_d}, $MBI->_new( $diff_e->babs()), 10);
229 elsif (!$diff_e->is_zero())
232 $MBI->_lsft( $self->{_n}, $MBI->_new( $diff_e), 10);
237 # both d and n look like (big)ints
239 $self->{sign} = '+'; # no sign => '+'
242 if ($n =~ /^([+-]?)0*([0-9]+)\z/) # first part ok?
244 $self->{sign} = $1 || '+'; # no sign => '+'
245 $self->{_n} = $MBI->_new($2 || 0);
248 if ($d =~ /^([+-]?)0*([0-9]+)\z/) # second part ok?
250 $self->{sign} =~ tr/+-/-+/ if ($1 || '') eq '-'; # negate if second part neg.
251 $self->{_d} = $MBI->_new($2 || 0);
254 if (!defined $self->{_n} || !defined $self->{_d})
256 $d = Math::BigInt->new($d,undef,undef) unless ref $d;
257 $n = Math::BigInt->new($n,undef,undef) unless ref $n;
259 if ($n->{sign} =~ /^[+-]$/ && $d->{sign} =~ /^[+-]$/)
261 # both parts are ok as integers (wierd 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();
269 $self->{sign} = '+'; # a default sign
270 return $self->bnan() if $n->is_nan() || $d->is_nan();
273 if ($n->is_inf() || $d->is_inf())
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};
281 return $self->binf($s);
284 return $self->bzero();
289 return $self->bnorm();
292 # simple string input
293 if (($n =~ /[\.eE]/) && $n !~ /^0x/)
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));
303 # for simple forms, use $MBI directly
304 if ($n =~ /^([+-]?)0*([0-9]+)\z/)
306 $self->{sign} = $1 || '+';
307 $self->{_n} = $MBI->_new($2 || 0);
308 $self->{_d} = $MBI->_one();
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$/;
325 # if two arguments, the first one is the class to "swallow" subclasses
333 return unless ref($x); # only for objects
335 my $self = bless {}, $c;
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};
345 ##############################################################################
349 # return (later set?) configuration data as hash ref
350 my $class = shift || 'Math::BigRat';
352 if (@_ == 1 && ref($_[0]) ne 'HASH')
354 my $cfg = $class->SUPER::config();
355 return $cfg->{$_[0]};
358 my $cfg = $class->SUPER::config(@_);
360 # now we need only to override the ones that are different from our parent
361 $cfg->{class} = $class;
366 ##############################################################################
370 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
372 if ($x->{sign} !~ /^[+-]$/) # inf, NaN etc
374 my $s = $x->{sign}; $s =~ s/^\+//; # +inf => inf
378 my $s = ''; $s = $x->{sign} if $x->{sign} ne '+'; # '+3/2' => '3/2'
380 return $s . $MBI->_str($x->{_n}) if $MBI->_is_one($x->{_d});
381 $s . $MBI->_str($x->{_n}) . '/' . $MBI->_str($x->{_d});
386 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
388 if ($x->{sign} !~ /^[+-]$/) # inf, NaN etc
390 my $s = $x->{sign}; $s =~ s/^\+//; # +inf => inf
394 my $s = ''; $s = $x->{sign} if $x->{sign} ne '+'; # +3 vs 3
395 $s . $MBI->_str($x->{_n}) . '/' . $MBI->_str($x->{_d});
400 # reduce the number to the shortest form
401 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
403 # Both parts must be objects of whatever we are using today.
404 if ( my $c = $MBI->_check($x->{_n}) )
406 require Carp; Carp::croak ("n did not pass the self-check ($c) in bnorm()");
408 if ( my $c = $MBI->_check($x->{_d}) )
410 require Carp; Carp::croak ("d did not pass the self-check ($c) in bnorm()");
413 # no normalize for NaN, inf etc.
414 return $x if $x->{sign} !~ /^[+-]$/;
416 # normalize zeros to 0/1
417 if ($MBI->_is_zero($x->{_n}))
419 $x->{sign} = '+'; # never leave a -0
420 $x->{_d} = $MBI->_one() unless $MBI->_is_one($x->{_d});
424 return $x if $MBI->_is_one($x->{_d}); # no need to reduce
426 # reduce other numbers
427 my $gcd = $MBI->_copy($x->{_n});
428 $gcd = $MBI->_gcd($gcd,$x->{_d});
430 if (!$MBI->_is_one($gcd))
432 $x->{_n} = $MBI->_div($x->{_n},$gcd);
433 $x->{_d} = $MBI->_div($x->{_d},$gcd);
438 ##############################################################################
443 # (BRAT or num_str) return BRAT
444 # negate number or make a negated number from string
445 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
447 return $x if $x->modify('bneg');
449 # for +0 dont negate (to have always normalized +0). Does nothing for 'NaN'
450 $x->{sign} =~ tr/+-/-+/ unless ($x->{sign} eq '+' && $MBI->_is_zero($x->{_n}));
454 ##############################################################################
459 # used by parent class bnan() to initialize number to NaN
465 my $class = ref($self);
466 # "$self" below will stringify the object, this blows up if $self is a
467 # partial object (happens under trap_nan), so fix it beforehand
468 $self->{_d} = $MBI->_zero() unless defined $self->{_d};
469 $self->{_n} = $MBI->_zero() unless defined $self->{_n};
470 Carp::croak ("Tried to set $self to NaN in $class\::_bnan()");
472 $self->{_n} = $MBI->_zero();
473 $self->{_d} = $MBI->_zero();
478 # used by parent class bone() to initialize number to +inf/-inf
484 my $class = ref($self);
485 # "$self" below will stringify the object, this blows up if $self is a
486 # partial object (happens under trap_nan), so fix it beforehand
487 $self->{_d} = $MBI->_zero() unless defined $self->{_d};
488 $self->{_n} = $MBI->_zero() unless defined $self->{_n};
489 Carp::croak ("Tried to set $self to inf in $class\::_binf()");
491 $self->{_n} = $MBI->_zero();
492 $self->{_d} = $MBI->_zero();
497 # used by parent class bone() to initialize number to +1/-1
499 $self->{_n} = $MBI->_one();
500 $self->{_d} = $MBI->_one();
505 # used by parent class bzero() to initialize number to 0
507 $self->{_n} = $MBI->_zero();
508 $self->{_d} = $MBI->_one();
511 ##############################################################################
516 # add two rational numbers
519 my ($self,$x,$y,@r) = (ref($_[0]),@_);
520 # objectify is costly, so avoid it
521 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
523 ($self,$x,$y,@r) = objectify(2,@_);
526 # +inf + +inf => +inf, -inf + -inf => -inf
527 return $x->binf(substr($x->{sign},0,1))
528 if $x->{sign} eq $y->{sign} && $x->{sign} =~ /^[+-]inf$/;
530 # +inf + -inf or -inf + +inf => NaN
531 return $x->bnan() if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/);
533 # 1 1 gcd(3,4) = 1 1*3 + 1*4 7
534 # - + - = --------- = --
537 # we do not compute the gcd() here, but simple do:
539 # - + - = --------- = --
542 # and bnorm() will then take care of the rest
545 $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_d});
548 my $m = $MBI->_mul( $MBI->_copy( $y->{_n} ), $x->{_d} );
551 ($x->{_n}, $x->{sign}) = _e_add( $x->{_n}, $m, $x->{sign}, $y->{sign});
554 $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_d});
556 # normalize result, and possible round
557 $x->bnorm()->round(@r);
562 # subtract two rational numbers
565 my ($self,$x,$y,@r) = (ref($_[0]),@_);
566 # objectify is costly, so avoid it
567 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
569 ($self,$x,$y,@r) = objectify(2,@_);
572 # flip sign of $x, call badd(), then flip sign of result
573 $x->{sign} =~ tr/+-/-+/
574 unless $x->{sign} eq '+' && $MBI->_is_zero($x->{_n}); # not -0
575 $x->badd($y,@r); # does norm and round
576 $x->{sign} =~ tr/+-/-+/
577 unless $x->{sign} eq '+' && $MBI->_is_zero($x->{_n}); # not -0
583 # multiply two rational numbers
586 my ($self,$x,$y,@r) = (ref($_[0]),@_);
587 # objectify is costly, so avoid it
588 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
590 ($self,$x,$y,@r) = objectify(2,@_);
593 return $x->bnan() if ($x->{sign} eq 'NaN' || $y->{sign} eq 'NaN');
596 if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/))
598 return $x->bnan() if $x->is_zero() || $y->is_zero();
599 # result will always be +-inf:
600 # +inf * +/+inf => +inf, -inf * -/-inf => +inf
601 # +inf * -/-inf => -inf, -inf * +/+inf => -inf
602 return $x->binf() if ($x->{sign} =~ /^\+/ && $y->{sign} =~ /^\+/);
603 return $x->binf() if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/);
604 return $x->binf('-');
607 # x== 0 # also: or y == 1 or y == -1
608 return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
611 # According to Knuth, this can be optimized by doing gcd twice (for d and n)
612 # and reducing in one step. This would save us the bnorm() at the end.
615 # - * - = ----- = - = -
618 $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_n});
619 $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_d});
622 $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
624 $x->bnorm()->round(@r);
629 # (dividend: BRAT or num_str, divisor: BRAT or num_str) return
630 # (BRAT,BRAT) (quo,rem) or BRAT (only rem)
633 my ($self,$x,$y,@r) = (ref($_[0]),@_);
634 # objectify is costly, so avoid it
635 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
637 ($self,$x,$y,@r) = objectify(2,@_);
640 return $self->_div_inf($x,$y)
641 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
643 # x== 0 # also: or y == 1 or y == -1
644 return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
646 # XXX TODO: list context, upgrade
647 # According to Knuth, this can be optimized by doing gcd twice (for d and n)
648 # and reducing in one step. This would save us the bnorm() at the end.
654 $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_d});
655 $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_n});
658 $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
660 $x->bnorm()->round(@r);
666 # compute "remainder" (in Perl way) of $x / $y
669 my ($self,$x,$y,@r) = (ref($_[0]),@_);
670 # objectify is costly, so avoid it
671 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
673 ($self,$x,$y,@r) = objectify(2,@_);
676 return $self->_div_inf($x,$y)
677 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
679 return $x if $x->is_zero(); # 0 / 7 = 0, mod 0
681 # compute $x - $y * floor($x/$y), keeping the sign of $x
683 # copy x to u, make it positive and then do a normal division ($u/$y)
684 my $u = bless { sign => '+' }, $self;
685 $u->{_n} = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d} );
686 $u->{_d} = $MBI->_mul( $MBI->_copy($x->{_d}), $y->{_n} );
689 if (! $MBI->_is_one($u->{_d}))
691 $u->{_n} = $MBI->_div($u->{_n},$u->{_d}); # 22/7 => 3/1 w/ truncate
692 # no need to set $u->{_d} to 1, since below we set it to $y->{_d} anyway
695 # now compute $y * $u
696 $u->{_d} = $MBI->_copy($y->{_d}); # 1 * $y->{_d}, see floor above
697 $u->{_n} = $MBI->_mul($u->{_n},$y->{_n});
699 my $xsign = $x->{sign}; $x->{sign} = '+'; # remember sign and make x positive
702 $x->{sign} = $xsign; # put sign back
704 $x->bnorm()->round(@r);
707 ##############################################################################
712 # decrement value (subtract 1)
713 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
715 return $x if $x->{sign} !~ /^[+-]$/; # NaN, inf, -inf
717 if ($x->{sign} eq '-')
719 $x->{_n} = $MBI->_add( $x->{_n}, $x->{_d}); # -5/2 => -7/2
723 if ($MBI->_acmp($x->{_n},$x->{_d}) < 0) # n < d?
726 $x->{_n} = $MBI->_sub( $MBI->_copy($x->{_d}), $x->{_n});
731 $x->{_n} = $MBI->_sub($x->{_n}, $x->{_d}); # 5/2 => 3/2
734 $x->bnorm()->round(@r);
739 # increment value (add 1)
740 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
742 return $x if $x->{sign} !~ /^[+-]$/; # NaN, inf, -inf
744 if ($x->{sign} eq '-')
746 if ($MBI->_acmp($x->{_n},$x->{_d}) < 0)
748 # -1/3 ++ => 2/3 (overflow at 0)
749 $x->{_n} = $MBI->_sub( $MBI->_copy($x->{_d}), $x->{_n});
754 $x->{_n} = $MBI->_sub($x->{_n}, $x->{_d}); # -5/2 => -3/2
759 $x->{_n} = $MBI->_add($x->{_n},$x->{_d}); # 5/2 => 7/2
761 $x->bnorm()->round(@r);
764 ##############################################################################
765 # is_foo methods (the rest is inherited)
769 # return true if arg (BRAT or num_str) is an integer
770 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
772 return 1 if ($x->{sign} =~ /^[+-]$/) && # NaN and +-inf aren't
773 $MBI->_is_one($x->{_d}); # x/y && y != 1 => no integer
779 # return true if arg (BRAT or num_str) is zero
780 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
782 return 1 if $x->{sign} eq '+' && $MBI->_is_zero($x->{_n});
788 # return true if arg (BRAT or num_str) is +1 or -1 if signis given
789 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
791 my $sign = $_[2] || ''; $sign = '+' if $sign ne '-';
793 if ($x->{sign} eq $sign && $MBI->_is_one($x->{_n}) && $MBI->_is_one($x->{_d}));
799 # return true if arg (BFLOAT or num_str) is odd or false if even
800 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
802 return 1 if ($x->{sign} =~ /^[+-]$/) && # NaN & +-inf aren't
803 ($MBI->_is_one($x->{_d}) && $MBI->_is_odd($x->{_n})); # x/2 is not, but 3/1
809 # return true if arg (BINT or num_str) is even or false if odd
810 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
812 return 0 if $x->{sign} !~ /^[+-]$/; # NaN & +-inf aren't
813 return 1 if ($MBI->_is_one($x->{_d}) # x/3 is never
814 && $MBI->_is_even($x->{_n})); # but 4/1 is
818 ##############################################################################
819 # parts() and friends
823 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
826 return Math::BigInt->new($x->{sign}) if ($x->{sign} !~ /^[+-]$/);
828 my $n = Math::BigInt->new($MBI->_str($x->{_n})); $n->{sign} = $x->{sign};
834 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
837 return Math::BigInt->new($x->{sign}) if $x->{sign} eq 'NaN';
839 return Math::BigInt->bone() if $x->{sign} !~ /^[+-]$/;
841 Math::BigInt->new($MBI->_str($x->{_d}));
846 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
848 my $c = 'Math::BigInt';
850 return ($c->bnan(),$c->bnan()) if $x->{sign} eq 'NaN';
851 return ($c->binf(),$c->binf()) if $x->{sign} eq '+inf';
852 return ($c->binf('-'),$c->binf()) if $x->{sign} eq '-inf';
854 my $n = $c->new( $MBI->_str($x->{_n}));
855 $n->{sign} = $x->{sign};
856 my $d = $c->new( $MBI->_str($x->{_d}));
862 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
864 return $nan unless $x->is_int();
865 $MBI->_len($x->{_n}); # length(-123/1) => length(123)
870 my ($self,$x,$n) = ref($_[0]) ? (undef,$_[0],$_[1]) : objectify(1,@_);
872 return $nan unless $x->is_int();
873 $MBI->_digit($x->{_n},$n || 0); # digit(-123/1,2) => digit(123,2)
876 ##############################################################################
877 # special calc routines
881 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
883 return $x if $x->{sign} !~ /^[+-]$/ || # not for NaN, inf
884 $MBI->_is_one($x->{_d}); # 22/1 => 22, 0/1 => 0
886 $x->{_n} = $MBI->_div($x->{_n},$x->{_d}); # 22/7 => 3/1 w/ truncate
887 $x->{_d} = $MBI->_one(); # d => 1
888 $x->{_n} = $MBI->_inc($x->{_n})
889 if $x->{sign} eq '+'; # +22/7 => 4/1
890 $x->{sign} = '+' if $MBI->_is_zero($x->{_n}); # -0 => 0
896 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
898 return $x if $x->{sign} !~ /^[+-]$/ || # not for NaN, inf
899 $MBI->_is_one($x->{_d}); # 22/1 => 22, 0/1 => 0
901 $x->{_n} = $MBI->_div($x->{_n},$x->{_d}); # 22/7 => 3/1 w/ truncate
902 $x->{_d} = $MBI->_one(); # d => 1
903 $x->{_n} = $MBI->_inc($x->{_n})
904 if $x->{sign} eq '-'; # -22/7 => -4/1
910 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
912 # if $x is not an integer
913 if (($x->{sign} ne '+') || (!$MBI->_is_one($x->{_d})))
918 $x->{_n} = $MBI->_fac($x->{_n});
919 # since _d is 1, we don't need to reduce/norm the result
928 my ($self,$x,$y,@r) = (ref($_[0]),@_);
929 # objectify is costly, so avoid it
930 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
932 ($self,$x,$y,@r) = objectify(2,@_);
935 return $x if $x->{sign} =~ /^[+-]inf$/; # -inf/+inf ** x
936 return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;
937 return $x->bone(@r) if $y->is_zero();
938 return $x->round(@r) if $x->is_one() || $y->is_one();
940 if ($x->{sign} eq '-' && $MBI->_is_one($x->{_n}) && $MBI->_is_one($x->{_d}))
942 # if $x == -1 and odd/even y => +1/-1
943 return $y->is_odd() ? $x->round(@r) : $x->babs()->round(@r);
944 # my Casio FX-5500L has a bug here: -1 ** 2 is -1, but -1 * -1 is 1;
946 # 1 ** -y => 1 / (1 ** |y|)
947 # so do test for negative $y after above's clause
949 return $x->round(@r) if $x->is_zero(); # 0**y => 0 (if not y <= 0)
951 # shortcut if y == 1/N (is then sqrt() respective broot())
952 if ($MBI->_is_one($y->{_n}))
954 return $x->bsqrt(@r) if $MBI->_is_two($y->{_d}); # 1/2 => sqrt
955 return $x->broot($MBI->_str($y->{_d}),@r); # 1/N => root(N)
958 # shortcut y/1 (and/or x/1)
959 if ($MBI->_is_one($y->{_d}))
961 # shortcut for x/1 and y/1
962 if ($MBI->_is_one($x->{_d}))
964 $x->{_n} = $MBI->_pow($x->{_n},$y->{_n}); # x/1 ** y/1 => (x ** y)/1
965 if ($y->{sign} eq '-')
967 # 0.2 ** -3 => 1/(0.2 ** 3)
968 ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n}); # swap
970 # correct sign; + ** + => +
971 if ($x->{sign} eq '-')
973 # - * - => +, - * - * - => -
974 $x->{sign} = '+' if $MBI->_is_even($y->{_n});
976 return $x->round(@r);
979 $x->{_n} = $MBI->_pow($x->{_n},$y->{_n}); # 5/2 ** y/1 => 5 ** y / 2 ** y
980 $x->{_d} = $MBI->_pow($x->{_d},$y->{_n});
981 if ($y->{sign} eq '-')
983 # 0.2 ** -3 => 1/(0.2 ** 3)
984 ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n}); # swap
986 # correct sign; + ** + => +
987 if ($x->{sign} eq '-')
989 # - * - => +, - * - * - => -
990 $x->{sign} = '+' if $MBI->_is_even($y->{_n});
992 return $x->round(@r);
995 # print STDERR "# $x $y\n";
999 # n/d n ______________
1000 # a/b = -\/ (a/b) ** d
1002 # (a/b) ** n == (a ** n) / (b ** n)
1003 $MBI->_pow($x->{_n}, $y->{_n} );
1004 $MBI->_pow($x->{_d}, $y->{_n} );
1006 return $x->broot($MBI->_str($y->{_d}),@r); # n/d => root(n)
1012 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1014 # objectify is costly, so avoid it
1015 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1017 ($self,$x,$y,@r) = objectify(2,$class,@_);
1021 return $x->bzero() if $x->is_one() && $y->{sign} eq '+';
1024 return $x->bnan() if $x->is_zero() || $x->{sign} ne '+' || $y->{sign} ne '+';
1026 if ($x->is_int() && $y->is_int())
1028 return $self->new($x->as_number()->blog($y->as_number(),@r));
1032 $x->_new_from_float( $x->_as_float()->blog(Math::BigFloat->new("$y"),@r) );
1038 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1040 # objectify is costly, so avoid it
1041 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1043 ($self,$x,$y,@r) = objectify(2,$class,@_);
1046 return $x->binf(@r) if $x->{sign} eq '+inf';
1047 return $x->bzero(@r) if $x->{sign} eq '-inf';
1049 # we need to limit the accuracy to protect against overflow
1051 my ($scale,@params);
1052 ($x,@params) = $x->_find_round_parameters(@r);
1054 # also takes care of the "error in _find_round_parameters?" case
1055 return $x if $x->{sign} eq 'NaN';
1057 # no rounding at all, so must use fallback
1058 if (scalar @params == 0)
1060 # simulate old behaviour
1061 $params[0] = $self->div_scale(); # and round to it as accuracy
1062 $params[1] = undef; # P = undef
1063 $scale = $params[0]+4; # at least four more for proper round
1064 $params[2] = $r[2]; # round mode by caller or undef
1065 $fallback = 1; # to clear a/p afterwards
1069 # the 4 below is empirical, and there might be cases where it's not enough...
1070 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined
1073 return $x->bone(@params) if $x->is_zero();
1075 # See the comments in Math::BigFloat on how this algorithm works.
1076 # Basically we calculate A and B (where B is faculty(N)) so that A/B = e
1078 my $x_org = $x->copy();
1081 # set $x directly from a cached string form
1082 $x->{_n} = $MBI->_new("90933395208605785401971970164779391644753259799242");
1083 $x->{_d} = $MBI->_new("33452526613163807108170062053440751665152000000000");
1088 # compute A and B so that e = A / B.
1090 # After some terms we end up with this, so we use it as a starting point:
1091 my $A = $MBI->_new("90933395208605785401971970164779391644753259799242");
1092 my $F = $MBI->_new(42); my $step = 42;
1094 # Compute how many steps we need to take to get $A and $B sufficiently big
1095 my $steps = Math::BigFloat::_len_to_steps($scale - 4);
1096 # print STDERR "# Doing $steps steps for ", $scale-4, " digits\n";
1097 while ($step++ <= $steps)
1099 # calculate $a * $f + 1
1100 $A = $MBI->_mul($A, $F);
1101 $A = $MBI->_inc($A);
1103 $F = $MBI->_inc($F);
1105 # compute $B as factorial of $steps (this is faster than doing it manually)
1106 my $B = $MBI->_fac($MBI->_new($steps));
1108 # print "A ", $MBI->_str($A), "\nB ", $MBI->_str($B), "\n";
1115 # $x contains now an estimate of e, with some surplus digits, so we can round
1116 if (!$x_org->is_one())
1118 # raise $x to the wanted power and round it in one step:
1119 $x->bpow($x_org, @params);
1123 # else just round the already computed result
1124 delete $x->{_a}; delete $x->{_p};
1125 # shortcut to not run through _find_round_parameters again
1126 if (defined $params[0])
1128 $x->bround($params[0],$params[2]); # then round accordingly
1132 $x->bfround($params[1],$params[2]); # then round accordingly
1137 # clear a/p after round, since user did not request it
1138 delete $x->{_a}; delete $x->{_p};
1147 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1149 # objectify is costly, so avoid it
1150 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1152 ($self,$x,$y,@r) = objectify(2,$class,@_);
1156 $x->_new_from_float( $x->_as_float()->bnok(Math::BigFloat->new("$y"),@r) );
1159 sub _float_from_part
1163 my $f = Math::BigFloat->bzero();
1164 $f->{_m} = $MBI->_copy($x);
1165 $f->{_e} = $MBI->_zero();
1174 local $Math::BigFloat::upgrade = undef;
1175 local $Math::BigFloat::accuracy = undef;
1176 local $Math::BigFloat::precision = undef;
1177 # 22/7 => 3.142857143..
1179 my $a = $x->accuracy() || 0;
1180 if ($a != 0 || !$MBI->_is_one($x->{_d}))
1183 return scalar Math::BigFloat->new($x->{sign} . $MBI->_str($x->{_n}))->bdiv( $MBI->_str($x->{_d}), $x->accuracy());
1186 Math::BigFloat->new($x->{sign} . $MBI->_str($x->{_n}));
1192 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1193 # objectify is costly, so avoid it
1194 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1196 ($self,$x,$y,@r) = objectify(2,@_);
1199 if ($x->is_int() && $y->is_int())
1201 return $self->new($x->as_number()->broot($y->as_number(),@r));
1205 $x->_new_from_float( $x->_as_float()->broot($y->_as_float(),@r) )->bnorm()->bround(@r);
1211 my ($self,$x,$y,$m,@r) = (ref($_[0]),@_);
1212 # objectify is costly, so avoid it
1213 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1215 ($self,$x,$y,$m,@r) = objectify(3,@_);
1218 # $x or $y or $m are NaN or +-inf => NaN
1220 if $x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/ ||
1221 $m->{sign} !~ /^[+-]$/;
1223 if ($x->is_int() && $y->is_int() && $m->is_int())
1225 return $self->new($x->as_number()->bmodpow($y->as_number(),$m,@r));
1228 warn ("bmodpow() not fully implemented");
1235 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1236 # objectify is costly, so avoid it
1237 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1239 ($self,$x,$y,@r) = objectify(2,@_);
1242 # $x or $y are NaN or +-inf => NaN
1244 if $x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/;
1246 if ($x->is_int() && $y->is_int())
1248 return $self->new($x->as_number()->bmodinv($y->as_number(),@r));
1251 warn ("bmodinv() not fully implemented");
1257 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
1259 return $x->bnan() if $x->{sign} !~ /^[+]/; # NaN, -inf or < 0
1260 return $x if $x->{sign} eq '+inf'; # sqrt(inf) == inf
1261 return $x->round(@r) if $x->is_zero() || $x->is_one();
1263 local $Math::BigFloat::upgrade = undef;
1264 local $Math::BigFloat::downgrade = undef;
1265 local $Math::BigFloat::precision = undef;
1266 local $Math::BigFloat::accuracy = undef;
1267 local $Math::BigInt::upgrade = undef;
1268 local $Math::BigInt::precision = undef;
1269 local $Math::BigInt::accuracy = undef;
1271 $x->{_n} = _float_from_part( $x->{_n} )->bsqrt();
1272 $x->{_d} = _float_from_part( $x->{_d} )->bsqrt();
1274 # XXX TODO: we probably can optimze this:
1276 # if sqrt(D) was not integer
1277 if ($x->{_d}->{_es} ne '+')
1279 $x->{_n}->blsft($x->{_d}->exponent()->babs(),10); # 7.1/4.51 => 7.1/45.1
1280 $x->{_d} = $MBI->_copy( $x->{_d}->{_m} ); # 7.1/45.1 => 71/45.1
1282 # if sqrt(N) was not integer
1283 if ($x->{_n}->{_es} ne '+')
1285 $x->{_d}->blsft($x->{_n}->exponent()->babs(),10); # 71/45.1 => 710/45.1
1286 $x->{_n} = $MBI->_copy( $x->{_n}->{_m} ); # 710/45.1 => 710/451
1289 # convert parts to $MBI again
1290 $x->{_n} = $MBI->_lsft( $MBI->_copy( $x->{_n}->{_m} ), $x->{_n}->{_e}, 10)
1291 if ref($x->{_n}) ne $MBI && ref($x->{_n}) ne 'ARRAY';
1292 $x->{_d} = $MBI->_lsft( $MBI->_copy( $x->{_d}->{_m} ), $x->{_d}->{_e}, 10)
1293 if ref($x->{_d}) ne $MBI && ref($x->{_d}) ne 'ARRAY';
1295 $x->bnorm()->round(@r);
1300 my ($self,$x,$y,$b,@r) = objectify(3,@_);
1302 $b = 2 unless defined $b;
1303 $b = $self->new($b) unless ref ($b);
1304 $x->bmul( $b->copy()->bpow($y), @r);
1310 my ($self,$x,$y,$b,@r) = objectify(3,@_);
1312 $b = 2 unless defined $b;
1313 $b = $self->new($b) unless ref ($b);
1314 $x->bdiv( $b->copy()->bpow($y), @r);
1318 ##############################################################################
1336 ##############################################################################
1341 # compare two signed numbers
1344 my ($self,$x,$y) = (ref($_[0]),@_);
1345 # objectify is costly, so avoid it
1346 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1348 ($self,$x,$y) = objectify(2,@_);
1351 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
1353 # handle +-inf and NaN
1354 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1355 return 0 if $x->{sign} eq $y->{sign} && $x->{sign} =~ /^[+-]inf$/;
1356 return +1 if $x->{sign} eq '+inf';
1357 return -1 if $x->{sign} eq '-inf';
1358 return -1 if $y->{sign} eq '+inf';
1361 # check sign for speed first
1362 return 1 if $x->{sign} eq '+' && $y->{sign} eq '-'; # does also 0 <=> -y
1363 return -1 if $x->{sign} eq '-' && $y->{sign} eq '+'; # does also -x <=> 0
1366 my $xz = $MBI->_is_zero($x->{_n});
1367 my $yz = $MBI->_is_zero($y->{_n});
1368 return 0 if $xz && $yz; # 0 <=> 0
1369 return -1 if $xz && $y->{sign} eq '+'; # 0 <=> +y
1370 return 1 if $yz && $x->{sign} eq '+'; # +x <=> 0
1372 my $t = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d});
1373 my $u = $MBI->_mul( $MBI->_copy($y->{_n}), $x->{_d});
1375 my $cmp = $MBI->_acmp($t,$u); # signs are equal
1376 $cmp = -$cmp if $x->{sign} eq '-'; # both are '-' => reverse
1382 # compare two numbers (as unsigned)
1385 my ($self,$x,$y) = (ref($_[0]),@_);
1386 # objectify is costly, so avoid it
1387 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1389 ($self,$x,$y) = objectify(2,$class,@_);
1392 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
1394 # handle +-inf and NaN
1395 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1396 return 0 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} =~ /^[+-]inf$/;
1397 return 1 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} !~ /^[+-]inf$/;
1401 my $t = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d});
1402 my $u = $MBI->_mul( $MBI->_copy($y->{_n}), $x->{_d});
1403 $MBI->_acmp($t,$u); # ignore signs
1406 ##############################################################################
1407 # output conversation
1411 # convert 17/8 => float (aka 2.125)
1412 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1414 return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, NaN, etc
1417 my $neg = ''; $neg = '-' if $x->{sign} eq '-';
1418 return $neg . $MBI->_num($x->{_n}) if $MBI->_is_one($x->{_d});
1420 $x->_as_float()->numify() + 0.0;
1425 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1428 return Math::BigInt->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
1430 my $u = Math::BigInt->bzero();
1431 $u->{sign} = $x->{sign};
1432 $u->{value} = $MBI->_div( $MBI->_copy($x->{_n}), $x->{_d}); # 22/7 => 3
1438 # return N/D as Math::BigFloat
1441 my ($self,$x,@r) = (ref($_[0]),@_);
1442 # objectify is costly, so avoid it
1443 ($self,$x,@r) = objectify(1,$class,@_) unless ref $_[0];
1446 return Math::BigFloat->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
1448 my $u = Math::BigFloat->bzero();
1449 $u->{sign} = $x->{sign};
1451 $u->{_m} = $MBI->_copy($x->{_n});
1452 $u->{_e} = $MBI->_zero();
1453 $u->bdiv( $MBI->_str($x->{_d}), @r);
1460 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1462 return $x unless $x->is_int();
1464 my $s = $x->{sign}; $s = '' if $s eq '+';
1465 $s . $MBI->_as_bin($x->{_n});
1470 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1472 return $x unless $x->is_int();
1474 my $s = $x->{sign}; $s = '' if $s eq '+';
1475 $s . $MBI->_as_hex($x->{_n});
1480 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1482 return $x unless $x->is_int();
1484 my $s = $x->{sign}; $s = '' if $s eq '+';
1485 $s . $MBI->_as_oct($x->{_n});
1488 ##############################################################################
1511 push @parts, Math::BigInt->from_oct($c);
1513 $class->new ( @parts );
1516 ##############################################################################
1523 my $lib = ''; my @a;
1526 for ( my $i = 0; $i < $l ; $i++)
1528 if ( $_[$i] eq ':constant' )
1530 # this rest causes overlord er load to step in
1531 overload::constant float => sub { $self->new(shift); };
1533 # elsif ($_[$i] eq 'upgrade')
1535 # # this causes upgrading
1536 # $upgrade = $_[$i+1]; # or undef to disable
1539 elsif ($_[$i] eq 'downgrade')
1541 # this causes downgrading
1542 $downgrade = $_[$i+1]; # or undef to disable
1545 elsif ($_[$i] =~ /^(lib|try|only)\z/)
1547 $lib = $_[$i+1] || ''; # default Calc
1548 $try = $1; # lib, try or only
1551 elsif ($_[$i] eq 'with')
1553 # this argument is no longer used
1554 #$MBI = $_[$i+1] || 'Math::BigInt::Calc'; # default Math::BigInt::Calc
1562 require Math::BigInt;
1564 # let use Math::BigInt lib => 'GMP'; use Math::BigRat; still have GMP
1567 my @c = split /\s*,\s*/, $lib;
1570 $_ =~ tr/a-zA-Z0-9://cd; # limit to sane characters
1572 $lib = join(",", @c);
1574 my @import = ('objectify');
1575 push @import, $try => $lib if $lib ne '';
1577 # MBI already loaded, so feed it our lib arguments
1578 Math::BigInt->import( @import );
1580 $MBI = Math::BigFloat->config()->{lib};
1582 # register us with MBI to get notified of future lib changes
1583 Math::BigInt::_register_callback( $self, sub { $MBI = $_[0]; } );
1585 # any non :constant stuff is handled by our parent, Exporter (loaded
1586 # by Math::BigFloat, even if @_ is empty, to give it a chance
1587 $self->SUPER::import(@a); # for subclasses
1588 $self->export_to_level(1,$self,@a); # need this, too
1597 Math::BigRat - Arbitrary big rational numbers
1603 my $x = Math::BigRat->new('3/7'); $x += '5/9';
1605 print $x->bstr(),"\n";
1608 my $y = Math::BigRat->new('inf');
1609 print "$y ", ($y->is_inf ? 'is' : 'is not') , " infinity\n";
1611 my $z = Math::BigRat->new(144); $z->bsqrt();
1615 Math::BigRat complements Math::BigInt and Math::BigFloat by providing support
1616 for arbitrary big rational numbers.
1620 You can change the underlying module that does the low-level
1621 math operations by using:
1623 use Math::BigRat try => 'GMP';
1625 Note: This needs Math::BigInt::GMP installed.
1627 The following would first try to find Math::BigInt::Foo, then
1628 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
1630 use Math::BigRat try => 'Foo,Math::BigInt::Bar';
1632 If you want to get warned when the fallback occurs, replace "try" with
1635 use Math::BigRat lib => 'Foo,Math::BigInt::Bar';
1637 If you want the code to die instead, replace "try" with
1640 use Math::BigRat only => 'Foo,Math::BigInt::Bar';
1644 Any methods not listed here are derived from Math::BigFloat (or
1645 Math::BigInt), so make sure you check these two modules for further
1650 $x = Math::BigRat->new('1/3');
1652 Create a new Math::BigRat object. Input can come in various forms:
1654 $x = Math::BigRat->new(123); # scalars
1655 $x = Math::BigRat->new('inf'); # infinity
1656 $x = Math::BigRat->new('123.3'); # float
1657 $x = Math::BigRat->new('1/3'); # simple string
1658 $x = Math::BigRat->new('1 / 3'); # spaced
1659 $x = Math::BigRat->new('1 / 0.1'); # w/ floats
1660 $x = Math::BigRat->new(Math::BigInt->new(3)); # BigInt
1661 $x = Math::BigRat->new(Math::BigFloat->new('3.1')); # BigFloat
1662 $x = Math::BigRat->new(Math::BigInt::Lite->new('2')); # BigLite
1664 # You can also give D and N as different objects:
1665 $x = Math::BigRat->new(
1666 Math::BigInt->new(-123),
1667 Math::BigInt->new(7),
1672 $n = $x->numerator();
1674 Returns a copy of the numerator (the part above the line) as signed BigInt.
1676 =head2 denominator()
1678 $d = $x->denominator();
1680 Returns a copy of the denominator (the part under the line) as positive BigInt.
1684 ($n,$d) = $x->parts();
1686 Return a list consisting of (signed) numerator and (unsigned) denominator as
1691 my $y = $x->numify();
1693 Returns the object as a scalar. This will lose some data if the object
1694 cannot be represented by a normal Perl scalar (integer or float), so
1695 use L<as_int()> or L<as_float()> instead.
1697 This routine is automatically used whenever a scalar is required:
1699 my $x = Math::BigRat->new('3/1');
1701 $y = $array[$x]; # set $y to 3
1703 =head2 as_int()/as_number()
1705 $x = Math::BigRat->new('13/7');
1706 print $x->as_int(),"\n"; # '1'
1708 Returns a copy of the object as BigInt, truncated to an integer.
1710 C<as_number()> is an alias for C<as_int()>.
1714 $x = Math::BigRat->new('13/7');
1715 print $x->as_float(),"\n"; # '1'
1717 $x = Math::BigRat->new('2/3');
1718 print $x->as_float(5),"\n"; # '0.66667'
1720 Returns a copy of the object as BigFloat, preserving the
1721 accuracy as wanted, or the default of 40 digits.
1723 This method was added in v0.22 of Math::BigRat (April 2008).
1727 $x = Math::BigRat->new('13');
1728 print $x->as_hex(),"\n"; # '0xd'
1730 Returns the BigRat as hexadecimal string. Works only for integers.
1734 $x = Math::BigRat->new('13');
1735 print $x->as_bin(),"\n"; # '0x1101'
1737 Returns the BigRat as binary string. Works only for integers.
1741 $x = Math::BigRat->new('13');
1742 print $x->as_oct(),"\n"; # '015'
1744 Returns the BigRat as octal string. Works only for integers.
1746 =head2 from_hex()/from_bin()/from_oct()
1748 my $h = Math::BigRat->from_hex('0x10');
1749 my $b = Math::BigRat->from_bin('0b10000000');
1750 my $o = Math::BigRat->from_oct('020');
1752 Create a BigRat from an hexadecimal, binary or octal number
1757 $len = $x->length();
1759 Return the length of $x in digitis for integer values.
1763 print Math::BigRat->new('123/1')->digit(1); # 1
1764 print Math::BigRat->new('123/1')->digit(-1); # 3
1766 Return the N'ths digit from X when X is an integer value.
1772 Reduce the number to the shortest form. This routine is called
1773 automatically whenever it is needed.
1779 Calculates the factorial of $x. For instance:
1781 print Math::BigRat->new('3/1')->bfac(),"\n"; # 1*2*3
1782 print Math::BigRat->new('5/1')->bfac(),"\n"; # 1*2*3*4*5
1784 Works currently only for integers.
1786 =head2 bround()/round()/bfround()
1788 Are not yet implemented.
1793 my $x = Math::BigRat->new('7/4');
1794 my $y = Math::BigRat->new('4/3');
1797 Set $x to the remainder of the division of $x by $y.
1803 Used to negate the object in-place.
1807 print "$x is 1\n" if $x->is_one();
1809 Return true if $x is exactly one, otherwise false.
1813 print "$x is 0\n" if $x->is_zero();
1815 Return true if $x is exactly zero, otherwise false.
1817 =head2 is_pos()/is_positive()
1819 print "$x is >= 0\n" if $x->is_positive();
1821 Return true if $x is positive (greater than or equal to zero), otherwise
1822 false. Please note that '+inf' is also positive, while 'NaN' and '-inf' aren't.
1824 C<is_positive()> is an alias for C<is_pos()>.
1826 =head2 is_neg()/is_negative()
1828 print "$x is < 0\n" if $x->is_negative();
1830 Return true if $x is negative (smaller than zero), otherwise false. Please
1831 note that '-inf' is also negative, while 'NaN' and '+inf' aren't.
1833 C<is_negative()> is an alias for C<is_neg()>.
1837 print "$x is an integer\n" if $x->is_int();
1839 Return true if $x has a denominator of 1 (e.g. no fraction parts), otherwise
1840 false. Please note that '-inf', 'inf' and 'NaN' aren't integer.
1844 print "$x is odd\n" if $x->is_odd();
1846 Return true if $x is odd, otherwise false.
1850 print "$x is even\n" if $x->is_even();
1852 Return true if $x is even, otherwise false.
1858 Set $x to the next bigger integer value (e.g. truncate the number to integer
1859 and then increment it by one).
1865 Truncate $x to an integer value.
1871 Calculate the square root of $x.
1877 Calculate the N'th root of $x.
1879 =head2 badd()/bmul()/bsub()/bdiv()/bdec()/binc()
1881 Please see the documentation in L<Math::BigInt>.
1887 Makes a deep copy of the object.
1889 Please see the documentation in L<Math::BigInt> for further details.
1891 =head2 bstr()/bsstr()
1893 my $x = Math::BigInt->new('8/4');
1894 print $x->bstr(),"\n"; # prints 1/2
1895 print $x->bsstr(),"\n"; # prints 1/2
1897 Return a string representating this object.
1899 =head2 bacmp()/bcmp()
1901 Used to compare numbers.
1903 Please see the documentation in L<Math::BigInt> for further details.
1905 =head2 blsft()/brsft()
1907 Used to shift numbers left/right.
1909 Please see the documentation in L<Math::BigInt> for further details.
1917 Please see the documentation in L<Math::BigInt> for further details.
1921 $x->bexp($accuracy); # calculate e ** X
1923 Calculates two integers A and B so that A/B is equal to C<e ** $x>, where C<e> is
1926 This method was added in v0.20 of Math::BigRat (May 2007).
1932 $x->bnok($y); # x over y (binomial coefficient n over k)
1934 Calculates the binomial coefficient n over k, also called the "choose"
1935 function. The result is equivalent to:
1941 This method was added in v0.20 of Math::BigRat (May 2007).
1947 print Dumper ( Math::BigRat->config() );
1948 print Math::BigRat->config()->{lib},"\n";
1950 Returns a hash containing the configuration, e.g. the version number, lib
1951 loaded etc. The following hash keys are currently filled in with the
1952 appropriate information.
1954 key RO/RW Description
1956 ============================================================
1957 lib RO Name of the Math library
1959 lib_version RO Version of 'lib'
1961 class RO The class of config you just called
1963 version RO version number of the class you used
1965 upgrade RW To which class numbers are upgraded
1967 downgrade RW To which class numbers are downgraded
1969 precision RW Global precision
1971 accuracy RW Global accuracy
1973 round_mode RW Global round mode
1975 div_scale RW Fallback accuracy for div
1977 trap_nan RW Trap creation of NaN (undef = no)
1979 trap_inf RW Trap creation of +inf/-inf (undef = no)
1982 By passing a reference to a hash you may set the configuration values. This
1983 works only for values that a marked with a C<RW> above, anything else is
1988 This is an internal routine that turns scalars into objects.
1992 Some things are not yet implemented, or only implemented half-way:
1996 =item inf handling (partial)
1998 =item NaN handling (partial)
2000 =item rounding (not implemented except for bceil/bfloor)
2002 =item $x ** $y where $y is not an integer
2004 =item bmod(), blog(), bmodinv() and bmodpow() (partial)
2010 This program is free software; you may redistribute it and/or modify it under
2011 the same terms as Perl itself.
2015 L<Math::BigFloat> and L<Math::Big> as well as L<Math::BigInt::BitVect>,
2016 L<Math::BigInt::Pari> and L<Math::BigInt::GMP>.
2018 See L<http://search.cpan.org/search?dist=bignum> for a way to use
2021 The package at L<http://search.cpan.org/search?dist=Math%3A%3ABigRat>
2022 may contain more documentation and examples as well as testcases.
2026 (C) by Tels L<http://bloodgate.com/> 2001 - 2009.
2028 Currently maintained by Jonathan "Duke" Leto <jonathan@leto.net> L<http://leto.net>