[Python-checkins] r78259 - python/branches/py3k-cdecimal/Modules/cdecimal/typearith.h

stefan.krah python-checkins at python.org
Sat Feb 20 18:17:48 CET 2010


Author: stefan.krah
Date: Sat Feb 20 18:17:48 2010
New Revision: 78259

Log:
Accommodate compilers without uint64_t.

Modified:
   python/branches/py3k-cdecimal/Modules/cdecimal/typearith.h

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/typearith.h
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/typearith.h	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/typearith.h	Sat Feb 20 18:17:48 2010
@@ -123,6 +123,7 @@
 
 #elif defined(CONFIG_32)
 #if defined(ANSI)
+#if !defined(LEGACY_COMPILER)
 static inline void
 _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
 {
@@ -144,6 +145,138 @@
 	*q = (mpd_uint_t)(hl / d); /* quotient is known to fit */
 	*r = (mpd_uint_t)(hl - (mpd_uuint_t)(*q) * d);
 }
+/* END ANSI + uint64_t */
+#else
+static inline void
+_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
+{
+	uint16_t w[4], carry;
+	uint16_t ah, al, bh, bl;
+	uint32_t hl;
+
+	ah = (uint16_t)(a>>16); al = (uint16_t)a;
+	bh = (uint16_t)(b>>16); bl = (uint16_t)b;
+
+	hl = al * bl;
+	w[0] = (uint16_t)hl;
+	carry = (uint16_t)(hl>>16);
+
+	hl = ah * bl + carry;
+	w[1] = (uint16_t)hl;
+	w[2] = (uint16_t)(hl>>16);
+
+	hl = al * bh + w[1];
+	w[1] = (uint16_t)hl;
+	carry = (uint16_t)(hl>>16);
+
+	hl = ah * bh + w[2] + carry;
+	w[2] = (uint16_t)hl;
+	w[3] = (uint16_t)(hl>>16);
+
+	*hi = ((uint32_t)w[3]<<16) + w[2];
+	*lo = ((uint32_t)w[1]<<16) + w[0];
+}
+
+/*
+ * By Henry S. Warren: http://www.hackersdelight.org/HDcode/divlu.c
+ * http://www.hackersdelight.org/permissions.htm:
+ * "You are free to use, copy, and distribute any of the code on this web
+ *  site, whether modified by you or not. You need not give attribution."
+ *
+ * Slightly modified, comments are mine.
+ */
+static inline int
+nlz(uint32_t x)
+{
+	int n;
+
+	if (x == 0) return(32);
+
+	n = 0;
+	if (x <= 0x0000FFFF) {n = n +16; x = x <<16;}
+	if (x <= 0x00FFFFFF) {n = n + 8; x = x << 8;}
+	if (x <= 0x0FFFFFFF) {n = n + 4; x = x << 4;}
+	if (x <= 0x3FFFFFFF) {n = n + 2; x = x << 2;}
+	if (x <= 0x7FFFFFFF) {n = n + 1;}
+
+	return n;
+}
+
+static inline void
+_mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t u1, mpd_uint_t u0,
+               mpd_uint_t v)
+{
+	const mpd_uint_t b = 65536;
+	mpd_uint_t un1, un0,
+	           vn1, vn0,
+	           q1, q0,
+	           un32, un21, un10,
+	           rhat;
+	int s;
+
+	assert(u1 < v);
+
+	s = nlz(v);
+	v = v << s;
+	vn1 = v >> 16;
+	vn0 = v & 0xFFFF;
+
+	un32 = (u1 << s) | (u0 >> (32 - s));
+	un10 = u0 << s;
+
+	un1 = un10 >> 16;
+	un0 = un10 & 0xFFFF;
+
+	q1 = un32 / vn1;
+	rhat = un32 - q1*vn1;
+again1:
+	if (q1 >= b || q1*vn0 > b*rhat + un1) {
+		q1 = q1 - 1;
+		rhat = rhat + vn1;
+		if (rhat < b) goto again1;
+	}
+
+	/*
+	 *  Before again1 we had:
+	 *      (1) q1*vn1   + rhat         = un32
+	 *      (2) q1*vn1*b + rhat*b + un1 = un32*b + un1
+	 *
+	 *  The statements inside the if-clause do not change the value
+	 *  of the left-hand side of (2), and the loop is only exited
+	 *  if q1*vn0 <= rhat*b + un1, so:
+	 *
+	 *      (3) q1*vn1*b + q1*vn0 <= un32*b + un1
+	 *      (4)              q1*v <= un32*b + un1
+	 *      (5)                 0 <= un32*b + un1 - q1*v
+	 *
+	 *  By (5) we are certain that the possible add-back step from
+	 *  Knuth's algorithm D is never required.
+	 *
+	 *  Since the final quotient is less than 2**32, the following
+	 *  must be true:
+	 *
+	 *      (6) un32*b + un1 - q1*v <= UINT32_MAX
+	 *
+	 *  This means that in the following line, the high words
+	 *  of un32*b and q1*v can be discarded without any effect
+	 *  on the result.
+	 */
+	un21 = un32*b + un1 - q1*v;
+
+	q0 = un21 / vn1;
+	rhat = un21 - q0*vn1;
+again2:
+	if (q0 >= b || q0*vn0 > b*rhat + un0) {
+		q0 = q0 - 1;
+		rhat = rhat + vn1;
+		if (rhat < b) goto again2;
+	}
+
+	*q = q1*b + q0;
+	*r = (un21*b + un0 - q0*v) >> s;
+}
+#endif /* END ANSI + LEGACY_COMPILER */
+
 /* END ANSI */
 
 #elif defined(__GNUC__) && defined(__i386__)


More information about the Python-checkins mailing list