[Gnucash-changes] r13107 - gnucash/trunk - Some gnc-numeric fixes (more to come).

Derek Atkins warlord at cvs.gnucash.org
Sat Feb 4 20:41:28 EST 2006


Author: warlord
Date: 2006-02-04 20:41:27 -0500 (Sat, 04 Feb 2006)
New Revision: 13107
Trac: http://svn.gnucash.org/trac/changeset/13107

Modified:
   gnucash/trunk/ChangeLog
   gnucash/trunk/lib/libqof/qof/gnc-numeric.c
Log:
Some gnc-numeric fixes (more to come).

	  - Fixes for handling reciprocal values.
	  - Mark a lot of places where potential overflow bugs
	    are not handled.



Modified: gnucash/trunk/ChangeLog
===================================================================
--- gnucash/trunk/ChangeLog	2006-02-05 00:16:38 UTC (rev 13106)
+++ gnucash/trunk/ChangeLog	2006-02-05 01:41:27 UTC (rev 13107)
@@ -1,3 +1,10 @@
+2006-02-04  Derek Atkins  <derek at ihtfp.com>
+
+	* lib/libqof/qof/gnc-numeric.c:
+	  - Fixes for handling reciprocal values.
+	  - Mark a lot of places where potential overflow bugs
+	    are not handled.
+
 2006-02-04  Joshua Sled  <jsled at asynchronous.org>
 
 	* src/doc/xml/gnucash-v2.rnc: Add reverse-engineered schema for

Modified: gnucash/trunk/lib/libqof/qof/gnc-numeric.c
===================================================================
--- gnucash/trunk/lib/libqof/qof/gnc-numeric.c	2006-02-05 00:16:38 UTC (rev 13106)
+++ gnucash/trunk/lib/libqof/qof/gnc-numeric.c	2006-02-05 01:41:27 UTC (rev 13107)
@@ -243,6 +243,14 @@
     return cmp128 (l,r);
   }
 
+  if (a.denom < 0)
+      a.denom *= -1;
+  if (b.denom < 0)
+      b.denom *= -1;
+
+  /* BUG: Possible overflow here..  Also, doesn't properly deal with
+   * reciprocal denominators.
+   */
   aa = a.num * a.denom;
   bb = b.num * b.denom;
 
@@ -270,6 +278,7 @@
 gboolean
 gnc_numeric_equal(gnc_numeric a, gnc_numeric b) 
 {
+  qofint128 l, r;
   if ((a.denom == b.denom) && (a.denom > 0))
   {
     return (a.num == b.num);
@@ -277,8 +286,8 @@
   if ((a.denom > 0) && (b.denom > 0))
   {
     // return (a.num*b.denom == b.num*a.denom);
-    qofint128 l = mult128 (a.num, b.denom);
-    qofint128 r = mult128 (b.num, a.denom);
+    l = mult128 (a.num, b.denom);
+    r = mult128 (b.num, a.denom);
     return equal128 (l, r);
 
 #if ALT_WAY_OF_CHECKING_EQUALITY
@@ -289,14 +298,24 @@
     return 1;
 #endif
   }
-  if ((a.denom < 0) && (b.denom < 0))
-  {    
-    return ((a.num * b.denom) == (a.denom * b.num));
+  if ((a.denom < 0) && (b.denom < 0)) {
+      l = mult128 (a.num, -a.denom);
+      r = mult128 (b.num, -b.denom);
+      return equal128 (l, r);
+  } else {
+      /* BUG: One of the numbers has a reciprocal denom, and the other
+         does not. I just don't know to handle this case in any
+         reasonably overflow-proof yet simple way.  So, this funtion
+         will simply get it wrong whenever the three multiplies
+         overflow 64-bits.  -CAS */
+      if (a.denom < 0) {
+          return ((a.num * -a.denom * b.denom) == b.num);
+      } else {
+          return (a.num == (b.num * a.denom * -b.denom));
+      }
   }
-  else 
-  {
-    return 0;
-  }
+
+  return ((a.num * b.denom) == (a.denom * b.num));
 }
 
 
@@ -355,20 +374,20 @@
   
   if(a.denom < 0) 
   {
-    a.num *= a.denom;
+    a.num *= -a.denom;  /* BUG: overflow not handled.  */
     a.denom = 1;
   }
 
   if(b.denom < 0) 
   {
-    b.num *= b.denom;
+    b.num *= -b.denom;  /* BUG: overflow not handled.  */
     b.denom = 1;
   }
 
   /* Get an exact answer.. same denominator is the common case. */ 
   if(a.denom == b.denom) 
   {
-    sum.num = a.num + b.num;
+    sum.num = a.num + b.num;  /* BUG: overflow not handled.  */
     sum.denom = a.denom;
   }
   else 
@@ -377,7 +396,7 @@
      *    sum.num = a.num*b.denom + b.num*a.denom;
      *    sum.denom = a.denom*b.denom;
      * but the multiply could overflow.  
-     * Computing the LCD minimizes likelyhood of overflow
+     * Computing the LCD minimizes likelihood of overflow
      */
     gint64 lcd;
     qofint128 ca, cb, cab;
@@ -468,12 +487,12 @@
   }
 
   if(a.denom < 0) {
-    a.num *= a.denom;
+    a.num *= -a.denom;  /* BUG: overflow not handled.  */
     a.denom = 1;
   }
 
   if(b.denom < 0) {
-    b.num *= b.denom;
+    b.num *= -b.denom;  /* BUG: overflow not handled.  */
     b.denom = 1;
   }
 
@@ -584,13 +603,13 @@
 
   if(a.denom < 0) 
   {
-    a.num *= a.denom;
+    a.num *= -a.denom;   /* BUG: overflow not handled.  */
     a.denom = 1;
   }
 
   if(b.denom < 0) 
   {
-    b.num *= b.denom;
+    b.num *= -b.denom;   /* BUG: overflow not handled.  */
     b.denom = 1;
   }
 
@@ -793,7 +812,7 @@
   
   /* If the denominator of the input value is negative, get rid of that. */
   if(in.denom < 0) {
-    in.num = in.num * (- in.denom);
+    in.num = in.num * (- in.denom);  /* BUG: overflow not handled.  */
     in.denom = 1;
   }
   
@@ -808,9 +827,9 @@
     denom     = - denom;
     denom_neg = 1;
     temp_a    = (in.num < 0) ? -in.num : in.num;
-    temp_bc   = in.denom * denom;
-    remainder = in.num % temp_bc;
-    out.num   = in.num / temp_bc;
+    temp_bc   = in.denom * denom;  /* BUG: overflow not handled.  */
+    remainder = temp_a % temp_bc;
+    out.num   = temp_a / temp_bc;
     out.denom = - denom;    
   }
   else 
@@ -1081,7 +1100,7 @@
   }
   else 
   {
-    return (double)(in.num * in.denom);
+    return (double)(in.num * -in.denom);
   }
 }
 



More information about the gnucash-changes mailing list