gdtoa-hexnan.c.patch   [plain text]


--- gdtoa-hexnan.c.orig	2008-03-15 10:08:33.000000000 -0700
+++ gdtoa-hexnan.c	2008-08-30 17:55:23.000000000 -0700
@@ -30,6 +30,7 @@ THIS SOFTWARE.
  * with " at " changed at "@" and " dot " changed to ".").	*/
 
 #include "gdtoaimp.h"
+#include <fpmath.h>
 
  static void
 #ifdef KR_headers
@@ -57,94 +58,53 @@ hexnan(sp, fpi, x0)
 hexnan( CONST char **sp, FPI *fpi, ULong *x0)
 #endif
 {
-	ULong c, h, *x, *x1, *xe;
+	int nbits, len;
+	char *cp;
 	CONST char *s;
-	int havedig, hd0, i, nbits;
 
-	if (!hexdig['0'])
-		hexdig_init_D2A();
-	nbits = fpi->nbits;
-	x = x0 + (nbits >> kshift);
-	if (nbits & kmask)
-		x++;
-	*--x = 0;
-	x1 = xe = x;
-	havedig = hd0 = i = 0;
+	if (sp == NULL || *sp == NULL || **sp != '(')
+		return STRTOG_NaN;
 	s = *sp;
-	/* allow optional initial 0x or 0X */
-	while((c = *(CONST unsigned char*)(s+1)) && c <= ' ')
-		++s;
-	if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
-	 && *(CONST unsigned char*)(s+3) > ' ')
-		s += 2;
-	while(c = *(CONST unsigned char*)++s) {
-		if (!(h = hexdig[c])) {
-			if (c <= ' ') {
-				if (hd0 < havedig) {
-					if (x < x1 && i < 8)
-						L_shift(x, x1, i);
-					if (x <= x0) {
-						i = 8;
-						continue;
-						}
-					hd0 = havedig;
-					*--x = 0;
-					x1 = x;
-					i = 0;
-					}
-				while(*(CONST unsigned char*)(s+1) <= ' ')
-					++s;
-				if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
-				 && *(CONST unsigned char*)(s+3) > ' ')
-					s += 2;
-				continue;
-				}
-			if (/*(*/ c == ')' && havedig) {
-				*sp = s + 1;
-				break;
-				}
-#ifndef GDTOA_NON_PEDANTIC_NANCHECK
-			do {
-				if (/*(*/ c == ')') {
-					*sp = s + 1;
-					break;
-					}
-				} while(c = *++s);
-#endif
+	if ((cp = strchr(s + 1, ')')) == NULL) {
+		*sp += strlen(s);
+		cp = s + 1;
+		}
+	else {
+		len = cp - (s + 1);
+		cp = alloca(len + 1);
+		if (!cp)
 			return STRTOG_NaN;
-			}
-		havedig++;
-		if (++i > 8) {
-			if (x <= x0)
-				continue;
-			i = 1;
-			*--x = 0;
-			}
-		*x = (*x << 4) | h & 0xf;
+		strlcpy(cp, s + 1, len + 1);
+		*sp += len + 2;
 		}
-	if (!havedig)
-		return STRTOG_NaN;
-	if (x < x1 && i < 8)
-		L_shift(x, x1, i);
-	if (x > x0) {
-		x1 = x0;
-		do *x1++ = *x++;
-			while(x <= xe);
-		do *x1++ = 0;
-			while(x1 <= xe);
+	nbits = fpi->nbits;
+	/* a hack */
+	if (nbits == 52) {	/* double */
+		union IEEEd2bits u;
+		u.d = nan(cp);
+		x0[1] = u.bits.manh;
+		x0[0] = u.bits.manl;
 		}
-	else {
-		/* truncate high-order word if necessary */
-		if ( (i = nbits & (ULbits-1)) !=0)
-			*xe &= ((ULong)0xffffffff) >> (ULbits - i);
+	else if (nbits < 52) {	/* float */
+		union IEEEf2bits u;
+		u.f = nanf(cp);
+		x0[0] = u.bits.man;
 		}
-	for(x1 = xe;; --x1) {
-		if (*x1 != 0)
-			break;
-		if (x1 == x0) {
-			*x1 = 1;
-			break;
-			}
+	else {			/* long double */
+		union IEEEl2bits u;
+		u.e = nanl(cp);
+#if defined(__ppc__) || defined(__ppc64__)
+		x0[3] = (ULong)(u.bits.manh >> 44);
+		x0[2] = (ULong)(u.bits.manh >> 12);
+		x0[1] = ((ULong)u.bits.manh & 0xfff) << 20 | (ULong)(u.bits.manl >> 32);
+		x0[0] = (ULong)u.bits.manl;
+#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+		x0[1] = (ULong)u.bits.manh;
+		x0[0] = (ULong)u.bits.manl;
+#else
+#error unsupported architecture
+#endif
 		}
+
 	return STRTOG_NaNbits;
 	}