home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / perl / 5.10.0 / Math / BigRat.pm < prev    next >
Encoding:
Perl POD Document  |  2009-06-26  |  50.3 KB  |  1,975 lines

  1.  
  2. #
  3. # "Tax the rat farms." - Lord Vetinari
  4. #
  5.  
  6. # The following hash values are used:
  7. #   sign : +,-,NaN,+inf,-inf
  8. #   _d   : denominator
  9. #   _n   : numeraotr (value = _n/_d)
  10. #   _a   : accuracy
  11. #   _p   : precision
  12. # You should not look at the innards of a BigRat - use the methods for this.
  13.  
  14. package Math::BigRat;
  15.  
  16. # anythig older is untested, and unlikely to work
  17. use 5.006;
  18. use strict;
  19.  
  20. use Math::BigFloat;
  21. use vars qw($VERSION @ISA $upgrade $downgrade
  22.             $accuracy $precision $round_mode $div_scale $_trap_nan $_trap_inf);
  23.  
  24. @ISA = qw(Math::BigFloat);
  25.  
  26. $VERSION = '0.21';
  27.  
  28. use overload;            # inherit overload from Math::BigFloat
  29.  
  30. BEGIN
  31.   { 
  32.   *objectify = \&Math::BigInt::objectify;     # inherit this from BigInt
  33.   *AUTOLOAD = \&Math::BigFloat::AUTOLOAD;    # can't inherit AUTOLOAD
  34.   # we inherit these from BigFloat because currently it is not possible
  35.   # that MBF has a different $MBI variable than we, because MBF also uses
  36.   # Math::BigInt::config->('lib'); (there is always only one library loaded)
  37.   *_e_add = \&Math::BigFloat::_e_add;
  38.   *_e_sub = \&Math::BigFloat::_e_sub;
  39.   *as_int = \&as_number;
  40.   *is_pos = \&is_positive;
  41.   *is_neg = \&is_negative;
  42.   }
  43.  
  44. ##############################################################################
  45. # Global constants and flags. Access these only via the accessor methods!
  46.  
  47. $accuracy = $precision = undef;
  48. $round_mode = 'even';
  49. $div_scale = 40;
  50. $upgrade = undef;
  51. $downgrade = undef;
  52.  
  53. # These are internally, and not to be used from the outside at all!
  54.  
  55. $_trap_nan = 0;                         # are NaNs ok? set w/ config()
  56. $_trap_inf = 0;                         # are infs ok? set w/ config()
  57.  
  58. # the package we are using for our private parts, defaults to:
  59. # Math::BigInt->config()->{lib}
  60. my $MBI = 'Math::BigInt::Calc';
  61.  
  62. my $nan = 'NaN';
  63. my $class = 'Math::BigRat';
  64.  
  65. sub isa
  66.   {
  67.   return 0 if $_[1] =~ /^Math::Big(Int|Float)/;        # we aren't
  68.   UNIVERSAL::isa(@_);
  69.   }
  70.  
  71. ##############################################################################
  72.  
  73. sub _new_from_float
  74.   {
  75.   # turn a single float input into a rational number (like '0.1')
  76.   my ($self,$f) = @_;
  77.  
  78.   return $self->bnan() if $f->is_nan();
  79.   return $self->binf($f->{sign}) if $f->{sign} =~ /^[+-]inf$/;
  80.  
  81.   $self->{_n} = $MBI->_copy( $f->{_m} );    # mantissa
  82.   $self->{_d} = $MBI->_one();
  83.   $self->{sign} = $f->{sign} || '+';
  84.   if ($f->{_es} eq '-')
  85.     {
  86.     # something like Math::BigRat->new('0.1');
  87.     # 1 / 1 => 1/10
  88.     $MBI->_lsft ( $self->{_d}, $f->{_e} ,10);    
  89.     }
  90.   else
  91.     {
  92.     # something like Math::BigRat->new('10');
  93.     # 1 / 1 => 10/1
  94.     $MBI->_lsft ( $self->{_n}, $f->{_e} ,10) unless 
  95.       $MBI->_is_zero($f->{_e});    
  96.     }
  97.   $self;
  98.   }
  99.  
  100. sub new
  101.   {
  102.   # create a Math::BigRat
  103.   my $class = shift;
  104.  
  105.   my ($n,$d) = @_;
  106.  
  107.   my $self = { }; bless $self,$class;
  108.  
  109.   # input like (BigInt) or (BigFloat):
  110.   if ((!defined $d) && (ref $n) && (!$n->isa('Math::BigRat')))
  111.     {
  112.     if ($n->isa('Math::BigFloat'))
  113.       {
  114.       $self->_new_from_float($n);
  115.       }
  116.     if ($n->isa('Math::BigInt'))
  117.       {
  118.       # TODO: trap NaN, inf
  119.       $self->{_n} = $MBI->_copy($n->{value});        # "mantissa" = N
  120.       $self->{_d} = $MBI->_one();            # d => 1
  121.       $self->{sign} = $n->{sign};
  122.       }
  123.     if ($n->isa('Math::BigInt::Lite'))
  124.       {
  125.       # TODO: trap NaN, inf
  126.       $self->{sign} = '+'; $self->{sign} = '-' if $$n < 0;
  127.       $self->{_n} = $MBI->_new(abs($$n));        # "mantissa" = N
  128.       $self->{_d} = $MBI->_one();            # d => 1
  129.       }
  130.     return $self->bnorm();                # normalize (120/1 => 12/10)
  131.     }
  132.  
  133.   # input like (BigInt,BigInt) or (BigLite,BigLite):
  134.   if (ref($d) && ref($n))
  135.     {
  136.     # do N first (for $self->{sign}):
  137.     if ($n->isa('Math::BigInt'))
  138.       {
  139.       # TODO: trap NaN, inf
  140.       $self->{_n} = $MBI->_copy($n->{value});        # "mantissa" = N
  141.       $self->{sign} = $n->{sign};
  142.       }
  143.     elsif ($n->isa('Math::BigInt::Lite'))
  144.       {
  145.       # TODO: trap NaN, inf
  146.       $self->{sign} = '+'; $self->{sign} = '-' if $$n < 0;
  147.       $self->{_n} = $MBI->_new(abs($$n));        # "mantissa" = $n
  148.       }
  149.     else
  150.       {
  151.       require Carp;
  152.       Carp::croak(ref($n) . " is not a recognized object format for Math::BigRat->new");
  153.       }
  154.     # now D:
  155.     if ($d->isa('Math::BigInt'))
  156.       {
  157.       # TODO: trap NaN, inf
  158.       $self->{_d} = $MBI->_copy($d->{value});        # "mantissa" = D
  159.       # +/+ or -/- => +, +/- or -/+ => -
  160.       $self->{sign} = $d->{sign} ne $self->{sign} ? '-' : '+';
  161.       }
  162.     elsif ($d->isa('Math::BigInt::Lite'))
  163.       {
  164.       # TODO: trap NaN, inf
  165.       $self->{_d} = $MBI->_new(abs($$d));        # "mantissa" = D
  166.       my $ds = '+'; $ds = '-' if $$d < 0;
  167.       # +/+ or -/- => +, +/- or -/+ => -
  168.       $self->{sign} = $ds ne $self->{sign} ? '-' : '+';
  169.       }
  170.     else
  171.       {
  172.       require Carp;
  173.       Carp::croak(ref($d) . " is not a recognized object format for Math::BigRat->new");
  174.       }
  175.     return $self->bnorm();                # normalize (120/1 => 12/10)
  176.     }
  177.   return $n->copy() if ref $n;                # already a BigRat
  178.  
  179.   if (!defined $n)
  180.     {
  181.     $self->{_n} = $MBI->_zero();            # undef => 0
  182.     $self->{_d} = $MBI->_one();
  183.     $self->{sign} = '+';
  184.     return $self;
  185.     }
  186.  
  187.   # string input with / delimiter
  188.   if ($n =~ /\s*\/\s*/)
  189.     {
  190.     return $class->bnan() if $n =~ /\/.*\//;    # 1/2/3 isn't valid
  191.     return $class->bnan() if $n =~ /\/\s*$/;    # 1/ isn't valid
  192.     ($n,$d) = split (/\//,$n);
  193.     # try as BigFloats first
  194.     if (($n =~ /[\.eE]/) || ($d =~ /[\.eE]/))
  195.       {
  196.       local $Math::BigFloat::accuracy = undef;
  197.       local $Math::BigFloat::precision = undef;
  198.  
  199.       # one of them looks like a float 
  200.       my $nf = Math::BigFloat->new($n,undef,undef);
  201.       $self->{sign} = '+';
  202.       return $self->bnan() if $nf->is_nan();
  203.  
  204.       $self->{_n} = $MBI->_copy( $nf->{_m} );    # get mantissa
  205.  
  206.       # now correct $self->{_n} due to $n
  207.       my $f = Math::BigFloat->new($d,undef,undef);
  208.       return $self->bnan() if $f->is_nan();
  209.       $self->{_d} = $MBI->_copy( $f->{_m} );
  210.  
  211.       # calculate the difference between nE and dE
  212.       my $diff_e = $nf->exponent()->bsub( $f->exponent);
  213.       if ($diff_e->is_negative())
  214.     {
  215.         # < 0: mul d with it
  216.         $MBI->_lsft( $self->{_d}, $MBI->_new( $diff_e->babs()), 10);
  217.     }
  218.       elsif (!$diff_e->is_zero())
  219.         {
  220.         # > 0: mul n with it
  221.         $MBI->_lsft( $self->{_n}, $MBI->_new( $diff_e), 10);
  222.         }
  223.       }
  224.     else
  225.       {
  226.       # both d and n look like (big)ints
  227.  
  228.       $self->{sign} = '+';                    # no sign => '+'
  229.       $self->{_n} = undef;
  230.       $self->{_d} = undef;
  231.       if ($n =~ /^([+-]?)0*([0-9]+)\z/)                # first part ok?
  232.     {
  233.     $self->{sign} = $1 || '+';                # no sign => '+'
  234.     $self->{_n} = $MBI->_new($2 || 0);
  235.         }
  236.  
  237.       if ($d =~ /^([+-]?)0*([0-9]+)\z/)                # second part ok?
  238.     {
  239.     $self->{sign} =~ tr/+-/-+/ if ($1 || '') eq '-';    # negate if second part neg.
  240.     $self->{_d} = $MBI->_new($2 || 0);
  241.         }
  242.  
  243.       if (!defined $self->{_n} || !defined $self->{_d})
  244.     {
  245.         $d = Math::BigInt->new($d,undef,undef) unless ref $d;
  246.         $n = Math::BigInt->new($n,undef,undef) unless ref $n;
  247.  
  248.         if ($n->{sign} =~ /^[+-]$/ && $d->{sign} =~ /^[+-]$/)
  249.       { 
  250.       # both parts are ok as integers (wierd things like ' 1e0'
  251.           $self->{_n} = $MBI->_copy($n->{value});
  252.           $self->{_d} = $MBI->_copy($d->{value});
  253.           $self->{sign} = $n->{sign};
  254.           $self->{sign} =~ tr/+-/-+/ if $d->{sign} eq '-';    # -1/-2 => 1/2
  255.           return $self->bnorm();
  256.       }
  257.  
  258.         $self->{sign} = '+';                    # a default sign
  259.         return $self->bnan() if $n->is_nan() || $d->is_nan();
  260.  
  261.     # handle inf cases:
  262.         if ($n->is_inf() || $d->is_inf())
  263.       {
  264.       if ($n->is_inf())
  265.         {
  266.         return $self->bnan() if $d->is_inf();        # both are inf => NaN
  267.         my $s = '+';         # '+inf/+123' or '-inf/-123'
  268.         $s = '-' if substr($n->{sign},0,1) ne $d->{sign};
  269.         # +-inf/123 => +-inf
  270.         return $self->binf($s);
  271.         }
  272.           # 123/inf => 0
  273.           return $self->bzero();
  274.       }
  275.     }
  276.       }
  277.  
  278.     return $self->bnorm();
  279.     }
  280.  
  281.   # simple string input
  282.   if (($n =~ /[\.eE]/))
  283.     {
  284.     # looks like a float, quacks like a float, so probably is a float
  285.     $self->{sign} = 'NaN';
  286.     local $Math::BigFloat::accuracy = undef;
  287.     local $Math::BigFloat::precision = undef;
  288.     $self->_new_from_float(Math::BigFloat->new($n,undef,undef));
  289.     }
  290.   else
  291.     {
  292.     # for simple forms, use $MBI directly
  293.     if ($n =~ /^([+-]?)0*([0-9]+)\z/)
  294.       {
  295.       $self->{sign} = $1 || '+';
  296.       $self->{_n} = $MBI->_new($2 || 0);
  297.       $self->{_d} = $MBI->_one();
  298.       }
  299.     else
  300.       {
  301.       my $n = Math::BigInt->new($n,undef,undef);
  302.       $self->{_n} = $MBI->_copy($n->{value});
  303.       $self->{_d} = $MBI->_one();
  304.       $self->{sign} = $n->{sign};
  305.       return $self->bnan() if $self->{sign} eq 'NaN';
  306.       return $self->binf($self->{sign}) if $self->{sign} =~ /^[+-]inf$/;
  307.       }
  308.     }
  309.   $self->bnorm();
  310.   }
  311.  
  312. sub copy
  313.   {
  314.   # if two arguments, the first one is the class to "swallow" subclasses
  315.   my ($c,$x) = @_;
  316.  
  317.   if (scalar @_ == 1)
  318.     {
  319.     $x = $_[0];
  320.     $c = ref($x);
  321.     }
  322.   return unless ref($x); # only for objects
  323.  
  324.   my $self = bless {}, $c;
  325.  
  326.   $self->{sign} = $x->{sign};
  327.   $self->{_d} = $MBI->_copy($x->{_d});
  328.   $self->{_n} = $MBI->_copy($x->{_n});
  329.   $self->{_a} = $x->{_a} if defined $x->{_a};
  330.   $self->{_p} = $x->{_p} if defined $x->{_p};
  331.   $self;
  332.   }
  333.  
  334. ##############################################################################
  335.  
  336. sub config
  337.   {
  338.   # return (later set?) configuration data as hash ref
  339.   my $class = shift || 'Math::BigRat';
  340.  
  341.   if (@_ == 1 && ref($_[0]) ne 'HASH')
  342.     {
  343.     my $cfg = $class->SUPER::config();
  344.     return $cfg->{$_[0]};
  345.     }
  346.  
  347.   my $cfg = $class->SUPER::config(@_);
  348.  
  349.   # now we need only to override the ones that are different from our parent
  350.   $cfg->{class} = $class;
  351.   $cfg->{with} = $MBI;
  352.   $cfg;
  353.   }
  354.  
  355. ##############################################################################
  356.  
  357. sub bstr
  358.   {
  359.   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
  360.  
  361.   if ($x->{sign} !~ /^[+-]$/)        # inf, NaN etc
  362.     {
  363.     my $s = $x->{sign}; $s =~ s/^\+//;     # +inf => inf
  364.     return $s;
  365.     }
  366.  
  367.   my $s = ''; $s = $x->{sign} if $x->{sign} ne '+';    # '+3/2' => '3/2'
  368.  
  369.   return $s . $MBI->_str($x->{_n}) if $MBI->_is_one($x->{_d});
  370.   $s . $MBI->_str($x->{_n}) . '/' . $MBI->_str($x->{_d});
  371.   }
  372.  
  373. sub bsstr
  374.   {
  375.   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
  376.  
  377.   if ($x->{sign} !~ /^[+-]$/)        # inf, NaN etc
  378.     {
  379.     my $s = $x->{sign}; $s =~ s/^\+//;     # +inf => inf
  380.     return $s;
  381.     }
  382.   
  383.   my $s = ''; $s = $x->{sign} if $x->{sign} ne '+';    # +3 vs 3
  384.   $s . $MBI->_str($x->{_n}) . '/' . $MBI->_str($x->{_d});
  385.   }
  386.  
  387. sub bnorm
  388.   {
  389.   # reduce the number to the shortest form
  390.   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
  391.  
  392.   # Both parts must be objects of whatever we are using today.
  393.   if ( my $c = $MBI->_check($x->{_n}) )
  394.     {
  395.     require Carp; Carp::croak ("n did not pass the self-check ($c) in bnorm()");
  396.     }
  397.   if ( my $c = $MBI->_check($x->{_d}) )
  398.     {
  399.     require Carp; Carp::croak ("d did not pass the self-check ($c) in bnorm()");
  400.     }
  401.  
  402.   # no normalize for NaN, inf etc.
  403.   return $x if $x->{sign} !~ /^[+-]$/;
  404.  
  405.   # normalize zeros to 0/1
  406.   if ($MBI->_is_zero($x->{_n}))
  407.     {
  408.     $x->{sign} = '+';                    # never leave a -0
  409.     $x->{_d} = $MBI->_one() unless $MBI->_is_one($x->{_d});
  410.     return $x;
  411.     }
  412.  
  413.   return $x if $MBI->_is_one($x->{_d});            # no need to reduce
  414.  
  415.   # reduce other numbers
  416.   my $gcd = $MBI->_copy($x->{_n});
  417.   $gcd = $MBI->_gcd($gcd,$x->{_d});
  418.   
  419.   if (!$MBI->_is_one($gcd))
  420.     {
  421.     $x->{_n} = $MBI->_div($x->{_n},$gcd);
  422.     $x->{_d} = $MBI->_div($x->{_d},$gcd);
  423.     }
  424.   $x;
  425.   }
  426.  
  427. ##############################################################################
  428. # sign manipulation
  429.  
  430. sub bneg
  431.   {
  432.   # (BRAT or num_str) return BRAT
  433.   # negate number or make a negated number from string
  434.   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
  435.  
  436.   return $x if $x->modify('bneg');
  437.  
  438.   # for +0 dont negate (to have always normalized +0). Does nothing for 'NaN'
  439.   $x->{sign} =~ tr/+-/-+/ unless ($x->{sign} eq '+' && $MBI->_is_zero($x->{_n}));
  440.   $x;
  441.   }
  442.  
  443. ##############################################################################
  444. # special values
  445.  
  446. sub _bnan
  447.   {
  448.   # used by parent class bnan() to initialize number to NaN
  449.   my $self = shift;
  450.  
  451.   if ($_trap_nan)
  452.     {
  453.     require Carp;
  454.     my $class = ref($self);
  455.     # "$self" below will stringify the object, this blows up if $self is a
  456.     # partial object (happens under trap_nan), so fix it beforehand
  457.     $self->{_d} = $MBI->_zero() unless defined $self->{_d};
  458.     $self->{_n} = $MBI->_zero() unless defined $self->{_n};
  459.     Carp::croak ("Tried to set $self to NaN in $class\::_bnan()");
  460.     }
  461.   $self->{_n} = $MBI->_zero();
  462.   $self->{_d} = $MBI->_zero();
  463.   }
  464.  
  465. sub _binf
  466.   {
  467.   # used by parent class bone() to initialize number to +inf/-inf
  468.   my $self = shift;
  469.  
  470.   if ($_trap_inf)
  471.     {
  472.     require Carp;
  473.     my $class = ref($self);
  474.     # "$self" below will stringify the object, this blows up if $self is a
  475.     # partial object (happens under trap_nan), so fix it beforehand
  476.     $self->{_d} = $MBI->_zero() unless defined $self->{_d};
  477.     $self->{_n} = $MBI->_zero() unless defined $self->{_n};
  478.     Carp::croak ("Tried to set $self to inf in $class\::_binf()");
  479.     }
  480.   $self->{_n} = $MBI->_zero();
  481.   $self->{_d} = $MBI->_zero();
  482.   }
  483.  
  484. sub _bone
  485.   {
  486.   # used by parent class bone() to initialize number to +1/-1
  487.   my $self = shift;
  488.   $self->{_n} = $MBI->_one();
  489.   $self->{_d} = $MBI->_one();
  490.   }
  491.  
  492. sub _bzero
  493.   {
  494.   # used by parent class bzero() to initialize number to 0
  495.   my $self = shift;
  496.   $self->{_n} = $MBI->_zero();
  497.   $self->{_d} = $MBI->_one();
  498.   }
  499.  
  500. ##############################################################################
  501. # mul/add/div etc
  502.  
  503. sub badd
  504.   {
  505.   # add two rational numbers
  506.  
  507.   # set up parameters
  508.   my ($self,$x,$y,@r) = (ref($_[0]),@_);
  509.   # objectify is costly, so avoid it
  510.   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
  511.     {
  512.     ($self,$x,$y,@r) = objectify(2,@_);
  513.     }
  514.  
  515.   # +inf + +inf => +inf,  -inf + -inf => -inf
  516.   return $x->binf(substr($x->{sign},0,1))
  517.     if $x->{sign} eq $y->{sign} && $x->{sign} =~ /^[+-]inf$/;
  518.  
  519.   # +inf + -inf or -inf + +inf => NaN
  520.   return $x->bnan() if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/);
  521.  
  522.   #  1   1    gcd(3,4) = 1    1*3 + 1*4    7
  523.   #  - + -                  = --------- = --                 
  524.   #  4   3                      4*3       12
  525.  
  526.   # we do not compute the gcd() here, but simple do:
  527.   #  5   7    5*3 + 7*4   43
  528.   #  - + -  = --------- = --                 
  529.   #  4   3       4*3      12
  530.  
  531.   # and bnorm() will then take care of the rest
  532.  
  533.   # 5 * 3
  534.   $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_d});
  535.  
  536.   # 7 * 4
  537.   my $m = $MBI->_mul( $MBI->_copy( $y->{_n} ), $x->{_d} );
  538.  
  539.   # 5 * 3 + 7 * 4
  540.   ($x->{_n}, $x->{sign}) = _e_add( $x->{_n}, $m, $x->{sign}, $y->{sign});
  541.  
  542.   # 4 * 3
  543.   $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_d});
  544.  
  545.   # normalize result, and possible round
  546.   $x->bnorm()->round(@r);
  547.   }
  548.  
  549. sub bsub
  550.   {
  551.   # subtract two rational numbers
  552.  
  553.   # set up parameters
  554.   my ($self,$x,$y,@r) = (ref($_[0]),@_);
  555.   # objectify is costly, so avoid it
  556.   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
  557.     {
  558.     ($self,$x,$y,@r) = objectify(2,@_);
  559.     }
  560.  
  561.   # flip sign of $x, call badd(), then flip sign of result
  562.   $x->{sign} =~ tr/+-/-+/
  563.     unless $x->{sign} eq '+' && $MBI->_is_zero($x->{_n});    # not -0
  564.   $x->badd($y,@r);                # does norm and round
  565.   $x->{sign} =~ tr/+-/-+/ 
  566.     unless $x->{sign} eq '+' && $MBI->_is_zero($x->{_n});    # not -0
  567.   $x;
  568.   }
  569.  
  570. sub bmul
  571.   {
  572.   # multiply two rational numbers
  573.   
  574.   # set up parameters
  575.   my ($self,$x,$y,@r) = (ref($_[0]),@_);
  576.   # objectify is costly, so avoid it
  577.   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
  578.     {
  579.     ($self,$x,$y,@r) = objectify(2,@_);
  580.     }
  581.  
  582.   return $x->bnan() if ($x->{sign} eq 'NaN' || $y->{sign} eq 'NaN');
  583.  
  584.   # inf handling
  585.   if (($x->{sign} =~ /^[+-]inf$/) || ($y->{sign} =~ /^[+-]inf$/))
  586.     {
  587.     return $x->bnan() if $x->is_zero() || $y->is_zero();
  588.     # result will always be +-inf:
  589.     # +inf * +/+inf => +inf, -inf * -/-inf => +inf
  590.     # +inf * -/-inf => -inf, -inf * +/+inf => -inf
  591.     return $x->binf() if ($x->{sign} =~ /^\+/ && $y->{sign} =~ /^\+/);
  592.     return $x->binf() if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/);
  593.     return $x->binf('-');
  594.     }
  595.  
  596.   # x== 0 # also: or y == 1 or y == -1
  597.   return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
  598.  
  599.   # XXX TODO:
  600.   # According to Knuth, this can be optimized by doing gcd twice (for d and n)
  601.   # and reducing in one step. This would save us the bnorm() at the end.
  602.  
  603.   #  1   2    1 * 2    2    1
  604.   #  - * - =  -----  = -  = -
  605.   #  4   3    4 * 3    12   6
  606.   
  607.   $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_n});
  608.   $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_d});
  609.  
  610.   # compute new sign
  611.   $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
  612.  
  613.   $x->bnorm()->round(@r);
  614.   }
  615.  
  616. sub bdiv
  617.   {
  618.   # (dividend: BRAT or num_str, divisor: BRAT or num_str) return
  619.   # (BRAT,BRAT) (quo,rem) or BRAT (only rem)
  620.  
  621.   # set up parameters
  622.   my ($self,$x,$y,@r) = (ref($_[0]),@_);
  623.   # objectify is costly, so avoid it
  624.   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
  625.     {
  626.     ($self,$x,$y,@r) = objectify(2,@_);
  627.     }
  628.  
  629.   return $self->_div_inf($x,$y)
  630.    if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
  631.  
  632.   # x== 0 # also: or y == 1 or y == -1
  633.   return wantarray ? ($x,$self->bzero()) : $x if $x->is_zero();
  634.  
  635.   # XXX TODO: list context, upgrade
  636.   # According to Knuth, this can be optimized by doing gcd twice (for d and n)
  637.   # and reducing in one step. This would save us the bnorm() at the end.
  638.  
  639.   # 1     1    1   3
  640.   # -  /  - == - * -
  641.   # 4     3    4   1
  642.   
  643.   $x->{_n} = $MBI->_mul( $x->{_n}, $y->{_d});
  644.   $x->{_d} = $MBI->_mul( $x->{_d}, $y->{_n});
  645.  
  646.   # compute new sign 
  647.   $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
  648.  
  649.   $x->bnorm()->round(@r);
  650.   $x;
  651.   }
  652.  
  653. sub bmod
  654.   {
  655.   # compute "remainder" (in Perl way) of $x / $y
  656.  
  657.   # set up parameters
  658.   my ($self,$x,$y,@r) = (ref($_[0]),@_);
  659.   # objectify is costly, so avoid it
  660.   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
  661.     {
  662.     ($self,$x,$y,@r) = objectify(2,@_);
  663.     }
  664.  
  665.   return $self->_div_inf($x,$y)
  666.    if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
  667.  
  668.   return $x if $x->is_zero();           # 0 / 7 = 0, mod 0
  669.  
  670.   # compute $x - $y * floor($x/$y), keeping the sign of $x
  671.  
  672.   # copy x to u, make it positive and then do a normal division ($u/$y)
  673.   my $u = bless { sign => '+' }, $self;
  674.   $u->{_n} = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d} );
  675.   $u->{_d} = $MBI->_mul( $MBI->_copy($x->{_d}), $y->{_n} );
  676.   
  677.   # compute floor(u)
  678.   if (! $MBI->_is_one($u->{_d}))
  679.     {
  680.     $u->{_n} = $MBI->_div($u->{_n},$u->{_d});    # 22/7 => 3/1 w/ truncate
  681.     # no need to set $u->{_d} to 1, since below we set it to $y->{_d} anyway
  682.     }
  683.   
  684.   # now compute $y * $u
  685.   $u->{_d} = $MBI->_copy($y->{_d});        # 1 * $y->{_d}, see floor above
  686.   $u->{_n} = $MBI->_mul($u->{_n},$y->{_n});
  687.  
  688.   my $xsign = $x->{sign}; $x->{sign} = '+';    # remember sign and make x positive
  689.   # compute $x - $u
  690.   $x->bsub($u);
  691.   $x->{sign} = $xsign;                # put sign back
  692.  
  693.   $x->bnorm()->round(@r);
  694.   }
  695.  
  696. ##############################################################################
  697. # bdec/binc
  698.  
  699. sub bdec
  700.   {
  701.   # decrement value (subtract 1)
  702.   my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
  703.  
  704.   return $x if $x->{sign} !~ /^[+-]$/;    # NaN, inf, -inf
  705.  
  706.   if ($x->{sign} eq '-')
  707.     {
  708.     $x->{_n} = $MBI->_add( $x->{_n}, $x->{_d});        # -5/2 => -7/2
  709.     }
  710.   else
  711.     {
  712.     if ($MBI->_acmp($x->{_n},$x->{_d}) < 0)        # n < d?
  713.       {
  714.       # 1/3 -- => -2/3
  715.       $x->{_n} = $MBI->_sub( $MBI->_copy($x->{_d}), $x->{_n});
  716.       $x->{sign} = '-';
  717.       }
  718.     else
  719.       {
  720.       $x->{_n} = $MBI->_sub($x->{_n}, $x->{_d});     # 5/2 => 3/2
  721.       }
  722.     }
  723.   $x->bnorm()->round(@r);
  724.   }
  725.  
  726. sub binc
  727.   {
  728.   # increment value (add 1)
  729.   my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
  730.   
  731.   return $x if $x->{sign} !~ /^[+-]$/;    # NaN, inf, -inf
  732.  
  733.   if ($x->{sign} eq '-')
  734.     {
  735.     if ($MBI->_acmp($x->{_n},$x->{_d}) < 0)
  736.       {
  737.       # -1/3 ++ => 2/3 (overflow at 0)
  738.       $x->{_n} = $MBI->_sub( $MBI->_copy($x->{_d}), $x->{_n});
  739.       $x->{sign} = '+';
  740.       }
  741.     else
  742.       {
  743.       $x->{_n} = $MBI->_sub($x->{_n}, $x->{_d});     # -5/2 => -3/2
  744.       }
  745.     }
  746.   else
  747.     {
  748.     $x->{_n} = $MBI->_add($x->{_n},$x->{_d});        # 5/2 => 7/2
  749.     }
  750.   $x->bnorm()->round(@r);
  751.   }
  752.  
  753. ##############################################################################
  754. # is_foo methods (the rest is inherited)
  755.  
  756. sub is_int
  757.   {
  758.   # return true if arg (BRAT or num_str) is an integer
  759.   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
  760.  
  761.   return 1 if ($x->{sign} =~ /^[+-]$/) &&    # NaN and +-inf aren't
  762.     $MBI->_is_one($x->{_d});            # x/y && y != 1 => no integer
  763.   0;
  764.   }
  765.  
  766. sub is_zero
  767.   {
  768.   # return true if arg (BRAT or num_str) is zero
  769.   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
  770.  
  771.   return 1 if $x->{sign} eq '+' && $MBI->_is_zero($x->{_n});
  772.   0;
  773.   }
  774.  
  775. sub is_one
  776.   {
  777.   # return true if arg (BRAT or num_str) is +1 or -1 if signis given
  778.   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
  779.  
  780.   my $sign = $_[2] || ''; $sign = '+' if $sign ne '-';
  781.   return 1
  782.    if ($x->{sign} eq $sign && $MBI->_is_one($x->{_n}) && $MBI->_is_one($x->{_d}));
  783.   0;
  784.   }
  785.  
  786. sub is_odd
  787.   {
  788.   # return true if arg (BFLOAT or num_str) is odd or false if even
  789.   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
  790.  
  791.   return 1 if ($x->{sign} =~ /^[+-]$/) &&        # NaN & +-inf aren't
  792.     ($MBI->_is_one($x->{_d}) && $MBI->_is_odd($x->{_n})); # x/2 is not, but 3/1
  793.   0;
  794.   }
  795.  
  796. sub is_even
  797.   {
  798.   # return true if arg (BINT or num_str) is even or false if odd
  799.   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
  800.  
  801.   return 0 if $x->{sign} !~ /^[+-]$/;            # NaN & +-inf aren't
  802.   return 1 if ($MBI->_is_one($x->{_d})            # x/3 is never
  803.      && $MBI->_is_even($x->{_n}));            # but 4/1 is
  804.   0;
  805.   }
  806.  
  807. ##############################################################################
  808. # parts() and friends
  809.  
  810. sub numerator
  811.   {
  812.   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
  813.  
  814.   # NaN, inf, -inf
  815.   return Math::BigInt->new($x->{sign}) if ($x->{sign} !~ /^[+-]$/);
  816.  
  817.   my $n = Math::BigInt->new($MBI->_str($x->{_n})); $n->{sign} = $x->{sign};
  818.   $n;
  819.   }
  820.  
  821. sub denominator
  822.   {
  823.   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
  824.  
  825.   # NaN
  826.   return Math::BigInt->new($x->{sign}) if $x->{sign} eq 'NaN';
  827.   # inf, -inf
  828.   return Math::BigInt->bone() if $x->{sign} !~ /^[+-]$/;
  829.   
  830.   Math::BigInt->new($MBI->_str($x->{_d}));
  831.   }
  832.  
  833. sub parts
  834.   {
  835.   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
  836.  
  837.   my $c = 'Math::BigInt';
  838.  
  839.   return ($c->bnan(),$c->bnan()) if $x->{sign} eq 'NaN';
  840.   return ($c->binf(),$c->binf()) if $x->{sign} eq '+inf';
  841.   return ($c->binf('-'),$c->binf()) if $x->{sign} eq '-inf';
  842.  
  843.   my $n = $c->new( $MBI->_str($x->{_n}));
  844.   $n->{sign} = $x->{sign};
  845.   my $d = $c->new( $MBI->_str($x->{_d}));
  846.   ($n,$d);
  847.   }
  848.  
  849. sub length
  850.   {
  851.   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
  852.  
  853.   return $nan unless $x->is_int();
  854.   $MBI->_len($x->{_n});                # length(-123/1) => length(123)
  855.   }
  856.  
  857. sub digit
  858.   {
  859.   my ($self,$x,$n) = ref($_[0]) ? (undef,$_[0],$_[1]) : objectify(1,@_);
  860.  
  861.   return $nan unless $x->is_int();
  862.   $MBI->_digit($x->{_n},$n || 0);        # digit(-123/1,2) => digit(123,2)
  863.   }
  864.  
  865. ##############################################################################
  866. # special calc routines
  867.  
  868. sub bceil
  869.   {
  870.   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
  871.  
  872.   return $x if $x->{sign} !~ /^[+-]$/ ||    # not for NaN, inf
  873.             $MBI->_is_one($x->{_d});        # 22/1 => 22, 0/1 => 0
  874.  
  875.   $x->{_n} = $MBI->_div($x->{_n},$x->{_d});    # 22/7 => 3/1 w/ truncate
  876.   $x->{_d} = $MBI->_one();            # d => 1
  877.   $x->{_n} = $MBI->_inc($x->{_n})
  878.     if $x->{sign} eq '+';            # +22/7 => 4/1
  879.   $x->{sign} = '+' if $MBI->_is_zero($x->{_n});    # -0 => 0
  880.   $x;
  881.   }
  882.  
  883. sub bfloor
  884.   {
  885.   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
  886.  
  887.   return $x if $x->{sign} !~ /^[+-]$/ ||    # not for NaN, inf
  888.             $MBI->_is_one($x->{_d});        # 22/1 => 22, 0/1 => 0
  889.  
  890.   $x->{_n} = $MBI->_div($x->{_n},$x->{_d});    # 22/7 => 3/1 w/ truncate
  891.   $x->{_d} = $MBI->_one();            # d => 1
  892.   $x->{_n} = $MBI->_inc($x->{_n})
  893.     if $x->{sign} eq '-';            # -22/7 => -4/1
  894.   $x;
  895.   }
  896.  
  897. sub bfac
  898.   {
  899.   my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
  900.  
  901.   # if $x is not an integer
  902.   if (($x->{sign} ne '+') || (!$MBI->_is_one($x->{_d})))
  903.     {
  904.     return $x->bnan();
  905.     }
  906.  
  907.   $x->{_n} = $MBI->_fac($x->{_n});
  908.   # since _d is 1, we don't need to reduce/norm the result
  909.   $x->round(@r);
  910.   }
  911.  
  912. sub bpow
  913.   {
  914.   # power ($x ** $y)
  915.  
  916.   # set up parameters
  917.   my ($self,$x,$y,@r) = (ref($_[0]),@_);
  918.   # objectify is costly, so avoid it
  919.   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
  920.     {
  921.     ($self,$x,$y,@r) = objectify(2,@_);
  922.     }
  923.  
  924.   return $x if $x->{sign} =~ /^[+-]inf$/;       # -inf/+inf ** x
  925.   return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;
  926.   return $x->bone(@r) if $y->is_zero();
  927.   return $x->round(@r) if $x->is_one() || $y->is_one();
  928.  
  929.   if ($x->{sign} eq '-' && $MBI->_is_one($x->{_n}) && $MBI->_is_one($x->{_d}))
  930.     {
  931.     # if $x == -1 and odd/even y => +1/-1
  932.     return $y->is_odd() ? $x->round(@r) : $x->babs()->round(@r);
  933.     # my Casio FX-5500L has a bug here: -1 ** 2 is -1, but -1 * -1 is 1;
  934.     }
  935.   # 1 ** -y => 1 / (1 ** |y|)
  936.   # so do test for negative $y after above's clause
  937.  
  938.   return $x->round(@r) if $x->is_zero();  # 0**y => 0 (if not y <= 0)
  939.  
  940.   # shortcut y/1 (and/or x/1)
  941.   if ($MBI->_is_one($y->{_d}))
  942.     {
  943.     # shortcut for x/1 and y/1
  944.     if ($MBI->_is_one($x->{_d}))
  945.       {
  946.       $x->{_n} = $MBI->_pow($x->{_n},$y->{_n});        # x/1 ** y/1 => (x ** y)/1
  947.       if ($y->{sign} eq '-')
  948.         {
  949.         # 0.2 ** -3 => 1/(0.2 ** 3)
  950.         ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n});    # swap
  951.         }
  952.       # correct sign; + ** + => +
  953.       if ($x->{sign} eq '-')
  954.         {
  955.         # - * - => +, - * - * - => -
  956.         $x->{sign} = '+' if $MBI->_is_even($y->{_n});    
  957.         }
  958.       return $x->round(@r);
  959.       }
  960.     # x/z ** y/1
  961.     $x->{_n} = $MBI->_pow($x->{_n},$y->{_n});        # 5/2 ** y/1 => 5 ** y / 2 ** y
  962.     $x->{_d} = $MBI->_pow($x->{_d},$y->{_n});
  963.     if ($y->{sign} eq '-')
  964.       {
  965.       # 0.2 ** -3 => 1/(0.2 ** 3)
  966.       ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n});    # swap
  967.       }
  968.     # correct sign; + ** + => +
  969.     if ($x->{sign} eq '-')
  970.       {
  971.       # - * - => +, - * - * - => -
  972.       $x->{sign} = '+' if $MBI->_is_even($y->{_n});    
  973.       }
  974.     return $x->round(@r);
  975.     }
  976.  
  977.   # regular calculation (this is wrong for d/e ** f/g)
  978.   my $pow2 = $self->bone();
  979.   my $y1 = $MBI->_div ( $MBI->_copy($y->{_n}), $y->{_d});
  980.   my $two = $MBI->_two();
  981.  
  982.   while (!$MBI->_is_one($y1))
  983.     {
  984.     $pow2->bmul($x) if $MBI->_is_odd($y1);
  985.     $MBI->_div($y1, $two);
  986.     $x->bmul($x);
  987.     }
  988.   $x->bmul($pow2) unless $pow2->is_one();
  989.   # n ** -x => 1/n ** x
  990.   ($x->{_d},$x->{_n}) = ($x->{_n},$x->{_d}) if $y->{sign} eq '-'; 
  991.   $x->bnorm()->round(@r);
  992.   }
  993.  
  994. sub blog
  995.   {
  996.   # set up parameters
  997.   my ($self,$x,$y,@r) = (ref($_[0]),@_);
  998.  
  999.   # objectify is costly, so avoid it
  1000.   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
  1001.     {
  1002.     ($self,$x,$y,@r) = objectify(2,$class,@_);
  1003.     }
  1004.  
  1005.   # blog(1,Y) => 0
  1006.   return $x->bzero() if $x->is_one() && $y->{sign} eq '+';
  1007.  
  1008.   # $x <= 0 => NaN
  1009.   return $x->bnan() if $x->is_zero() || $x->{sign} ne '+' || $y->{sign} ne '+';
  1010.  
  1011.   if ($x->is_int() && $y->is_int())
  1012.     {
  1013.     return $self->new($x->as_number()->blog($y->as_number(),@r));
  1014.     }
  1015.  
  1016.   # do it with floats
  1017.   $x->_new_from_float( $x->_as_float()->blog(Math::BigFloat->new("$y"),@r) );
  1018.   }
  1019.  
  1020. sub bexp
  1021.   {
  1022.   # set up parameters
  1023.   my ($self,$x,$y,$a,$p,$r) = (ref($_[0]),@_);
  1024.  
  1025.   # objectify is costly, so avoid it
  1026.   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
  1027.     {
  1028.     ($self,$x,$y,$a,$p,$r) = objectify(2,$class,@_);
  1029.     }
  1030.  
  1031.   return $x->binf() if $x->{sign} eq '+inf';
  1032.   return $x->bzero() if $x->{sign} eq '-inf';
  1033.  
  1034.   # we need to limit the accuracy to protect against overflow
  1035.   my $fallback = 0;
  1036.   my ($scale,@params);
  1037.   ($x,@params) = $x->_find_round_parameters($a,$p,$r);
  1038.  
  1039.   # also takes care of the "error in _find_round_parameters?" case
  1040.   return $x if $x->{sign} eq 'NaN';
  1041.  
  1042.   # no rounding at all, so must use fallback
  1043.   if (scalar @params == 0)
  1044.     {
  1045.     # simulate old behaviour
  1046.     $params[0] = $self->div_scale();    # and round to it as accuracy
  1047.     $params[1] = undef;                 # P = undef
  1048.     $scale = $params[0]+4;              # at least four more for proper round
  1049.     $params[2] = $r;                    # round mode by caller or undef
  1050.     $fallback = 1;                      # to clear a/p afterwards
  1051.     }
  1052.   else
  1053.     {
  1054.     # the 4 below is empirical, and there might be cases where it's not enough...
  1055.     $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined
  1056.     }
  1057.  
  1058.   return $x->bone(@params) if $x->is_zero();
  1059.  
  1060.   # See the comments in Math::BigFloat on how this algorithm works.
  1061.   # Basically we calculate A and B (where B is faculty(N)) so that A/B = e
  1062.  
  1063.   my $x_org = $x->copy();
  1064.   if ($scale <= 75)
  1065.     {
  1066.     # set $x directly from a cached string form
  1067.     $x->{_n} = $MBI->_new("90933395208605785401971970164779391644753259799242");
  1068.     $x->{_d} = $MBI->_new("33452526613163807108170062053440751665152000000000");
  1069.     $x->{sign} = '+';
  1070.     }
  1071.   else
  1072.     {
  1073.     # compute A and B so that e = A / B.
  1074.  
  1075.     # After some terms we end up with this, so we use it as a starting point:
  1076.     my $A = $MBI->_new("90933395208605785401971970164779391644753259799242");
  1077.     my $F = $MBI->_new(42); my $step = 42;
  1078.  
  1079.     # Compute how many steps we need to take to get $A and $B sufficiently big
  1080.     my $steps = Math::BigFloat::_len_to_steps($scale - 4);
  1081. #    print STDERR "# Doing $steps steps for ", $scale-4, " digits\n";
  1082.     while ($step++ <= $steps)
  1083.       {
  1084.       # calculate $a * $f + 1
  1085.       $A = $MBI->_mul($A, $F);
  1086.       $A = $MBI->_inc($A);
  1087.       # increment f
  1088.       $F = $MBI->_inc($F);
  1089.       }
  1090.     # compute $B as factorial of $steps (this is faster than doing it manually)
  1091.     my $B = $MBI->_fac($MBI->_new($steps));
  1092.  
  1093. #  print "A ", $MBI->_str($A), "\nB ", $MBI->_str($B), "\n";
  1094.  
  1095.     $x->{_n} = $A;
  1096.     $x->{_d} = $B;
  1097.     $x->{sign} = '+';
  1098.     }
  1099.  
  1100.   # $x contains now an estimate of e, with some surplus digits, so we can round
  1101.   if (!$x_org->is_one())
  1102.     {
  1103.     # raise $x to the wanted power and round it in one step:
  1104.     $x->bpow($x_org, @params);
  1105.     }
  1106.   else
  1107.     {
  1108.     # else just round the already computed result
  1109.     delete $x->{_a}; delete $x->{_p};
  1110.     # shortcut to not run through _find_round_parameters again
  1111.     if (defined $params[0])
  1112.       {
  1113.       $x->bround($params[0],$params[2]);                # then round accordingly
  1114.       }
  1115.     else
  1116.       {
  1117.       $x->bfround($params[1],$params[2]);               # then round accordingly
  1118.       }
  1119.     }
  1120.   if ($fallback)
  1121.     {
  1122.     # clear a/p after round, since user did not request it
  1123.     delete $x->{_a}; delete $x->{_p};
  1124.     }
  1125.  
  1126.   $x;
  1127.   }
  1128.  
  1129. sub bnok
  1130.   {
  1131.   # set up parameters
  1132.   my ($self,$x,$y,@r) = (ref($_[0]),@_);
  1133.  
  1134.   # objectify is costly, so avoid it
  1135.   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
  1136.     {
  1137.     ($self,$x,$y,@r) = objectify(2,$class,@_);
  1138.     }
  1139.  
  1140.   # do it with floats
  1141.   $x->_new_from_float( $x->_as_float()->bnok(Math::BigFloat->new("$y"),@r) );
  1142.   }
  1143.  
  1144. sub _float_from_part
  1145.   {
  1146.   my $x = shift;
  1147.  
  1148.   my $f = Math::BigFloat->bzero();
  1149.   $f->{_m} = $MBI->_copy($x);
  1150.   $f->{_e} = $MBI->_zero();
  1151.  
  1152.   $f;
  1153.   }
  1154.  
  1155. sub _as_float
  1156.   {
  1157.   my $x = shift;
  1158.  
  1159.   local $Math::BigFloat::upgrade = undef;
  1160.   local $Math::BigFloat::accuracy = undef;
  1161.   local $Math::BigFloat::precision = undef;
  1162.   # 22/7 => 3.142857143..
  1163.  
  1164.   my $a = $x->accuracy() || 0;
  1165.   if ($a != 0 || !$MBI->_is_one($x->{_d}))
  1166.     {
  1167.     # n/d
  1168.     return Math::BigFloat->new($x->{sign} . $MBI->_str($x->{_n}))->bdiv( $MBI->_str($x->{_d}), $x->accuracy());
  1169.     }
  1170.   # just n
  1171.   Math::BigFloat->new($x->{sign} . $MBI->_str($x->{_n}));
  1172.   }
  1173.  
  1174. sub broot
  1175.   {
  1176.   # set up parameters
  1177.   my ($self,$x,$y,@r) = (ref($_[0]),@_);
  1178.   # objectify is costly, so avoid it
  1179.   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
  1180.     {
  1181.     ($self,$x,$y,@r) = objectify(2,@_);
  1182.     }
  1183.  
  1184.   if ($x->is_int() && $y->is_int())
  1185.     {
  1186.     return $self->new($x->as_number()->broot($y->as_number(),@r));
  1187.     }
  1188.  
  1189.   # do it with floats
  1190.   $x->_new_from_float( $x->_as_float()->broot($y,@r) );
  1191.   }
  1192.  
  1193. sub bmodpow
  1194.   {
  1195.   # set up parameters
  1196.   my ($self,$x,$y,$m,@r) = (ref($_[0]),@_);
  1197.   # objectify is costly, so avoid it
  1198.   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
  1199.     {
  1200.     ($self,$x,$y,$m,@r) = objectify(3,@_);
  1201.     }
  1202.  
  1203.   # $x or $y or $m are NaN or +-inf => NaN
  1204.   return $x->bnan()
  1205.    if $x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/ ||
  1206.    $m->{sign} !~ /^[+-]$/;
  1207.  
  1208.   if ($x->is_int() && $y->is_int() && $m->is_int())
  1209.     {
  1210.     return $self->new($x->as_number()->bmodpow($y->as_number(),$m,@r));
  1211.     }
  1212.  
  1213.   warn ("bmodpow() not fully implemented");
  1214.   $x->bnan();
  1215.   }
  1216.  
  1217. sub bmodinv
  1218.   {
  1219.   # set up parameters
  1220.   my ($self,$x,$y,@r) = (ref($_[0]),@_);
  1221.   # objectify is costly, so avoid it
  1222.   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
  1223.     {
  1224.     ($self,$x,$y,@r) = objectify(2,@_);
  1225.     }
  1226.  
  1227.   # $x or $y are NaN or +-inf => NaN
  1228.   return $x->bnan() 
  1229.    if $x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/;
  1230.  
  1231.   if ($x->is_int() && $y->is_int())
  1232.     {
  1233.     return $self->new($x->as_number()->bmodinv($y->as_number(),@r));
  1234.     }
  1235.  
  1236.   warn ("bmodinv() not fully implemented");
  1237.   $x->bnan();
  1238.   }
  1239.  
  1240. sub bsqrt
  1241.   {
  1242.   my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
  1243.  
  1244.   return $x->bnan() if $x->{sign} !~ /^[+]/;    # NaN, -inf or < 0
  1245.   return $x if $x->{sign} eq '+inf';            # sqrt(inf) == inf
  1246.   return $x->round(@r) if $x->is_zero() || $x->is_one();
  1247.  
  1248.   local $Math::BigFloat::upgrade = undef;
  1249.   local $Math::BigFloat::downgrade = undef;
  1250.   local $Math::BigFloat::precision = undef;
  1251.   local $Math::BigFloat::accuracy = undef;
  1252.   local $Math::BigInt::upgrade = undef;
  1253.   local $Math::BigInt::precision = undef;
  1254.   local $Math::BigInt::accuracy = undef;
  1255.  
  1256.   $x->{_n} = _float_from_part( $x->{_n} )->bsqrt();
  1257.   $x->{_d} = _float_from_part( $x->{_d} )->bsqrt();
  1258.  
  1259.   # XXX TODO: we probably can optimze this:
  1260.  
  1261.   # if sqrt(D) was not integer
  1262.   if ($x->{_d}->{_es} ne '+')
  1263.     {
  1264.     $x->{_n}->blsft($x->{_d}->exponent()->babs(),10);    # 7.1/4.51 => 7.1/45.1
  1265.     $x->{_d} = $MBI->_copy( $x->{_d}->{_m} );        # 7.1/45.1 => 71/45.1
  1266.     }
  1267.   # if sqrt(N) was not integer
  1268.   if ($x->{_n}->{_es} ne '+')
  1269.     {
  1270.     $x->{_d}->blsft($x->{_n}->exponent()->babs(),10);    # 71/45.1 => 710/45.1
  1271.     $x->{_n} = $MBI->_copy( $x->{_n}->{_m} );        # 710/45.1 => 710/451
  1272.     }
  1273.  
  1274.   # convert parts to $MBI again 
  1275.   $x->{_n} = $MBI->_lsft( $MBI->_copy( $x->{_n}->{_m} ), $x->{_n}->{_e}, 10)
  1276.     if ref($x->{_n}) ne $MBI && ref($x->{_n}) ne 'ARRAY';
  1277.   $x->{_d} = $MBI->_lsft( $MBI->_copy( $x->{_d}->{_m} ), $x->{_d}->{_e}, 10)
  1278.     if ref($x->{_d}) ne $MBI && ref($x->{_d}) ne 'ARRAY';
  1279.  
  1280.   $x->bnorm()->round(@r);
  1281.   }
  1282.  
  1283. sub blsft
  1284.   {
  1285.   my ($self,$x,$y,$b,@r) = objectify(3,@_);
  1286.  
  1287.   $b = 2 unless defined $b;
  1288.   $b = $self->new($b) unless ref ($b);
  1289.   $x->bmul( $b->copy()->bpow($y), @r);
  1290.   $x;
  1291.   }
  1292.  
  1293. sub brsft
  1294.   {
  1295.   my ($self,$x,$y,$b,@r) = objectify(3,@_);
  1296.  
  1297.   $b = 2 unless defined $b;
  1298.   $b = $self->new($b) unless ref ($b);
  1299.   $x->bdiv( $b->copy()->bpow($y), @r);
  1300.   $x;
  1301.   }
  1302.  
  1303. ##############################################################################
  1304. # round
  1305.  
  1306. sub round
  1307.   {
  1308.   $_[0];
  1309.   }
  1310.  
  1311. sub bround
  1312.   {
  1313.   $_[0];
  1314.   }
  1315.  
  1316. sub bfround
  1317.   {
  1318.   $_[0];
  1319.   }
  1320.  
  1321. ##############################################################################
  1322. # comparing
  1323.  
  1324. sub bcmp
  1325.   {
  1326.   # compare two signed numbers 
  1327.   
  1328.   # set up parameters
  1329.   my ($self,$x,$y) = (ref($_[0]),@_);
  1330.   # objectify is costly, so avoid it
  1331.   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
  1332.     {
  1333.     ($self,$x,$y) = objectify(2,@_);
  1334.     }
  1335.  
  1336.   if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
  1337.     {
  1338.     # handle +-inf and NaN
  1339.     return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
  1340.     return 0 if $x->{sign} eq $y->{sign} && $x->{sign} =~ /^[+-]inf$/;
  1341.     return +1 if $x->{sign} eq '+inf';
  1342.     return -1 if $x->{sign} eq '-inf';
  1343.     return -1 if $y->{sign} eq '+inf';
  1344.     return +1;
  1345.     }
  1346.   # check sign for speed first
  1347.   return 1 if $x->{sign} eq '+' && $y->{sign} eq '-';   # does also 0 <=> -y
  1348.   return -1 if $x->{sign} eq '-' && $y->{sign} eq '+';  # does also -x <=> 0
  1349.  
  1350.   # shortcut
  1351.   my $xz = $MBI->_is_zero($x->{_n});
  1352.   my $yz = $MBI->_is_zero($y->{_n});
  1353.   return 0 if $xz && $yz;                               # 0 <=> 0
  1354.   return -1 if $xz && $y->{sign} eq '+';                # 0 <=> +y
  1355.   return 1 if $yz && $x->{sign} eq '+';                 # +x <=> 0
  1356.  
  1357.   my $t = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d});
  1358.   my $u = $MBI->_mul( $MBI->_copy($y->{_n}), $x->{_d});
  1359.  
  1360.   my $cmp = $MBI->_acmp($t,$u);                # signs are equal
  1361.   $cmp = -$cmp if $x->{sign} eq '-';            # both are '-' => reverse
  1362.   $cmp;
  1363.   }
  1364.  
  1365. sub bacmp
  1366.   {
  1367.   # compare two numbers (as unsigned)
  1368.  
  1369.   # set up parameters
  1370.   my ($self,$x,$y) = (ref($_[0]),@_);
  1371.   # objectify is costly, so avoid it
  1372.   if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
  1373.     {
  1374.     ($self,$x,$y) = objectify(2,$class,@_);
  1375.     }
  1376.  
  1377.   if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/))
  1378.     {
  1379.     # handle +-inf and NaN
  1380.     return undef if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
  1381.     return 0 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} =~ /^[+-]inf$/;
  1382.     return 1 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} !~ /^[+-]inf$/;
  1383.     return -1;
  1384.     }
  1385.  
  1386.   my $t = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d});
  1387.   my $u = $MBI->_mul( $MBI->_copy($y->{_n}), $x->{_d});
  1388.   $MBI->_acmp($t,$u);                    # ignore signs
  1389.   }
  1390.  
  1391. ##############################################################################
  1392. # output conversation
  1393.  
  1394. sub numify
  1395.   {
  1396.   # convert 17/8 => float (aka 2.125)
  1397.   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
  1398.  
  1399.   return $x->bstr() if $x->{sign} !~ /^[+-]$/;    # inf, NaN, etc
  1400.  
  1401.   # N/1 => N
  1402.   my $neg = ''; $neg = '-' if $x->{sign} eq '-';
  1403.   return $neg . $MBI->_num($x->{_n}) if $MBI->_is_one($x->{_d});
  1404.  
  1405.   $x->_as_float()->numify() + 0.0;
  1406.   }
  1407.  
  1408. sub as_number
  1409.   {
  1410.   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
  1411.  
  1412.   # NaN, inf etc
  1413.   return Math::BigInt->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
  1414.  
  1415.   my $u = Math::BigInt->bzero();
  1416.   $u->{sign} = $x->{sign};
  1417.   $u->{value} = $MBI->_div( $MBI->_copy($x->{_n}), $x->{_d});    # 22/7 => 3
  1418.   $u;
  1419.   }
  1420.  
  1421. sub as_bin
  1422.   {
  1423.   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
  1424.  
  1425.   return $x unless $x->is_int();
  1426.  
  1427.   my $s = $x->{sign}; $s = '' if $s eq '+';
  1428.   $s . $MBI->_as_bin($x->{_n});
  1429.   }
  1430.  
  1431. sub as_hex
  1432.   {
  1433.   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
  1434.  
  1435.   return $x unless $x->is_int();
  1436.  
  1437.   my $s = $x->{sign}; $s = '' if $s eq '+';
  1438.   $s . $MBI->_as_hex($x->{_n});
  1439.   }
  1440.  
  1441. sub as_oct
  1442.   {
  1443.   my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
  1444.  
  1445.   return $x unless $x->is_int();
  1446.  
  1447.   my $s = $x->{sign}; $s = '' if $s eq '+';
  1448.   $s . $MBI->_as_oct($x->{_n});
  1449.   }
  1450.  
  1451. ##############################################################################
  1452.  
  1453. sub from_hex
  1454.   {
  1455.   my $class = shift;
  1456.  
  1457.   $class->new(@_);
  1458.   }
  1459.  
  1460. sub from_bin
  1461.   {
  1462.   my $class = shift;
  1463.  
  1464.   $class->new(@_);
  1465.   }
  1466.  
  1467. sub from_oct
  1468.   {
  1469.   my $class = shift;
  1470.  
  1471.   my @parts;
  1472.   for my $c (@_)
  1473.     {
  1474.     push @parts, Math::BigInt->from_oct($c);
  1475.     }
  1476.   $class->new ( @parts );
  1477.   }
  1478.  
  1479. ##############################################################################
  1480. # import
  1481.  
  1482. sub import
  1483.   {
  1484.   my $self = shift;
  1485.   my $l = scalar @_;
  1486.   my $lib = ''; my @a;
  1487.   my $try = 'try';
  1488.  
  1489.   for ( my $i = 0; $i < $l ; $i++)
  1490.     {
  1491.     if ( $_[$i] eq ':constant' )
  1492.       {
  1493.       # this rest causes overlord er load to step in
  1494.       overload::constant float => sub { $self->new(shift); };
  1495.       }
  1496. #    elsif ($_[$i] eq 'upgrade')
  1497. #      {
  1498. #     # this causes upgrading
  1499. #      $upgrade = $_[$i+1];        # or undef to disable
  1500. #      $i++;
  1501. #      }
  1502.     elsif ($_[$i] eq 'downgrade')
  1503.       {
  1504.       # this causes downgrading
  1505.       $downgrade = $_[$i+1];        # or undef to disable
  1506.       $i++;
  1507.       }
  1508.     elsif ($_[$i] =~ /^(lib|try|only)\z/)
  1509.       {
  1510.       $lib = $_[$i+1] || '';        # default Calc
  1511.       $try = $1;            # lib, try or only
  1512.       $i++;
  1513.       }
  1514.     elsif ($_[$i] eq 'with')
  1515.       {
  1516.       # this argument is no longer used
  1517.       #$MBI = $_[$i+1] || 'Math::BigInt::Calc';    # default Math::BigInt::Calc
  1518.       $i++;
  1519.       }
  1520.     else
  1521.       {
  1522.       push @a, $_[$i];
  1523.       }
  1524.     }
  1525.   require Math::BigInt;
  1526.  
  1527.   # let use Math::BigInt lib => 'GMP'; use Math::BigRat; still have GMP
  1528.   if ($lib ne '')
  1529.     {
  1530.     my @c = split /\s*,\s*/, $lib;
  1531.     foreach (@c)
  1532.       {
  1533.       $_ =~ tr/a-zA-Z0-9://cd;                    # limit to sane characters
  1534.       }
  1535.     $lib = join(",", @c);
  1536.     }
  1537.   my @import = ('objectify');
  1538.   push @import, $try => $lib if $lib ne '';
  1539.  
  1540.   # MBI already loaded, so feed it our lib arguments
  1541.   Math::BigInt->import( @import );
  1542.  
  1543.   $MBI = Math::BigFloat->config()->{lib};
  1544.  
  1545.   # register us with MBI to get notified of future lib changes
  1546.   Math::BigInt::_register_callback( $self, sub { $MBI = $_[0]; } );
  1547.   
  1548.   # any non :constant stuff is handled by our parent, Exporter (loaded
  1549.   # by Math::BigFloat, even if @_ is empty, to give it a chance
  1550.   $self->SUPER::import(@a);             # for subclasses
  1551.   $self->export_to_level(1,$self,@a);   # need this, too
  1552.   }
  1553.  
  1554. 1;
  1555.  
  1556. __END__
  1557.  
  1558. =head1 NAME
  1559.  
  1560. Math::BigRat - Arbitrary big rational numbers
  1561.  
  1562. =head1 SYNOPSIS
  1563.  
  1564.     use Math::BigRat;
  1565.  
  1566.     my $x = Math::BigRat->new('3/7'); $x += '5/9';
  1567.  
  1568.     print $x->bstr(),"\n";
  1569.       print $x ** 2,"\n";
  1570.  
  1571.     my $y = Math::BigRat->new('inf');
  1572.     print "$y ", ($y->is_inf ? 'is' : 'is not') , " infinity\n";
  1573.  
  1574.     my $z = Math::BigRat->new(144); $z->bsqrt();
  1575.  
  1576. =head1 DESCRIPTION
  1577.  
  1578. Math::BigRat complements Math::BigInt and Math::BigFloat by providing support
  1579. for arbitrary big rational numbers.
  1580.  
  1581. =head2 MATH LIBRARY
  1582.  
  1583. You can change the underlying module that does the low-level
  1584. math operations by using:
  1585.  
  1586.     use Math::BigRat try => 'GMP';
  1587.  
  1588. Note: This needs Math::BigInt::GMP installed.
  1589.  
  1590. The following would first try to find Math::BigInt::Foo, then
  1591. Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
  1592.  
  1593.     use Math::BigRat try => 'Foo,Math::BigInt::Bar';
  1594.  
  1595. If you want to get warned when the fallback occurs, replace "try" with
  1596. "lib":
  1597.  
  1598.     use Math::BigRat lib => 'Foo,Math::BigInt::Bar';
  1599.  
  1600. If you want the code to die instead, replace "try" with
  1601. "only":
  1602.  
  1603.     use Math::BigRat only => 'Foo,Math::BigInt::Bar';
  1604.  
  1605. =head1 METHODS
  1606.  
  1607. Any methods not listed here are derived from Math::BigFloat (or
  1608. Math::BigInt), so make sure you check these two modules for further
  1609. information.
  1610.  
  1611. =head2 new()
  1612.  
  1613.     $x = Math::BigRat->new('1/3');
  1614.  
  1615. Create a new Math::BigRat object. Input can come in various forms:
  1616.  
  1617.     $x = Math::BigRat->new(123);                # scalars
  1618.     $x = Math::BigRat->new('inf');                # infinity
  1619.     $x = Math::BigRat->new('123.3');            # float
  1620.     $x = Math::BigRat->new('1/3');                # simple string
  1621.     $x = Math::BigRat->new('1 / 3');            # spaced
  1622.     $x = Math::BigRat->new('1 / 0.1');            # w/ floats
  1623.     $x = Math::BigRat->new(Math::BigInt->new(3));        # BigInt
  1624.     $x = Math::BigRat->new(Math::BigFloat->new('3.1'));    # BigFloat
  1625.     $x = Math::BigRat->new(Math::BigInt::Lite->new('2'));    # BigLite
  1626.  
  1627.     # You can also give D and N as different objects:
  1628.     $x = Math::BigRat->new(
  1629.         Math::BigInt->new(-123),
  1630.         Math::BigInt->new(7),
  1631.         );            # => -123/7
  1632.  
  1633. =head2 numerator()
  1634.  
  1635.     $n = $x->numerator();
  1636.  
  1637. Returns a copy of the numerator (the part above the line) as signed BigInt.
  1638.  
  1639. =head2 denominator()
  1640.     
  1641.     $d = $x->denominator();
  1642.  
  1643. Returns a copy of the denominator (the part under the line) as positive BigInt.
  1644.  
  1645. =head2 parts()
  1646.  
  1647.     ($n,$d) = $x->parts();
  1648.  
  1649. Return a list consisting of (signed) numerator and (unsigned) denominator as
  1650. BigInts.
  1651.  
  1652. =head2 numify()
  1653.  
  1654.     my $y = $x->numify();
  1655.  
  1656. Returns the object as a scalar. This will lose some data if the object
  1657. cannot be represented by a normal Perl scalar (integer or float), so
  1658. use as_int() instead.
  1659.  
  1660. This routine is automatically used whenever a scalar is required:
  1661.  
  1662.     my $x = Math::BigRat->new('3/1');
  1663.     @array = (1,2,3);
  1664.     $y = $array[$x];        # set $y to 3
  1665.  
  1666. =head2 as_int()/as_number()
  1667.  
  1668.     $x = Math::BigRat->new('13/7');
  1669.     print $x->as_int(),"\n";        # '1'
  1670.  
  1671. Returns a copy of the object as BigInt, truncated to an integer.
  1672.  
  1673. C<as_number()> is an alias for C<as_int()>.
  1674.  
  1675. =head2 as_hex()
  1676.  
  1677.     $x = Math::BigRat->new('13');
  1678.     print $x->as_hex(),"\n";        # '0xd'
  1679.  
  1680. Returns the BigRat as hexadecimal string. Works only for integers. 
  1681.  
  1682. =head2 as_bin()
  1683.  
  1684.     $x = Math::BigRat->new('13');
  1685.     print $x->as_bin(),"\n";        # '0x1101'
  1686.  
  1687. Returns the BigRat as binary string. Works only for integers. 
  1688.  
  1689. =head2 as_oct()
  1690.  
  1691.     $x = Math::BigRat->new('13');
  1692.     print $x->as_oct(),"\n";        # '015'
  1693.  
  1694. Returns the BigRat as octal string. Works only for integers. 
  1695.  
  1696. =head2 from_hex()/from_bin()/from_oct()
  1697.  
  1698.     my $h = Math::BigRat->from_hex('0x10');
  1699.     my $b = Math::BigRat->from_bin('0b10000000');
  1700.     my $o = Math::BigRat->from_oct('020');
  1701.  
  1702. Create a BigRat from an hexadecimal, binary or octal number
  1703. in string form.
  1704.  
  1705. =head2 length()
  1706.  
  1707.     $len = $x->length();
  1708.  
  1709. Return the length of $x in digitis for integer values.
  1710.  
  1711. =head2 digit()
  1712.  
  1713.     print Math::BigRat->new('123/1')->digit(1);    # 1
  1714.     print Math::BigRat->new('123/1')->digit(-1);    # 3
  1715.  
  1716. Return the N'ths digit from X when X is an integer value.
  1717.  
  1718. =head2 bnorm()
  1719.  
  1720.     $x->bnorm();
  1721.  
  1722. Reduce the number to the shortest form. This routine is called
  1723. automatically whenever it is needed.
  1724.  
  1725. =head2 bfac()
  1726.  
  1727.     $x->bfac();
  1728.  
  1729. Calculates the factorial of $x. For instance:
  1730.  
  1731.     print Math::BigRat->new('3/1')->bfac(),"\n";    # 1*2*3
  1732.     print Math::BigRat->new('5/1')->bfac(),"\n";    # 1*2*3*4*5
  1733.  
  1734. Works currently only for integers.
  1735.  
  1736. =head2 bround()/round()/bfround()
  1737.  
  1738. Are not yet implemented.
  1739.  
  1740. =head2 bmod()
  1741.  
  1742.     use Math::BigRat;
  1743.     my $x = Math::BigRat->new('7/4');
  1744.     my $y = Math::BigRat->new('4/3');
  1745.     print $x->bmod($y);
  1746.  
  1747. Set $x to the remainder of the division of $x by $y.
  1748.  
  1749. =head2 bneg()
  1750.  
  1751.     $x->bneg();
  1752.  
  1753. Used to negate the object in-place.
  1754.  
  1755. =head2 is_one()
  1756.  
  1757.     print "$x is 1\n" if $x->is_one();
  1758.  
  1759. Return true if $x is exactly one, otherwise false.
  1760.  
  1761. =head2 is_zero()
  1762.  
  1763.     print "$x is 0\n" if $x->is_zero();
  1764.  
  1765. Return true if $x is exactly zero, otherwise false.
  1766.  
  1767. =head2 is_pos()/is_positive()
  1768.  
  1769.     print "$x is >= 0\n" if $x->is_positive();
  1770.  
  1771. Return true if $x is positive (greater than or equal to zero), otherwise
  1772. false. Please note that '+inf' is also positive, while 'NaN' and '-inf' aren't.
  1773.  
  1774. C<is_positive()> is an alias for C<is_pos()>.
  1775.  
  1776. =head2 is_neg()/is_negative()
  1777.  
  1778.     print "$x is < 0\n" if $x->is_negative();
  1779.  
  1780. Return true if $x is negative (smaller than zero), otherwise false. Please
  1781. note that '-inf' is also negative, while 'NaN' and '+inf' aren't.
  1782.  
  1783. C<is_negative()> is an alias for C<is_neg()>.
  1784.  
  1785. =head2 is_int()
  1786.  
  1787.     print "$x is an integer\n" if $x->is_int();
  1788.  
  1789. Return true if $x has a denominator of 1 (e.g. no fraction parts), otherwise
  1790. false. Please note that '-inf', 'inf' and 'NaN' aren't integer.
  1791.  
  1792. =head2 is_odd()
  1793.  
  1794.     print "$x is odd\n" if $x->is_odd();
  1795.  
  1796. Return true if $x is odd, otherwise false.
  1797.  
  1798. =head2 is_even()
  1799.  
  1800.     print "$x is even\n" if $x->is_even();
  1801.  
  1802. Return true if $x is even, otherwise false.
  1803.  
  1804. =head2 bceil()
  1805.  
  1806.     $x->bceil();
  1807.  
  1808. Set $x to the next bigger integer value (e.g. truncate the number to integer
  1809. and then increment it by one).
  1810.  
  1811. =head2 bfloor()
  1812.     
  1813.     $x->bfloor();
  1814.  
  1815. Truncate $x to an integer value.
  1816.  
  1817. =head2 bsqrt()
  1818.     
  1819.     $x->bsqrt();
  1820.  
  1821. Calculate the square root of $x.
  1822.  
  1823. =head2 broot()
  1824.     
  1825.     $x->broot($n);
  1826.  
  1827. Calculate the N'th root of $x.
  1828.  
  1829. =head2 badd()/bmul()/bsub()/bdiv()/bdec()/binc()
  1830.  
  1831. Please see the documentation in L<Math::BigInt>.
  1832.  
  1833. =head2 copy()
  1834.  
  1835.     my $z = $x->copy();
  1836.  
  1837. Makes a deep copy of the object.
  1838.  
  1839. Please see the documentation in L<Math::BigInt> for further details.
  1840.  
  1841. =head2 bstr()/bsstr()
  1842.  
  1843.     my $x = Math::BigInt->new('8/4');
  1844.     print $x->bstr(),"\n";            # prints 1/2
  1845.     print $x->bsstr(),"\n";            # prints 1/2
  1846.  
  1847. Return a string representating this object.
  1848.  
  1849. =head2 bacmp()/bcmp()
  1850.  
  1851. Used to compare numbers.
  1852.  
  1853. Please see the documentation in L<Math::BigInt> for further details.
  1854.  
  1855. =head2 blsft()/brsft()
  1856.  
  1857. Used to shift numbers left/right.
  1858.  
  1859. Please see the documentation in L<Math::BigInt> for further details.
  1860.  
  1861. =head2 bpow()
  1862.  
  1863.     $x->bpow($y);
  1864.  
  1865. Compute $x ** $y.
  1866.  
  1867. Please see the documentation in L<Math::BigInt> for further details.
  1868.  
  1869. =head2 bexp()
  1870.  
  1871.     $x->bexp($accuracy);        # calculate e ** X
  1872.  
  1873. Calculates two integers A and B so that A/B is equal to C<e ** $x>, where C<e> is
  1874. Euler's number.
  1875.  
  1876. This method was added in v0.20 of Math::BigRat (May 2007).
  1877.  
  1878. See also L<blog()>.
  1879.  
  1880. =head2 bnok()
  1881.  
  1882.     $x->bnok($y);           # x over y (binomial coefficient n over k)
  1883.  
  1884. Calculates the binomial coefficient n over k, also called the "choose"
  1885. function. The result is equivalent to:
  1886.  
  1887.     ( n )      n!
  1888.     | - |  = -------
  1889.     ( k )    k!(n-k)!
  1890.  
  1891. This method was added in v0.20 of Math::BigRat (May 2007).
  1892.  
  1893. =head2 config()
  1894.  
  1895.         use Data::Dumper;
  1896.  
  1897.         print Dumper ( Math::BigRat->config() );
  1898.         print Math::BigRat->config()->{lib},"\n";
  1899.  
  1900. Returns a hash containing the configuration, e.g. the version number, lib
  1901. loaded etc. The following hash keys are currently filled in with the
  1902. appropriate information.
  1903.  
  1904.         key             RO/RW   Description
  1905.                                 Example
  1906.         ============================================================
  1907.         lib             RO      Name of the Math library
  1908.                                 Math::BigInt::Calc
  1909.         lib_version     RO      Version of 'lib'
  1910.                                 0.30
  1911.         class           RO      The class of config you just called
  1912.                                 Math::BigRat
  1913.         version         RO      version number of the class you used
  1914.                                 0.10
  1915.         upgrade         RW      To which class numbers are upgraded
  1916.                                 undef
  1917.         downgrade       RW      To which class numbers are downgraded
  1918.                                 undef
  1919.         precision       RW      Global precision
  1920.                                 undef
  1921.         accuracy        RW      Global accuracy
  1922.                                 undef
  1923.         round_mode      RW      Global round mode
  1924.                                 even
  1925.         div_scale       RW      Fallback accuracy for div
  1926.                                 40
  1927.         trap_nan        RW      Trap creation of NaN (undef = no)
  1928.                                 undef
  1929.         trap_inf        RW      Trap creation of +inf/-inf (undef = no)
  1930.                                 undef
  1931.  
  1932. By passing a reference to a hash you may set the configuration values. This
  1933. works only for values that a marked with a C<RW> above, anything else is
  1934. read-only.
  1935.  
  1936. =head1 BUGS
  1937.  
  1938. Some things are not yet implemented, or only implemented half-way:
  1939.  
  1940. =over 2
  1941.  
  1942. =item inf handling (partial)
  1943.  
  1944. =item NaN handling (partial)
  1945.  
  1946. =item rounding (not implemented except for bceil/bfloor)
  1947.  
  1948. =item $x ** $y where $y is not an integer
  1949.  
  1950. =item bmod(), blog(), bmodinv() and bmodpow() (partial)
  1951.  
  1952. =back
  1953.  
  1954. =head1 LICENSE
  1955.  
  1956. This program is free software; you may redistribute it and/or modify it under
  1957. the same terms as Perl itself.
  1958.  
  1959. =head1 SEE ALSO
  1960.  
  1961. L<Math::BigFloat> and L<Math::Big> as well as L<Math::BigInt::BitVect>,
  1962. L<Math::BigInt::Pari> and  L<Math::BigInt::GMP>.
  1963.  
  1964. See L<http://search.cpan.org/search?dist=bignum> for a way to use
  1965. Math::BigRat.
  1966.  
  1967. The package at L<http://search.cpan.org/search?dist=Math%3A%3ABigRat>
  1968. may contain more documentation and examples as well as testcases.
  1969.  
  1970. =head1 AUTHORS
  1971.  
  1972. (C) by Tels L<http://bloodgate.com/> 2001 - 2007.
  1973.  
  1974. =cut
  1975.