7static constexpr f32 F_PI = 3.1415927f;
8static constexpr f32 F_TAU = 6.283185f;
9static constexpr f32 DEG2RAD = 0.017453292f;
10static constexpr f32 DEG2RAD360 = 0.034906585f;
11static constexpr f32 RAD2DEG = 57.2957795f;
12static constexpr f32 DEG2FIDX = 256.0f / 360.0f;
13static constexpr f32 RAD2FIDX = 128.0f / F_PI;
14static constexpr f32 FIDX2RAD = F_PI / 128.0f;
19[[nodiscard]] f32
frsqrt(f32 x);
22[[nodiscard]]
static inline f32 sqrt(f32 x) {
23 return x > 0.0f ?
frsqrt(x) * x : 0.0f;
26[[nodiscard]] f32 SinFIdx(f32 fidx);
27[[nodiscard]] f32 CosFIdx(f32 fidx);
28[[nodiscard]] f32 AtanFIdx_(f32 fidx);
29[[nodiscard]] f32 Atan2FIdx(f32 x, f32 y);
33[[nodiscard]]
static inline f32
sin(f32 x) {
34 return SinFIdx(x * RAD2FIDX);
39[[nodiscard]]
static inline f32
cos(f32 x) {
40 return CosFIdx(x * RAD2FIDX);
44[[nodiscard]]
static inline f32 acos(f32 x) {
49[[nodiscard]]
static inline f32 atan2(f32 y, f32 x) {
50 return Atan2FIdx(y, x) * FIDX2RAD;
53[[nodiscard]]
static inline f32 abs(f32 x) {
61 u64 bits = std::bit_cast<u64>(x);
62 bits = (bits & 0xfffffffff8000000ULL) + (bits & 0x8000000);
63 return std::bit_cast<f64>(bits);
68[[nodiscard]]
static inline f32
fma(f32 x, f32 y, f32 z) {
69 return static_cast<f32
>(
70 static_cast<f64
>(x) *
force25Bit(
static_cast<f64
>(y)) +
static_cast<f64
>(z));
75[[nodiscard]]
static inline f32
fms(f32 x, f32 y, f32 z) {
76 return static_cast<f32
>(
77 static_cast<f64
>(x) *
force25Bit(
static_cast<f64
>(y)) -
static_cast<f64
>(z));
87 constexpr c64(
const f64 p) {
91 constexpr c64(
const u64 p) {
99static constexpr u64 EXPONENT_SHIFT_F64 = 52;
100static constexpr u64 MANTISSA_MASK_F64 = 0x000fffffffffffffULL;
101static constexpr u64 EXPONENT_MASK_F64 = 0x7ff0000000000000ULL;
102static constexpr u64 SIGN_MASK_F64 = 0x8000000000000000ULL;
104static constexpr std::array<BaseAndDec, 32> RSQRTE_TABLE = {{
105 {0x69fa000000000ULL, -0x15a0000000LL},
106 {0x5f2e000000000ULL, -0x13cc000000LL},
107 {0x554a000000000ULL, -0x1234000000LL},
108 {0x4c30000000000ULL, -0x10d4000000LL},
109 {0x43c8000000000ULL, -0x0f9c000000LL},
110 {0x3bfc000000000ULL, -0x0e88000000LL},
111 {0x34b8000000000ULL, -0x0d94000000LL},
112 {0x2df0000000000ULL, -0x0cb8000000LL},
113 {0x2794000000000ULL, -0x0bf0000000LL},
114 {0x219c000000000ULL, -0x0b40000000LL},
115 {0x1bfc000000000ULL, -0x0aa0000000LL},
116 {0x16ae000000000ULL, -0x0a0c000000LL},
117 {0x11a8000000000ULL, -0x0984000000LL},
118 {0x0ce6000000000ULL, -0x090c000000LL},
119 {0x0862000000000ULL, -0x0898000000LL},
120 {0x0416000000000ULL, -0x082c000000LL},
121 {0xffe8000000000ULL, -0x1e90000000LL},
122 {0xf0a4000000000ULL, -0x1c00000000LL},
123 {0xe2a8000000000ULL, -0x19c0000000LL},
124 {0xd5c8000000000ULL, -0x17c8000000LL},
125 {0xc9e4000000000ULL, -0x1610000000LL},
126 {0xbedc000000000ULL, -0x1490000000LL},
127 {0xb498000000000ULL, -0x1330000000LL},
128 {0xab00000000000ULL, -0x11f8000000LL},
129 {0xa204000000000ULL, -0x10e8000000LL},
130 {0x9994000000000ULL, -0x0fe8000000LL},
131 {0x91a0000000000ULL, -0x0f08000000LL},
132 {0x8a1c000000000ULL, -0x0e38000000LL},
133 {0x8304000000000ULL, -0x0d78000000LL},
134 {0x7c48000000000ULL, -0x0cc8000000LL},
135 {0x75e4000000000ULL, -0x0c28000000LL},
136 {0x6fd0000000000ULL, -0x0b98000000LL},
139[[nodiscard]]
static inline f64 frsqrte(
const f64 val) {
142 u64 mantissa = bits.u & MANTISSA_MASK_F64;
143 s64 exponent = bits.u & EXPONENT_MASK_F64;
144 bool sign = (bits.u & SIGN_MASK_F64) != 0;
147 if (mantissa == 0 && exponent == 0) {
148 return std::copysign(std::numeric_limits<f64>::infinity(), bits.f);
152 if (exponent == EXPONENT_MASK_F64) {
154 return sign ? std::numeric_limits<f64>::quiet_NaN() : 0.0;
162 return std::numeric_limits<f64>::quiet_NaN();
169 u32 shift = std::countl_zero(mantissa) -
static_cast<u32>(63 - EXPONENT_SHIFT_F64);
172 mantissa &= MANTISSA_MASK_F64;
175 exponent -=
static_cast<s64
>(shift - 1) << EXPONENT_SHIFT_F64;
181 u32 key =
static_cast<u32>((
static_cast<u64
>(exponent) | mantissa) >> 37);
183 (
static_cast<u64
>((0xbfcLL << EXPONENT_SHIFT_F64) - exponent) >> 1) & EXPONENT_MASK_F64;
186 const auto &entry = RSQRTE_TABLE[0x1f & (key >> 11)];
190 u64 new_mantissa =
static_cast<u64
>(entry.base + entry.dec *
static_cast<s64
>(key & 0x7ff));
192 return c64(new_exp | new_mantissa).f;
This header houses common data types such as our integral types and enums.
Math functions and constants used in the base game.
static f32 fma(f32 x, f32 y, f32 z)
Fused multiply-add operation.
static f64 force25Bit(f64 x)
This is used to mimic the Wii's floating-point unit.
static f32 fms(f32 x, f32 y, f32 z)
Fused multiply-subtract operation.