7static constexpr f32 F_PI = 3.1415927f;
8static constexpr f32 F_TAU = 6.2831855f;
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;
15static constexpr f32 HALF_PI = F_PI / 2.0f;
20[[nodiscard]] f32
frsqrt(f32 x);
23[[nodiscard]]
static inline f32 sqrt(f32 x) {
24 return x > 0.0f ? x *
frsqrt(x) : 0.0f;
27[[nodiscard]] f32 SinFIdx(f32 fidx);
28[[nodiscard]] f32 CosFIdx(f32 fidx);
29[[nodiscard]] std::pair<f32, f32> SinCosFIdx(f32 fidx);
30[[nodiscard]] f32 AtanFIdx_(f32 fidx);
31[[nodiscard]] f32 Atan2FIdx(f32 x, f32 y);
33u32 FindRootsQuadratic(f32 a, f32 b, f32 c, f32 &root1, f32 &root2);
37[[nodiscard]]
static inline f32
sin(f32 x) {
38 return SinFIdx(x * RAD2FIDX);
43[[nodiscard]]
static inline f32
cos(f32 x) {
44 return CosFIdx(x * RAD2FIDX);
48[[nodiscard]]
static inline f32 asin(f32 x) {
53[[nodiscard]]
static inline f32 acos(f32 x) {
58[[nodiscard]]
static inline f32 atan2(f32 y, f32 x) {
59 return Atan2FIdx(y, x) * FIDX2RAD;
62[[nodiscard]]
static inline f32 abs(f32 x) {
70 u64 bits = std::bit_cast<u64>(x);
71 bits = (bits & 0xfffffffff8000000ULL) + (bits & 0x8000000);
72 return std::bit_cast<f64>(bits);
77[[nodiscard]]
static inline f32
fma(f32 x, f32 y, f32 z) {
78 return static_cast<f32
>(
79 static_cast<f64
>(x) *
force25Bit(
static_cast<f64
>(y)) +
static_cast<f64
>(z));
84[[nodiscard]]
static inline f32
fms(f32 x, f32 y, f32 z) {
85 return static_cast<f32
>(
86 static_cast<f64
>(x) *
force25Bit(
static_cast<f64
>(y)) -
static_cast<f64
>(z));
102 constexpr c32(
const f32 p) {
106 constexpr c32(
const u32 p) {
115 constexpr c64(
const f64 p) {
119 constexpr c64(
const u64 p) {
127static constexpr u64 EXPONENT_SHIFT_F64 = 52;
128static constexpr u64 MANTISSA_MASK_F64 = 0x000fffffffffffffULL;
129static constexpr u64 EXPONENT_MASK_F64 = 0x7ff0000000000000ULL;
130static constexpr u64 SIGN_MASK_F64 = 0x8000000000000000ULL;
132static constexpr std::array<BaseAndDec64, 32> RSQRTE_TABLE = {{
133 {0x69fa000000000ULL, -0x15a0000000LL},
134 {0x5f2e000000000ULL, -0x13cc000000LL},
135 {0x554a000000000ULL, -0x1234000000LL},
136 {0x4c30000000000ULL, -0x10d4000000LL},
137 {0x43c8000000000ULL, -0x0f9c000000LL},
138 {0x3bfc000000000ULL, -0x0e88000000LL},
139 {0x34b8000000000ULL, -0x0d94000000LL},
140 {0x2df0000000000ULL, -0x0cb8000000LL},
141 {0x2794000000000ULL, -0x0bf0000000LL},
142 {0x219c000000000ULL, -0x0b40000000LL},
143 {0x1bfc000000000ULL, -0x0aa0000000LL},
144 {0x16ae000000000ULL, -0x0a0c000000LL},
145 {0x11a8000000000ULL, -0x0984000000LL},
146 {0x0ce6000000000ULL, -0x090c000000LL},
147 {0x0862000000000ULL, -0x0898000000LL},
148 {0x0416000000000ULL, -0x082c000000LL},
149 {0xffe8000000000ULL, -0x1e90000000LL},
150 {0xf0a4000000000ULL, -0x1c00000000LL},
151 {0xe2a8000000000ULL, -0x19c0000000LL},
152 {0xd5c8000000000ULL, -0x17c8000000LL},
153 {0xc9e4000000000ULL, -0x1610000000LL},
154 {0xbedc000000000ULL, -0x1490000000LL},
155 {0xb498000000000ULL, -0x1330000000LL},
156 {0xab00000000000ULL, -0x11f8000000LL},
157 {0xa204000000000ULL, -0x10e8000000LL},
158 {0x9994000000000ULL, -0x0fe8000000LL},
159 {0x91a0000000000ULL, -0x0f08000000LL},
160 {0x8a1c000000000ULL, -0x0e38000000LL},
161 {0x8304000000000ULL, -0x0d78000000LL},
162 {0x7c48000000000ULL, -0x0cc8000000LL},
163 {0x75e4000000000ULL, -0x0c28000000LL},
164 {0x6fd0000000000ULL, -0x0b98000000LL},
167[[nodiscard]]
static inline f64 frsqrte(
const f64 val) {
170 u64 mantissa = bits.u & MANTISSA_MASK_F64;
171 s64 exponent = bits.u & EXPONENT_MASK_F64;
172 bool sign = (bits.u & SIGN_MASK_F64) != 0;
175 if (mantissa == 0 && exponent == 0) {
176 return std::copysign(std::numeric_limits<f64>::infinity(), bits.f);
180 if (exponent == EXPONENT_MASK_F64) {
182 return sign ? std::numeric_limits<f64>::quiet_NaN() : 0.0;
190 return std::numeric_limits<f64>::quiet_NaN();
197 u32 shift = std::countl_zero(mantissa) -
static_cast<u32
>(63 - EXPONENT_SHIFT_F64);
200 mantissa &= MANTISSA_MASK_F64;
203 exponent -=
static_cast<s64
>(shift - 1) << EXPONENT_SHIFT_F64;
209 u32 key =
static_cast<u32
>((
static_cast<u64
>(exponent) | mantissa) >> 37);
211 (
static_cast<u64
>((0xbfcLL << EXPONENT_SHIFT_F64) - exponent) >> 1) & EXPONENT_MASK_F64;
214 const auto &entry = RSQRTE_TABLE[0x1f & (key >> 11)];
218 u64 new_mantissa =
static_cast<u64
>(entry.base + entry.dec *
static_cast<s64
>(key & 0x7ff));
220 return c64(new_exp | new_mantissa).f;
223static constexpr std::array<BaseAndDec32, 32> FRES_TABLE = {{
224 {0x00fff000UL, -0x3e1L},
225 {0x00f07000UL, -0x3a7L},
226 {0x00e1d400UL, -0x371L},
227 {0x00d41000UL, -0x340L},
228 {0x00c71000UL, -0x313L},
229 {0x00bac400UL, -0x2eaL},
230 {0x00af2000UL, -0x2c4L},
231 {0x00a41000UL, -0x2a0L},
232 {0x00999000UL, -0x27fL},
233 {0x008f9400UL, -0x261L},
234 {0x00861000UL, -0x245L},
235 {0x007d0000UL, -0x22aL},
236 {0x00745800UL, -0x212L},
237 {0x006c1000UL, -0x1fbL},
238 {0x00642800UL, -0x1e5L},
239 {0x005c9400UL, -0x1d1L},
240 {0x00555000UL, -0x1beL},
241 {0x004e5800UL, -0x1acL},
242 {0x0047ac00UL, -0x19bL},
243 {0x00413c00UL, -0x18bL},
244 {0x003b1000UL, -0x17cL},
245 {0x00352000UL, -0x16eL},
246 {0x002f5c00UL, -0x15bL},
247 {0x0029f000UL, -0x15bL},
248 {0x00248800UL, -0x143L},
249 {0x001f7c00UL, -0x143L},
250 {0x001a7000UL, -0x12dL},
251 {0x0015bc00UL, -0x12dL},
252 {0x00110800UL, -0x11aL},
253 {0x000ca000UL, -0x11aL},
254 {0x00083800UL, -0x108L},
255 {0x00041800UL, -0x106L},
258[[nodiscard]]
static inline f32 fres(
const f32 val) {
259 static constexpr u32 EXPONENT_SHIFT_F32 = 23;
260 static constexpr u64 EXPONENT_SHIFT_F64 = 52;
261 static constexpr u32 EXPONENT_MASK_F32 = 0x7f800000UL;
262 static constexpr u64 EXPONENT_MASK_F64 = 0x7ff0000000000000ULL;
263 static constexpr u32 MANTISSA_MASK_F32 = 0x007fffffUL;
264 static constexpr u32 SIGN_MASK_F32 = 0x80000000UL;
265 static constexpr u64 SIGN_MASK_F64 = 0x8000000000000000ULL;
266 static constexpr u64 QUIET_BIT_F64 = 0x0008000000000000ULL;
267 static constexpr c64 LARGEST_FLOAT(
static_cast<u64
>(0x47d0000000000000ULL));
271 u32 mantissa =
static_cast<u32
>(
272 bits.u >> (EXPONENT_SHIFT_F64 -
static_cast<u64
>(EXPONENT_SHIFT_F32))) &
274 s32 exponent =
static_cast<s32
>((bits.u & EXPONENT_MASK_F64) >> EXPONENT_SHIFT_F64) - 0x380;
275 u32 sign =
static_cast<u32
>(bits.u >> 32) & SIGN_MASK_F32;
278 bool nonzero = (bits.u & !SIGN_MASK_F64) != 0;
282 c32 cresult(sign | (EXPONENT_MASK_F32 - (1 << EXPONENT_SHIFT_F32)) | MANTISSA_MASK_F32);
285 return std::copysignf(std::numeric_limits<f32>::infinity(), val);
289 if ((bits.u & EXPONENT_MASK_F64) >= LARGEST_FLOAT.u) {
290 if (mantissa == 0 || (bits.u & EXPONENT_MASK_F64) != EXPONENT_MASK_F64) {
292 return std::copysignf(0.0f, val);
293 }
else if ((bits.u & QUIET_BIT_F64) != 0) {
298 return std::numeric_limits<f32>::quiet_NaN();
303 u32 key = mantissa >> 18;
304 s32 new_exp = 253 - exponent;
305 const auto &entry = FRES_TABLE[key];
309 static_cast<u32
>(entry.base + entry.dec * (
static_cast<s32
>((mantissa >> 8) & 0x3ff)));
310 u32 new_mantissa = pre_shift >> 1;
317 u32 temp = sign |
static_cast<u32
>(new_exp) << EXPONENT_SHIFT_F32 | new_mantissa;
324[[nodiscard]]
static inline f32
finv(f32 x) {
326 f32 invDouble = inv + inv;
327 f32 invSquare = inv * inv;
328 return -
fms(x, invSquare, invDouble);
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 finv(f32 x)
Fused Newton-Raphson operation.
static f32 fms(f32 x, f32 y, f32 z)
Fused multiply-subtract operation.