1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
#pragma once
namespace nall {
template<u32 Precision> struct IntegerPrimitive {
static_assert(Precision >= 1 && Precision <= 64);
using stype =
conditional_t<Precision <= 8, s8,
conditional_t<Precision <= 16, s16,
conditional_t<Precision <= 32, s32,
conditional_t<Precision <= 64, s64,
void>>>>;
using utype = typename Natural<Precision>::utype;
IntegerPrimitive() = default;
template<u32 Bits> IntegerPrimitive(IntegerPrimitive<Bits> value) { data = cast(value); }
template<typename T> IntegerPrimitive(const T& value) { data = cast(value); }
explicit IntegerPrimitive(const char* value) { data = cast(toInteger(value)); }
operator stype() const { return data; }
auto operator++(s32) { auto value = *this; data = cast(data + 1); return value; }
auto operator--(s32) { auto value = *this; data = cast(data - 1); return value; }
auto& operator++() { data = cast(data + 1); return *this; }
auto& operator--() { data = cast(data - 1); return *this; }
template<typename T> auto& operator =(const T& value) { data = cast( value); return *this; }
template<typename T> auto& operator *=(const T& value) { data = cast(data * value); return *this; }
template<typename T> auto& operator /=(const T& value) { data = cast(data / value); return *this; }
template<typename T> auto& operator %=(const T& value) { data = cast(data % value); return *this; }
template<typename T> auto& operator +=(const T& value) { data = cast(data + value); return *this; }
template<typename T> auto& operator -=(const T& value) { data = cast(data - value); return *this; }
template<typename T> auto& operator<<=(const T& value) { data = cast(data << value); return *this; }
template<typename T> auto& operator>>=(const T& value) { data = cast(data >> value); return *this; }
template<typename T> auto& operator &=(const T& value) { data = cast(data & value); return *this; }
template<typename T> auto& operator ^=(const T& value) { data = cast(data ^ value); return *this; }
template<typename T> auto& operator |=(const T& value) { data = cast(data | value); return *this; }
private:
static constexpr auto mask() -> utype {
return ~0ull >> 64 - Precision;
}
static constexpr auto sign() -> utype {
return 1ull << Precision - 1;
}
auto cast(stype value) const -> stype {
return (value & mask() ^ sign()) - sign();
}
stype data;
};
template<u32 Precision> struct Integer {
static_assert(Precision >= 1 && Precision <= 64);
static constexpr auto bits() -> u32 { return Precision; }
using stype =
conditional_t<Precision <= 8, s8,
conditional_t<Precision <= 16, s16,
conditional_t<Precision <= 32, s32,
conditional_t<Precision <= 64, s64,
void>>>>;
using utype = typename Natural<Precision>::utype;
static constexpr auto mask() -> utype { return ~0ull >> 64 - Precision; }
static constexpr auto sign() -> utype { return 1ull << Precision - 1; }
Integer() : data(0) {}
template<u32 Bits> Integer(Integer<Bits> value) { data = cast(value); }
template<typename T> Integer(const T& value) { data = cast(value); }
explicit Integer(const char* value) { data = cast(toInteger(value)); }
operator stype() const { return data; }
auto operator++(s32) { auto value = *this; data = cast(data + 1); return value; }
auto operator--(s32) { auto value = *this; data = cast(data - 1); return value; }
auto& operator++() { data = cast(data + 1); return *this; }
auto& operator--() { data = cast(data - 1); return *this; }
template<typename T> auto& operator =(const T& value) { data = cast( value); return *this; }
template<typename T> auto& operator *=(const T& value) { data = cast(data * value); return *this; }
template<typename T> auto& operator /=(const T& value) { data = cast(data / value); return *this; }
template<typename T> auto& operator %=(const T& value) { data = cast(data % value); return *this; }
template<typename T> auto& operator +=(const T& value) { data = cast(data + value); return *this; }
template<typename T> auto& operator -=(const T& value) { data = cast(data - value); return *this; }
template<typename T> auto& operator<<=(const T& value) { data = cast(data << value); return *this; }
template<typename T> auto& operator>>=(const T& value) { data = cast(data >> value); return *this; }
template<typename T> auto& operator &=(const T& value) { data = cast(data & value); return *this; }
template<typename T> auto& operator ^=(const T& value) { data = cast(data ^ value); return *this; }
template<typename T> auto& operator |=(const T& value) { data = cast(data | value); return *this; }
auto bit(s32 index) -> DynamicBitRange<Integer> { return {*this, index}; }
auto bit(s32 index) const -> const DynamicBitRange<Integer> { return {(Integer&)*this, index}; }
auto bit(s32 lo, s32 hi) -> DynamicBitRange<Integer> { return {*this, lo, hi}; }
auto bit(s32 lo, s32 hi) const -> const DynamicBitRange<Integer> { return {(Integer&)*this, lo, hi}; }
auto byte(s32 index) -> DynamicBitRange<Integer> { return {*this, index * 8 + 0, index * 8 + 7}; }
auto byte(s32 index) const -> const DynamicBitRange<Integer> { return {(Integer&)*this, index * 8 + 0, index * 8 + 7}; }
auto mask(s32 index) const -> utype {
return data & 1 << index;
}
auto mask(s32 lo, s32 hi) const -> utype {
return data & (~0ull >> 64 - (hi - lo + 1) << lo);
}
auto slice(s32 index) const { return Natural<>{bit(index)}; }
auto slice(s32 lo, s32 hi) const { return Natural<>{bit(lo, hi)}; }
static auto clamp(s64 value) -> stype {
constexpr s64 b = 1ull << bits() - 1;
constexpr s64 m = b - 1;
return value > m ? m : value < -b ? -b : value;
}
auto clip(u32 bits) -> stype {
const u64 b = 1ull << bits - 1;
const u64 m = b * 2 - 1;
return (data & m ^ b) - b;
}
auto serialize(serializer& s) { s(data); }
auto natural() const -> Natural<Precision>;
private:
auto cast(stype value) const -> stype {
return (value & mask() ^ sign()) - sign();
}
stype data;
};
}
|