3 # "Tax the rat farms." - Lord Vetinari
6 # The following hash values are used:
7 # sign : +,-,NaN,+inf,-inf
9 # _n : numerator (value = _n/_d)
12 # You should not look at the innards of a BigRat - use the methods for this.
16 # anything 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 (weird things like ' 1e0'
262 $self->{_n} = $MBI->_copy($n->{value});
263 $self->{_d} = $MBI->_copy($d->{value});
264 $self->{sign} = $n->{sign};
265 $self->{sign} =~ tr/+-/-+/ if $d->{sign} eq '-'; # -1/-2 => 1/2
266 return $self->bnorm();
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(
407 "n did not pass the self-check ($c) in bnorm()");
409 if ( my $c = $MBI->_check($x->{_d}) )
411 require Carp; Carp::croak(
412 "d did not pass the self-check ($c) in bnorm()");
415 # no normalize for NaN, inf etc.
416 return $x if $x->{sign} !~ /^[+-]$/;
418 # normalize zeros to 0/1
419 if ($MBI->_is_zero($x->{_n}))
421 $x->{sign} = '+'; # never leave a -0
422 $x->{_d} = $MBI->_one() unless $MBI->_is_one($x->{_d});
426 return $x if $MBI->_is_one($x->{_d}); # no need to reduce
428 # reduce other numbers
429 my $gcd = $MBI->_copy($x->{_n});
430 $gcd = $MBI->_gcd($gcd,$x->{_d});
432 if (!$MBI->_is_one($gcd))
434 $x->{_n} = $MBI->_div($x->{_n},$gcd);
435 $x->{_d} = $MBI->_div($x->{_d},$gcd);
440 ##############################################################################
445 # (BRAT or num_str) return BRAT
446 # negate number or make a negated number from string
447 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
449 return $x if $x->modify('bneg');
451 # for +0 do not negate (to have always normalized +0). Does nothing for 'NaN'
452 $x->{sign} =~ tr/+-/-+/
453 unless ($x->{sign} eq '+' && $MBI->_is_zero($x->{_n}));
457 ##############################################################################
462 # used by parent class bnan() to initialize number to NaN
468 my $class = ref($self);
469 # "$self" below will stringify the object, this blows up if $self is a
470 # partial object (happens under trap_nan), so fix it beforehand
471 $self->{_d} = $MBI->_zero() unless defined $self->{_d};
472 $self->{_n} = $MBI->_zero() unless defined $self->{_n};
473 Carp::croak ("Tried to set $self to NaN in $class\::_bnan()");
475 $self->{_n} = $MBI->_zero();
476 $self->{_d} = $MBI->_zero();
481 # used by parent class bone() to initialize number to +inf/-inf
487 my $class = ref($self);
488 # "$self" below will stringify the object, this blows up if $self is a
489 # partial object (happens under trap_nan), so fix it beforehand
490 $self->{_d} = $MBI->_zero() unless defined $self->{_d};
491 $self->{_n} = $MBI->_zero() unless defined $self->{_n};
492 Carp::croak ("Tried to set $self to inf in $class\::_binf()");
494 $self->{_n} = $MBI->_zero();
495 $self->{_d} = $MBI->_zero();
500 # used by parent class bone() to initialize number to +1/-1
502 $self->{_n} = $MBI->_one();
503 $self->{_d} = $MBI->_one();
508 # used by parent class bzero() to initialize number to 0
510 $self->{_n} = $MBI->_zero();
511 $self->{_d} = $MBI->_one();
514 ##############################################################################
519 # add two rational numbers
522 my ($self,$x,$y,@r) = (ref($_[0]),@_);
523 # objectify is costly, so avoid it
524 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
526 ($self,$x,$y,@r) = objectify(2,@_);
529 # +inf + +inf => +inf, -inf + -inf => -inf
530 return $x->binf(substr($x->{sign},0,1))
531 if $x->{sign} eq $y->{sign} && $x->{sign} =~ /^[+-]inf$/;
533 # +inf + -inf or -inf + +inf => NaN
534 return $x->bnan() if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/);
536 # 1 1 gcd(3,4) = 1 1*3 + 1*4 7
537 # - + - = --------- = --
540 # we do not compute the gcd() here, but simple do:
542 # - + - = --------- = --
545 # and bnorm() will then take care of the rest
548 $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_d});
551 my $m = $MBI->_mul( $MBI->_copy( $y->{_n} ), $x->{_d} );
554 ($x->{_n}, $x->{sign}) = _e_add( $x->{_n}, $m, $x->{sign}, $y->{sign});
557 $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_d});
559 # normalize result, and possible round
560 $x->bnorm()->round(@r);
565 # subtract two rational numbers
568 my ($self,$x,$y,@r) = (ref($_[0]),@_);
569 # objectify is costly, so avoid it
570 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
572 ($self,$x,$y,@r) = objectify(2,@_);
575 # flip sign of $x, call badd(), then flip sign of result
576 $x->{sign} =~ tr/+-/-+/
577 unless $x->{sign} eq '+' && $MBI->_is_zero($x->{_n}); # not -0
578 $x->badd($y,@r); # does norm and round
579 $x->{sign} =~ tr/+-/-+/
580 unless $x->{sign} eq '+' && $MBI->_is_zero($x->{_n}); # not -0
586 # multiply two rational numbers
589 my ($self,$x,$y,@r) = (ref($_[0]),@_);
590 # objectify is costly, so avoid it
591 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
593 ($self,$x,$y,@r) = objectify(2,@_);
596 return $x->bnan() if ($x->{sign} eq 'NaN' || $y->{sign} eq 'NaN');
599 if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/))
601 return $x->bnan() if $x->is_zero() || $y->is_zero();
602 # result will always be +-inf:
603 # +inf * +/+inf => +inf, -inf * -/-inf => +inf
604 # +inf * -/-inf => -inf, -inf * +/+inf => -inf
605 return $x->binf() if ($x->{sign} =~ /^\+/ && $y->{sign} =~ /^\+/);
606 return $x->binf() if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/);
607 return $x->binf('-');
610 # x== 0 # also: or y == 1 or y == -1
611 return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
614 # According to Knuth, this can be optimized by doing gcd twice (for d and n)
615 # and reducing in one step. This would save us the bnorm() at the end.
618 # - * - = ----- = - = -
621 $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_n});
622 $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_d});
625 $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
627 $x->bnorm()->round(@r);
632 # (dividend: BRAT or num_str, divisor: BRAT or num_str) return
633 # (BRAT,BRAT) (quo,rem) or BRAT (only rem)
636 my ($self,$x,$y,@r) = (ref($_[0]),@_);
637 # objectify is costly, so avoid it
638 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
640 ($self,$x,$y,@r) = objectify(2,@_);
643 return $self->_div_inf($x,$y)
644 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
646 # x== 0 # also: or y == 1 or y == -1
647 return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
649 # XXX TODO: list context, upgrade
650 # According to Knuth, this can be optimized by doing gcd twice (for d and n)
651 # and reducing in one step. This would save us the bnorm() at the end.
657 $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_d});
658 $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_n});
661 $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
663 $x->bnorm()->round(@r);
669 # compute "remainder" (in Perl way) of $x / $y
672 my ($self,$x,$y,@r) = (ref($_[0]),@_);
673 # objectify is costly, so avoid it
674 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
676 ($self,$x,$y,@r) = objectify(2,@_);
679 return $self->_div_inf($x,$y)
680 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
682 return $x if $x->is_zero(); # 0 / 7 = 0, mod 0
684 # compute $x - $y * floor($x/$y), keeping the sign of $x
686 # copy x to u, make it positive and then do a normal division ($u/$y)
687 my $u = bless { sign => '+' }, $self;
688 $u->{_n} = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d} );
689 $u->{_d} = $MBI->_mul( $MBI->_copy($x->{_d}), $y->{_n} );
692 if (! $MBI->_is_one($u->{_d}))
694 $u->{_n} = $MBI->_div($u->{_n},$u->{_d}); # 22/7 => 3/1 w/ truncate
695 # no need to set $u->{_d} to 1, since below we set it to $y->{_d} anyway
698 # now compute $y * $u
699 $u->{_d} = $MBI->_copy($y->{_d}); # 1 * $y->{_d}, see floor above
700 $u->{_n} = $MBI->_mul($u->{_n},$y->{_n});
702 my $xsign = $x->{sign}; $x->{sign} = '+'; # remember sign and make x positive
705 $x->{sign} = $xsign; # put sign back
707 $x->bnorm()->round(@r);
710 ##############################################################################
715 # decrement value (subtract 1)
716 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
718 return $x if $x->{sign} !~ /^[+-]$/; # NaN, inf, -inf
720 if ($x->{sign} eq '-')
722 $x->{_n} = $MBI->_add( $x->{_n}, $x->{_d}); # -5/2 => -7/2
726 if ($MBI->_acmp($x->{_n},$x->{_d}) < 0) # n < d?
729 $x->{_n} = $MBI->_sub( $MBI->_copy($x->{_d}), $x->{_n});
734 $x->{_n} = $MBI->_sub($x->{_n}, $x->{_d}); # 5/2 => 3/2
737 $x->bnorm()->round(@r);
742 # increment value (add 1)
743 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
745 return $x if $x->{sign} !~ /^[+-]$/; # NaN, inf, -inf
747 if ($x->{sign} eq '-')
749 if ($MBI->_acmp($x->{_n},$x->{_d}) < 0)
751 # -1/3 ++ => 2/3 (overflow at 0)
752 $x->{_n} = $MBI->_sub( $MBI->_copy($x->{_d}), $x->{_n});
757 $x->{_n} = $MBI->_sub($x->{_n}, $x->{_d}); # -5/2 => -3/2
762 $x->{_n} = $MBI->_add($x->{_n},$x->{_d}); # 5/2 => 7/2
764 $x->bnorm()->round(@r);
767 ##############################################################################
768 # is_foo methods (the rest is inherited)
772 # return true if arg (BRAT or num_str) is an integer
773 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
775 return 1 if ($x->{sign} =~ /^[+-]$/) && # NaN and +-inf aren't
776 $MBI->_is_one($x->{_d}); # x/y && y != 1 => no integer
782 # return true if arg (BRAT or num_str) is zero
783 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
785 return 1 if $x->{sign} eq '+' && $MBI->_is_zero($x->{_n});
791 # return true if arg (BRAT or num_str) is +1 or -1 if signis given
792 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
794 my $sign = $_[2] || ''; $sign = '+' if $sign ne '-';
796 if ($x->{sign} eq $sign && $MBI->_is_one($x->{_n}) && $MBI->_is_one($x->{_d}));
802 # return true if arg (BFLOAT or num_str) is odd or false if even
803 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
805 return 1 if ($x->{sign} =~ /^[+-]$/) && # NaN & +-inf aren't
806 ($MBI->_is_one($x->{_d}) && $MBI->_is_odd($x->{_n})); # x/2 is not, but 3/1
812 # return true if arg (BINT or num_str) is even or false if odd
813 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
815 return 0 if $x->{sign} !~ /^[+-]$/; # NaN & +-inf aren't
816 return 1 if ($MBI->_is_one($x->{_d}) # x/3 is never
817 && $MBI->_is_even($x->{_n})); # but 4/1 is
821 ##############################################################################
822 # parts() and friends
826 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
829 return Math::BigInt->new($x->{sign}) if ($x->{sign} !~ /^[+-]$/);
831 my $n = Math::BigInt->new($MBI->_str($x->{_n})); $n->{sign} = $x->{sign};
837 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
840 return Math::BigInt->new($x->{sign}) if $x->{sign} eq 'NaN';
842 return Math::BigInt->bone() if $x->{sign} !~ /^[+-]$/;
844 Math::BigInt->new($MBI->_str($x->{_d}));
849 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
851 my $c = 'Math::BigInt';
853 return ($c->bnan(),$c->bnan()) if $x->{sign} eq 'NaN';
854 return ($c->binf(),$c->binf()) if $x->{sign} eq '+inf';
855 return ($c->binf('-'),$c->binf()) if $x->{sign} eq '-inf';
857 my $n = $c->new( $MBI->_str($x->{_n}));
858 $n->{sign} = $x->{sign};
859 my $d = $c->new( $MBI->_str($x->{_d}));
865 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
867 return $nan unless $x->is_int();
868 $MBI->_len($x->{_n}); # length(-123/1) => length(123)
873 my ($self,$x,$n) = ref($_[0]) ? (undef,$_[0],$_[1]) : objectify(1,@_);
875 return $nan unless $x->is_int();
876 $MBI->_digit($x->{_n},$n || 0); # digit(-123/1,2) => digit(123,2)
879 ##############################################################################
880 # special calc routines
884 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
886 return $x if $x->{sign} !~ /^[+-]$/ || # not for NaN, inf
887 $MBI->_is_one($x->{_d}); # 22/1 => 22, 0/1 => 0
889 $x->{_n} = $MBI->_div($x->{_n},$x->{_d}); # 22/7 => 3/1 w/ truncate
890 $x->{_d} = $MBI->_one(); # d => 1
891 $x->{_n} = $MBI->_inc($x->{_n})
892 if $x->{sign} eq '+'; # +22/7 => 4/1
893 $x->{sign} = '+' if $MBI->_is_zero($x->{_n}); # -0 => 0
899 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
901 return $x if $x->{sign} !~ /^[+-]$/ || # not for NaN, inf
902 $MBI->_is_one($x->{_d}); # 22/1 => 22, 0/1 => 0
904 $x->{_n} = $MBI->_div($x->{_n},$x->{_d}); # 22/7 => 3/1 w/ truncate
905 $x->{_d} = $MBI->_one(); # d => 1
906 $x->{_n} = $MBI->_inc($x->{_n})
907 if $x->{sign} eq '-'; # -22/7 => -4/1
913 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
915 # if $x is not an integer
916 if (($x->{sign} ne '+') || (!$MBI->_is_one($x->{_d})))
921 $x->{_n} = $MBI->_fac($x->{_n});
922 # since _d is 1, we don't need to reduce/norm the result
931 my ($self,$x,$y,@r) = (ref($_[0]),@_);
932 # objectify is costly, so avoid it
933 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
935 ($self,$x,$y,@r) = objectify(2,@_);
938 return $x if $x->{sign} =~ /^[+-]inf$/; # -inf/+inf ** x
939 return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;
940 return $x->bone(@r) if $y->is_zero();
941 return $x->round(@r) if $x->is_one() || $y->is_one();
943 if ($x->{sign} eq '-' && $MBI->_is_one($x->{_n}) && $MBI->_is_one($x->{_d}))
945 # if $x == -1 and odd/even y => +1/-1
946 return $y->is_odd() ? $x->round(@r) : $x->babs()->round(@r);
947 # my Casio FX-5500L has a bug here: -1 ** 2 is -1, but -1 * -1 is 1;
949 # 1 ** -y => 1 / (1 ** |y|)
950 # so do test for negative $y after above's clause
952 return $x->round(@r) if $x->is_zero(); # 0**y => 0 (if not y <= 0)
954 # shortcut if y == 1/N (is then sqrt() respective broot())
955 if ($MBI->_is_one($y->{_n}))
957 return $x->bsqrt(@r) if $MBI->_is_two($y->{_d}); # 1/2 => sqrt
958 return $x->broot($MBI->_str($y->{_d}),@r); # 1/N => root(N)
961 # shortcut y/1 (and/or x/1)
962 if ($MBI->_is_one($y->{_d}))
964 # shortcut for x/1 and y/1
965 if ($MBI->_is_one($x->{_d}))
967 $x->{_n} = $MBI->_pow($x->{_n},$y->{_n}); # x/1 ** y/1 => (x ** y)/1
968 if ($y->{sign} eq '-')
970 # 0.2 ** -3 => 1/(0.2 ** 3)
971 ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n}); # swap
973 # correct sign; + ** + => +
974 if ($x->{sign} eq '-')
976 # - * - => +, - * - * - => -
977 $x->{sign} = '+' if $MBI->_is_even($y->{_n});
979 return $x->round(@r);
982 $x->{_n} = $MBI->_pow($x->{_n},$y->{_n}); # 5/2 ** y/1 => 5 ** y / 2 ** y
983 $x->{_d} = $MBI->_pow($x->{_d},$y->{_n});
984 if ($y->{sign} eq '-')
986 # 0.2 ** -3 => 1/(0.2 ** 3)
987 ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n}); # swap
989 # correct sign; + ** + => +
990 if ($x->{sign} eq '-')
992 # - * - => +, - * - * - => -
993 $x->{sign} = '+' if $MBI->_is_even($y->{_n});
995 return $x->round(@r);
998 # print STDERR "# $x $y\n";
1002 # n/d n ______________
1003 # a/b = -\/ (a/b) ** d
1005 # (a/b) ** n == (a ** n) / (b ** n)
1006 $MBI->_pow($x->{_n}, $y->{_n} );
1007 $MBI->_pow($x->{_d}, $y->{_n} );
1009 return $x->broot($MBI->_str($y->{_d}),@r); # n/d => root(n)
1015 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1017 # objectify is costly, so avoid it
1018 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1020 ($self,$x,$y,@r) = objectify(2,$class,@_);
1024 return $x->bzero() if $x->is_one() && $y->{sign} eq '+';
1027 return $x->bnan() if $x->is_zero() || $x->{sign} ne '+' || $y->{sign} ne '+';
1029 if ($x->is_int() && $y->is_int())
1031 return $self->new($x->as_number()->blog($y->as_number(),@r));
1035 $x->_new_from_float( $x->_as_float()->blog(Math::BigFloat->new("$y"),@r) );
1041 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1043 # objectify is costly, so avoid it
1044 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1046 ($self,$x,$y,@r) = objectify(2,$class,@_);
1049 return $x->binf(@r) if $x->{sign} eq '+inf';
1050 return $x->bzero(@r) if $x->{sign} eq '-inf';
1052 # we need to limit the accuracy to protect against overflow
1054 my ($scale,@params);
1055 ($x,@params) = $x->_find_round_parameters(@r);
1057 # also takes care of the "error in _find_round_parameters?" case
1058 return $x if $x->{sign} eq 'NaN';
1060 # no rounding at all, so must use fallback
1061 if (scalar @params == 0)
1063 # simulate old behaviour
1064 $params[0] = $self->div_scale(); # and round to it as accuracy
1065 $params[1] = undef; # P = undef
1066 $scale = $params[0]+4; # at least four more for proper round
1067 $params[2] = $r[2]; # round mode by caller or undef
1068 $fallback = 1; # to clear a/p afterwards
1072 # the 4 below is empirical, and there might be cases where it's not enough...
1073 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined
1076 return $x->bone(@params) if $x->is_zero();
1078 # See the comments in Math::BigFloat on how this algorithm works.
1079 # Basically we calculate A and B (where B is faculty(N)) so that A/B = e
1081 my $x_org = $x->copy();
1084 # set $x directly from a cached string form
1086 $MBI->_new("90933395208605785401971970164779391644753259799242");
1088 $MBI->_new("33452526613163807108170062053440751665152000000000");
1093 # compute A and B so that e = A / B.
1095 # After some terms we end up with this, so we use it as a starting point:
1096 my $A = $MBI->_new("90933395208605785401971970164779391644753259799242");
1097 my $F = $MBI->_new(42); my $step = 42;
1099 # Compute how many steps we need to take to get $A and $B sufficiently big
1100 my $steps = Math::BigFloat::_len_to_steps($scale - 4);
1101 # print STDERR "# Doing $steps steps for ", $scale-4, " digits\n";
1102 while ($step++ <= $steps)
1104 # calculate $a * $f + 1
1105 $A = $MBI->_mul($A, $F);
1106 $A = $MBI->_inc($A);
1108 $F = $MBI->_inc($F);
1110 # compute $B as factorial of $steps (this is faster than doing it manually)
1111 my $B = $MBI->_fac($MBI->_new($steps));
1113 # print "A ", $MBI->_str($A), "\nB ", $MBI->_str($B), "\n";
1120 # $x contains now an estimate of e, with some surplus digits, so we can round
1121 if (!$x_org->is_one())
1123 # raise $x to the wanted power and round it in one step:
1124 $x->bpow($x_org, @params);
1128 # else just round the already computed result
1129 delete $x->{_a}; delete $x->{_p};
1130 # shortcut to not run through _find_round_parameters again
1131 if (defined $params[0])
1133 $x->bround($params[0],$params[2]); # then round accordingly
1137 $x->bfround($params[1],$params[2]); # then round accordingly
1142 # clear a/p after round, since user did not request it
1143 delete $x->{_a}; delete $x->{_p};
1152 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1154 # objectify is costly, so avoid it
1155 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1157 ($self,$x,$y,@r) = objectify(2,$class,@_);
1161 $x->_new_from_float( $x->_as_float()->bnok(Math::BigFloat->new("$y"),@r) );
1164 sub _float_from_part
1168 my $f = Math::BigFloat->bzero();
1169 $f->{_m} = $MBI->_copy($x);
1170 $f->{_e} = $MBI->_zero();
1179 local $Math::BigFloat::upgrade = undef;
1180 local $Math::BigFloat::accuracy = undef;
1181 local $Math::BigFloat::precision = undef;
1182 # 22/7 => 3.142857143..
1184 my $a = $x->accuracy() || 0;
1185 if ($a != 0 || !$MBI->_is_one($x->{_d}))
1188 return scalar Math::BigFloat->new($x->{sign} . $MBI->_str($x->{_n}))->bdiv( $MBI->_str($x->{_d}), $x->accuracy());
1191 Math::BigFloat->new($x->{sign} . $MBI->_str($x->{_n}));
1197 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1198 # objectify is costly, so avoid it
1199 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1201 ($self,$x,$y,@r) = objectify(2,@_);
1204 if ($x->is_int() && $y->is_int())
1206 return $self->new($x->as_number()->broot($y->as_number(),@r));
1210 $x->_new_from_float( $x->_as_float()->broot($y->_as_float(),@r) )->bnorm()->bround(@r);
1216 my ($self,$x,$y,$m,@r) = (ref($_[0]),@_);
1217 # objectify is costly, so avoid it
1218 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1220 ($self,$x,$y,$m,@r) = objectify(3,@_);
1223 # $x or $y or $m are NaN or +-inf => NaN
1225 if $x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/ ||
1226 $m->{sign} !~ /^[+-]$/;
1228 if ($x->is_int() && $y->is_int() && $m->is_int())
1230 return $self->new($x->as_number()->bmodpow($y->as_number(),$m,@r));
1233 warn ("bmodpow() not fully implemented");
1240 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1241 # objectify is costly, so avoid it
1242 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1244 ($self,$x,$y,@r) = objectify(2,@_);
1247 # $x or $y are NaN or +-inf => NaN
1249 if $x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/;
1251 if ($x->is_int() && $y->is_int())
1253 return $self->new($x->as_number()->bmodinv($y->as_number(),@r));
1256 warn ("bmodinv() not fully implemented");
1262 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
1264 return $x->bnan() if $x->{sign} !~ /^[+]/; # NaN, -inf or < 0
1265 return $x if $x->{sign} eq '+inf'; # sqrt(inf) == inf
1266 return $x->round(@r) if $x->is_zero() || $x->is_one();
1268 local $Math::BigFloat::upgrade = undef;
1269 local $Math::BigFloat::downgrade = undef;
1270 local $Math::BigFloat::precision = undef;
1271 local $Math::BigFloat::accuracy = undef;
1272 local $Math::BigInt::upgrade = undef;
1273 local $Math::BigInt::precision = undef;
1274 local $Math::BigInt::accuracy = undef;
1276 $x->{_n} = _float_from_part( $x->{_n} )->bsqrt();
1277 $x->{_d} = _float_from_part( $x->{_d} )->bsqrt();
1279 # XXX TODO: we probably can optimize this:
1281 # if sqrt(D) was not integer
1282 if ($x->{_d}->{_es} ne '+')
1284 $x->{_n}->blsft($x->{_d}->exponent()->babs(),10); # 7.1/4.51 => 7.1/45.1
1285 $x->{_d} = $MBI->_copy( $x->{_d}->{_m} ); # 7.1/45.1 => 71/45.1
1287 # if sqrt(N) was not integer
1288 if ($x->{_n}->{_es} ne '+')
1290 $x->{_d}->blsft($x->{_n}->exponent()->babs(),10); # 71/45.1 => 710/45.1
1291 $x->{_n} = $MBI->_copy( $x->{_n}->{_m} ); # 710/45.1 => 710/451
1294 # convert parts to $MBI again
1295 $x->{_n} = $MBI->_lsft( $MBI->_copy( $x->{_n}->{_m} ), $x->{_n}->{_e}, 10)
1296 if ref($x->{_n}) ne $MBI && ref($x->{_n}) ne 'ARRAY';
1297 $x->{_d} = $MBI->_lsft( $MBI->_copy( $x->{_d}->{_m} ), $x->{_d}->{_e}, 10)
1298 if ref($x->{_d}) ne $MBI && ref($x->{_d}) ne 'ARRAY';
1300 $x->bnorm()->round(@r);
1305 my ($self,$x,$y,$b,@r) = objectify(3,@_);
1307 $b = 2 unless defined $b;
1308 $b = $self->new($b) unless ref ($b);
1309 $x->bmul( $b->copy()->bpow($y), @r);
1315 my ($self,$x,$y,$b,@r) = objectify(3,@_);
1317 $b = 2 unless defined $b;
1318 $b = $self->new($b) unless ref ($b);
1319 $x->bdiv( $b->copy()->bpow($y), @r);
1323 ##############################################################################
1341 ##############################################################################
1346 # compare two signed numbers
1349 my ($self,$x,$y) = (ref($_[0]),@_);
1350 # objectify is costly, so avoid it
1351 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1353 ($self,$x,$y) = objectify(2,@_);
1356 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
1358 # handle +-inf and NaN
1359 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1360 return 0 if $x->{sign} eq $y->{sign} && $x->{sign} =~ /^[+-]inf$/;
1361 return +1 if $x->{sign} eq '+inf';
1362 return -1 if $x->{sign} eq '-inf';
1363 return -1 if $y->{sign} eq '+inf';
1366 # check sign for speed first
1367 return 1 if $x->{sign} eq '+' && $y->{sign} eq '-'; # does also 0 <=> -y
1368 return -1 if $x->{sign} eq '-' && $y->{sign} eq '+'; # does also -x <=> 0
1371 my $xz = $MBI->_is_zero($x->{_n});
1372 my $yz = $MBI->_is_zero($y->{_n});
1373 return 0 if $xz && $yz; # 0 <=> 0
1374 return -1 if $xz && $y->{sign} eq '+'; # 0 <=> +y
1375 return 1 if $yz && $x->{sign} eq '+'; # +x <=> 0
1377 my $t = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d});
1378 my $u = $MBI->_mul( $MBI->_copy($y->{_n}), $x->{_d});
1380 my $cmp = $MBI->_acmp($t,$u); # signs are equal
1381 $cmp = -$cmp if $x->{sign} eq '-'; # both are '-' => reverse
1387 # compare two numbers (as unsigned)
1390 my ($self,$x,$y) = (ref($_[0]),@_);
1391 # objectify is costly, so avoid it
1392 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1394 ($self,$x,$y) = objectify(2,$class,@_);
1397 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
1399 # handle +-inf and NaN
1400 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1401 return 0 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} =~ /^[+-]inf$/;
1402 return 1 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} !~ /^[+-]inf$/;
1406 my $t = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d});
1407 my $u = $MBI->_mul( $MBI->_copy($y->{_n}), $x->{_d});
1408 $MBI->_acmp($t,$u); # ignore signs
1411 ##############################################################################
1412 # output conversation
1416 # convert 17/8 => float (aka 2.125)
1417 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1419 return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, NaN, etc
1422 my $neg = ''; $neg = '-' if $x->{sign} eq '-';
1423 return $neg . $MBI->_num($x->{_n}) if $MBI->_is_one($x->{_d});
1425 $x->_as_float()->numify() + 0.0;
1430 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1433 return Math::BigInt->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
1435 my $u = Math::BigInt->bzero();
1436 $u->{value} = $MBI->_div( $MBI->_copy($x->{_n}), $x->{_d}); # 22/7 => 3
1437 $u->bneg if $x->{sign} eq '-'; # no negative zero
1443 # return N/D as Math::BigFloat
1446 my ($self,$x,@r) = (ref($_[0]),@_);
1447 # objectify is costly, so avoid it
1448 ($self,$x,@r) = objectify(1,$class,@_) unless ref $_[0];
1451 return Math::BigFloat->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
1453 my $u = Math::BigFloat->bzero();
1454 $u->{sign} = $x->{sign};
1456 $u->{_m} = $MBI->_copy($x->{_n});
1457 $u->{_e} = $MBI->_zero();
1458 $u->bdiv( $MBI->_str($x->{_d}), @r);
1465 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1467 return $x unless $x->is_int();
1469 my $s = $x->{sign}; $s = '' if $s eq '+';
1470 $s . $MBI->_as_bin($x->{_n});
1475 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1477 return $x unless $x->is_int();
1479 my $s = $x->{sign}; $s = '' if $s eq '+';
1480 $s . $MBI->_as_hex($x->{_n});
1485 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1487 return $x unless $x->is_int();
1489 my $s = $x->{sign}; $s = '' if $s eq '+';
1490 $s . $MBI->_as_oct($x->{_n});
1493 ##############################################################################
1516 push @parts, Math::BigInt->from_oct($c);
1518 $class->new ( @parts );
1521 ##############################################################################
1528 my $lib = ''; my @a;
1531 for ( my $i = 0; $i < $l ; $i++)
1533 if ( $_[$i] eq ':constant' )
1535 # this rest causes overlord er load to step in
1536 overload::constant float => sub { $self->new(shift); };
1538 # elsif ($_[$i] eq 'upgrade')
1540 # # this causes upgrading
1541 # $upgrade = $_[$i+1]; # or undef to disable
1544 elsif ($_[$i] eq 'downgrade')
1546 # this causes downgrading
1547 $downgrade = $_[$i+1]; # or undef to disable
1550 elsif ($_[$i] =~ /^(lib|try|only)\z/)
1552 $lib = $_[$i+1] || ''; # default Calc
1553 $try = $1; # lib, try or only
1556 elsif ($_[$i] eq 'with')
1558 # this argument is no longer used
1559 #$MBI = $_[$i+1] || 'Math::BigInt::Calc'; # default Math::BigInt::Calc
1567 require Math::BigInt;
1569 # let use Math::BigInt lib => 'GMP'; use Math::BigRat; still have GMP
1572 my @c = split /\s*,\s*/, $lib;
1575 $_ =~ tr/a-zA-Z0-9://cd; # limit to sane characters
1577 $lib = join(",", @c);
1579 my @import = ('objectify');
1580 push @import, $try => $lib if $lib ne '';
1582 # MBI already loaded, so feed it our lib arguments
1583 Math::BigInt->import( @import );
1585 $MBI = Math::BigFloat->config()->{lib};
1587 # register us with MBI to get notified of future lib changes
1588 Math::BigInt::_register_callback( $self, sub { $MBI = $_[0]; } );
1590 # any non :constant stuff is handled by our parent, Exporter (loaded
1591 # by Math::BigFloat, even if @_ is empty, to give it a chance
1592 $self->SUPER::import(@a); # for subclasses
1593 $self->export_to_level(1,$self,@a); # need this, too
1604 Math::BigRat - Arbitrary big rational numbers
1610 my $x = Math::BigRat->new('3/7'); $x += '5/9';
1612 print $x->bstr(),"\n";
1615 my $y = Math::BigRat->new('inf');
1616 print "$y ", ($y->is_inf ? 'is' : 'is not') , " infinity\n";
1618 my $z = Math::BigRat->new(144); $z->bsqrt();
1622 Math::BigRat complements Math::BigInt and Math::BigFloat by providing support
1623 for arbitrary big rational numbers.
1627 You can change the underlying module that does the low-level
1628 math operations by using:
1630 use Math::BigRat try => 'GMP';
1632 Note: This needs Math::BigInt::GMP installed.
1634 The following would first try to find Math::BigInt::Foo, then
1635 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
1637 use Math::BigRat try => 'Foo,Math::BigInt::Bar';
1639 If you want to get warned when the fallback occurs, replace "try" with
1642 use Math::BigRat lib => 'Foo,Math::BigInt::Bar';
1644 If you want the code to die instead, replace "try" with
1647 use Math::BigRat only => 'Foo,Math::BigInt::Bar';
1651 Any methods not listed here are derived from Math::BigFloat (or
1652 Math::BigInt), so make sure you check these two modules for further
1657 $x = Math::BigRat->new('1/3');
1659 Create a new Math::BigRat object. Input can come in various forms:
1661 $x = Math::BigRat->new(123); # scalars
1662 $x = Math::BigRat->new('inf'); # infinity
1663 $x = Math::BigRat->new('123.3'); # float
1664 $x = Math::BigRat->new('1/3'); # simple string
1665 $x = Math::BigRat->new('1 / 3'); # spaced
1666 $x = Math::BigRat->new('1 / 0.1'); # w/ floats
1667 $x = Math::BigRat->new(Math::BigInt->new(3)); # BigInt
1668 $x = Math::BigRat->new(Math::BigFloat->new('3.1')); # BigFloat
1669 $x = Math::BigRat->new(Math::BigInt::Lite->new('2')); # BigLite
1671 # You can also give D and N as different objects:
1672 $x = Math::BigRat->new(
1673 Math::BigInt->new(-123),
1674 Math::BigInt->new(7),
1679 $n = $x->numerator();
1681 Returns a copy of the numerator (the part above the line) as signed BigInt.
1683 =head2 denominator()
1685 $d = $x->denominator();
1687 Returns a copy of the denominator (the part under the line) as positive BigInt.
1691 ($n,$d) = $x->parts();
1693 Return a list consisting of (signed) numerator and (unsigned) denominator as
1698 my $y = $x->numify();
1700 Returns the object as a scalar. This will lose some data if the object
1701 cannot be represented by a normal Perl scalar (integer or float), so
1702 use L<as_int()|/as_int()E<sol>as_number()> or L</as_float()> instead.
1704 This routine is automatically used whenever a scalar is required:
1706 my $x = Math::BigRat->new('3/1');
1708 $y = $array[$x]; # set $y to 3
1710 =head2 as_int()/as_number()
1712 $x = Math::BigRat->new('13/7');
1713 print $x->as_int(),"\n"; # '1'
1715 Returns a copy of the object as BigInt, truncated to an integer.
1717 C<as_number()> is an alias for C<as_int()>.
1721 $x = Math::BigRat->new('13/7');
1722 print $x->as_float(),"\n"; # '1'
1724 $x = Math::BigRat->new('2/3');
1725 print $x->as_float(5),"\n"; # '0.66667'
1727 Returns a copy of the object as BigFloat, preserving the
1728 accuracy as wanted, or the default of 40 digits.
1730 This method was added in v0.22 of Math::BigRat (April 2008).
1734 $x = Math::BigRat->new('13');
1735 print $x->as_hex(),"\n"; # '0xd'
1737 Returns the BigRat as hexadecimal string. Works only for integers.
1741 $x = Math::BigRat->new('13');
1742 print $x->as_bin(),"\n"; # '0x1101'
1744 Returns the BigRat as binary string. Works only for integers.
1748 $x = Math::BigRat->new('13');
1749 print $x->as_oct(),"\n"; # '015'
1751 Returns the BigRat as octal string. Works only for integers.
1753 =head2 from_hex()/from_bin()/from_oct()
1755 my $h = Math::BigRat->from_hex('0x10');
1756 my $b = Math::BigRat->from_bin('0b10000000');
1757 my $o = Math::BigRat->from_oct('020');
1759 Create a BigRat from an hexadecimal, binary or octal number
1764 $len = $x->length();
1766 Return the length of $x in digits for integer values.
1770 print Math::BigRat->new('123/1')->digit(1); # 1
1771 print Math::BigRat->new('123/1')->digit(-1); # 3
1773 Return the N'ths digit from X when X is an integer value.
1779 Reduce the number to the shortest form. This routine is called
1780 automatically whenever it is needed.
1786 Calculates the factorial of $x. For instance:
1788 print Math::BigRat->new('3/1')->bfac(),"\n"; # 1*2*3
1789 print Math::BigRat->new('5/1')->bfac(),"\n"; # 1*2*3*4*5
1791 Works currently only for integers.
1793 =head2 bround()/round()/bfround()
1795 Are not yet implemented.
1800 my $x = Math::BigRat->new('7/4');
1801 my $y = Math::BigRat->new('4/3');
1804 Set $x to the remainder of the division of $x by $y.
1810 Used to negate the object in-place.
1814 print "$x is 1\n" if $x->is_one();
1816 Return true if $x is exactly one, otherwise false.
1820 print "$x is 0\n" if $x->is_zero();
1822 Return true if $x is exactly zero, otherwise false.
1824 =head2 is_pos()/is_positive()
1826 print "$x is >= 0\n" if $x->is_positive();
1828 Return true if $x is positive (greater than or equal to zero), otherwise
1829 false. Please note that '+inf' is also positive, while 'NaN' and '-inf' aren't.
1831 C<is_positive()> is an alias for C<is_pos()>.
1833 =head2 is_neg()/is_negative()
1835 print "$x is < 0\n" if $x->is_negative();
1837 Return true if $x is negative (smaller than zero), otherwise false. Please
1838 note that '-inf' is also negative, while 'NaN' and '+inf' aren't.
1840 C<is_negative()> is an alias for C<is_neg()>.
1844 print "$x is an integer\n" if $x->is_int();
1846 Return true if $x has a denominator of 1 (e.g. no fraction parts), otherwise
1847 false. Please note that '-inf', 'inf' and 'NaN' aren't integer.
1851 print "$x is odd\n" if $x->is_odd();
1853 Return true if $x is odd, otherwise false.
1857 print "$x is even\n" if $x->is_even();
1859 Return true if $x is even, otherwise false.
1865 Set $x to the next bigger integer value (e.g. truncate the number to integer
1866 and then increment it by one).
1872 Truncate $x to an integer value.
1878 Calculate the square root of $x.
1884 Calculate the N'th root of $x.
1886 =head2 badd()/bmul()/bsub()/bdiv()/bdec()/binc()
1888 Please see the documentation in L<Math::BigInt>.
1894 Makes a deep copy of the object.
1896 Please see the documentation in L<Math::BigInt> for further details.
1898 =head2 bstr()/bsstr()
1900 my $x = Math::BigInt->new('8/4');
1901 print $x->bstr(),"\n"; # prints 1/2
1902 print $x->bsstr(),"\n"; # prints 1/2
1904 Return a string representing this object.
1906 =head2 bacmp()/bcmp()
1908 Used to compare numbers.
1910 Please see the documentation in L<Math::BigInt> for further details.
1912 =head2 blsft()/brsft()
1914 Used to shift numbers left/right.
1916 Please see the documentation in L<Math::BigInt> for further details.
1924 Please see the documentation in L<Math::BigInt> for further details.
1928 $x->bexp($accuracy); # calculate e ** X
1930 Calculates two integers A and B so that A/B is equal to C<e ** $x>, where C<e> is
1933 This method was added in v0.20 of Math::BigRat (May 2007).
1939 $x->bnok($y); # x over y (binomial coefficient n over k)
1941 Calculates the binomial coefficient n over k, also called the "choose"
1942 function. The result is equivalent to:
1948 This method was added in v0.20 of Math::BigRat (May 2007).
1954 print Dumper ( Math::BigRat->config() );
1955 print Math::BigRat->config()->{lib},"\n";
1957 Returns a hash containing the configuration, e.g. the version number, lib
1958 loaded etc. The following hash keys are currently filled in with the
1959 appropriate information.
1961 key RO/RW Description
1963 ============================================================
1964 lib RO Name of the Math library
1966 lib_version RO Version of 'lib'
1968 class RO The class of config you just called
1970 version RO version number of the class you used
1972 upgrade RW To which class numbers are upgraded
1974 downgrade RW To which class numbers are downgraded
1976 precision RW Global precision
1978 accuracy RW Global accuracy
1980 round_mode RW Global round mode
1982 div_scale RW Fallback accuracy for div
1984 trap_nan RW Trap creation of NaN (undef = no)
1986 trap_inf RW Trap creation of +inf/-inf (undef = no)
1989 By passing a reference to a hash you may set the configuration values. This
1990 works only for values that a marked with a C<RW> above, anything else is
1995 This is an internal routine that turns scalars into objects.
1999 Please report any bugs or feature requests to
2000 C<bug-math-bigrat at rt.cpan.org>, or through the web interface at
2001 L<https://rt.cpan.org/Ticket/Create.html?Queue=Math-BigRat>
2003 We will be notified, and then you'll automatically be notified of progress on
2004 your bug as I make changes.
2008 You can find documentation for this module with the perldoc command.
2010 perldoc Math::BigRat
2012 You can also look for information at:
2016 =item * RT: CPAN's request tracker
2018 L<https://rt.cpan.org/Public/Dist/Display.html?Name=Math-BigRat>
2020 =item * AnnoCPAN: Annotated CPAN documentation
2022 L<http://annocpan.org/dist/Math-BigRat>
2024 =item * CPAN Ratings
2026 L<http://cpanratings.perl.org/dist/Math-BigRat>
2030 L<http://search.cpan.org/dist/Math-BigRat/>
2032 =item * CPAN Testers Matrix
2034 L<http://matrix.cpantesters.org/?dist=Math-BigRat>
2036 =item * The Bignum mailing list
2040 =item * Post to mailing list
2042 C<bignum at lists.scsys.co.uk>
2044 =item * View mailing list
2046 L<http://lists.scsys.co.uk/pipermail/bignum/>
2048 =item * Subscribe/Unsubscribe
2050 L<http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/bignum>
2058 This program is free software; you may redistribute it and/or modify it under
2059 the same terms as Perl itself.
2063 L<bigrat>, L<Math::BigFloat> and L<Math::BigInt> as well as the backends
2064 L<Math::BigInt::FastCalc>, L<Math::BigInt::GMP>, and L<Math::BigInt::Pari>.
2068 (C) by Tels L<http://bloodgate.com/> 2001 - 2009.
2070 Currently maintained by Jonathan "Duke" Leto <jonathan@leto.net> L<http://leto.net>