[Gnucash-changes] remove 32-bit limits that show up in division calculations (could cause

Linas Vepstas linas at cvs.gnucash.org
Sat Jun 26 12:16:56 EDT 2004


Log Message:
-----------
remove 32-bit limits that show up in division calculations
(could cause overflow during certain pricing calculations)

Modified Files:
--------------
    gnucash/src/engine:
        gnc-numeric.c

Revision Data
-------------
Index: gnc-numeric.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/gnc-numeric.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -Lsrc/engine/gnc-numeric.c -Lsrc/engine/gnc-numeric.c -u -r1.39 -r1.40
--- src/engine/gnc-numeric.c
+++ src/engine/gnc-numeric.c
@@ -146,16 +146,14 @@
   quotient.lo = lo + n.lo/d;
 
   /* Deal with low remainder bits.
-   * There's probably a more efficient way of doing this.
-   * XXX This algo breaks if the value of teh denominator 
-   * is larger than 2 billion.
+   * Is there a more efficient way of doing this?
    */
-  guint64 rnd = quotient.lo;
-  rnd *= d;
-  rnd &= 0x7fffffff;
-  rnd = (n.lo & 0x7fffffff) - rnd;
-  rnd &= 0x7fffffff;
-  rnd /= d;
+  gncint128 mu = mult128 (quotient.lo, d);
+
+  gint64 nn = 0x7fffffffffffffffULL & n.lo;
+  gint64 rr = 0x7fffffffffffffffULL & mu.lo;
+  gint64 rnd = nn - rr;
+  rnd /= d;   
 
   /* ?? will this ever overflow ? */
   qlo = quotient.lo;
@@ -171,21 +169,20 @@
   return quotient;
 }
 
-/** Return the remainder of a signed 128-bit number modulo a signed 64-bit,
- *  XXX the current algo only works for divisor values less than 1<<31 
- *  (2 billion)
+/** Return the remainder of a signed 128-bit number modulo 
+ *  a signed 64-bit.  I beleive that ths algo is overflow-free,
+ *  but should be audited some more ... 
  */
 static inline gint64
 rem128 (gncint128 n, gint64 d)
 {
   gncint128 quotient = div128 (n,d);
 
-  guint64 rnd = quotient.lo;
-  rnd *= d;
-  rnd &= 0x7fffffff;
-  rnd = (n.lo & 0x7fffffff) - rnd;
-  rnd &= 0x7fffffff;
-  return rnd;
+  gncint128 mu = mult128 (quotient.lo, d);
+
+  gint64 nn = 0x7fffffffffffffffULL & n.lo;
+  gint64 rr = 0x7fffffffffffffffULL & mu.lo;
+  return nn - rr;
 }
 
 /** Return the ratio n/d reduced so that there are no common factors. */


More information about the gnucash-changes mailing list