You've already forked pico-launcher
mirror of
https://github.com/LNH-team/pico-launcher.git
synced 2026-01-09 16:28:48 -08:00
479 lines
13 KiB
C++
479 lines
13 KiB
C++
#pragma once
|
|
#include <libtwl/math/mathDiv.h>
|
|
|
|
template <typename T, u32 FractionBits>
|
|
class fixed
|
|
{
|
|
protected:
|
|
T _value;
|
|
|
|
constexpr fixed(T rawValue, int dummy)
|
|
: _value(rawValue) { }
|
|
|
|
public:
|
|
constexpr fixed() { }
|
|
|
|
template <typename T2>
|
|
constexpr fixed(fixed<T2, FractionBits> value)
|
|
: _value(value.GetRawValue()) { }
|
|
|
|
template <typename T2, u32 OtherFractionBits>
|
|
explicit constexpr fixed(fixed<T2, OtherFractionBits> value)
|
|
{
|
|
if (FractionBits == OtherFractionBits)
|
|
_value = value.GetRawValue();
|
|
else if (OtherFractionBits < FractionBits)
|
|
_value = value.GetRawValue() << (FractionBits - OtherFractionBits);
|
|
else
|
|
{
|
|
const T2 rounding = (T2)(1ULL << ((OtherFractionBits - FractionBits) - 1));
|
|
const int shift = OtherFractionBits - FractionBits;
|
|
_value = (value.GetRawValue() + rounding) >> shift;
|
|
}
|
|
}
|
|
|
|
constexpr fixed(int value)
|
|
: _value(value << FractionBits) { }
|
|
|
|
constexpr fixed(s64 value)
|
|
: _value(value << FractionBits) { }
|
|
|
|
constexpr fixed(float value)
|
|
: _value(std::round(value * (1 << FractionBits))) { }
|
|
|
|
constexpr fixed(double value)
|
|
: _value(std::round(value * (1 << FractionBits))) { }
|
|
|
|
constexpr fixed(long double value)
|
|
: _value(std::round(value * (1 << FractionBits))) { }
|
|
|
|
constexpr T Int() const
|
|
{
|
|
return _value >> FractionBits;
|
|
}
|
|
|
|
constexpr T GetRawValue() const { return _value; }
|
|
};
|
|
|
|
template <u32 FractionBits>
|
|
class fix32;
|
|
|
|
template <u32 FractionBits>
|
|
class fix64;
|
|
|
|
template <u32 FractionBits>
|
|
class fix16 : public fixed<s16, FractionBits>
|
|
{
|
|
constexpr fix16(s16 rawValue, int dummy)
|
|
: fixed<s16, FractionBits>(rawValue, dummy) { }
|
|
|
|
public:
|
|
constexpr fix16() { }
|
|
|
|
constexpr fix16(const fix16<FractionBits>& value)
|
|
: fixed<s16, FractionBits>(value) { }
|
|
|
|
template <typename T2, u32 OtherFractionBits>
|
|
explicit constexpr fix16(const fixed<T2, OtherFractionBits>& value)
|
|
: fixed<s16, FractionBits>(value) { }
|
|
|
|
constexpr fix16(s16 value)
|
|
: fixed<s16, FractionBits>(value) { }
|
|
|
|
constexpr fix16(int value)
|
|
: fixed<s16, FractionBits>(value) { }
|
|
|
|
constexpr fix16(float value)
|
|
: fixed<s16, FractionBits>(value) { }
|
|
|
|
constexpr fix16(double value)
|
|
: fixed<s16, FractionBits>(value) { }
|
|
|
|
constexpr fix16(long double value)
|
|
: fixed<s16, FractionBits>(value) { }
|
|
|
|
constexpr bool operator<(const fix16& other) const
|
|
{
|
|
return this->_value < other._value;
|
|
}
|
|
|
|
constexpr bool operator<=(const fix16& other) const
|
|
{
|
|
return this->_value <= other._value;
|
|
}
|
|
|
|
constexpr bool operator>(const fix16& other) const
|
|
{
|
|
return this->_value > other._value;
|
|
}
|
|
|
|
constexpr bool operator>=(const fix16& other) const
|
|
{
|
|
return this->_value >= other._value;
|
|
}
|
|
|
|
constexpr fix16 operator-() const
|
|
{
|
|
return FromRawValue(-this->_value);
|
|
}
|
|
|
|
constexpr fix16 operator+(const fix16& other) const
|
|
{
|
|
return FromRawValue(this->_value + other._value);
|
|
}
|
|
|
|
template <typename TOther>
|
|
constexpr fix16 operator+(TOther other) const
|
|
{
|
|
return FromRawValue(this->_value + fix16(other)._value);
|
|
}
|
|
|
|
template <typename TLhs>
|
|
constexpr friend fix16 operator+(TLhs lhs, const fix16& rhs)
|
|
{
|
|
return FromRawValue(fix16(lhs)._value + rhs._value);
|
|
}
|
|
|
|
constexpr fix16 operator-(const fix16& other) const
|
|
{
|
|
return FromRawValue(this->_value - other._value);
|
|
}
|
|
|
|
template <typename TOther>
|
|
constexpr fix16 operator-(TOther other) const
|
|
{
|
|
return FromRawValue(this->_value - fix16(other)._value);
|
|
}
|
|
|
|
template <typename TLhs>
|
|
constexpr friend fix16 operator-(TLhs lhs, fix16 rhs)
|
|
{
|
|
return FromRawValue(fix16(lhs)._value - rhs._value);
|
|
}
|
|
|
|
constexpr fix16 operator<<(int rhs) const
|
|
{
|
|
return FromRawValue(this->_value << rhs);
|
|
}
|
|
|
|
constexpr fix16 operator>>(int rhs) const
|
|
{
|
|
return FromRawValue(this->_value >> rhs);
|
|
}
|
|
|
|
constexpr fix16 abs() const
|
|
{
|
|
return FromRawValue(std::abs(this->_value));
|
|
}
|
|
|
|
template <u32 OtherFractionBits>
|
|
constexpr fix32<FractionBits + OtherFractionBits> LongMul(const fix16<OtherFractionBits>& other) const
|
|
{
|
|
return fix32<FractionBits + OtherFractionBits>::FromRawValue(this->_value * other.GetRawValue());
|
|
}
|
|
|
|
template <u32 OtherFractionBits>
|
|
constexpr fix64<FractionBits + OtherFractionBits> LongMul(const fix32<OtherFractionBits>& other) const
|
|
{
|
|
return fix64<FractionBits + OtherFractionBits>::FromRawValue(this->_value * (s64)other._value);
|
|
}
|
|
|
|
template <u32 OtherFractionBits>
|
|
constexpr fix16 operator*(const fix16<OtherFractionBits>& other) const
|
|
{
|
|
return fix16(LongMul(other));
|
|
}
|
|
|
|
template <u32 OtherFractionBits>
|
|
constexpr fix16 operator*(const fix32<OtherFractionBits>& other) const
|
|
{
|
|
return fix16(LongMul(other));
|
|
}
|
|
|
|
constexpr fix16 operator*(s16 other) const
|
|
{
|
|
return FromRawValue(this->_value * other);
|
|
}
|
|
|
|
constexpr friend fix16 operator*(s16 lhs, const fix16& rhs)
|
|
{
|
|
return FromRawValue(lhs * rhs.GetRawValue());
|
|
}
|
|
|
|
template <u32 OtherFractionBits>
|
|
constexpr fix16 operator/(const fix16<OtherFractionBits>& other) const
|
|
{
|
|
s32 lhs = (s32)this->_value << 16;
|
|
s32 rhs = other.GetRawValue();
|
|
s32 divResult;
|
|
if (std::is_constant_evaluated())
|
|
divResult = lhs / rhs;
|
|
else
|
|
divResult = math_div32(lhs, rhs);
|
|
return fix16(fix32<FractionBits + 16 - OtherFractionBits>::FromRawValue(divResult));
|
|
}
|
|
|
|
static constexpr fix16 FromRawValue(s16 value)
|
|
{
|
|
return fix16(value, 0);
|
|
}
|
|
};
|
|
|
|
template <u32 FractionBits>
|
|
class fix32 : public fixed<int, FractionBits>
|
|
{
|
|
constexpr fix32(int rawValue, int dummy)
|
|
: fixed<int, FractionBits>(rawValue, dummy) { }
|
|
|
|
public:
|
|
constexpr fix32() { }
|
|
|
|
constexpr fix32(const fix16<FractionBits>& value)
|
|
: fixed<int, FractionBits>(value) { }
|
|
|
|
constexpr fix32(const fix32<FractionBits>& value)
|
|
: fixed<int, FractionBits>(value) { }
|
|
|
|
template <typename T2, u32 OtherFractionBits>
|
|
explicit constexpr fix32(const fixed<T2, OtherFractionBits>& value)
|
|
: fixed<int, FractionBits>(value) { }
|
|
|
|
constexpr fix32(int value)
|
|
: fixed<int, FractionBits>(value) { }
|
|
|
|
constexpr fix32(float value)
|
|
: fixed<int, FractionBits>(value) { }
|
|
|
|
constexpr fix32(double value)
|
|
: fixed<int, FractionBits>(value) { }
|
|
|
|
constexpr fix32(long double value)
|
|
: fixed<int, FractionBits>(value) { }
|
|
|
|
constexpr bool operator==(const fix32& other) const
|
|
{
|
|
return this->_value == other._value;
|
|
}
|
|
|
|
constexpr bool operator!=(const fix32& other) const
|
|
{
|
|
return this->_value != other._value;
|
|
}
|
|
|
|
constexpr bool operator<(const fix32& other) const
|
|
{
|
|
return this->_value < other._value;
|
|
}
|
|
|
|
constexpr bool operator<=(const fix32& other) const
|
|
{
|
|
return this->_value <= other._value;
|
|
}
|
|
|
|
constexpr bool operator>(const fix32& other) const
|
|
{
|
|
return this->_value > other._value;
|
|
}
|
|
|
|
constexpr bool operator>=(const fix32& other) const
|
|
{
|
|
return this->_value >= other._value;
|
|
}
|
|
|
|
constexpr fix32 operator-() const
|
|
{
|
|
return FromRawValue(-this->_value);
|
|
}
|
|
|
|
constexpr fix32 operator+(const fix32& other) const
|
|
{
|
|
return FromRawValue(this->_value + other._value);
|
|
}
|
|
|
|
template <typename TOther>
|
|
constexpr fix32 operator+(TOther other) const
|
|
{
|
|
return FromRawValue(this->_value + fix32(other)._value);
|
|
}
|
|
|
|
template <typename TLhs>
|
|
constexpr friend fix32 operator+(TLhs lhs, const fix32& rhs)
|
|
{
|
|
return FromRawValue(fix32(lhs)._value + rhs._value);
|
|
}
|
|
|
|
constexpr fix32 operator-(const fix32& other) const
|
|
{
|
|
return FromRawValue(this->_value - other._value);
|
|
}
|
|
|
|
constexpr fix32 operator-(int other) const
|
|
{
|
|
return FromRawValue(this->_value - fix32(other)._value);
|
|
}
|
|
|
|
constexpr friend fix32 operator-(int lhs, const fix32& rhs)
|
|
{
|
|
return FromRawValue(fix32(lhs)._value - rhs._value);
|
|
}
|
|
|
|
constexpr fix32 operator/(int other) const
|
|
{
|
|
return FromRawValue(this->_value / other);
|
|
}
|
|
|
|
constexpr fix32 operator<<(int rhs) const
|
|
{
|
|
return FromRawValue(this->_value << rhs);
|
|
}
|
|
|
|
constexpr fix32 operator>>(int rhs) const
|
|
{
|
|
return FromRawValue(this->_value >> rhs);
|
|
}
|
|
|
|
constexpr fix32 Abs() const
|
|
{
|
|
return FromRawValue(std::abs(this->_value));
|
|
}
|
|
|
|
template <u32 OtherFractionBits>
|
|
constexpr fix64<FractionBits + OtherFractionBits> LongMul(const fix16<OtherFractionBits>& other) const
|
|
{
|
|
return fix64<FractionBits + OtherFractionBits>::FromRawValue((s64)this->_value * other.GetRawValue());
|
|
}
|
|
|
|
template <u32 OtherFractionBits>
|
|
constexpr fix64<FractionBits + OtherFractionBits> LongMul(const fix32<OtherFractionBits>& other) const
|
|
{
|
|
return fix64<FractionBits + OtherFractionBits>::FromRawValue((s64)this->_value * other.GetRawValue());
|
|
}
|
|
|
|
constexpr fix64<FractionBits> LongMul(int other) const
|
|
{
|
|
return fix64<FractionBits>::FromRawValue((s64)this->_value * other);
|
|
}
|
|
|
|
template <u32 OtherFractionBits>
|
|
constexpr fix32 operator*(const fix16<OtherFractionBits>& other) const
|
|
{
|
|
return fix32(LongMul(other));
|
|
}
|
|
|
|
template <u32 OtherFractionBits>
|
|
constexpr fix32 operator*(const fix32<OtherFractionBits>& other) const
|
|
{
|
|
return fix32(LongMul(other));
|
|
}
|
|
|
|
constexpr fix32 operator*(int other) const
|
|
{
|
|
return FromRawValue(this->_value * other);
|
|
}
|
|
|
|
constexpr friend fix32 operator*(int lhs, const fix32& rhs)
|
|
{
|
|
return FromRawValue(lhs * rhs.GetRawValue());
|
|
}
|
|
|
|
template <u32 OtherFractionBits>
|
|
constexpr fix32 operator/(const fix16<OtherFractionBits>& other) const
|
|
{
|
|
s64 lhs = (s64)this->_value << 32;
|
|
s32 rhs = other.GetRawValue();
|
|
s64 divResult;
|
|
if (std::is_constant_evaluated())
|
|
divResult = lhs / rhs;
|
|
else
|
|
divResult = math_div6432(lhs, rhs);
|
|
return fix32(fix64<FractionBits + 32 - OtherFractionBits>::FromRawValue(divResult));
|
|
}
|
|
|
|
template <u32 OtherFractionBits>
|
|
constexpr fix32 operator/(const fix32<OtherFractionBits>& other) const
|
|
{
|
|
s64 lhs = (s64)this->_value << 32;
|
|
s32 rhs = other.GetRawValue();
|
|
s64 divResult;
|
|
if (std::is_constant_evaluated())
|
|
divResult = lhs / rhs;
|
|
else
|
|
divResult = math_div6432(lhs, rhs);
|
|
return fix32(fix64<FractionBits + 32 - OtherFractionBits>::FromRawValue(divResult));
|
|
}
|
|
|
|
static constexpr fix32 FromRawValue(int value)
|
|
{
|
|
return fix32(value, 0);
|
|
}
|
|
};
|
|
|
|
// static constexpr fix32<12> operator""fx(long double value) { return fix32<12>(value); }
|
|
|
|
template <u32 FractionBits>
|
|
class fix64 : public fixed<s64, FractionBits>
|
|
{
|
|
constexpr fix64(s64 rawValue, int dummy)
|
|
: fixed<s64, FractionBits>(rawValue, dummy) { }
|
|
|
|
public:
|
|
constexpr fix64() { }
|
|
|
|
template <typename T2>
|
|
constexpr fix64(const fixed<T2, FractionBits>& value)
|
|
: fixed<s64, FractionBits>(value) { }
|
|
|
|
template <typename T2, u32 OtherFractionBits>
|
|
explicit constexpr fix64(const fixed<T2, OtherFractionBits>& value)
|
|
: fixed<s64, FractionBits>(value) { }
|
|
|
|
constexpr fix64(int value)
|
|
: fixed<s64, FractionBits>(value) { }
|
|
|
|
constexpr fix64(s64 value)
|
|
: fixed<s64, FractionBits>(value) { }
|
|
|
|
constexpr fix64(float value)
|
|
: fixed<s64, FractionBits>(value) { }
|
|
|
|
constexpr fix64(double value)
|
|
: fixed<s64, FractionBits>(value) { }
|
|
|
|
constexpr fix64(long double value)
|
|
: fixed<s64, FractionBits>(value) { }
|
|
|
|
constexpr bool operator<(const fix64& other) const
|
|
{
|
|
return this->_value < other._value;
|
|
}
|
|
|
|
constexpr bool operator<=(const fix64& other) const
|
|
{
|
|
return this->_value <= other._value;
|
|
}
|
|
|
|
constexpr bool operator>(const fix64& other) const
|
|
{
|
|
return this->_value > other._value;
|
|
}
|
|
|
|
constexpr bool operator>=(const fix64& other) const
|
|
{
|
|
return this->_value >= other._value;
|
|
}
|
|
|
|
constexpr fix64 operator+(const fix64& other) const
|
|
{
|
|
return FromRawValue(this->_value + other._value);
|
|
}
|
|
|
|
constexpr fix64 operator-(const fix64& other) const
|
|
{
|
|
return FromRawValue(this->_value - other._value);
|
|
}
|
|
|
|
static constexpr fix64 FromRawValue(s64 value)
|
|
{
|
|
return fix64(value, 0);
|
|
}
|
|
}; |