mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-20 15:40:23 +00:00
Basic constexpr support for u128 (MSVC)
Added explicit conversion op to u64. Added constexpr path for +,-,>>,<< ops. Make almost all methods constexpr. Removed a lot of redundancy.
This commit is contained in:
parent
6c18e00977
commit
c0f3d1f06d
@ -296,9 +296,9 @@ struct alignas(16) u128
|
||||
{
|
||||
u64 lo, hi;
|
||||
|
||||
u128() = default;
|
||||
u128() noexcept = default;
|
||||
|
||||
constexpr u128(u64 l)
|
||||
constexpr u128(u64 l) noexcept
|
||||
: lo(l)
|
||||
, hi(0)
|
||||
{
|
||||
@ -309,167 +309,204 @@ struct alignas(16) u128
|
||||
return !!(lo | hi);
|
||||
}
|
||||
|
||||
friend u128 operator+(const u128& l, const u128& r)
|
||||
constexpr explicit operator u64() const noexcept
|
||||
{
|
||||
u128 value;
|
||||
_addcarry_u64(_addcarry_u64(0, r.lo, l.lo, &value.lo), r.hi, l.hi, &value.hi);
|
||||
return lo;
|
||||
}
|
||||
|
||||
constexpr friend u128 operator+(const u128& l, const u128& r)
|
||||
{
|
||||
u128 value = l;
|
||||
value += r;
|
||||
return value;
|
||||
}
|
||||
|
||||
friend u128 operator+(const u128& l, u64 r)
|
||||
constexpr friend u128 operator-(const u128& l, const u128& r)
|
||||
{
|
||||
u128 value;
|
||||
_addcarry_u64(_addcarry_u64(0, r, l.lo, &value.lo), l.hi, 0, &value.hi);
|
||||
u128 value = l;
|
||||
value -= r;
|
||||
return value;
|
||||
}
|
||||
|
||||
friend u128 operator+(u64 l, const u128& r)
|
||||
{
|
||||
u128 value;
|
||||
_addcarry_u64(_addcarry_u64(0, r.lo, l, &value.lo), 0, r.hi, &value.hi);
|
||||
return value;
|
||||
}
|
||||
|
||||
friend u128 operator-(const u128& l, const u128& r)
|
||||
{
|
||||
u128 value;
|
||||
_subborrow_u64(_subborrow_u64(0, l.lo, r.lo, &value.lo), l.hi, r.hi, &value.hi);
|
||||
return value;
|
||||
}
|
||||
|
||||
friend u128 operator-(const u128& l, u64 r)
|
||||
{
|
||||
u128 value;
|
||||
_subborrow_u64(_subborrow_u64(0, l.lo, r, &value.lo), l.hi, 0, &value.hi);
|
||||
return value;
|
||||
}
|
||||
|
||||
friend u128 operator-(u64 l, const u128& r)
|
||||
{
|
||||
u128 value;
|
||||
_subborrow_u64(_subborrow_u64(0, l, r.lo, &value.lo), 0, r.hi, &value.hi);
|
||||
return value;
|
||||
}
|
||||
|
||||
u128 operator+() const
|
||||
constexpr u128 operator+() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
u128 operator-() const
|
||||
constexpr u128 operator-() const
|
||||
{
|
||||
u128 value;
|
||||
_subborrow_u64(_subborrow_u64(0, 0, lo, &value.lo), 0, hi, &value.hi);
|
||||
u128 value{};
|
||||
value -= *this;
|
||||
return value;
|
||||
}
|
||||
|
||||
u128& operator++()
|
||||
constexpr u128& operator++()
|
||||
{
|
||||
_addcarry_u64(_addcarry_u64(0, 1, lo, &lo), 0, hi, &hi);
|
||||
*this += 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
u128 operator++(int)
|
||||
constexpr u128 operator++(int)
|
||||
{
|
||||
u128 value = *this;
|
||||
_addcarry_u64(_addcarry_u64(0, 1, lo, &lo), 0, hi, &hi);
|
||||
*this += 1;
|
||||
return value;
|
||||
}
|
||||
|
||||
u128& operator--()
|
||||
constexpr u128& operator--()
|
||||
{
|
||||
_subborrow_u64(_subborrow_u64(0, lo, 1, &lo), hi, 0, &hi);
|
||||
*this -= 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
u128 operator--(int)
|
||||
constexpr u128 operator--(int)
|
||||
{
|
||||
u128 value = *this;
|
||||
_subborrow_u64(_subborrow_u64(0, lo, 1, &lo), hi, 0, &hi);
|
||||
*this -= 1;
|
||||
return value;
|
||||
}
|
||||
|
||||
u128 operator<<(u128 shift_value)
|
||||
constexpr u128 operator<<(u128 shift_value) const
|
||||
{
|
||||
const u64 v0 = lo << (shift_value.lo & 63);
|
||||
const u64 v1 = __shiftleft128(lo, hi, static_cast<uchar>(shift_value.lo));
|
||||
|
||||
u128 value;
|
||||
value.lo = (shift_value.lo & 64) ? 0 : v0;
|
||||
value.hi = (shift_value.lo & 64) ? v0 : v1;
|
||||
u128 value = *this;
|
||||
value <<= shift_value;
|
||||
return value;
|
||||
}
|
||||
|
||||
u128 operator>>(u128 shift_value)
|
||||
constexpr u128 operator>>(u128 shift_value) const
|
||||
{
|
||||
const u64 v0 = hi >> (shift_value.lo & 63);
|
||||
const u64 v1 = __shiftright128(lo, hi, static_cast<uchar>(shift_value.lo));
|
||||
|
||||
u128 value;
|
||||
value.lo = (shift_value.lo & 64) ? v0 : v1;
|
||||
value.hi = (shift_value.lo & 64) ? 0 : v0;
|
||||
u128 value = *this;
|
||||
value >>= shift_value;
|
||||
return value;
|
||||
}
|
||||
|
||||
u128 operator~() const
|
||||
constexpr u128 operator~() const
|
||||
{
|
||||
u128 value;
|
||||
u128 value{};
|
||||
value.lo = ~lo;
|
||||
value.hi = ~hi;
|
||||
return value;
|
||||
}
|
||||
|
||||
friend u128 operator&(const u128& l, const u128& r)
|
||||
constexpr friend u128 operator&(const u128& l, const u128& r)
|
||||
{
|
||||
u128 value;
|
||||
u128 value{};
|
||||
value.lo = l.lo & r.lo;
|
||||
value.hi = l.hi & r.hi;
|
||||
return value;
|
||||
}
|
||||
|
||||
friend u128 operator|(const u128& l, const u128& r)
|
||||
constexpr friend u128 operator|(const u128& l, const u128& r)
|
||||
{
|
||||
u128 value;
|
||||
u128 value{};
|
||||
value.lo = l.lo | r.lo;
|
||||
value.hi = l.hi | r.hi;
|
||||
return value;
|
||||
}
|
||||
|
||||
friend u128 operator^(const u128& l, const u128& r)
|
||||
constexpr friend u128 operator^(const u128& l, const u128& r)
|
||||
{
|
||||
u128 value;
|
||||
u128 value{};
|
||||
value.lo = l.lo ^ r.lo;
|
||||
value.hi = l.hi ^ r.hi;
|
||||
return value;
|
||||
}
|
||||
|
||||
u128& operator+=(const u128& r)
|
||||
constexpr u128& operator+=(const u128& r)
|
||||
{
|
||||
_addcarry_u64(_addcarry_u64(0, r.lo, lo, &lo), r.hi, hi, &hi);
|
||||
if (std::is_constant_evaluated())
|
||||
{
|
||||
lo += r.lo;
|
||||
hi += r.hi + (lo < r.lo);
|
||||
}
|
||||
else
|
||||
{
|
||||
_addcarry_u64(_addcarry_u64(0, r.lo, lo, &lo), r.hi, hi, &hi);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
u128& operator+=(uint64_t r)
|
||||
constexpr u128& operator-=(const u128& r)
|
||||
{
|
||||
_addcarry_u64(_addcarry_u64(0, r, lo, &lo), 0, hi, &hi);
|
||||
if (std::is_constant_evaluated())
|
||||
{
|
||||
hi -= r.hi + (lo < r.lo);
|
||||
lo -= r.lo;
|
||||
}
|
||||
else
|
||||
{
|
||||
_subborrow_u64(_subborrow_u64(0, lo, r.lo, &lo), hi, r.hi, &hi);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
u128& operator&=(const u128& r)
|
||||
constexpr u128& operator<<=(const u128& r)
|
||||
{
|
||||
if (std::is_constant_evaluated())
|
||||
{
|
||||
if (r.hi == 0 && r.lo < 64)
|
||||
{
|
||||
hi = (hi << r.lo) | (lo >> (64 - r.lo));
|
||||
lo = (lo << r.lo);
|
||||
return *this;
|
||||
}
|
||||
else if (r.hi == 0 && r.lo < 128)
|
||||
{
|
||||
hi = (lo << (r.lo - 64));
|
||||
lo = 0;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
const u64 v0 = lo << (r.lo & 63);
|
||||
const u64 v1 = __shiftleft128(lo, hi, static_cast<uchar>(r.lo));
|
||||
lo = (r.lo & 64) ? 0 : v0;
|
||||
hi = (r.lo & 64) ? v0 : v1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr u128& operator>>=(const u128& r)
|
||||
{
|
||||
if (std::is_constant_evaluated())
|
||||
{
|
||||
if (r.hi == 0 && r.lo < 64)
|
||||
{
|
||||
lo = (lo >> r.lo) | (hi << (64 - r.lo));
|
||||
hi = (hi >> r.lo);
|
||||
return *this;
|
||||
}
|
||||
else if (r.hi == 0 && r.lo < 128)
|
||||
{
|
||||
lo = (hi >> (r.lo - 64));
|
||||
hi = 0;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
const u64 v0 = hi >> (r.lo & 63);
|
||||
const u64 v1 = __shiftright128(lo, hi, static_cast<uchar>(r.lo));
|
||||
lo = (r.lo & 64) ? v0 : v1;
|
||||
hi = (r.lo & 64) ? 0 : v0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr u128& operator&=(const u128& r)
|
||||
{
|
||||
lo &= r.lo;
|
||||
hi &= r.hi;
|
||||
return *this;
|
||||
}
|
||||
|
||||
u128& operator|=(const u128& r)
|
||||
constexpr u128& operator|=(const u128& r)
|
||||
{
|
||||
lo |= r.lo;
|
||||
hi |= r.hi;
|
||||
return *this;
|
||||
}
|
||||
|
||||
u128& operator^=(const u128& r)
|
||||
constexpr u128& operator^=(const u128& r)
|
||||
{
|
||||
lo ^= r.lo;
|
||||
hi ^= r.hi;
|
||||
|
Loading…
x
Reference in New Issue
Block a user