[quake3-commits] r2291 - trunk/code/game

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Sun Jul 1 12:43:28 EDT 2012


Author: thilo
Date: 2012-07-01 12:43:28 -0400 (Sun, 01 Jul 2012)
New Revision: 2291

Modified:
   trunk/code/game/bg_lib.c
Log:
More intelligent exponentiation in strtod/strtol (#5487) - patch by Ben Millwood


Modified: trunk/code/game/bg_lib.c
===================================================================
--- trunk/code/game/bg_lib.c	2012-07-01 16:29:43 UTC (rev 2290)
+++ trunk/code/game/bg_lib.c	2012-07-01 16:43:28 UTC (rev 2291)
@@ -768,6 +768,43 @@
 
 #endif
 
+/*
+===============
+powN
+
+Raise a double to a integer power
+===============
+*/
+static double powN( double base, int exp )
+{
+	if( exp >= 0 )
+	{
+		double result = 1.0;
+
+		// calculate x, x^2, x^4, ... by repeated squaring
+		// and multiply together the ones corresponding to the
+		// binary digits of the exponent
+		// e.g. x^73 = x^(1 + 8 + 64) = x * x^8 * x^64
+		while( exp > 0 )
+		{
+			if( exp % 2 == 1 )
+				result *= base;
+
+			base *= base;
+			exp /= 2;
+		}
+
+		return result;
+	}
+	// if exp is INT_MIN, the next clause will be upset,
+	// because -exp isn't representable
+	else if( exp == INT_MIN )
+		return powN( base, exp + 1 ) / base;
+	// x < 0
+	else
+		return 1.0 / powN( base, -exp );
+}
+
 double tan( double x ) {
 	return sin(x) / cos(x);
 }
@@ -1042,7 +1079,6 @@
 		if( end != s && tolower( *nptr ) == 'p' )
 		{
 			int exp;
-			float res2;
 			// apparently (confusingly) the exponent should be
 			// decimal
 			exp = strtol( &nptr[1], (char **)&end, 10 );
@@ -1053,28 +1089,8 @@
 					*endptr = (char *)nptr;
 				return res;
 			}
-			if( exp > 0 )
-			{
-				while( exp-- > 0 )
-				{
-					res2 = res * 2;
-					// check for infinity
-					if( res2 <= res )
-						break;
-					res = res2;
-				}
-			}
-			else
-			{
-				while( exp++ < 0 )
-				{
-					res2 = res / 2;
-					// check for underflow
-					if( res2 >= res )
-						break;
-					res = res2;
-				}
-			}
+
+			res *= powN( 2, exp );
 		}
 		if( endptr )
 			*endptr = (char *)end;
@@ -1108,7 +1124,6 @@
 		if( p != end && tolower( *nptr ) == 'e' )
 		{
 			int exp;
-			float res10;
 			exp = strtol( &nptr[1], (char **)&end, 10 );
 			if( &nptr[1] == end )
 			{
@@ -1117,30 +1132,8 @@
 					*endptr = (char *)nptr;
 				return res;
 			}
-			if( exp > 0 )
-			{
-				while( exp-- > 0 )
-				{
-					res10 = res * 10;
-					// check for infinity to save us time
-					if( res10 <= res )
-						break;
-					res = res10;
-				}
-			}
-			else if( exp < 0 )
-			{
-				while( exp++ < 0 )
-				{
-					res10 = res / 10;
-					// check for underflow
-					// (test for 0 would probably be just
-					// as good)
-					if( res10 >= res )
-						break;
-					res = res10;
-				}
-			}
+
+			res *= powN( 10, exp );
 		}
 		if( endptr )
 			*endptr = (char *)end;
@@ -1907,19 +1900,6 @@
   return result;
 }
 
-static LDOUBLE pow10 (int exp)
-{
-  LDOUBLE result = 1;
-
-  while (exp)
-  {
-    result *= 10;
-    exp--;
-  }
-  
-  return result;
-}
-
 static long round (LDOUBLE value)
 {
   long intpart;
@@ -1982,12 +1962,12 @@
   /* We "cheat" by converting the fractional part to integer by
    * multiplying by a factor of 10
    */
-  fracpart = round ((pow10 (max)) * (ufvalue - intpart));
+  fracpart = round ((powN (10, max)) * (ufvalue - intpart));
 
-  if (fracpart >= pow10 (max))
+  if (fracpart >= powN (10, max))
   {
     intpart++;
-    fracpart -= pow10 (max);
+    fracpart -= powN (10, max);
   }
 
 #ifdef DEBUG_SNPRINTF



More information about the quake3-commits mailing list