3 # "Tax the rat farms." - Lord Vetinari
6 # The following hash values are used:
7 # sign : +,-,NaN,+inf,-inf
9 # _n : numeraotr (value = _n/_d)
12 # You should not look at the innards of a BigRat - use the methods for this.
16 # anythig older is untested, and unlikely to work
21 use vars qw($VERSION @ISA $upgrade $downgrade
22 $accuracy $precision $round_mode $div_scale $_trap_nan $_trap_inf);
24 @ISA = qw(Math::BigFloat);
27 $VERSION = eval $VERSION;
29 use overload; # inherit overload from Math::BigFloat
33 *objectify = \&Math::BigInt::objectify; # inherit this from BigInt
34 *AUTOLOAD = \&Math::BigFloat::AUTOLOAD; # can't inherit AUTOLOAD
35 # we inherit these from BigFloat because currently it is not possible
36 # that MBF has a different $MBI variable than we, because MBF also uses
37 # Math::BigInt::config->('lib'); (there is always only one library loaded)
38 *_e_add = \&Math::BigFloat::_e_add;
39 *_e_sub = \&Math::BigFloat::_e_sub;
40 *as_int = \&as_number;
41 *is_pos = \&is_positive;
42 *is_neg = \&is_negative;
45 ##############################################################################
46 # Global constants and flags. Access these only via the accessor methods!
48 $accuracy = $precision = undef;
54 # These are internally, and not to be used from the outside at all!
56 $_trap_nan = 0; # are NaNs ok? set w/ config()
57 $_trap_inf = 0; # are infs ok? set w/ config()
59 # the package we are using for our private parts, defaults to:
60 # Math::BigInt->config()->{lib}
61 my $MBI = 'Math::BigInt::Calc';
64 my $class = 'Math::BigRat';
68 return 0 if $_[1] =~ /^Math::Big(Int|Float)/; # we aren't
72 ##############################################################################
76 # turn a single float input into a rational number (like '0.1')
79 return $self->bnan() if $f->is_nan();
80 return $self->binf($f->{sign}) if $f->{sign} =~ /^[+-]inf$/;
82 $self->{_n} = $MBI->_copy( $f->{_m} ); # mantissa
83 $self->{_d} = $MBI->_one();
84 $self->{sign} = $f->{sign} || '+';
87 # something like Math::BigRat->new('0.1');
89 $MBI->_lsft ( $self->{_d}, $f->{_e} ,10);
93 # something like Math::BigRat->new('10');
95 $MBI->_lsft ( $self->{_n}, $f->{_e} ,10) unless
96 $MBI->_is_zero($f->{_e});
103 # create a Math::BigRat
108 my $self = { }; bless $self,$class;
110 # input like (BigInt) or (BigFloat):
111 if ((!defined $d) && (ref $n) && (!$n->isa('Math::BigRat')))
113 if ($n->isa('Math::BigFloat'))
115 $self->_new_from_float($n);
117 if ($n->isa('Math::BigInt'))
119 # TODO: trap NaN, inf
120 $self->{_n} = $MBI->_copy($n->{value}); # "mantissa" = N
121 $self->{_d} = $MBI->_one(); # d => 1
122 $self->{sign} = $n->{sign};
124 if ($n->isa('Math::BigInt::Lite'))
126 # TODO: trap NaN, inf
127 $self->{sign} = '+'; $self->{sign} = '-' if $$n < 0;
128 $self->{_n} = $MBI->_new(abs($$n)); # "mantissa" = N
129 $self->{_d} = $MBI->_one(); # d => 1
131 return $self->bnorm(); # normalize (120/1 => 12/10)
134 # input like (BigInt,BigInt) or (BigLite,BigLite):
135 if (ref($d) && ref($n))
137 # do N first (for $self->{sign}):
138 if ($n->isa('Math::BigInt'))
140 # TODO: trap NaN, inf
141 $self->{_n} = $MBI->_copy($n->{value}); # "mantissa" = N
142 $self->{sign} = $n->{sign};
144 elsif ($n->isa('Math::BigInt::Lite'))
146 # TODO: trap NaN, inf
147 $self->{sign} = '+'; $self->{sign} = '-' if $$n < 0;
148 $self->{_n} = $MBI->_new(abs($$n)); # "mantissa" = $n
153 Carp::croak(ref($n) . " is not a recognized object format for Math::BigRat->new");
156 if ($d->isa('Math::BigInt'))
158 # TODO: trap NaN, inf
159 $self->{_d} = $MBI->_copy($d->{value}); # "mantissa" = D
160 # +/+ or -/- => +, +/- or -/+ => -
161 $self->{sign} = $d->{sign} ne $self->{sign} ? '-' : '+';
163 elsif ($d->isa('Math::BigInt::Lite'))
165 # TODO: trap NaN, inf
166 $self->{_d} = $MBI->_new(abs($$d)); # "mantissa" = D
167 my $ds = '+'; $ds = '-' if $$d < 0;
168 # +/+ or -/- => +, +/- or -/+ => -
169 $self->{sign} = $ds ne $self->{sign} ? '-' : '+';
174 Carp::croak(ref($d) . " is not a recognized object format for Math::BigRat->new");
176 return $self->bnorm(); # normalize (120/1 => 12/10)
178 return $n->copy() if ref $n; # already a BigRat
182 $self->{_n} = $MBI->_zero(); # undef => 0
183 $self->{_d} = $MBI->_one();
188 # string input with / delimiter
189 if ($n =~ /\s*\/\s*/)
191 return $class->bnan() if $n =~ /\/.*\//; # 1/2/3 isn't valid
192 return $class->bnan() if $n =~ /\/\s*$/; # 1/ isn't valid
193 ($n,$d) = split (/\//,$n);
194 # try as BigFloats first
195 if (($n =~ /[\.eE]/) || ($d =~ /[\.eE]/))
197 local $Math::BigFloat::accuracy = undef;
198 local $Math::BigFloat::precision = undef;
200 # one of them looks like a float
201 my $nf = Math::BigFloat->new($n,undef,undef);
203 return $self->bnan() if $nf->is_nan();
205 $self->{_n} = $MBI->_copy( $nf->{_m} ); # get mantissa
207 # now correct $self->{_n} due to $n
208 my $f = Math::BigFloat->new($d,undef,undef);
209 return $self->bnan() if $f->is_nan();
210 $self->{_d} = $MBI->_copy( $f->{_m} );
212 # calculate the difference between nE and dE
213 my $diff_e = $nf->exponent()->bsub( $f->exponent);
214 if ($diff_e->is_negative())
217 $MBI->_lsft( $self->{_d}, $MBI->_new( $diff_e->babs()), 10);
219 elsif (!$diff_e->is_zero())
222 $MBI->_lsft( $self->{_n}, $MBI->_new( $diff_e), 10);
227 # both d and n look like (big)ints
229 $self->{sign} = '+'; # no sign => '+'
232 if ($n =~ /^([+-]?)0*([0-9]+)\z/) # first part ok?
234 $self->{sign} = $1 || '+'; # no sign => '+'
235 $self->{_n} = $MBI->_new($2 || 0);
238 if ($d =~ /^([+-]?)0*([0-9]+)\z/) # second part ok?
240 $self->{sign} =~ tr/+-/-+/ if ($1 || '') eq '-'; # negate if second part neg.
241 $self->{_d} = $MBI->_new($2 || 0);
244 if (!defined $self->{_n} || !defined $self->{_d})
246 $d = Math::BigInt->new($d,undef,undef) unless ref $d;
247 $n = Math::BigInt->new($n,undef,undef) unless ref $n;
249 if ($n->{sign} =~ /^[+-]$/ && $d->{sign} =~ /^[+-]$/)
251 # both parts are ok as integers (wierd things like ' 1e0'
252 $self->{_n} = $MBI->_copy($n->{value});
253 $self->{_d} = $MBI->_copy($d->{value});
254 $self->{sign} = $n->{sign};
255 $self->{sign} =~ tr/+-/-+/ if $d->{sign} eq '-'; # -1/-2 => 1/2
256 return $self->bnorm();
259 $self->{sign} = '+'; # a default sign
260 return $self->bnan() if $n->is_nan() || $d->is_nan();
263 if ($n->is_inf() || $d->is_inf())
267 return $self->bnan() if $d->is_inf(); # both are inf => NaN
268 my $s = '+'; # '+inf/+123' or '-inf/-123'
269 $s = '-' if substr($n->{sign},0,1) ne $d->{sign};
271 return $self->binf($s);
274 return $self->bzero();
279 return $self->bnorm();
282 # simple string input
283 if (($n =~ /[\.eE]/) && $n !~ /^0x/)
285 # looks like a float, quacks like a float, so probably is a float
286 $self->{sign} = 'NaN';
287 local $Math::BigFloat::accuracy = undef;
288 local $Math::BigFloat::precision = undef;
289 $self->_new_from_float(Math::BigFloat->new($n,undef,undef));
293 # for simple forms, use $MBI directly
294 if ($n =~ /^([+-]?)0*([0-9]+)\z/)
296 $self->{sign} = $1 || '+';
297 $self->{_n} = $MBI->_new($2 || 0);
298 $self->{_d} = $MBI->_one();
302 my $n = Math::BigInt->new($n,undef,undef);
303 $self->{_n} = $MBI->_copy($n->{value});
304 $self->{_d} = $MBI->_one();
305 $self->{sign} = $n->{sign};
306 return $self->bnan() if $self->{sign} eq 'NaN';
307 return $self->binf($self->{sign}) if $self->{sign} =~ /^[+-]inf$/;
315 # if two arguments, the first one is the class to "swallow" subclasses
323 return unless ref($x); # only for objects
325 my $self = bless {}, $c;
327 $self->{sign} = $x->{sign};
328 $self->{_d} = $MBI->_copy($x->{_d});
329 $self->{_n} = $MBI->_copy($x->{_n});
330 $self->{_a} = $x->{_a} if defined $x->{_a};
331 $self->{_p} = $x->{_p} if defined $x->{_p};
335 ##############################################################################
339 # return (later set?) configuration data as hash ref
340 my $class = shift || 'Math::BigRat';
342 if (@_ == 1 && ref($_[0]) ne 'HASH')
344 my $cfg = $class->SUPER::config();
345 return $cfg->{$_[0]};
348 my $cfg = $class->SUPER::config(@_);
350 # now we need only to override the ones that are different from our parent
351 $cfg->{class} = $class;
356 ##############################################################################
360 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
362 if ($x->{sign} !~ /^[+-]$/) # inf, NaN etc
364 my $s = $x->{sign}; $s =~ s/^\+//; # +inf => inf
368 my $s = ''; $s = $x->{sign} if $x->{sign} ne '+'; # '+3/2' => '3/2'
370 return $s . $MBI->_str($x->{_n}) if $MBI->_is_one($x->{_d});
371 $s . $MBI->_str($x->{_n}) . '/' . $MBI->_str($x->{_d});
376 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
378 if ($x->{sign} !~ /^[+-]$/) # inf, NaN etc
380 my $s = $x->{sign}; $s =~ s/^\+//; # +inf => inf
384 my $s = ''; $s = $x->{sign} if $x->{sign} ne '+'; # +3 vs 3
385 $s . $MBI->_str($x->{_n}) . '/' . $MBI->_str($x->{_d});
390 # reduce the number to the shortest form
391 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
393 # Both parts must be objects of whatever we are using today.
394 if ( my $c = $MBI->_check($x->{_n}) )
396 require Carp; Carp::croak ("n did not pass the self-check ($c) in bnorm()");
398 if ( my $c = $MBI->_check($x->{_d}) )
400 require Carp; Carp::croak ("d did not pass the self-check ($c) in bnorm()");
403 # no normalize for NaN, inf etc.
404 return $x if $x->{sign} !~ /^[+-]$/;
406 # normalize zeros to 0/1
407 if ($MBI->_is_zero($x->{_n}))
409 $x->{sign} = '+'; # never leave a -0
410 $x->{_d} = $MBI->_one() unless $MBI->_is_one($x->{_d});
414 return $x if $MBI->_is_one($x->{_d}); # no need to reduce
416 # reduce other numbers
417 my $gcd = $MBI->_copy($x->{_n});
418 $gcd = $MBI->_gcd($gcd,$x->{_d});
420 if (!$MBI->_is_one($gcd))
422 $x->{_n} = $MBI->_div($x->{_n},$gcd);
423 $x->{_d} = $MBI->_div($x->{_d},$gcd);
428 ##############################################################################
433 # (BRAT or num_str) return BRAT
434 # negate number or make a negated number from string
435 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
437 return $x if $x->modify('bneg');
439 # for +0 dont negate (to have always normalized +0). Does nothing for 'NaN'
440 $x->{sign} =~ tr/+-/-+/ unless ($x->{sign} eq '+' && $MBI->_is_zero($x->{_n}));
444 ##############################################################################
449 # used by parent class bnan() to initialize number to NaN
455 my $class = ref($self);
456 # "$self" below will stringify the object, this blows up if $self is a
457 # partial object (happens under trap_nan), so fix it beforehand
458 $self->{_d} = $MBI->_zero() unless defined $self->{_d};
459 $self->{_n} = $MBI->_zero() unless defined $self->{_n};
460 Carp::croak ("Tried to set $self to NaN in $class\::_bnan()");
462 $self->{_n} = $MBI->_zero();
463 $self->{_d} = $MBI->_zero();
468 # used by parent class bone() to initialize number to +inf/-inf
474 my $class = ref($self);
475 # "$self" below will stringify the object, this blows up if $self is a
476 # partial object (happens under trap_nan), so fix it beforehand
477 $self->{_d} = $MBI->_zero() unless defined $self->{_d};
478 $self->{_n} = $MBI->_zero() unless defined $self->{_n};
479 Carp::croak ("Tried to set $self to inf in $class\::_binf()");
481 $self->{_n} = $MBI->_zero();
482 $self->{_d} = $MBI->_zero();
487 # used by parent class bone() to initialize number to +1/-1
489 $self->{_n} = $MBI->_one();
490 $self->{_d} = $MBI->_one();
495 # used by parent class bzero() to initialize number to 0
497 $self->{_n} = $MBI->_zero();
498 $self->{_d} = $MBI->_one();
501 ##############################################################################
506 # add two rational numbers
509 my ($self,$x,$y,@r) = (ref($_[0]),@_);
510 # objectify is costly, so avoid it
511 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
513 ($self,$x,$y,@r) = objectify(2,@_);
516 # +inf + +inf => +inf, -inf + -inf => -inf
517 return $x->binf(substr($x->{sign},0,1))
518 if $x->{sign} eq $y->{sign} && $x->{sign} =~ /^[+-]inf$/;
520 # +inf + -inf or -inf + +inf => NaN
521 return $x->bnan() if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/);
523 # 1 1 gcd(3,4) = 1 1*3 + 1*4 7
524 # - + - = --------- = --
527 # we do not compute the gcd() here, but simple do:
529 # - + - = --------- = --
532 # and bnorm() will then take care of the rest
535 $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_d});
538 my $m = $MBI->_mul( $MBI->_copy( $y->{_n} ), $x->{_d} );
541 ($x->{_n}, $x->{sign}) = _e_add( $x->{_n}, $m, $x->{sign}, $y->{sign});
544 $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_d});
546 # normalize result, and possible round
547 $x->bnorm()->round(@r);
552 # subtract two rational numbers
555 my ($self,$x,$y,@r) = (ref($_[0]),@_);
556 # objectify is costly, so avoid it
557 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
559 ($self,$x,$y,@r) = objectify(2,@_);
562 # flip sign of $x, call badd(), then flip sign of result
563 $x->{sign} =~ tr/+-/-+/
564 unless $x->{sign} eq '+' && $MBI->_is_zero($x->{_n}); # not -0
565 $x->badd($y,@r); # does norm and round
566 $x->{sign} =~ tr/+-/-+/
567 unless $x->{sign} eq '+' && $MBI->_is_zero($x->{_n}); # not -0
573 # multiply two rational numbers
576 my ($self,$x,$y,@r) = (ref($_[0]),@_);
577 # objectify is costly, so avoid it
578 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
580 ($self,$x,$y,@r) = objectify(2,@_);
583 return $x->bnan() if ($x->{sign} eq 'NaN' || $y->{sign} eq 'NaN');
586 if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/))
588 return $x->bnan() if $x->is_zero() || $y->is_zero();
589 # result will always be +-inf:
590 # +inf * +/+inf => +inf, -inf * -/-inf => +inf
591 # +inf * -/-inf => -inf, -inf * +/+inf => -inf
592 return $x->binf() if ($x->{sign} =~ /^\+/ && $y->{sign} =~ /^\+/);
593 return $x->binf() if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/);
594 return $x->binf('-');
597 # x== 0 # also: or y == 1 or y == -1
598 return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
601 # According to Knuth, this can be optimized by doing gcd twice (for d and n)
602 # and reducing in one step. This would save us the bnorm() at the end.
605 # - * - = ----- = - = -
608 $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_n});
609 $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_d});
612 $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
614 $x->bnorm()->round(@r);
619 # (dividend: BRAT or num_str, divisor: BRAT or num_str) return
620 # (BRAT,BRAT) (quo,rem) or BRAT (only rem)
623 my ($self,$x,$y,@r) = (ref($_[0]),@_);
624 # objectify is costly, so avoid it
625 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
627 ($self,$x,$y,@r) = objectify(2,@_);
630 return $self->_div_inf($x,$y)
631 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
633 # x== 0 # also: or y == 1 or y == -1
634 return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
636 # XXX TODO: list context, upgrade
637 # According to Knuth, this can be optimized by doing gcd twice (for d and n)
638 # and reducing in one step. This would save us the bnorm() at the end.
644 $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_d});
645 $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_n});
648 $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
650 $x->bnorm()->round(@r);
656 # compute "remainder" (in Perl way) of $x / $y
659 my ($self,$x,$y,@r) = (ref($_[0]),@_);
660 # objectify is costly, so avoid it
661 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
663 ($self,$x,$y,@r) = objectify(2,@_);
666 return $self->_div_inf($x,$y)
667 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
669 return $x if $x->is_zero(); # 0 / 7 = 0, mod 0
671 # compute $x - $y * floor($x/$y), keeping the sign of $x
673 # copy x to u, make it positive and then do a normal division ($u/$y)
674 my $u = bless { sign => '+' }, $self;
675 $u->{_n} = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d} );
676 $u->{_d} = $MBI->_mul( $MBI->_copy($x->{_d}), $y->{_n} );
679 if (! $MBI->_is_one($u->{_d}))
681 $u->{_n} = $MBI->_div($u->{_n},$u->{_d}); # 22/7 => 3/1 w/ truncate
682 # no need to set $u->{_d} to 1, since below we set it to $y->{_d} anyway
685 # now compute $y * $u
686 $u->{_d} = $MBI->_copy($y->{_d}); # 1 * $y->{_d}, see floor above
687 $u->{_n} = $MBI->_mul($u->{_n},$y->{_n});
689 my $xsign = $x->{sign}; $x->{sign} = '+'; # remember sign and make x positive
692 $x->{sign} = $xsign; # put sign back
694 $x->bnorm()->round(@r);
697 ##############################################################################
702 # decrement value (subtract 1)
703 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
705 return $x if $x->{sign} !~ /^[+-]$/; # NaN, inf, -inf
707 if ($x->{sign} eq '-')
709 $x->{_n} = $MBI->_add( $x->{_n}, $x->{_d}); # -5/2 => -7/2
713 if ($MBI->_acmp($x->{_n},$x->{_d}) < 0) # n < d?
716 $x->{_n} = $MBI->_sub( $MBI->_copy($x->{_d}), $x->{_n});
721 $x->{_n} = $MBI->_sub($x->{_n}, $x->{_d}); # 5/2 => 3/2
724 $x->bnorm()->round(@r);
729 # increment value (add 1)
730 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
732 return $x if $x->{sign} !~ /^[+-]$/; # NaN, inf, -inf
734 if ($x->{sign} eq '-')
736 if ($MBI->_acmp($x->{_n},$x->{_d}) < 0)
738 # -1/3 ++ => 2/3 (overflow at 0)
739 $x->{_n} = $MBI->_sub( $MBI->_copy($x->{_d}), $x->{_n});
744 $x->{_n} = $MBI->_sub($x->{_n}, $x->{_d}); # -5/2 => -3/2
749 $x->{_n} = $MBI->_add($x->{_n},$x->{_d}); # 5/2 => 7/2
751 $x->bnorm()->round(@r);
754 ##############################################################################
755 # is_foo methods (the rest is inherited)
759 # return true if arg (BRAT or num_str) is an integer
760 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
762 return 1 if ($x->{sign} =~ /^[+-]$/) && # NaN and +-inf aren't
763 $MBI->_is_one($x->{_d}); # x/y && y != 1 => no integer
769 # return true if arg (BRAT or num_str) is zero
770 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
772 return 1 if $x->{sign} eq '+' && $MBI->_is_zero($x->{_n});
778 # return true if arg (BRAT or num_str) is +1 or -1 if signis given
779 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
781 my $sign = $_[2] || ''; $sign = '+' if $sign ne '-';
783 if ($x->{sign} eq $sign && $MBI->_is_one($x->{_n}) && $MBI->_is_one($x->{_d}));
789 # return true if arg (BFLOAT or num_str) is odd or false if even
790 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
792 return 1 if ($x->{sign} =~ /^[+-]$/) && # NaN & +-inf aren't
793 ($MBI->_is_one($x->{_d}) && $MBI->_is_odd($x->{_n})); # x/2 is not, but 3/1
799 # return true if arg (BINT or num_str) is even or false if odd
800 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
802 return 0 if $x->{sign} !~ /^[+-]$/; # NaN & +-inf aren't
803 return 1 if ($MBI->_is_one($x->{_d}) # x/3 is never
804 && $MBI->_is_even($x->{_n})); # but 4/1 is
808 ##############################################################################
809 # parts() and friends
813 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
816 return Math::BigInt->new($x->{sign}) if ($x->{sign} !~ /^[+-]$/);
818 my $n = Math::BigInt->new($MBI->_str($x->{_n})); $n->{sign} = $x->{sign};
824 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
827 return Math::BigInt->new($x->{sign}) if $x->{sign} eq 'NaN';
829 return Math::BigInt->bone() if $x->{sign} !~ /^[+-]$/;
831 Math::BigInt->new($MBI->_str($x->{_d}));
836 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
838 my $c = 'Math::BigInt';
840 return ($c->bnan(),$c->bnan()) if $x->{sign} eq 'NaN';
841 return ($c->binf(),$c->binf()) if $x->{sign} eq '+inf';
842 return ($c->binf('-'),$c->binf()) if $x->{sign} eq '-inf';
844 my $n = $c->new( $MBI->_str($x->{_n}));
845 $n->{sign} = $x->{sign};
846 my $d = $c->new( $MBI->_str($x->{_d}));
852 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
854 return $nan unless $x->is_int();
855 $MBI->_len($x->{_n}); # length(-123/1) => length(123)
860 my ($self,$x,$n) = ref($_[0]) ? (undef,$_[0],$_[1]) : objectify(1,@_);
862 return $nan unless $x->is_int();
863 $MBI->_digit($x->{_n},$n || 0); # digit(-123/1,2) => digit(123,2)
866 ##############################################################################
867 # special calc routines
871 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
873 return $x if $x->{sign} !~ /^[+-]$/ || # not for NaN, inf
874 $MBI->_is_one($x->{_d}); # 22/1 => 22, 0/1 => 0
876 $x->{_n} = $MBI->_div($x->{_n},$x->{_d}); # 22/7 => 3/1 w/ truncate
877 $x->{_d} = $MBI->_one(); # d => 1
878 $x->{_n} = $MBI->_inc($x->{_n})
879 if $x->{sign} eq '+'; # +22/7 => 4/1
880 $x->{sign} = '+' if $MBI->_is_zero($x->{_n}); # -0 => 0
886 my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
888 return $x if $x->{sign} !~ /^[+-]$/ || # not for NaN, inf
889 $MBI->_is_one($x->{_d}); # 22/1 => 22, 0/1 => 0
891 $x->{_n} = $MBI->_div($x->{_n},$x->{_d}); # 22/7 => 3/1 w/ truncate
892 $x->{_d} = $MBI->_one(); # d => 1
893 $x->{_n} = $MBI->_inc($x->{_n})
894 if $x->{sign} eq '-'; # -22/7 => -4/1
900 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
902 # if $x is not an integer
903 if (($x->{sign} ne '+') || (!$MBI->_is_one($x->{_d})))
908 $x->{_n} = $MBI->_fac($x->{_n});
909 # since _d is 1, we don't need to reduce/norm the result
918 my ($self,$x,$y,@r) = (ref($_[0]),@_);
919 # objectify is costly, so avoid it
920 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
922 ($self,$x,$y,@r) = objectify(2,@_);
925 return $x if $x->{sign} =~ /^[+-]inf$/; # -inf/+inf ** x
926 return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;
927 return $x->bone(@r) if $y->is_zero();
928 return $x->round(@r) if $x->is_one() || $y->is_one();
930 if ($x->{sign} eq '-' && $MBI->_is_one($x->{_n}) && $MBI->_is_one($x->{_d}))
932 # if $x == -1 and odd/even y => +1/-1
933 return $y->is_odd() ? $x->round(@r) : $x->babs()->round(@r);
934 # my Casio FX-5500L has a bug here: -1 ** 2 is -1, but -1 * -1 is 1;
936 # 1 ** -y => 1 / (1 ** |y|)
937 # so do test for negative $y after above's clause
939 return $x->round(@r) if $x->is_zero(); # 0**y => 0 (if not y <= 0)
941 # shortcut if y == 1/N (is then sqrt() respective broot())
942 if ($MBI->_is_one($y->{_n}))
944 return $x->bsqrt(@r) if $MBI->_is_two($y->{_d}); # 1/2 => sqrt
945 return $x->broot($MBI->_str($y->{_d}),@r); # 1/N => root(N)
948 # shortcut y/1 (and/or x/1)
949 if ($MBI->_is_one($y->{_d}))
951 # shortcut for x/1 and y/1
952 if ($MBI->_is_one($x->{_d}))
954 $x->{_n} = $MBI->_pow($x->{_n},$y->{_n}); # x/1 ** y/1 => (x ** y)/1
955 if ($y->{sign} eq '-')
957 # 0.2 ** -3 => 1/(0.2 ** 3)
958 ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n}); # swap
960 # correct sign; + ** + => +
961 if ($x->{sign} eq '-')
963 # - * - => +, - * - * - => -
964 $x->{sign} = '+' if $MBI->_is_even($y->{_n});
966 return $x->round(@r);
969 $x->{_n} = $MBI->_pow($x->{_n},$y->{_n}); # 5/2 ** y/1 => 5 ** y / 2 ** y
970 $x->{_d} = $MBI->_pow($x->{_d},$y->{_n});
971 if ($y->{sign} eq '-')
973 # 0.2 ** -3 => 1/(0.2 ** 3)
974 ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n}); # swap
976 # correct sign; + ** + => +
977 if ($x->{sign} eq '-')
979 # - * - => +, - * - * - => -
980 $x->{sign} = '+' if $MBI->_is_even($y->{_n});
982 return $x->round(@r);
985 # print STDERR "# $x $y\n";
989 # n/d n ______________
990 # a/b = -\/ (a/b) ** d
992 # (a/b) ** n == (a ** n) / (b ** n)
993 $MBI->_pow($x->{_n}, $y->{_n} );
994 $MBI->_pow($x->{_d}, $y->{_n} );
996 return $x->broot($MBI->_str($y->{_d}),@r); # n/d => root(n)
1002 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1004 # objectify is costly, so avoid it
1005 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1007 ($self,$x,$y,@r) = objectify(2,$class,@_);
1011 return $x->bzero() if $x->is_one() && $y->{sign} eq '+';
1014 return $x->bnan() if $x->is_zero() || $x->{sign} ne '+' || $y->{sign} ne '+';
1016 if ($x->is_int() && $y->is_int())
1018 return $self->new($x->as_number()->blog($y->as_number(),@r));
1022 $x->_new_from_float( $x->_as_float()->blog(Math::BigFloat->new("$y"),@r) );
1028 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1030 # objectify is costly, so avoid it
1031 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1033 ($self,$x,$y,@r) = objectify(2,$class,@_);
1036 return $x->binf(@r) if $x->{sign} eq '+inf';
1037 return $x->bzero(@r) if $x->{sign} eq '-inf';
1039 # we need to limit the accuracy to protect against overflow
1041 my ($scale,@params);
1042 ($x,@params) = $x->_find_round_parameters(@r);
1044 # also takes care of the "error in _find_round_parameters?" case
1045 return $x if $x->{sign} eq 'NaN';
1047 # no rounding at all, so must use fallback
1048 if (scalar @params == 0)
1050 # simulate old behaviour
1051 $params[0] = $self->div_scale(); # and round to it as accuracy
1052 $params[1] = undef; # P = undef
1053 $scale = $params[0]+4; # at least four more for proper round
1054 $params[2] = $r[2]; # round mode by caller or undef
1055 $fallback = 1; # to clear a/p afterwards
1059 # the 4 below is empirical, and there might be cases where it's not enough...
1060 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined
1063 return $x->bone(@params) if $x->is_zero();
1065 # See the comments in Math::BigFloat on how this algorithm works.
1066 # Basically we calculate A and B (where B is faculty(N)) so that A/B = e
1068 my $x_org = $x->copy();
1071 # set $x directly from a cached string form
1072 $x->{_n} = $MBI->_new("90933395208605785401971970164779391644753259799242");
1073 $x->{_d} = $MBI->_new("33452526613163807108170062053440751665152000000000");
1078 # compute A and B so that e = A / B.
1080 # After some terms we end up with this, so we use it as a starting point:
1081 my $A = $MBI->_new("90933395208605785401971970164779391644753259799242");
1082 my $F = $MBI->_new(42); my $step = 42;
1084 # Compute how many steps we need to take to get $A and $B sufficiently big
1085 my $steps = Math::BigFloat::_len_to_steps($scale - 4);
1086 # print STDERR "# Doing $steps steps for ", $scale-4, " digits\n";
1087 while ($step++ <= $steps)
1089 # calculate $a * $f + 1
1090 $A = $MBI->_mul($A, $F);
1091 $A = $MBI->_inc($A);
1093 $F = $MBI->_inc($F);
1095 # compute $B as factorial of $steps (this is faster than doing it manually)
1096 my $B = $MBI->_fac($MBI->_new($steps));
1098 # print "A ", $MBI->_str($A), "\nB ", $MBI->_str($B), "\n";
1105 # $x contains now an estimate of e, with some surplus digits, so we can round
1106 if (!$x_org->is_one())
1108 # raise $x to the wanted power and round it in one step:
1109 $x->bpow($x_org, @params);
1113 # else just round the already computed result
1114 delete $x->{_a}; delete $x->{_p};
1115 # shortcut to not run through _find_round_parameters again
1116 if (defined $params[0])
1118 $x->bround($params[0],$params[2]); # then round accordingly
1122 $x->bfround($params[1],$params[2]); # then round accordingly
1127 # clear a/p after round, since user did not request it
1128 delete $x->{_a}; delete $x->{_p};
1137 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1139 # objectify is costly, so avoid it
1140 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1142 ($self,$x,$y,@r) = objectify(2,$class,@_);
1146 $x->_new_from_float( $x->_as_float()->bnok(Math::BigFloat->new("$y"),@r) );
1149 sub _float_from_part
1153 my $f = Math::BigFloat->bzero();
1154 $f->{_m} = $MBI->_copy($x);
1155 $f->{_e} = $MBI->_zero();
1164 local $Math::BigFloat::upgrade = undef;
1165 local $Math::BigFloat::accuracy = undef;
1166 local $Math::BigFloat::precision = undef;
1167 # 22/7 => 3.142857143..
1169 my $a = $x->accuracy() || 0;
1170 if ($a != 0 || !$MBI->_is_one($x->{_d}))
1173 return scalar Math::BigFloat->new($x->{sign} . $MBI->_str($x->{_n}))->bdiv( $MBI->_str($x->{_d}), $x->accuracy());
1176 Math::BigFloat->new($x->{sign} . $MBI->_str($x->{_n}));
1182 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1183 # objectify is costly, so avoid it
1184 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1186 ($self,$x,$y,@r) = objectify(2,@_);
1189 if ($x->is_int() && $y->is_int())
1191 return $self->new($x->as_number()->broot($y->as_number(),@r));
1195 $x->_new_from_float( $x->_as_float()->broot($y->_as_float(),@r) )->bnorm()->bround(@r);
1201 my ($self,$x,$y,$m,@r) = (ref($_[0]),@_);
1202 # objectify is costly, so avoid it
1203 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1205 ($self,$x,$y,$m,@r) = objectify(3,@_);
1208 # $x or $y or $m are NaN or +-inf => NaN
1210 if $x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/ ||
1211 $m->{sign} !~ /^[+-]$/;
1213 if ($x->is_int() && $y->is_int() && $m->is_int())
1215 return $self->new($x->as_number()->bmodpow($y->as_number(),$m,@r));
1218 warn ("bmodpow() not fully implemented");
1225 my ($self,$x,$y,@r) = (ref($_[0]),@_);
1226 # objectify is costly, so avoid it
1227 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1229 ($self,$x,$y,@r) = objectify(2,@_);
1232 # $x or $y are NaN or +-inf => NaN
1234 if $x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/;
1236 if ($x->is_int() && $y->is_int())
1238 return $self->new($x->as_number()->bmodinv($y->as_number(),@r));
1241 warn ("bmodinv() not fully implemented");
1247 my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
1249 return $x->bnan() if $x->{sign} !~ /^[+]/; # NaN, -inf or < 0
1250 return $x if $x->{sign} eq '+inf'; # sqrt(inf) == inf
1251 return $x->round(@r) if $x->is_zero() || $x->is_one();
1253 local $Math::BigFloat::upgrade = undef;
1254 local $Math::BigFloat::downgrade = undef;
1255 local $Math::BigFloat::precision = undef;
1256 local $Math::BigFloat::accuracy = undef;
1257 local $Math::BigInt::upgrade = undef;
1258 local $Math::BigInt::precision = undef;
1259 local $Math::BigInt::accuracy = undef;
1261 $x->{_n} = _float_from_part( $x->{_n} )->bsqrt();
1262 $x->{_d} = _float_from_part( $x->{_d} )->bsqrt();
1264 # XXX TODO: we probably can optimze this:
1266 # if sqrt(D) was not integer
1267 if ($x->{_d}->{_es} ne '+')
1269 $x->{_n}->blsft($x->{_d}->exponent()->babs(),10); # 7.1/4.51 => 7.1/45.1
1270 $x->{_d} = $MBI->_copy( $x->{_d}->{_m} ); # 7.1/45.1 => 71/45.1
1272 # if sqrt(N) was not integer
1273 if ($x->{_n}->{_es} ne '+')
1275 $x->{_d}->blsft($x->{_n}->exponent()->babs(),10); # 71/45.1 => 710/45.1
1276 $x->{_n} = $MBI->_copy( $x->{_n}->{_m} ); # 710/45.1 => 710/451
1279 # convert parts to $MBI again
1280 $x->{_n} = $MBI->_lsft( $MBI->_copy( $x->{_n}->{_m} ), $x->{_n}->{_e}, 10)
1281 if ref($x->{_n}) ne $MBI && ref($x->{_n}) ne 'ARRAY';
1282 $x->{_d} = $MBI->_lsft( $MBI->_copy( $x->{_d}->{_m} ), $x->{_d}->{_e}, 10)
1283 if ref($x->{_d}) ne $MBI && ref($x->{_d}) ne 'ARRAY';
1285 $x->bnorm()->round(@r);
1290 my ($self,$x,$y,$b,@r) = objectify(3,@_);
1292 $b = 2 unless defined $b;
1293 $b = $self->new($b) unless ref ($b);
1294 $x->bmul( $b->copy()->bpow($y), @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->bdiv( $b->copy()->bpow($y), @r);
1308 ##############################################################################
1326 ##############################################################################
1331 # compare two signed numbers
1334 my ($self,$x,$y) = (ref($_[0]),@_);
1335 # objectify is costly, so avoid it
1336 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1338 ($self,$x,$y) = objectify(2,@_);
1341 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
1343 # handle +-inf and NaN
1344 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1345 return 0 if $x->{sign} eq $y->{sign} && $x->{sign} =~ /^[+-]inf$/;
1346 return +1 if $x->{sign} eq '+inf';
1347 return -1 if $x->{sign} eq '-inf';
1348 return -1 if $y->{sign} eq '+inf';
1351 # check sign for speed first
1352 return 1 if $x->{sign} eq '+' && $y->{sign} eq '-'; # does also 0 <=> -y
1353 return -1 if $x->{sign} eq '-' && $y->{sign} eq '+'; # does also -x <=> 0
1356 my $xz = $MBI->_is_zero($x->{_n});
1357 my $yz = $MBI->_is_zero($y->{_n});
1358 return 0 if $xz && $yz; # 0 <=> 0
1359 return -1 if $xz && $y->{sign} eq '+'; # 0 <=> +y
1360 return 1 if $yz && $x->{sign} eq '+'; # +x <=> 0
1362 my $t = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d});
1363 my $u = $MBI->_mul( $MBI->_copy($y->{_n}), $x->{_d});
1365 my $cmp = $MBI->_acmp($t,$u); # signs are equal
1366 $cmp = -$cmp if $x->{sign} eq '-'; # both are '-' => reverse
1372 # compare two numbers (as unsigned)
1375 my ($self,$x,$y) = (ref($_[0]),@_);
1376 # objectify is costly, so avoid it
1377 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
1379 ($self,$x,$y) = objectify(2,$class,@_);
1382 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
1384 # handle +-inf and NaN
1385 return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1386 return 0 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} =~ /^[+-]inf$/;
1387 return 1 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} !~ /^[+-]inf$/;
1391 my $t = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d});
1392 my $u = $MBI->_mul( $MBI->_copy($y->{_n}), $x->{_d});
1393 $MBI->_acmp($t,$u); # ignore signs
1396 ##############################################################################
1397 # output conversation
1401 # convert 17/8 => float (aka 2.125)
1402 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1404 return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, NaN, etc
1407 my $neg = ''; $neg = '-' if $x->{sign} eq '-';
1408 return $neg . $MBI->_num($x->{_n}) if $MBI->_is_one($x->{_d});
1410 $x->_as_float()->numify() + 0.0;
1415 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1418 return Math::BigInt->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
1420 my $u = Math::BigInt->bzero();
1421 $u->{sign} = $x->{sign};
1422 $u->{value} = $MBI->_div( $MBI->_copy($x->{_n}), $x->{_d}); # 22/7 => 3
1428 # return N/D as Math::BigFloat
1431 my ($self,$x,@r) = (ref($_[0]),@_);
1432 # objectify is costly, so avoid it
1433 ($self,$x,@r) = objectify(1,$class,@_) unless ref $_[0];
1436 return Math::BigFloat->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
1438 my $u = Math::BigFloat->bzero();
1439 $u->{sign} = $x->{sign};
1441 $u->{_m} = $MBI->_copy($x->{_n});
1442 $u->{_e} = $MBI->_zero();
1443 $u->bdiv( $MBI->_str($x->{_d}), @r);
1450 my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
1452 return $x unless $x->is_int();
1454 my $s = $x->{sign}; $s = '' if $s eq '+';
1455 $s . $MBI->_as_bin($x->{_n});
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_hex($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_oct($x->{_n});
1478 ##############################################################################
1501 push @parts, Math::BigInt->from_oct($c);
1503 $class->new ( @parts );
1506 ##############################################################################
1513 my $lib = ''; my @a;
1516 for ( my $i = 0; $i < $l ; $i++)
1518 if ( $_[$i] eq ':constant' )
1520 # this rest causes overlord er load to step in
1521 overload::constant float => sub { $self->new(shift); };
1523 # elsif ($_[$i] eq 'upgrade')
1525 # # this causes upgrading
1526 # $upgrade = $_[$i+1]; # or undef to disable
1529 elsif ($_[$i] eq 'downgrade')
1531 # this causes downgrading
1532 $downgrade = $_[$i+1]; # or undef to disable
1535 elsif ($_[$i] =~ /^(lib|try|only)\z/)
1537 $lib = $_[$i+1] || ''; # default Calc
1538 $try = $1; # lib, try or only
1541 elsif ($_[$i] eq 'with')
1543 # this argument is no longer used
1544 #$MBI = $_[$i+1] || 'Math::BigInt::Calc'; # default Math::BigInt::Calc
1552 require Math::BigInt;
1554 # let use Math::BigInt lib => 'GMP'; use Math::BigRat; still have GMP
1557 my @c = split /\s*,\s*/, $lib;
1560 $_ =~ tr/a-zA-Z0-9://cd; # limit to sane characters
1562 $lib = join(",", @c);
1564 my @import = ('objectify');
1565 push @import, $try => $lib if $lib ne '';
1567 # MBI already loaded, so feed it our lib arguments
1568 Math::BigInt->import( @import );
1570 $MBI = Math::BigFloat->config()->{lib};
1572 # register us with MBI to get notified of future lib changes
1573 Math::BigInt::_register_callback( $self, sub { $MBI = $_[0]; } );
1575 # any non :constant stuff is handled by our parent, Exporter (loaded
1576 # by Math::BigFloat, even if @_ is empty, to give it a chance
1577 $self->SUPER::import(@a); # for subclasses
1578 $self->export_to_level(1,$self,@a); # need this, too
1587 Math::BigRat - Arbitrary big rational numbers
1593 my $x = Math::BigRat->new('3/7'); $x += '5/9';
1595 print $x->bstr(),"\n";
1598 my $y = Math::BigRat->new('inf');
1599 print "$y ", ($y->is_inf ? 'is' : 'is not') , " infinity\n";
1601 my $z = Math::BigRat->new(144); $z->bsqrt();
1605 Math::BigRat complements Math::BigInt and Math::BigFloat by providing support
1606 for arbitrary big rational numbers.
1610 You can change the underlying module that does the low-level
1611 math operations by using:
1613 use Math::BigRat try => 'GMP';
1615 Note: This needs Math::BigInt::GMP installed.
1617 The following would first try to find Math::BigInt::Foo, then
1618 Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
1620 use Math::BigRat try => 'Foo,Math::BigInt::Bar';
1622 If you want to get warned when the fallback occurs, replace "try" with
1625 use Math::BigRat lib => 'Foo,Math::BigInt::Bar';
1627 If you want the code to die instead, replace "try" with
1630 use Math::BigRat only => 'Foo,Math::BigInt::Bar';
1634 Any methods not listed here are derived from Math::BigFloat (or
1635 Math::BigInt), so make sure you check these two modules for further
1640 $x = Math::BigRat->new('1/3');
1642 Create a new Math::BigRat object. Input can come in various forms:
1644 $x = Math::BigRat->new(123); # scalars
1645 $x = Math::BigRat->new('inf'); # infinity
1646 $x = Math::BigRat->new('123.3'); # float
1647 $x = Math::BigRat->new('1/3'); # simple string
1648 $x = Math::BigRat->new('1 / 3'); # spaced
1649 $x = Math::BigRat->new('1 / 0.1'); # w/ floats
1650 $x = Math::BigRat->new(Math::BigInt->new(3)); # BigInt
1651 $x = Math::BigRat->new(Math::BigFloat->new('3.1')); # BigFloat
1652 $x = Math::BigRat->new(Math::BigInt::Lite->new('2')); # BigLite
1654 # You can also give D and N as different objects:
1655 $x = Math::BigRat->new(
1656 Math::BigInt->new(-123),
1657 Math::BigInt->new(7),
1662 $n = $x->numerator();
1664 Returns a copy of the numerator (the part above the line) as signed BigInt.
1666 =head2 denominator()
1668 $d = $x->denominator();
1670 Returns a copy of the denominator (the part under the line) as positive BigInt.
1674 ($n,$d) = $x->parts();
1676 Return a list consisting of (signed) numerator and (unsigned) denominator as
1681 my $y = $x->numify();
1683 Returns the object as a scalar. This will lose some data if the object
1684 cannot be represented by a normal Perl scalar (integer or float), so
1685 use L<as_int()> or L<as_float()> instead.
1687 This routine is automatically used whenever a scalar is required:
1689 my $x = Math::BigRat->new('3/1');
1691 $y = $array[$x]; # set $y to 3
1693 =head2 as_int()/as_number()
1695 $x = Math::BigRat->new('13/7');
1696 print $x->as_int(),"\n"; # '1'
1698 Returns a copy of the object as BigInt, truncated to an integer.
1700 C<as_number()> is an alias for C<as_int()>.
1704 $x = Math::BigRat->new('13/7');
1705 print $x->as_float(),"\n"; # '1'
1707 $x = Math::BigRat->new('2/3');
1708 print $x->as_float(5),"\n"; # '0.66667'
1710 Returns a copy of the object as BigFloat, preserving the
1711 accuracy as wanted, or the default of 40 digits.
1713 This method was added in v0.22 of Math::BigRat (April 2008).
1717 $x = Math::BigRat->new('13');
1718 print $x->as_hex(),"\n"; # '0xd'
1720 Returns the BigRat as hexadecimal string. Works only for integers.
1724 $x = Math::BigRat->new('13');
1725 print $x->as_bin(),"\n"; # '0x1101'
1727 Returns the BigRat as binary string. Works only for integers.
1731 $x = Math::BigRat->new('13');
1732 print $x->as_oct(),"\n"; # '015'
1734 Returns the BigRat as octal string. Works only for integers.
1736 =head2 from_hex()/from_bin()/from_oct()
1738 my $h = Math::BigRat->from_hex('0x10');
1739 my $b = Math::BigRat->from_bin('0b10000000');
1740 my $o = Math::BigRat->from_oct('020');
1742 Create a BigRat from an hexadecimal, binary or octal number
1747 $len = $x->length();
1749 Return the length of $x in digitis for integer values.
1753 print Math::BigRat->new('123/1')->digit(1); # 1
1754 print Math::BigRat->new('123/1')->digit(-1); # 3
1756 Return the N'ths digit from X when X is an integer value.
1762 Reduce the number to the shortest form. This routine is called
1763 automatically whenever it is needed.
1769 Calculates the factorial of $x. For instance:
1771 print Math::BigRat->new('3/1')->bfac(),"\n"; # 1*2*3
1772 print Math::BigRat->new('5/1')->bfac(),"\n"; # 1*2*3*4*5
1774 Works currently only for integers.
1776 =head2 bround()/round()/bfround()
1778 Are not yet implemented.
1783 my $x = Math::BigRat->new('7/4');
1784 my $y = Math::BigRat->new('4/3');
1787 Set $x to the remainder of the division of $x by $y.
1793 Used to negate the object in-place.
1797 print "$x is 1\n" if $x->is_one();
1799 Return true if $x is exactly one, otherwise false.
1803 print "$x is 0\n" if $x->is_zero();
1805 Return true if $x is exactly zero, otherwise false.
1807 =head2 is_pos()/is_positive()
1809 print "$x is >= 0\n" if $x->is_positive();
1811 Return true if $x is positive (greater than or equal to zero), otherwise
1812 false. Please note that '+inf' is also positive, while 'NaN' and '-inf' aren't.
1814 C<is_positive()> is an alias for C<is_pos()>.
1816 =head2 is_neg()/is_negative()
1818 print "$x is < 0\n" if $x->is_negative();
1820 Return true if $x is negative (smaller than zero), otherwise false. Please
1821 note that '-inf' is also negative, while 'NaN' and '+inf' aren't.
1823 C<is_negative()> is an alias for C<is_neg()>.
1827 print "$x is an integer\n" if $x->is_int();
1829 Return true if $x has a denominator of 1 (e.g. no fraction parts), otherwise
1830 false. Please note that '-inf', 'inf' and 'NaN' aren't integer.
1834 print "$x is odd\n" if $x->is_odd();
1836 Return true if $x is odd, otherwise false.
1840 print "$x is even\n" if $x->is_even();
1842 Return true if $x is even, otherwise false.
1848 Set $x to the next bigger integer value (e.g. truncate the number to integer
1849 and then increment it by one).
1855 Truncate $x to an integer value.
1861 Calculate the square root of $x.
1867 Calculate the N'th root of $x.
1869 =head2 badd()/bmul()/bsub()/bdiv()/bdec()/binc()
1871 Please see the documentation in L<Math::BigInt>.
1877 Makes a deep copy of the object.
1879 Please see the documentation in L<Math::BigInt> for further details.
1881 =head2 bstr()/bsstr()
1883 my $x = Math::BigInt->new('8/4');
1884 print $x->bstr(),"\n"; # prints 1/2
1885 print $x->bsstr(),"\n"; # prints 1/2
1887 Return a string representating this object.
1889 =head2 bacmp()/bcmp()
1891 Used to compare numbers.
1893 Please see the documentation in L<Math::BigInt> for further details.
1895 =head2 blsft()/brsft()
1897 Used to shift numbers left/right.
1899 Please see the documentation in L<Math::BigInt> for further details.
1907 Please see the documentation in L<Math::BigInt> for further details.
1911 $x->bexp($accuracy); # calculate e ** X
1913 Calculates two integers A and B so that A/B is equal to C<e ** $x>, where C<e> is
1916 This method was added in v0.20 of Math::BigRat (May 2007).
1922 $x->bnok($y); # x over y (binomial coefficient n over k)
1924 Calculates the binomial coefficient n over k, also called the "choose"
1925 function. The result is equivalent to:
1931 This method was added in v0.20 of Math::BigRat (May 2007).
1937 print Dumper ( Math::BigRat->config() );
1938 print Math::BigRat->config()->{lib},"\n";
1940 Returns a hash containing the configuration, e.g. the version number, lib
1941 loaded etc. The following hash keys are currently filled in with the
1942 appropriate information.
1944 key RO/RW Description
1946 ============================================================
1947 lib RO Name of the Math library
1949 lib_version RO Version of 'lib'
1951 class RO The class of config you just called
1953 version RO version number of the class you used
1955 upgrade RW To which class numbers are upgraded
1957 downgrade RW To which class numbers are downgraded
1959 precision RW Global precision
1961 accuracy RW Global accuracy
1963 round_mode RW Global round mode
1965 div_scale RW Fallback accuracy for div
1967 trap_nan RW Trap creation of NaN (undef = no)
1969 trap_inf RW Trap creation of +inf/-inf (undef = no)
1972 By passing a reference to a hash you may set the configuration values. This
1973 works only for values that a marked with a C<RW> above, anything else is
1978 This is an internal routine that turns scalars into objects.
1982 Some things are not yet implemented, or only implemented half-way:
1986 =item inf handling (partial)
1988 =item NaN handling (partial)
1990 =item rounding (not implemented except for bceil/bfloor)
1992 =item $x ** $y where $y is not an integer
1994 =item bmod(), blog(), bmodinv() and bmodpow() (partial)
2000 This program is free software; you may redistribute it and/or modify it under
2001 the same terms as Perl itself.
2005 L<Math::BigFloat> and L<Math::Big> as well as L<Math::BigInt::BitVect>,
2006 L<Math::BigInt::Pari> and L<Math::BigInt::GMP>.
2008 See L<http://search.cpan.org/search?dist=bignum> for a way to use
2011 The package at L<http://search.cpan.org/search?dist=Math%3A%3ABigRat>
2012 may contain more documentation and examples as well as testcases.
2016 (C) by Tels L<http://bloodgate.com/> 2001 - 2009.
2018 Currently maintained by Jonathan "Duke" Leto <jonathan@leto.net> L<http://leto.net>