[Gnucash-changes] Better "carry" flag to not overrun a signed
64-bit int (#114980).
Derek Atkins
warlord at cvs.gnucash.org
Fri Jun 25 12:15:42 EDT 2004
Log Message:
-----------
Better "carry" flag to not overrun a signed 64-bit int (#114980).
* src/engine/gnc-numeric.c: small change to the 128-bit math
routines to actually mark a 'carry bit' to denote numbers
>= 2^63 to fix bug #144980.
Modified Files:
--------------
gnucash:
ChangeLog
gnucash/src/engine:
gnc-numeric.c
Revision Data
-------------
Index: ChangeLog
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/ChangeLog,v
retrieving revision 1.1818
retrieving revision 1.1819
diff -LChangeLog -LChangeLog -u -r1.1818 -r1.1819
--- ChangeLog
+++ ChangeLog
@@ -1,3 +1,9 @@
+2004-06-25 Derek Atkins <derek at ihtfp.com>
+
+ * src/engine/gnc-numeric.c: small change to the 128-bit math
+ routines to actually mark a 'carry bit' to denote numbers
+ >= 2^63 to fix bug #144980.
+
2004-06-24 Derek Atkins <derek at ihtfp.com>
* Makefile.am: be sure to rebuild make-gnucash-patch and
Index: gnc-numeric.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/gnc-numeric.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -Lsrc/engine/gnc-numeric.c -Lsrc/engine/gnc-numeric.c -u -r1.34 -r1.35
--- src/engine/gnc-numeric.c
+++ src/engine/gnc-numeric.c
@@ -49,6 +49,7 @@
guint64 hi;
guint64 lo;
short isneg;
+ short carry;
} gncint128;
/** Multiply a pair of signed 64-bit numbers,
@@ -109,6 +110,7 @@
prod.lo = d0 + (sum<<32);
prod.hi = carry + e1 + f1 + g0 + (g1<<32);
+ prod.carry = (prod.hi || (sum >> 31));
return prod;
}
@@ -162,6 +164,9 @@
quotient.hi += 1;
}
+ /* compute the carry situation */
+ quotient.carry = (quotient.hi || (quotient.lo >> 63));
+
return quotient;
}
@@ -205,7 +210,7 @@
/* num now holds the GCD (Greatest Common Divisor) */
gncint128 red = div128 (n, num);
- if (red.hi)
+ if (red.carry)
{
return gnc_numeric_error (GNC_ERROR_OVERFLOW);
}
@@ -216,22 +221,23 @@
}
#ifdef TEST_128_BIT_MULT
-void pr (gint64 a, gint64 b)
+static void pr (gint64 a, gint64 b)
{
gncint128 prod = mult128 (a,b);
- printf ("%lld * %lld = %lld %llu (0x%llx %llx)\n", a,b, prod.hi, prod.lo, prod.hi, prod.lo);
+ printf ("%lld * %lld = %lld %llu (0x%llx %llx) %hd\n",
+ a, b, prod.hi, prod.lo, prod.hi, prod.lo, prod.carry);
}
-void prd (gint64 a, gint64 b, gint64 c)
+static void prd (gint64 a, gint64 b, gint64 c)
{
gncint128 prod = mult128 (a,b);
gncint128 quot = div128 (prod, c);
gint64 rem = rem128 (prod, c);
- printf ("%lld * %lld / %lld = %lld %llu + %lld (0x%llx %llx)\n", a,b, c, quot.hi,
-quot.lo, rem, quot.hi, quot.lo);
+ printf ("%lld * %lld / %lld = %lld %llu + %lld (0x%llx %llx) %hd\n",
+ a, b, c, quot.hi, quot.lo, rem, quot.hi, quot.lo, quot.carry);
}
-main ()
+int main ()
{
pr (2,2);
@@ -252,6 +258,8 @@
pr (x,x);
pr (x,-x);
+ pr (1000000, 10000000000000);
+
prd (x,x,2);
prd (x,x,3);
prd (x,x,4);
@@ -266,6 +274,8 @@
prd (540,x,5);
prd (777,x,7);
prd (1111,x,11);
+
+ return 0;
}
#endif /* TEST_128_BIT_MULT */
@@ -635,7 +645,7 @@
product.denom = a.denom*b.denom;
/* If it looks to be overflowing, try to reduce the fraction ... */
- if (0 != bigprod.hi)
+ if (bigprod.carry)
{
product = reduce128 (bigprod, product.denom);
if (gnc_numeric_check (product))
More information about the gnucash-changes
mailing list