Upgrade to Math::BigRat 0.07.
authorJarkko Hietaniemi <jhi@iki.fi>
Wed, 5 Jun 2002 00:27:47 +0000 (00:27 +0000)
committerJarkko Hietaniemi <jhi@iki.fi>
Wed, 5 Jun 2002 00:27:47 +0000 (00:27 +0000)
p4raw-id: //depot/perl@16994

lib/Math/BigRat.pm
lib/Math/BigRat/t/bigfltpm.inc
lib/Math/BigRat/t/bigfltrt.t
lib/Math/BigRat/t/bigrat.t
lib/Math/BigRat/t/bigratpm.inc
lib/Math/BigRat/t/bigratpm.t

index e08e661..41c4e10 100644 (file)
@@ -1,4 +1,7 @@
-#!/usr/bin/perl -w
+
+#
+# "Tax the rat farms."
+#
 
 # The following hash values are used:
 #   sign : +,-,NaN,+inf,-inf
@@ -10,7 +13,7 @@
 
 package Math::BigRat;
 
-require 5.005_02;
+require 5.005_03;
 use strict;
 
 use Exporter;
@@ -21,7 +24,7 @@ use vars qw($VERSION @ISA $PACKAGE @EXPORT_OK $upgrade $downgrade
 @ISA = qw(Exporter Math::BigFloat);
 @EXPORT_OK = qw();
 
-$VERSION = '0.06';
+$VERSION = '0.07';
 
 use overload;                          # inherit from Math::BigFloat
 
@@ -70,7 +73,6 @@ sub _new_from_float
     # 1 / 1 => 10/1
     $self->{_n}->blsft($f->{_e},10) unless $f->{_e}->is_zero();        
     }
-#  print "float new $self->{_n} / $self->{_d}\n";
   $self;
   }
 
@@ -83,26 +85,12 @@ sub new
 
   my $self = { }; bless $self,$class;
  
-#  print "ref ",ref($n),"\n";
-#  if (ref($n))
-#    {
-#  print "isa float " if $n->isa('Math::BigFloat');
-#  print "isa int " if $n->isa('Math::BigInt');
-#  print "isa rat " if $n->isa('Math::BigRat');
-#  print "isa lite " if $n->isa('Math::BigInt::Lite');
-#    }
-#  else
-#    {
-#    print "scalar $n\n";
-#    }
   # input like (BigInt,BigInt) or (BigFloat,BigFloat) not handled yet
 
   if ((!defined $d) && (ref $n) && (!$n->isa('Math::BigRat')))
     {
-#    print "is ref, but not rat\n";
     if ($n->isa('Math::BigFloat'))
       {
-   #   print "is ref, and float\n";
       return $self->_new_from_float($n)->bnorm();
       }
     if ($n->isa('Math::BigInt'))
@@ -114,7 +102,6 @@ sub new
       }
     if ($n->isa('Math::BigInt::Lite'))
       {
-#      print "is ref, and lite\n";
       $self->{_n} = $MBI->new($$n);            # "mantissa" = $n
       $self->{_d} = $MBI->bone();
       $self->{sign} = $self->{_n}->{sign}; $self->{_n}->{sign} = '+';
@@ -122,8 +109,6 @@ sub new
       }
     }
   return $n->copy() if ref $n;
-      
-#  print "is string\n";
 
   if (!defined $n)
     {
@@ -173,8 +158,9 @@ sub new
   # simple string input
   if (($n =~ /[\.eE]/))
     {
+    # work around bug in BigFloat that makes 1.1.2 valid
+    return $self->bnan() if $n =~ /\..*\./;
     # looks like a float
-#    print "float-like string $d\n";
     $self->_new_from_float(Math::BigFloat->new($n));
     }
   else
@@ -182,6 +168,8 @@ sub new
     $self->{_n} = $MBI->new($n);
     $self->{_d} = $MBI->bone();
     $self->{sign} = $self->{_n}->{sign}; $self->{_n}->{sign} = '+';
+    return $self->bnan() if $self->{sign} eq 'NaN';
+    return $self->binf($self->{sign}) if $self->{sign} =~ /^[+-]inf$/;
     }
   $self->bnorm();
   }
@@ -198,7 +186,6 @@ sub bstr
     return $s;
     }
 
-#  print "bstr $x->{sign} $x->{_n} $x->{_d}\n";
   my $s = ''; $s = $x->{sign} if $x->{sign} ne '+';    # +3 vs 3
 
   return $s.$x->{_n}->bstr() if $x->{_d}->is_one(); 
@@ -238,8 +225,6 @@ sub bnorm
   $x->{_d}->{_a} = undef; $x->{_n}->{_a} = undef;
   $x->{_d}->{_p} = undef; $x->{_n}->{_p} = undef; 
 
-#  print "$x->{sign} $x->{_n} / $x->{_d} => ";
-
   # no normalize for NaN, inf etc.
   return $x if $x->{sign} !~ /^[+-]$/;
 
@@ -247,27 +232,23 @@ sub bnorm
   if (($x->{sign} =~ /^[+-]$/) &&
       ($x->{_n}->is_zero()))
     {
-    $x->{sign} = '+';                                          # never -0
+    $x->{sign} = '+';                                  # never -0
     $x->{_d} = $MBI->bone() unless $x->{_d}->is_one();
     return $x;
     }
 
-  return $x if $x->{_d}->is_one();
+  return $x if $x->{_d}->is_one();                     # no need to reduce
 
   # reduce other numbers
-  # print "bgcd $x->{_n} (",ref($x->{_n}),") $x->{_d} (",ref($x->{_d}),")\n";
   # disable upgrade in BigInt, otherwise deep recursion
   local $Math::BigInt::upgrade = undef;
   my $gcd = $x->{_n}->bgcd($x->{_d});
 
   if (!$gcd->is_one())
     {
-#    print "normalize $x->{_d} / $x->{_n} => ";
     $x->{_n}->bdiv($gcd);
     $x->{_d}->bdiv($gcd);
-#    print "$x->{_d} / $x->{_n}\n";
     }
-#  print "$x->{_n} / $x->{_d}\n";
   $x;
   }
 
@@ -278,32 +259,32 @@ sub _bnan
   {
   # used by parent class bone() to initialize number to 1
   my $self = shift;
-  $self->{_n} = Math::BigInt->bzero();
-  $self->{_d} = Math::BigInt->bzero();
+  $self->{_n} = $MBI->bzero();
+  $self->{_d} = $MBI->bzero();
   }
 
 sub _binf
   {
   # used by parent class bone() to initialize number to 1
   my $self = shift;
-  $self->{_n} = Math::BigInt->bzero();
-  $self->{_d} = Math::BigInt->bzero();
+  $self->{_n} = $MBI->bzero();
+  $self->{_d} = $MBI->bzero();
   }
 
 sub _bone
   {
   # used by parent class bone() to initialize number to 1
   my $self = shift;
-  $self->{_n} = Math::BigInt->bone();
-  $self->{_d} = Math::BigInt->bone();
+  $self->{_n} = $MBI->bone();
+  $self->{_d} = $MBI->bone();
   }
 
 sub _bzero
   {
   # used by parent class bone() to initialize number to 1
   my $self = shift;
-  $self->{_n} = Math::BigInt->bzero();
-  $self->{_d} = Math::BigInt->bone();
+  $self->{_n} = $MBI->bzero();
+  $self->{_d} = $MBI->bone();
   }
 
 ##############################################################################
@@ -314,13 +295,8 @@ sub badd
   # add two rationals
   my ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
 
-#  print "rat badd\n";
-#  print "ref($x) = ",ref($x),"\n";
-#  print "ref($y) = ",ref($y),"\n";
   $x = $self->new($x) unless $x->isa($self);
   $y = $self->new($y) unless $y->isa($self);
-#  print "ref($x) = ",ref($x),"\n";
-#  print "ref($y) = ",ref($y),"\n";
 
   return $x->bnan() if ($x->{sign} eq 'NaN' || $y->{sign} eq 'NaN');
 
@@ -434,7 +410,6 @@ sub bdiv
   $x = $class->new($x) unless $x->isa($class);
   $y = $class->new($y) unless $y->isa($class);
 
-#  print "rat bdiv $x $y ",ref($x)," ",ref($y),"\n";
   return $self->_div_inf($x,$y)
    if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/) || $y->is_zero());
 
@@ -449,16 +424,75 @@ sub bdiv
   $x->{_n}->bmul($y->{_d});
   $x->{_d}->bmul($y->{_n});
 
-#  print "result $x->{_d} $x->{_n}\n";
   # compute new sign 
   $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
 
   $x->bnorm()->round($a,$p,$r);
-#  print "result $x->{_d} $x->{_n}\n";
   $x;
   }
 
 ##############################################################################
+# bdec/binc
+
+sub bdec
+  {
+  # decrement value (subtract 1)
+  my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
+
+  return $x if $x->{sign} !~ /^[+-]$/; # NaN, inf, -inf
+
+  if ($x->{sign} eq '-')
+    {
+    $x->{_n}->badd($x->{_d});  # -5/2 => -7/2
+    }
+  else
+    {
+    if ($x->{_n}->bacmp($x->{_d}) < 0)
+      {
+      # 1/3 -- => -2/3
+      $x->{_n} = $x->{_d} - $x->{_n};
+      $x->{sign} = '-';
+      }
+    else
+      {
+      $x->{_n}->bsub($x->{_d});                # 5/2 => 3/2
+      }
+    }
+  $x->bnorm()->round(@r);
+
+  #$x->bsub($self->bone())->round(@r);
+  }
+
+sub binc
+  {
+  # increment value (add 1)
+  my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
+  
+  return $x if $x->{sign} !~ /^[+-]$/; # NaN, inf, -inf
+
+  if ($x->{sign} eq '-')
+    {
+    if ($x->{_n}->bacmp($x->{_d}) < 0)
+      {
+      # -1/3 ++ => 2/3 (overflow at 0)
+      $x->{_n} = $x->{_d} - $x->{_n};
+      $x->{sign} = '+';
+      }
+    else
+      {
+      $x->{_n}->bsub($x->{_d});                # -5/2 => -3/2
+      }
+    }
+  else
+    {
+    $x->{_n}->badd($x->{_d});  # 5/2 => 7/2
+    }
+  $x->bnorm()->round(@r);
+
+  #$x->badd($self->bone())->round(@r);
+  }
+
+##############################################################################
 # is_foo methods (the rest is inherited)
 
 sub is_int
@@ -523,7 +557,9 @@ BEGIN
 sub numerator
   {
   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
+
+  return $MBI->new($x->{sign}) if ($x->{sign} !~ /^[+-]$/);
+
   my $n = $x->{_n}->copy(); $n->{sign} = $x->{sign};
   $n;
   }
@@ -532,6 +568,7 @@ sub denominator
   {
   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
 
+  return $MBI->new($x->{sign}) if ($x->{sign} !~ /^[+-]$/);
   $x->{_d}->copy(); 
   }
 
@@ -539,9 +576,13 @@ sub parts
   {
   my ($self,$x) = ref($_[0]) ? (ref($_[0]),$_[0]) : objectify(1,@_);
 
+  return ($self->bnan(),$self->bnan()) if $x->{sign} eq 'NaN';
+  return ($self->binf(),$self->binf()) if $x->{sign} eq '+inf';
+  return ($self->binf('-'),$self->binf()) if $x->{sign} eq '-inf';
+
   my $n = $x->{_n}->copy();
   $n->{sign} = $x->{sign};
-  return ($x->{_n}->copy(),$x->{_d}->copy());
+  return ($n,$x->{_d}->copy());
   }
 
 sub length
@@ -564,9 +605,10 @@ sub bceil
   return $x unless $x->{sign} =~ /^[+-]$/;
   return $x if $x->{_d}->is_one();             # 22/1 => 22, 0/1 => 0
 
-  $x->{_n}->bdiv($x->{_d});                    # 22/7 => 3/1
+  $x->{_n}->bdiv($x->{_d});                    # 22/7 => 3/1 w/ truncate
   $x->{_d}->bone();
   $x->{_n}->binc() if $x->{sign} eq '+';       # +22/7 => 4/1
+  $x->{sign} = '+' if $x->{_n}->is_zero();     # -0 => 0
   $x;
   }
 
@@ -577,7 +619,7 @@ sub bfloor
   return $x unless $x->{sign} =~ /^[+-]$/;
   return $x if $x->{_d}->is_one();             # 22/1 => 22, 0/1 => 0
 
-  $x->{_n}->bdiv($x->{_d});                    # 22/7 => 3/1
+  $x->{_n}->bdiv($x->{_d});                    # 22/7 => 3/1 w/ truncate
   $x->{_d}->bone();
   $x->{_n}->binc() if $x->{sign} eq '-';       # -22/7 => -4/1
   $x;
@@ -585,7 +627,14 @@ sub bfloor
 
 sub bfac
   {
-  return Math::BigRat->bnan();
+  my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
+
+  if (($x->{sign} eq '+') && ($x->{_d}->is_one()))
+    {
+    $x->{_n}->bfac();
+    return $x->round(@r);
+    }
+  $x->bnan();
   }
 
 sub bpow
@@ -607,12 +656,49 @@ sub bpow
  #  return $x->bnan() if $y->{sign} eq '-';
   return $x->round(@r) if $x->is_zero();  # 0**y => 0 (if not y <= 0)
 
+  # shortcut y/1 (and/or x/1)
+  if ($y->{_d}->is_one())
+    {
+    # shortcut for x/1 and y/1
+    if ($x->{_d}->is_one())
+      {
+      $x->{_n}->bpow($y->{_n});                # x/1 ** y/1 => (x ** y)/1
+      if ($y->{sign} eq '-')
+        {
+        # 0.2 ** -3 => 1/(0.2 ** 3)
+        ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n});     # swap
+        }
+      # correct sign; + ** + => +
+      if ($x->{sign} eq '-')
+        {
+        # - * - => +, - * - * - => -
+        $x->{sign} = '+' if $y->{_n}->is_even();       
+        }
+      return $x->round(@r);
+      }
+    # x/z ** y/1
+    $x->{_n}->bpow($y->{_n});          # 5/2 ** y/1 => 5 ** y / 2 ** y
+    $x->{_d}->bpow($y->{_n});
+    if ($y->{sign} eq '-')
+      {
+      # 0.2 ** -3 => 1/(0.2 ** 3)
+      ($x->{_n},$x->{_d}) = ($x->{_d},$x->{_n});       # swap
+      }
+    # correct sign; + ** + => +
+    if ($x->{sign} eq '-')
+      {
+      # - * - => +, - * - * - => -
+      $x->{sign} = '+' if $y->{_n}->is_even(); 
+      }
+    return $x->round(@r);
+    }
+
+  # regular calculation (this is wrong for d/e ** f/g)
   my $pow2 = $self->__one();
-  my $y1 = Math::BigInt->new($y->{_n}/$y->{_d})->babs();
-  my $two = Math::BigInt->new(2);
+  my $y1 = $MBI->new($y->{_n}/$y->{_d})->babs();
+  my $two = $MBI->new(2);
   while (!$y1->is_one())
     {
-    print "at $y1 (= $x)\n";
     $pow2->bmul($x) if $y1->is_odd();
     $y1->bdiv($two);
     $x->bmul($x);
@@ -786,13 +872,9 @@ sub import
     }
   else
     {
-    # MBI not loaded, or with ne "Math::BigInt"
+    # MBI not loaded, or not with "Math::BigInt"
     $lib .= ",$mbilib" if defined $mbilib;
 
-#  my @parts = split /::/, $MBI;                # Math::BigInt => Math BigInt
-#  my $file = pop @parts; $file .= '.pm';       # BigInt => BigInt.pm
-#  $file = File::Spec->catfile (@parts, $file);
-
     if ($] < 5.006)
       {
       # Perl < 5.6.0 dies with "out of memory!" when eval() and ':constant' is
@@ -902,33 +984,29 @@ BigInts.
 
 Returns a copy of the object as BigInt by truncating it to integer.
 
-=head2 bfac()/blog()
+=head2 bfac()
 
-Are not yet implemented.
-
-=head2 bround()/round()/bfround()
-
-Are not yet implemented.
+       $x->bfac();
 
+Calculates the factorial of $x. For instance:
 
-=head1 BUGS
+       print Math::BigRat->new('3/1')->bfac(),"\n";    # 1*2*3
+       print Math::BigRat->new('5/1')->bfac(),"\n";    # 1*2*3*4*5
 
-=over 2
+Only works for integers for now.
 
-=item perl -Mbigrat -le 'print 1 + 2/3'
+=head2 blog()
 
-This produces wrongly NaN. It is unclear why. The following variants all work:
+Is not yet implemented.
 
-       perl -Mbigrat -le 'print 1/3 + 2/3'
-       perl -Mbigrat -le 'print 1/3 + 2'
+=head2 bround()/round()/bfround()
 
-This also does not work:
+Are not yet implemented.
 
-       perl -Mbigrat -le 'print 1+3+1/2'
 
-=back
+=head1 BUGS
 
-Please see also L<Math::BigInt>.
+Some things are not yet implemented, or only implemented half-way.
 
 =head1 LICENSE
 
index 5b3f4f1..36bb35d 100644 (file)
@@ -4,7 +4,7 @@ ok ($class->config()->{lib},$CL);
 
 while (<DATA>)
   {
-  chop;
+  chomp;
   $_ =~ s/#.*$//;      # remove comments
   $_ =~ s/\s+$//;      # trailing spaces
   next if /^$/;                # skip empty lines & comments
@@ -1054,10 +1054,10 @@ abc:1:abc:NaN
 152403346:12345:4321
 87654321:87654321:0
 # now some floating point tests
-123:2.5:0.5
-1230:2.5:0
-123.4:2.5:0.9
-123e1:25:5
+#123:2.5:0.5
+#1230:2.5:0
+#123.4:2.5:0.9
+#123e1:25:5
 &ffac
 Nanfac:NaN
 -1:NaN
index a456320..d408b23 100755 (executable)
@@ -41,4 +41,4 @@ $CL = "Math::BigInt::Calc";
 ok (1,1);
 
 # does not fully work yet  
-# require 'bigfltpm.inc';      # all tests here for sharing
+#require 'bigfltpm.inc';       # all tests here for sharing
index f1aba64..b59d9f0 100755 (executable)
@@ -8,7 +8,7 @@ BEGIN
   $| = 1;
   chdir 't' if -d 't';
   unshift @INC, '../lib'; # for running manually
-  plan tests => 83;
+  plan tests => 136;
   }
 
 # testing of Math::BigRat
@@ -45,99 +45,151 @@ foreach my $func (qw/new bnorm/)
   $x = $cr->$func('0.1/0.1');  ok ($x,'1');
   $x = $cr->$func('1e2/10');   ok ($x,10);
   $x = $cr->$func('1e2/1e1');  ok ($x,10);
-  $x = $cr->$func('1 / 3');            ok ($x,'1/3');
+  $x = $cr->$func('1 / 3');    ok ($x,'1/3');
   $x = $cr->$func('-1 / 3');   ok ($x,'-1/3');
-  $x = $cr->$func('NaN');              ok ($x,'NaN');
-  $x = $cr->$func('inf');              ok ($x,'inf');
-  $x = $cr->$func('-inf');             ok ($x,'-inf');
-  $x = $cr->$func('1/');               ok ($x,'NaN');
+  $x = $cr->$func('NaN');      ok ($x,'NaN');
+  $x = $cr->$func('inf');      ok ($x,'inf');
+  $x = $cr->$func('-inf');     ok ($x,'-inf');
+  $x = $cr->$func('1/');       ok ($x,'NaN');
 
   # input ala '1+1/3' isn't parsed ok yet
-  $x = $cr->$func('1+1/3');            ok ($x,'NaN');
+  $x = $cr->$func('1+1/3');    ok ($x,'NaN');
 
   ############################################################################
   # other classes as input
 
-  $x = $cr->$func($mbi->new(1231));            ok ($x,'1231');
-  $x = $cr->$func($mbf->new(1232));            ok ($x,'1232');
+  $x = $cr->$func($mbi->new(1231));    ok ($x,'1231');
+  $x = $cr->$func($mbf->new(1232));    ok ($x,'1232');
   $x = $cr->$func($mbf->new(1232.3));  ok ($x,'12323/10');
   }
+$x =  $cr->new('-0'); ok ($x,'0'); ok ($x->{_n}, '0'); ok ($x->{_d},'1');
+$x =  $cr->new('NaN'); ok ($x,'NaN'); ok ($x->{_n}, '0'); ok ($x->{_d},'0');
+$x =  $cr->new('-NaN'); ok ($x,'NaN'); ok ($x->{_n}, '0'); ok ($x->{_d},'0');
+$x =  $cr->new('-1r4'); ok ($x,'NaN'); ok ($x->{_n}, '0'); ok ($x->{_d},'0');
+
+$x =  $cr->new('+inf'); ok ($x,'inf'); ok ($x->{_n}, '0'); ok ($x->{_d},'0');
+$x =  $cr->new('-inf'); ok ($x,'-inf'); ok ($x->{_n}, '0'); ok ($x->{_d},'0');
+$x =  $cr->new('123a4'); ok ($x,'NaN'); ok ($x->{_n}, '0'); ok ($x->{_d},'0');
+
+# wrong inputs
+$x =  $cr->new('1e2e2'); ok ($x,'NaN'); ok ($x->{_n}, '0'); ok ($x->{_d},'0');
+$x =  $cr->new('1+2+2'); ok ($x,'NaN'); ok ($x->{_n}, '0'); ok ($x->{_d},'0');
+# failed due to BigFlaot bug
+$x =  $cr->new('1.2.2'); ok ($x,'NaN'); ok ($x->{_n}, '0'); ok ($x->{_d},'0');
+
+ok ($cr->new('123a4'),'NaN');
+ok ($cr->new('123e4'),'1230000');
+ok ($cr->new('-NaN'),'NaN');
+ok ($cr->new('NaN'),'NaN');
+ok ($cr->new('+inf'),'inf');
+ok ($cr->new('-inf'),'-inf');
 
 ##############################################################################
 # mixed arguments
 
-ok (Math::BigRat->new('3/7')->badd(1),'10/7');
-ok (Math::BigRat->new('3/10')->badd(1.1),'7/5');
-ok (Math::BigRat->new('3/7')->badd(Math::BigInt->new(1)),'10/7');
-ok (Math::BigRat->new('3/10')->badd(Math::BigFloat->new('1.1')),'7/5');
+ok ($cr->new('3/7')->badd(1),'10/7');
+ok ($cr->new('3/10')->badd(1.1),'7/5');
+ok ($cr->new('3/7')->badd($mbi->new(1)),'10/7');
+ok ($cr->new('3/10')->badd($mbf->new('1.1')),'7/5');
 
-ok (Math::BigRat->new('3/7')->bsub(1),'-4/7');
-ok (Math::BigRat->new('3/10')->bsub(1.1),'-4/5');
-ok (Math::BigRat->new('3/7')->bsub(Math::BigInt->new(1)),'-4/7');
-ok (Math::BigRat->new('3/10')->bsub(Math::BigFloat->new('1.1')),'-4/5');
+ok ($cr->new('3/7')->bsub(1),'-4/7');
+ok ($cr->new('3/10')->bsub(1.1),'-4/5');
+ok ($cr->new('3/7')->bsub($mbi->new(1)),'-4/7');
+ok ($cr->new('3/10')->bsub($mbf->new('1.1')),'-4/5');
 
-ok (Math::BigRat->new('3/7')->bmul(1),'3/7');
-ok (Math::BigRat->new('3/10')->bmul(1.1),'33/100');
-ok (Math::BigRat->new('3/7')->bmul(Math::BigInt->new(1)),'3/7');
-ok (Math::BigRat->new('3/10')->bmul(Math::BigFloat->new('1.1')),'33/100');
+ok ($cr->new('3/7')->bmul(1),'3/7');
+ok ($cr->new('3/10')->bmul(1.1),'33/100');
+ok ($cr->new('3/7')->bmul($mbi->new(1)),'3/7');
+ok ($cr->new('3/10')->bmul($mbf->new('1.1')),'33/100');
 
-ok (Math::BigRat->new('3/7')->bdiv(1),'3/7');
-ok (Math::BigRat->new('3/10')->bdiv(1.1),'3/11');
-ok (Math::BigRat->new('3/7')->bdiv(Math::BigInt->new(1)),'3/7');
-ok (Math::BigRat->new('3/10')->bdiv(Math::BigFloat->new('1.1')),'3/11');
+ok ($cr->new('3/7')->bdiv(1),'3/7');
+ok ($cr->new('3/10')->bdiv(1.1),'3/11');
+ok ($cr->new('3/7')->bdiv($mbi->new(1)),'3/7');
+ok ($cr->new('3/10')->bdiv($mbf->new('1.1')),'3/11');
 
 ##############################################################################
-$x = Math::BigRat->new('1/4'); $y = Math::BigRat->new('1/3');
+$x = $cr->new('1/4'); $y = $cr->new('1/3');
 ok ($x + $y, '7/12');
 ok ($x * $y, '1/12');
 ok ($x / $y, '3/4');
 
-$x = Math::BigRat->new('7/5'); $x *= '3/2'; 
+$x = $cr->new('7/5'); $x *= '3/2'; 
 ok ($x,'21/10');
 $x -= '0.1';
 ok ($x,'2');   # not 21/10
 
-$x = Math::BigRat->new('2/3');         $y = Math::BigRat->new('3/2');
+$x = $cr->new('2/3');          $y = $cr->new('3/2');
 ok ($x > $y,'');               
 ok ($x < $y,1);
 ok ($x == $y,'');
 
-$x = Math::BigRat->new('-2/3');                $y = Math::BigRat->new('3/2');
+$x = $cr->new('-2/3');         $y = $cr->new('3/2');
 ok ($x > $y,'');               
 ok ($x < $y,'1');
 ok ($x == $y,'');
 
-$x = Math::BigRat->new('-2/3');                $y = Math::BigRat->new('-2/3');
+$x = $cr->new('-2/3');         $y = $cr->new('-2/3');
 ok ($x > $y,'');               
 ok ($x < $y,'');
 ok ($x == $y,'1');
 
-$x = Math::BigRat->new('-2/3');                $y = Math::BigRat->new('-1/3');
+$x = $cr->new('-2/3');         $y = $cr->new('-1/3');
 ok ($x > $y,'');               
 ok ($x < $y,'1');
 ok ($x == $y,'');
 
-$x = Math::BigRat->new('-124');                $y = Math::BigRat->new('-122');
+$x = $cr->new('-124');         $y = $cr->new('-122');
 ok ($x->bacmp($y),1);
 
-$x = Math::BigRat->new('-124');                $y = Math::BigRat->new('-122');
+$x = $cr->new('-124');         $y = $cr->new('-122');
 ok ($x->bcmp($y),-1);
 
-$x = Math::BigRat->new('3/7');         $y = Math::BigRat->new('5/7');
+$x = $cr->new('3/7');          $y = $cr->new('5/7');
 ok ($x+$y,'8/7');
 
-$x = Math::BigRat->new('3/7');         $y = Math::BigRat->new('5/7');
+$x = $cr->new('3/7');          $y = $cr->new('5/7');
 ok ($x*$y,'15/49');
 
-$x = Math::BigRat->new('3/5');         $y = Math::BigRat->new('5/7');
+$x = $cr->new('3/5');          $y = $cr->new('5/7');
 ok ($x*$y,'3/7');
 
-$x = Math::BigRat->new('3/5');         $y = Math::BigRat->new('5/7');
+$x = $cr->new('3/5');          $y = $cr->new('5/7');
 ok ($x/$y,'21/25');
 
-$x = Math::BigRat->new('-144/9'); $x->bsqrt(); ok ($x,'NaN');
-$x = Math::BigRat->new('144/9');  $x->bsqrt(); ok ($x,'4');
+$x = $cr->new('-144/9')->bsqrt();      ok ($x,'NaN');
+$x = $cr->new('144/9')->bsqrt();       ok ($x,'4');
 
+##############################################################################
+# bpow
+
+$x = $cr->new('2/1');  $z = $x->bpow('3/1'); ok ($x,'8');
+
+##############################################################################
+# bfac
+
+$x = $cr->new('1');  $x->bfac(); ok ($x,'1');
+for (my $i = 0; $i < 8; $i++)
+  {
+  $x = $cr->new("$i/1")->bfac(); ok ($x,$mbi->new($i)->bfac());
+  }
+
+# test for $self->bnan() vs. $x->bnan();
+$x = $cr->new('-1'); $x->bfac(); ok ($x,'NaN');        
+
+##############################################################################
+# binc/bdec
+
+$x =  $cr->new('3/2'); ok ($x->binc(),'5/2');
+$x =  $cr->new('15/6'); ok ($x->bdec(),'3/2');
+
+##############################################################################
+# bfloor/bceil
+
+$x = $cr->new('-7/7'); ok ($x->{_n}, '1'); ok ($x->{_d}, '1');
+$x = $cr->new('-7/7')->bfloor(); ok ($x->{_n}, '1'); ok ($x->{_d}, '1');
+
+##############################################################################
 # done
 
 1;
index bbec697..0f77c33 100644 (file)
@@ -4,7 +4,7 @@ ok ($class->config()->{lib},$CL);
 
 while (<DATA>)
   {
-  chop;
+  chomp;
   $_ =~ s/#.*$//;      # remove comments
   $_ =~ s/\s+$//;      # trailing spaces
   next if /^$/;                # skip empty lines & comments
@@ -87,6 +87,8 @@ while (<DATA>)
         $try .= '$x->bacmp($y);';
       } elsif ($f eq "bpow") {
         $try .= '$x ** $y;';
+      } elsif ($f eq "fpow") {
+        $try .= '$x->bpow($y);';
       } elsif ($f eq "badd") {
         $try .= '$x + $y;';
       } elsif ($f eq "bsub") {
@@ -568,15 +570,17 @@ NaN:0
 NaN:0
 -inf:1
 +inf:0
-#&parts
-#0:0 1
-#1:1 0
-#123:123 0
-#-123:-123 0
-#-1200:-12 2
-#NaNparts:NaN NaN
-#+inf:inf inf
-#-inf:-inf inf
+&parts
+0:0 1
+1:1 1
+123:123 1
+-123:-123 1
+-1200:-1200 1
+5/7:5 7
+-5/7:-5 7
+NaNparts:NaN NaN
++inf:inf inf
+-inf:-inf inf
 #&exponent
 #0:1
 #1:0
@@ -631,6 +635,20 @@ abc:NaN
 -51:-51
 -51.2:-52
 12.2:12
+3/7:0
+6/7:0
+7/7:1
+8/7:1
+13/7:1
+14/7:2
+15/7:2
+-3/7:-1
+-6/7:-1
+-7/1:-7
+-8/7:-2
+-13/7:-2
+-14/7:-2
+-15/7:-3
 &fceil
 0:0
 abc:NaN
@@ -640,3 +658,64 @@ abc:NaN
 -51:-51
 -51.2:-51
 12.2:13
+3/7:1
+6/7:1
+8/7:2
+13/7:2
+14/7:2
+15/7:3
+-3/7:0
+-6/7:0
+-8/7:-1
+-13/7:-1
+-14/7:-2
+-15/7:-2
+&ffac
+NaN:NaN
+1:1
+-1:NaN
+&bpow
+# bpow test for overload of **
+2:2:4
+3:3:27
+&fpow
+2/1:3/1:8
+3/1:3/1:27
+5/2:3/1:125/8
+-2/1:3/1:-8
+-3/1:3/1:-27
+-5/2:3/1:-125/8
+-2/1:4/1:16
+-3/1:4/1:81
+-5/2:4/1:625/16
+-5/2:-4/1:16/625
+1/5:-3:125
+-1/5:-3:-125
+&numerator
+NaN:NaN
+inf:inf
+-inf:-inf
+3/7:3
+-3/7:-3
+0:0
+1:1
+&denominator
+NaN:NaN
+inf:inf
+-inf:-inf
+3/7:7
+0:1
+1/1:1
+-3/7:7
+&finc
+3/2:5/2
+-15/6:-3/2
+NaN:NaN
+-1/3:2/3
+-2/7:5/7
+&fdec
+15/6:3/2
+-3/2:-5/2
+1/3:-2/3
+2/7:-5/7
+NaN:NaN
index 37c431c..1ef0a88 100755 (executable)
@@ -26,7 +26,7 @@ BEGIN
     }
   print "# INC = @INC\n";
 
-  plan tests => 414;
+  plan tests => 491;
   }
 
 use Math::BigRat;