64-bit FixedMul and FixedSqrt, integer sqrt functions
This commit is contained in:
parent
6e6a94a6af
commit
30614c758c
2 changed files with 67 additions and 0 deletions
|
|
@ -61,6 +61,45 @@ fixed_t FixedSqrt(fixed_t x)
|
|||
#endif
|
||||
}
|
||||
|
||||
// Shitty 64-bit duplicate so certain distancing edgecases in k_odds die
|
||||
INT64 FixedSqrt64(INT64 x)
|
||||
{
|
||||
#ifdef HAVE_SQRT
|
||||
const float fx = FixedToFloat64(x);
|
||||
float fr;
|
||||
#ifdef HAVE_SQRTF
|
||||
fr = sqrtf(fx);
|
||||
#else
|
||||
fr = (float)sqrt(fx);
|
||||
#endif
|
||||
return FloatToFixed64(fr);
|
||||
#else
|
||||
// The neglected art of Fixed Point arithmetic
|
||||
// Jetro Lauha
|
||||
// Seminar Presentation
|
||||
// Assembly 2006, 3rd- 6th August 2006
|
||||
// (Revised: September 13, 2006)
|
||||
// URL: http://jet.ro/files/The_neglected_art_of_Fixed_Point_arithmetic_20060913.pdf
|
||||
register UINT64 root, remHi, remLo, testDiv, count;
|
||||
root = 0; /* Clear root */
|
||||
remHi = 0; /* Clear high part of partial remainder */
|
||||
remLo = x; /* Get argument into low part of partial remainder */
|
||||
count = (31 + (FRACBITS >> 1)); /* Load loop counter */
|
||||
do
|
||||
{
|
||||
remHi = (remHi << 2) | (remLo >> 62); remLo <<= 2; /* get 2 bits of arg */
|
||||
root <<= 1; /* Get ready for the next bit in the root */
|
||||
testDiv = (root << 1) + 1; /* Test radical */
|
||||
if (remHi >= testDiv)
|
||||
{
|
||||
remHi -= testDiv;
|
||||
root += 1;
|
||||
}
|
||||
} while (count-- != 0);
|
||||
return root;
|
||||
#endif
|
||||
}
|
||||
|
||||
fixed_t FixedHypot(fixed_t x, fixed_t y)
|
||||
{
|
||||
// Moved the code from R_PointToDist2 to here,
|
||||
|
|
@ -1122,6 +1161,11 @@ FUNCMATH FUNCINLINE static inline fixed_t FixedMulC(fixed_t a, fixed_t b)
|
|||
return (fixed_t)((((INT64)a * b)) / FRACUNIT);
|
||||
}
|
||||
|
||||
FUNCMATH FUNCINLINE static inline INT64 FixedMul64C(fixed_t a, fixed_t b)
|
||||
{
|
||||
return (INt64)((((INT64)a * b)) / FRACUNIT);
|
||||
}
|
||||
|
||||
FUNCMATH FUNCINLINE static inline fixed_t FixedDivC2(fixed_t a, fixed_t b)
|
||||
{
|
||||
INT64 ret;
|
||||
|
|
|
|||
|
|
@ -55,11 +55,21 @@ FUNCMATH FUNCINLINE static ATTRINLINE float FixedToFloat(fixed_t x)
|
|||
return x / (float)FRACUNIT;
|
||||
}
|
||||
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE float FixedToFloat64(INT64 x)
|
||||
{
|
||||
return (float)x / (float)FRACUNIT;
|
||||
}
|
||||
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FloatToFixed(float f)
|
||||
{
|
||||
return (fixed_t)(f * FRACUNIT);
|
||||
}
|
||||
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE INT64 FloatToFixed64(float f)
|
||||
{
|
||||
return (INT64)(f * FRACUNIT);
|
||||
}
|
||||
|
||||
// for backwards compat
|
||||
#define FIXED_TO_FLOAT(x) FixedToFloat(x) // (((float)(x)) / ((float)FRACUNIT))
|
||||
#define FLOAT_TO_FIXED(f) FloatToFixed(f) // (fixed_t)((f) * ((float)FRACUNIT))
|
||||
|
|
@ -79,6 +89,13 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedMul(fixed_t a, fixed_t b)
|
|||
return (fixed_t)(((UINT64)((INT64)a * b)) >> FRACBITS);
|
||||
}
|
||||
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE INT64 FixedMul64(INT64 a, INT64 b)
|
||||
{
|
||||
// Need to cast to unsigned before shifting to avoid undefined behaviour
|
||||
// for negative integers
|
||||
return (INT64)(((UINT64)(a * b)) >> FRACBITS);
|
||||
}
|
||||
|
||||
/** \brief The FixedDiv2 function
|
||||
|
||||
\param a fixed_t number
|
||||
|
|
@ -145,6 +162,12 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedPercentageFloat(float fpercen
|
|||
|
||||
*/
|
||||
FUNCMATH fixed_t FixedSqrt(fixed_t x);
|
||||
FUNCMATH INT64 FixedSqrt64(INT64 x);
|
||||
|
||||
// Theoretically, we can feed this any integer value and it'll output an
|
||||
// accurate square root * 256.
|
||||
#define IntSqrt(x) (INT32)(FixedSqrt(x) / 256)
|
||||
#define IntSqrt64(x) (INT64)(FixedSqrt64(x) / 256)
|
||||
|
||||
/** \brief The FixedHypot function
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue