summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBen Millwood <thebenmachine@gmail.com>2012-04-06 21:33:24 +0000
committerTim Angus <tim@ngus.net>2013-01-03 00:18:15 +0000
commitfe4829a0fa9647e94011df58621a5982df2cd7e8 (patch)
tree87f9b0a55dba6fac43ea0b316d688a8336ab0748 /src
parentd75076a7dcdd85ff66d68b7611a86d1832f1f360 (diff)
* Calculate some exponentiation more efficiently/sensibly in bg_lib.c
Diffstat (limited to 'src')
-rw-r--r--src/game/bg_lib.c106
1 files changed, 44 insertions, 62 deletions
diff --git a/src/game/bg_lib.c b/src/game/bg_lib.c
index dd31e946..94af5f18 100644
--- a/src/game/bg_lib.c
+++ b/src/game/bg_lib.c
@@ -818,6 +818,43 @@ double rint( double v )
return floor( v );
}
+/*
+===============
+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 );
@@ -1540,28 +1577,8 @@ double strtod( const char *nptr, char **endptr )
*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;
@@ -1604,30 +1621,8 @@ double strtod( const char *nptr, char **endptr )
*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;
@@ -2540,19 +2535,6 @@ static LDOUBLE abs_val (LDOUBLE value)
return result;
}
-static LDOUBLE pow10 (int exp)
-{
- LDOUBLE result = 1;
-
- while (exp)
- {
- result *= 10;
- exp--;
- }
-
- return result;
-}
-
static long round (LDOUBLE value)
{
long intpart;
@@ -2615,12 +2597,12 @@ static int fmtfp (char *buffer, size_t *currlen, size_t maxlen,
/* 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