[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