Rope: Use integer sqrt algorithm for calculating distances

rope
Armin Burgmeier 2012-05-06 20:16:00 +02:00
parent e16de2d46f
commit 7452f11dca
5 changed files with 40 additions and 6 deletions

View File

@ -29,6 +29,16 @@
#ifdef C4REAL_USE_FIXNUM
C4Fixed Sqrt(C4Fixed x)
{
assert(x.val >= 0);
assert(FIXED_SHIFT % 2 == 0);
C4Fixed ret;
ret.val = SqrtI(x.val) << (FIXED_SHIFT >> 1);
return ret;
}
// static table with sinus values from 0.00 degree to 90.00 degree inclusively
long SineTable[9001] =
{

View File

@ -71,6 +71,7 @@ class C4Fixed
friend C4Fixed itofix(int32_t x, int32_t prec);
friend float fixtof(const C4Fixed &x);
friend C4Fixed ftofix(float x);
friend C4Fixed Sqrt(C4Fixed x);
#else
friend void FIXED_TO_FLOAT(float *pVal);
#endif
@ -296,6 +297,8 @@ inline C4Real C4REAL100(int x) { return itofix(x, 100); }
inline C4Real C4REAL256(int x) { C4Fixed r; r.val = x * FIXED_FPF / 256; return r; }
inline C4Real C4REAL10(int x) { return itofix(x, 10); }
C4Fixed Sqrt(C4Fixed x);
#else
// *** wrap C4Real to float

View File

@ -71,6 +71,28 @@ int Pow(int base, int exponent)
return result;
}
/* Fast(?) Integer square root */
uint32_t SqrtI(uint32_t a)
{
uint32_t rem = 0;
uint32_t root = 0;
for(unsigned int i = 0; i < (sizeof(a)*8)/2; i++)
{
root <<= 1;
rem = ((rem << 2) + (a >> (sizeof(a)*8 - 2)));
a <<= 2;
root ++;
if(root <= rem)
{
rem -= root;
root++;
}
else
root--;
}
return root >> 1;
}
bool ForLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
bool (*fnCallback)(int32_t, int32_t, int32_t), int32_t iPar,
int32_t *lastx, int32_t *lasty)

View File

@ -48,6 +48,7 @@ int32_t Distance(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2);
int Angle(int iX1, int iY1, int iX2, int iY2);
int Pow(int base, int exponent);
int32_t StrToI32(const char *s, int base, const char **scan_end);
uint32_t SqrtI(uint32_t a);
#include <cstring>
inline void ZeroMem(void *lpMem, size_t dwSize)

View File

@ -36,17 +36,15 @@ namespace
float v;
};
// TODO: For all square roots, we must avoid floating point by using an
// integer-based Sqrt algorithm
// TODO: Could also use an approximation which works without Sqrt, especially
// if this becomes a performance bottleneck. http://www.azillionmonkeys.com/qed/sqroot.html
// TODO: If the sqrts become a performance bottleneck we could also use an
// approximation which works without Sqrt, cf. http://www.azillionmonkeys.com/qed/sqroot.html
C4Real Len(C4Real dx, C4Real dy)
{
// Prevent possible overflow
if(Abs(dx) > 120 || Abs(dy) > 120)
return ftofix(sqrt(fixtoi(dx)*fixtoi(dx) + fixtoi(dy)*fixtoi(dy)));
return itofix(SqrtI(fixtoi(dx)*fixtoi(dx) + fixtoi(dy)*fixtoi(dy)));// ftofix(sqrt(fixtoi(dx)*fixtoi(dx) + fixtoi(dy)*fixtoi(dy)));
else
return ftofix(sqrt(fixtof(dx*dx + dy*dy)));
return Sqrt(dx*dx + dy*dy);//ftofix(sqrt(fixtof(dx*dx + dy*dy)));
}
// For use in initializer list