Commit d59d0077 authored by Richard Gobeille's avatar Richard Gobeille

engine: more fix16 cleanup

There's an optimization or two in here, but tbh I just like deleting shit.
parent 2723852d
......@@ -32,43 +32,20 @@ static CONSTEXPR const fix16_t FIX16_MAX = 0x7FFFFFFF; /*!< the maximum val
static CONSTEXPR const fix16_t FIX16_MIN = 0x80000000; /*!< the minimum value of fix16_t */
static CONSTEXPR const fix16_t FIX16_OVERFLOW = 0x80000000; /*!< the value used to indicate overflows */
static CONSTEXPR const fix16_t fix16_one = 0x00010000; /*!< fix16_t value of 1 */
static CONSTEXPR const fix16_t fix16_one = 0x00010000; /*!< fix16_t value of 1 */
static CONSTEXPR const fix16_t fix16_half = 0x00008000; /*!< fix16_t value of 0.5 */
static CONSTEXPR const float flt_f161r = 1.f / fix16_one; /*!< reciprocal of fix16_one as a float */
/* Conversion functions between fix16_t and float/integer.
* These are inlined to allow compiler to optimize away constant numbers
*/
static FORCE_INLINE CONSTEXPR fix16_t fix16_from_int(int a) { return a * fix16_one; }
static FORCE_INLINE CONSTEXPR float fix16_to_float(fix16_t a) { return (float)a / fix16_one; }
static FORCE_INLINE CONSTEXPR double fix16_to_dbl(fix16_t a) { return (double)a / fix16_one; }
static inline int fix16_to_int(fix16_t a)
{
#ifdef FIXMATH_NO_ROUNDING
return (a >> 16);
#else
if (a >= 0)
return (a + (fix16_one >> 1)) / fix16_one;
return (a - (fix16_one >> 1)) / fix16_one;
#endif
}
static inline fix16_t fix16_from_float(float a)
{
float temp = a * fix16_one;
#ifndef FIXMATH_NO_ROUNDING
temp += (temp >= 0) ? 0.5f : -0.5f;
#endif
return (fix16_t)temp;
}
static FORCE_INLINE CONSTEXPR int fix16_to_int(fix16_t a) { return (a + (a >= 0 ? fix16_half : -fix16_half)) / fix16_one; }
static FORCE_INLINE CONSTEXPR float fix16_to_float(fix16_t a) { return (float)a * flt_f161r; }
static FORCE_INLINE CONSTEXPR double fix16_to_dbl(fix16_t a) { return (double)a * flt_f161r; }
static inline fix16_t fix16_from_dbl(double a)
{
double temp = a * fix16_one;
#ifndef FIXMATH_NO_ROUNDING
temp += (temp >= 0) ? 0.5f : -0.5f;
#endif
return (fix16_t)temp;
}
static FORCE_INLINE CONSTEXPR fix16_t fix16_from_int(int a) { return a * fix16_one; }
static FORCE_INLINE CONSTEXPR fix16_t fix16_from_float(float a) { return (fix16_t)(a * fix16_one + (a >= 0 ? 0.5f : -0.5f)); }
static FORCE_INLINE CONSTEXPR fix16_t fix16_from_dbl(double a) { return (fix16_t)(a * fix16_one + (a >= 0 ? 0.5 : -0.5)); }
/* Macro for defining fix16_t constant values.
The functions above can't be used from e.g. global variable initializers,
......@@ -81,18 +58,12 @@ static inline fix16_t fix16_from_dbl(double a)
*/
#define F16(x) ((fix16_t)(((x) >= 0) ? ((x) * 65536.0 + 0.5) : ((x) * 65536.0 - 0.5)))
static FORCE_INLINE CONSTEXPR fix16_t fix16_abs(fix16_t x)
{ return (x < 0 ? -x : x); }
static FORCE_INLINE CONSTEXPR fix16_t fix16_floor(fix16_t x)
{ return (x & 0xFFFF0000UL); }
static FORCE_INLINE CONSTEXPR fix16_t fix16_ceil(fix16_t x)
{ return (x & 0xFFFF0000UL) + ((x & 0x0000FFFFUL) ? fix16_one : 0); }
static FORCE_INLINE CONSTEXPR fix16_t fix16_min(fix16_t x, fix16_t y)
{ return (x < y ? x : y); }
static FORCE_INLINE CONSTEXPR fix16_t fix16_max(fix16_t x, fix16_t y)
{ return (x > y ? x : y); }
static FORCE_INLINE CONSTEXPR fix16_t fix16_clamp(fix16_t x, fix16_t lo, fix16_t hi)
{ return fix16_min(fix16_max(x, lo), hi); }
static FORCE_INLINE CONSTEXPR fix16_t fix16_abs(fix16_t x) { return (x < 0 ? -x : x); }
static FORCE_INLINE CONSTEXPR fix16_t fix16_floor(fix16_t x) { return (x & 0xFFFF0000UL); }
static FORCE_INLINE CONSTEXPR fix16_t fix16_ceil(fix16_t x) { return (x & 0xFFFF0000UL) + ((x & 0x0000FFFFUL) ? fix16_one : 0); }
static FORCE_INLINE CONSTEXPR fix16_t fix16_min(fix16_t x, fix16_t y) { return (x < y ? x : y); }
static FORCE_INLINE CONSTEXPR fix16_t fix16_max(fix16_t x, fix16_t y) { return (x > y ? x : y); }
static FORCE_INLINE CONSTEXPR fix16_t fix16_clamp(fix16_t x, fix16_t lo, fix16_t hi) { return fix16_min(fix16_max(x, lo), hi); }
/* Subtraction and addition with overflow detection. */
extern fix16_t fix16_add(fix16_t a, fix16_t b) FIXMATH_FUNC_ATTRS;
......@@ -137,19 +108,16 @@ extern fix16_t fix16_lerp16(fix16_t inArg0, fix16_t inArg1, uint16_t inFract) FI
extern fix16_t fix16_lerp32(fix16_t inArg0, fix16_t inArg1, uint32_t inFract) FIXMATH_FUNC_ATTRS;
static const fix16_t fix16_rad_to_deg_mult = 3754936;
static inline fix16_t fix16_rad_to_deg(fix16_t radians)
{ return fix16_mul(radians, fix16_rad_to_deg_mult); }
static CONSTEXPR const fix16_t fix16_rad_to_deg_mult = 3754936;
static FORCE_INLINE fix16_t fix16_rad_to_deg(fix16_t radians) { return fix16_mul(radians, fix16_rad_to_deg_mult); }
static const fix16_t fix16_deg_to_rad_mult = 1144;
static inline fix16_t fix16_deg_to_rad(fix16_t degrees)
{ return fix16_mul(degrees, fix16_deg_to_rad_mult); }
static CONSTEXPR const fix16_t fix16_deg_to_rad_mult = 1144;
static FORCE_INLINE fix16_t fix16_deg_to_rad(fix16_t degrees) { return fix16_mul(degrees, fix16_deg_to_rad_mult); }
/*! Returns the square of the given fix16_t.
*/
static inline fix16_t fix16_sq(fix16_t x)
{ return fix16_mul(x, x); }
static inline fix16_t fix16_sq(fix16_t x) { return fix16_mul(x, x); }
/*! Convert fix16_t value to a string.
* Required buffer length for largest values is 13 bytes.
......@@ -162,91 +130,9 @@ extern void fix16_to_str(fix16_t value, char *buf, int decimals);
*/
extern fix16_t fix16_from_str(const char *buf);
/** Helper macro for F16C. Replace token with its number of characters/digits. */
#define FIXMATH_TOKLEN(token) ( sizeof( #token ) - 1 )
/** Helper macro for F16C. Handles pow(10, n) for n from 0 to 8. */
#define FIXMATH_CONSTANT_POW10(times) ( \
(times == 0) ? 1ULL \
: (times == 1) ? 10ULL \
: (times == 2) ? 100ULL \
: (times == 3) ? 1000ULL \
: (times == 4) ? 10000ULL \
: (times == 5) ? 100000ULL \
: (times == 6) ? 1000000ULL \
: (times == 7) ? 10000000ULL \
: 100000000ULL \
)
/** Helper macro for F16C, the type uint64_t is only used at compile time and
* shouldn't be visible in the generated code.
*
* @note We do not use fix16_one instead of 65536ULL, because the
* "use of a const variable in a constant expression is nonstandard in C".
*/
#define FIXMATH_CONVERT_MANTISSA(m) \
( (unsigned) \
( \
( \
( \
(uint64_t)( ( ( 1 ## m ## ULL ) - FIXMATH_CONSTANT_POW10(FIXMATH_TOKLEN(m)) ) * FIXMATH_CONSTANT_POW10(5 - FIXMATH_TOKLEN(m)) ) \
* 100000ULL * 65536ULL \
) \
+ 5000000000ULL /* rounding: + 0.5 */ \
) \
/ \
10000000000LL \
) \
)
#define FIXMATH_COMBINE_I_M(i, m) \
( \
( \
( i ) \
<< 16 \
) \
| \
( \
FIXMATH_CONVERT_MANTISSA(m) \
& 0xFFFF \
) \
)
/** Create int16_t (Q16.16) constant from separate integer and mantissa part.
*
* Only tested on 32-bit ARM Cortex-M0 / x86 Intel.
*
* This macro is needed when compiling with options like "--fpu=none",
* which forbid all and every use of float and related types and
* would thus make it impossible to have fix16_t constants.
*
* Just replace uses of F16() with F16C() like this:
* F16(123.1234) becomes F16C(123,1234)
*
* @warning Specification of any value outside the mentioned intervals
* WILL result in undefined behavior!
*
* @note Regardless of the specified minimum and maximum values for i and m below,
* the total value of the number represented by i and m MUST be in the interval
* ]-32768.00000:32767.99999[ else usage with this macro will yield undefined behavior.
*
* @param i Signed integer constant with a value in the interval ]-32768:32767[.
* @param m Positive integer constant in the interval ]0:99999[ (fractional part/mantissa).
*/
#define F16C(i, m) \
( (fix16_t) \
( \
(( #i[0] ) == '-') \
? -FIXMATH_COMBINE_I_M((unsigned)( ( (i) * -1) ), m) \
: FIXMATH_COMBINE_I_M((unsigned)i, m) \
) \
)
#ifdef __cplusplus
}
#include "pragmas.h"
#include "fix16.hpp"
#endif
......
This diff is collapsed.
......@@ -9,6 +9,8 @@
#ifndef pragmas_h_
#define pragmas_h_
#include "libdivide.h"
#ifdef __cplusplus
extern "C" {
#endif
......
......@@ -75,10 +75,8 @@ FIXMATH_FUNC_ATTRS fix16_t fix16_mul(fix16_t inArg0, fix16_t inArg1)
if (~upper)
return FIX16_OVERFLOW;
#ifndef FIXMATH_NO_ROUNDING
// This adjustment is required in order to round -1/2 correctly
product--;
#endif
}
else
{
......@@ -86,14 +84,10 @@ FIXMATH_FUNC_ATTRS fix16_t fix16_mul(fix16_t inArg0, fix16_t inArg1)
return FIX16_OVERFLOW;
}
#ifdef FIXMATH_NO_ROUNDING
return product >> 16;
#else
fix16_t result = product >> 16;
result += (product & 0x8000) >> 15;
return result;
#endif
}
/* Wrapper around fix16_mul to add saturating arithmetic. */
......@@ -179,10 +173,8 @@ FIXMATH_FUNC_ATTRS fix16_t fix16_div(fix16_t a, fix16_t b)
bit_pos--;
}
#ifndef FIXMATH_NO_ROUNDING
// Quotient is always positive so rounding is easy
quotient++;
#endif
fix16_t result = quotient >> 1;
......
......@@ -23,7 +23,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef gamevars_h_
#define gamevars_h_
#include "fix16.hpp"
#include "gamedef.h"
#include "vfs.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment