mpf_sub bug (essentially same as reldiff bug)

Kevin Ryde user42 at zip.com.au
Thu May 13 23:07:03 CEST 2004


I think the patch below may do the trick, the problem was truncation
to destination precision before stripping high zeros from the rest of
the longer operand.  The worst effect of this was to give a result 0
for two unequal operands, as you found.

At the same time I noticed the exponent in the case of a result 0 was
not right, which can affect certain subsequent operations.

-- 
All followups to gmp-bugs at swox.com please.

-------------- next part --------------
--- sub.c.~1.11.~	2002-05-16 09:20:45.000000000 +1000
+++ sub.c	2004-05-13 17:59:04.000000000 +1000
@@ -1,6 +1,6 @@
 /* mpf_sub -- Subtract two floats.
 
-Copyright 1993, 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
+Copyright 1993, 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free Software
 Foundation, Inc.
 
 This file is part of the GNU MP Library.
@@ -105,26 +105,29 @@
 
 		  if (usize == 0)
 		    {
+                      /* u cancels high limbs of v, result is rest of v */
+		      negate ^= 1;
+                    cancellation:
+                      /* strip high zeros before truncating to prec */
+                      while (vsize != 0 && vp[vsize - 1] == 0)
+                        {
+                          vsize--;
+                          exp--;
+                        }
 		      if (vsize > prec)
 			{
 			  vp += vsize - prec;
 			  vsize = prec;
 			}
-		      rsize = vsize;
-		      tp = (mp_ptr) vp;
-		      negate ^= 1;
-		      goto normalize;
+                      MPN_COPY_INCR (rp, vp, vsize);
+                      rsize = vsize;
+                      goto done;
 		    }
 		  if (vsize == 0)
 		    {
-		      if (usize > prec)
-			{
-			  up += usize - prec;
-			  usize = prec;
-			}
-		      rsize = usize;
-		      tp = (mp_ptr) up;
-		      goto normalize;
+                      vp = up;
+                      vsize = usize;
+                      goto cancellation;
 		    }
 		}
 	      while (up[usize - 1] == vp[vsize - 1]);
@@ -401,6 +404,8 @@
 
  done:
   r->_mp_size = negate ? -rsize : rsize;
+  if (rsize == 0)
+    exp = 0;
   r->_mp_exp = exp;
   TMP_FREE (marker);
 }


More information about the gmp-bugs mailing list