forked from Mirrors/openclonk
Rope: Use integer sqrt algorithm for calculating distances
parent
e16de2d46f
commit
7452f11dca
|
@ -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] =
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue