64-bit FixedMul and FixedSqrt, integer sqrt functions

This commit is contained in:
Anonimus 2025-10-01 10:09:31 -04:00
parent 6e6a94a6af
commit 30614c758c
2 changed files with 67 additions and 0 deletions

View file

@ -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;

View file

@ -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