23#if __has_include(<bit>)
27#if defined(__BYTE_ORDER__)
28#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
29#define CE_LARGE_INTEGER_LE
30#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
31#define CE_LARGE_INTEGER_BE
33#error Endianess not supported
36#define CE_LARGE_INTEGER_LE
38#error Endianess not supported
41#if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16 && defined(CRT_HAS_128BIT)
42#define CE_LARGE_INTEGER_HAS_INT128
54 static_assert(
sizeof(Hi) ==
sizeof(Low),
"Hi and Low type should have same size!");
55 static_assert(std::is_unsigned<Low>::value,
"The Low part must be unsigned!");
63#if defined(CE_LARGE_INTEGER_LE)
66#elif defined(CE_LARGE_INTEGER_BE)
71#if defined(CE_LARGE_INTEGER_LE)
72 constexpr LargeInteger(Hi high, Low low) : low(low), high(high) {}
73#elif defined(CE_LARGE_INTEGER_BE)
76 : high(high), low(low) {}
107 template<
typename Tp,
108 typename = std::enable_if_t<std::is_integral_v<Tp>>>
111 [](Tp value)
constexpr {
112 if constexpr(
sizeof(Hi) <
sizeof(Tp)) {
113 return Hi(value >> (
sizeof(Low) * 8));
118 static_cast<Low
>(value)) {}
124 template<
typename Tp,
typename = std::enable_if_t<std::is_
integral_v<Tp>>> [[nodiscard]]
constexpr explicit operator Tp() const noexcept {
125 if constexpr(
sizeof(Tp) <=
sizeof(Low)) {
126 return static_cast<Tp
>(low);
128 return static_cast<Tp
>(low) | (
static_cast<Tp
>(high) << (
sizeof(Low) * 8));
132#if defined(CE_LARGE_INTEGER_HAS_INT128)
134 using Native = std::conditional_t<std::is_signed<Hi>::value, __int128,
unsigned __int128>;
140 :
LargeInteger(Hi(value >> (
sizeof(Low) * 8)), Low(value)) {}
146 [[nodiscard]]
constexpr explicit operator unsigned __int128() const noexcept {
147 return static_cast<unsigned __int128
>(high) << (
sizeof(Low) * 8) |
static_cast<unsigned __int128
>(low);
153 constexpr LargeInteger(
unsigned __int128 value)
noexcept
154 : LargeInteger(
static_cast<__int128
>(value)) {}
160 [[nodiscard]]
constexpr explicit operator __int128() const noexcept {
return static_cast<__int128
>(
static_cast<unsigned __int128
>(*this)); }
167#if defined(CE_LARGE_INTEGER_HAS_INT128)
170 :
LargeInteger(Hi(std::ldexp(value, -
static_cast<int>(
sizeof(Low) * 8))) - (value < 0), Low(value)) {
176 [[nodiscard]]
constexpr explicit
177 operator float() const noexcept {
178#if defined(CE_LARGE_INTEGER_HAS_INT128)
179 return static_cast<float>(
static_cast<Native
>(*this));
181 return static_cast<float>(
static_cast<long double>(*this));
189#if defined(CE_LARGE_INTEGER_HAS_INT128)
192 :
LargeInteger(Hi(std::ldexp(value, -
static_cast<int>(
sizeof(Low) * 8))) - (value < 0), Low(value)) {
198 [[nodiscard]]
constexpr explicit
199 operator double() const noexcept {
200#if defined(CE_LARGE_INTEGER_HAS_INT128)
201 return static_cast<double>(
static_cast<Native
>(*this));
203 return static_cast<double>(
static_cast<long double>(*this));
211#if defined(CE_LARGE_INTEGER_HAS_INT128)
214 :
LargeInteger(Hi(std::ldexp(value, -
static_cast<int>(
sizeof(Low) * 8))) - (value < 0), Low(value)) {
220 [[nodiscard]]
constexpr explicit
221 operator long double() const noexcept {
222 using Tp =
long double;
223#if defined(CE_LARGE_INTEGER_HAS_INT128)
224 return static_cast<Tp
>(
static_cast<Native
>(*this));
226 if constexpr(std::is_signed<Hi>::value) {
227 using UnsignedType =
typename std::make_unsigned<LargeInteger>::type;
228 return high < 0 ? -
static_cast<Tp
>(UnsignedType(-*
this)) : +
static_cast<Tp
>(UnsignedType(+*
this));
230 return std::ldexp(Tp(high),
sizeof(Low) * 8) + Tp(low);
239 [[nodiscard]]
constexpr explicit operator bool() const noexcept {
return high || low; }
248 template<
typename Tp>
static constexpr Tp halfMask = (Tp(1) << (4 *
sizeof(Tp))) - Tp(1);
249 template<
typename Tp>
static constexpr size_t bits =
sizeof(Tp) * 8;
250 template<
typename Tp>
static constexpr size_t halfBits =
bits<Tp> / 2;
272 const T a_lo = a.low;
273 const T a_hi = a.high;
274 const T b_lo = b.low;
275 const T b_hi = b.high;
290 Ans.high += (
N.high *
M.low) + (
N.low *
M.high);
324 inline namespace literals {
326 template<
char _Ch,
int _Rad>
327 struct static_digit : std::integral_constant<
328 int, '0' <= _Ch && _Ch <= '9'
330 : 'a' <= _Ch && _Ch <= 'z'
332 : 'A' <= _Ch && _Ch <= 'Z' ? _Ch - 'A' + 10 : _Rad> {
333 static_assert(_Rad > static_digit::value, "character not a digit");
336 template<typename, int, char...>
337 struct int128_literal_radix;
339 template<typename Tp, int _Rad, char _Ch>
340 struct int128_literal_radix<Tp, _Rad, _Ch> {
341 constexpr operator Tp() const { return Tp(static_digit<_Ch, _Rad>::value); }
343 constexpr Tp operator()(Tp v) const { return v * Tp(_Rad) + static_cast<Tp>(*this); }
346 template<typename Tp, int _Rad, char _Ch, char... _Args>
347 struct int128_literal_radix<Tp, _Rad, _Ch, _Args...> {
348 int128_literal_radix<Tp, _Rad, _Ch> _Cur;
349 int128_literal_radix<Tp, _Rad, _Args...> _Tgt;
351 constexpr operator Tp() const { return _Tgt(_Cur); };
353 constexpr Tp operator()(Tp v) const { return _Tgt(_Cur(v)); };
356 template<typename Tp, char... _Args>
357 struct int128_literal : int128_literal_radix<Tp, 10, _Args...> {};
358 template<typename Tp>
359 struct int128_literal<Tp, '0'> : int128_literal_radix<Tp, 10, '0'> {};
360 template<typename Tp, char... _Args>
361 struct int128_literal<Tp, '0', _Args...> : int128_literal_radix<Tp, 8, _Args...> {};
362 template<typename Tp, char... _Args>
363 struct int128_literal<Tp, '0', 'x', _Args...> : int128_literal_radix<Tp, 16, _Args...> {};
364 template<typename Tp, char... _Args>
365 struct int128_literal<Tp, '0', 'X', _Args...> : int128_literal_radix<Tp, 16, _Args...> {};
366 template<typename Tp, char... _Args>
367 struct int128_literal<Tp, '0', 'b', _Args...> : int128_literal_radix<Tp, 2, _Args...> {};
368 template<typename Tp, char... _Args>
369 struct int128_literal<Tp, '0', 'B', _Args...> : int128_literal_radix<Tp, 2, _Args...> {};
372 template<char... _Args>
373 constexpr UInt128 operator"" _u128() {
374 return impl_::int128_literal<UInt128, _Args...>();
377 template<char... _Args>
378 constexpr Int128 operator"" _i128() {
379 return impl_::int128_literal<Int128, _Args...>();
384 template<typename> struct LargeIntegerCLZHelper;
386#if defined(__cpp_lib_bitops)
387 template<typename T> struct LargeIntegerCLZHelper {
388 static constexpr int clz(T val) { return std::countl_zero(val); }
390#elif CE_COMPILER_CLANG || CE_COMPILER_GNUC
391 template<> struct LargeIntegerCLZHelper<unsigned char> {
392 static constexpr int clz(unsigned int val) { return __builtin_clzs(val) - 8; }
395 template<> struct LargeIntegerCLZHelper<unsigned short> {
396 static constexpr int clz(unsigned int val) { return __builtin_clzs(val); }
399 template<> struct LargeIntegerCLZHelper<unsigned int> {
400 static constexpr int clz(unsigned int val) { return __builtin_clz(val); }
403 template<> struct LargeIntegerCLZHelper<unsigned long> {
404 static constexpr int clz(unsigned long val) { return __builtin_clzl(val); }
407 template<> struct LargeIntegerCLZHelper<unsigned long long> {
408 static constexpr int clz(unsigned long long val) { return __builtin_clzll(val); }
410#elif CE_COMPILER_MSVC
411 template<> struct LargeIntegerCLZHelper<unsigned char> {
412 static int clz(unsigned char val) { return int(__lzcnt16(val) - 8); }
415 template<> struct LargeIntegerCLZHelper<unsigned short> {
416 static int clz(unsigned short val) { return int(__lzcnt16(val)); }
419 template<> struct LargeIntegerCLZHelper<unsigned int> {
420 static int clz(unsigned int val) { return int(__lzcnt(val)); }
423 template<> struct LargeIntegerCLZHelper<unsigned __int64> {
424 static int clz(unsigned __int64 val) { return int(__lzcnt64(val)); }
427#error Unsupported compiler!
430 template<typename High, typename Low> struct LargeIntegerCLZHelper<LargeInteger<High, Low>> {
431 static constexpr int clz(LargeInteger<High, Low> val) {
432 return val.high ? LargeIntegerCLZHelper<Low>::clz(Low(val.high)) : 4 * sizeof(val) + LargeIntegerCLZHelper<Low>::clz(val.low);
436 template<typename Hi, typename Low>
437 static LargeInteger<Hi, Low>& slowdiv(LargeInteger<Hi, Low>& dividend, LargeInteger<Hi, Low> divisor, LargeInteger<Hi, Low>& quot) {
438 quot = LargeInteger<Hi, Low>(0);
439 if(dividend < divisor)
441 if(dividend.high == 0) {
442 quot.low = dividend.low / divisor.low;
443 dividend.low %= divisor.low;
446 auto zend = LargeIntegerCLZHelper<LargeInteger<Hi, Low>>::clz(dividend);
447 auto zsor = LargeIntegerCLZHelper<LargeInteger<Hi, Low>>::clz(divisor);
450 for(zsor -= zend, divisor <<= zsor;; divisor >>= 1, quot <<= 1) {
451 if(dividend >= divisor) {
453 quot |= LargeInteger<Hi, Low>(1);
466 template<typename Hi, typename Low>
467 [[nodiscard]] constexpr LargeInteger<Hi, Low> operator+(LargeInteger<Hi, Low> lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
469 return {Hi(lhs.high + rhs.high + (lhs.low + rhs.low < lhs.low)), static_cast<Low>(lhs.low + rhs.low)};
478 template<typename Hi, typename Low>
479 [[nodiscard]] constexpr LargeInteger<Hi, Low> operator-(LargeInteger<Hi, Low> lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
480 return {Hi(lhs.high - rhs.high - (lhs.low < rhs.low)), static_cast<Low>(lhs.low - rhs.low)};
489 template<typename Hi, typename Low>
490 [[nodiscard]] constexpr LargeInteger<Hi, Low> operator*(LargeInteger<Hi, Low> lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
491 return LargeInteger<Hi, Low>(Hi(Hi(lhs.low) * rhs.high + Hi(rhs.low) * lhs.high) + Hi(lhs.low >> halfBits<Low>) * Hi(rhs.low >> halfBits<Low>),
492 (lhs.low & halfMask<Low>)*(rhs.low & halfMask<Low>)) +
493 (LargeInteger<Hi, Low>(Hi(0), (lhs.low >> halfBits<Low>)*(rhs.low & halfMask<Low>)) << halfBits<Low>)+(
494 LargeInteger<Hi, Low>(Hi(0), (rhs.low >> halfBits<Low>)*(lhs.low & halfMask<Low>)) << halfBits<Low>);
683 template<typename Hi, typename Low>
684 [[nodiscard]] constexpr LargeInteger<Hi, Low> operator/(LargeInteger<Hi, Low> lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
685 if constexpr(std::is_unsigned_v<Hi>) {
688 LargeInteger<Hi, Low> quot(0);
689 slowdiv(lhs, rhs, quot);
692 using UT = LargeInteger<typename std::make_unsigned<Hi>::type, Low>;
694 bool nneg_ = lhs.high < 0;
695 bool dneg_ = rhs.high < 0;
696 UT a = UT(nneg_ ? -lhs : lhs);
697 UT b = UT(dneg_ ? -rhs : rhs);
702 return LargeInteger<Hi, Low>(nneg_ ^ dneg_ ? -quot : quot);
712 template<typename Hi, typename Low>
713 [[nodiscard]] constexpr LargeInteger<Hi, Low> operator%(LargeInteger<Hi, Low> lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
714 if constexpr(std::is_unsigned_v<Hi>) {
716 LargeInteger<Hi, Low> quot(0);
717 return slowdiv(lhs, rhs, quot);
719 using UT = LargeInteger<typename std::make_unsigned<Hi>::type, Low>;
720 bool neg_ = lhs.high < 0;
722 UT a = UT(neg_ ? -lhs : lhs);
723 UT b = UT(rhs.high < 0 ? -rhs : rhs);
726 auto rem = slowdiv(a, b, quot);
728 return LargeInteger<Hi, Low>(neg_ ? -rem : rem);
738 template<typename Hi, typename Low>
739 [[nodiscard]] constexpr LargeInteger<Hi, Low> operator&(LargeInteger<Hi, Low> lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
740 return {static_cast<Hi>(lhs.high & rhs.high), static_cast<Low>(lhs.low & rhs.low)};
749 template<typename Hi, typename Low>
750 [[nodiscard]] constexpr LargeInteger<Hi, Low> operator|(LargeInteger<Hi, Low> lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
751 return {static_cast<Hi>(lhs.high | rhs.high), static_cast<Low>(lhs.low | rhs.low)};
760 template<typename Hi, typename Low>
761 [[nodiscard]] constexpr LargeInteger<Hi, Low> operator^(LargeInteger<Hi, Low> lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
762 return {static_cast<Hi>(lhs.high ^ rhs.high), static_cast<Low>(lhs.low ^ rhs.low)};
771 template<typename Hi, typename Low> [[nodiscard]] constexpr LargeInteger<Hi, Low> operator<<(LargeInteger<Hi, Low> lhs, int rhs) noexcept {
773 constexpr Low bitsMinusOne = bits<Low> - 1;
774 return Low(rhs) & bits<Low> ? LargeInteger<Hi, Low>(Hi(lhs.low << int(Low(rhs) & bitsMinusOne)), Low(0))
775 : Low(rhs) & bitsMinusOne
776 ? LargeInteger<Hi, Low>(Hi((Low(lhs.high) << int(Low(rhs) & bitsMinusOne)) | (lhs.low >> int(Low(bits<Low>) - (Low(rhs) & bitsMinusOne)))),
777 lhs.low << int(Low(rhs) & bitsMinusOne))
787 template<typename Hi, typename Low> [[nodiscard]] constexpr LargeInteger<Hi, Low> operator>>(LargeInteger<Hi, Low> lhs, int rhs) noexcept {
788 using T = LargeInteger<Hi, Low>;
789 constexpr Low bitsMinusOne = bits<Low> - 1;
792 if constexpr(std::is_signed<T>::value) {
793 return Low(rhs) & bits<Low> ? T(Hi(lhs.high < 0 ? -1 : 0),
794 Low(lhs.high >> int(Low(rhs) & bitsMinusOne)))
796 Low(rhs) & bitsMinusOne
797 ? T(Hi(lhs.high >> int(Low(rhs) & bitsMinusOne)),
799 Low(Hi(lhs.high) << int(Low(bits<Low>) - (Low(rhs) & bitsMinusOne)) |
800 Hi(lhs.low >> int(Low(rhs) & bitsMinusOne))))
803 return Low(rhs) & bits<Low> ? T(0, lhs.high >> int(Low(rhs) & bitsMinusOne))
804 : Low(rhs) & bitsMinusOne
805 ? T(lhs.high >> int(Low(rhs) & bitsMinusOne),
806 (lhs.high << int(Low(bits<Low>) - (Low(rhs) & bitsMinusOne)) |
807 Hi(lhs.low >> int(Low(rhs) & bitsMinusOne))))
813#if defined(CE_LARGE_INTEGER_HAS_INT128)
818 [[nodiscard]] inline constexpr Int128 operator+(Int128 lhs, Int128 rhs) noexcept {
819 using Native = __int128;
820 return static_cast<Native>(lhs) + static_cast<Native>(rhs);
827 [[nodiscard]] inline constexpr UInt128 operator+(UInt128 lhs, UInt128 rhs) noexcept {
828 using Native = unsigned __int128;
829 return static_cast<Native>(lhs) + static_cast<Native>(rhs);
836 [[nodiscard]] inline constexpr Int128 operator-(Int128 lhs, Int128 rhs) noexcept {
837 using Native = __int128;
838 return static_cast<Native>(lhs) - static_cast<Native>(rhs);
845 [[nodiscard]] inline constexpr UInt128 operator-(UInt128 lhs, UInt128 rhs) noexcept {
846 using Native = unsigned __int128;
847 return static_cast<Native>(lhs) - static_cast<Native>(rhs);
854 [[nodiscard]] inline constexpr Int128 operator*(Int128 lhs, Int128 rhs) noexcept {
855 using Native = __int128;
856 return static_cast<Native>(lhs) * static_cast<Native>(rhs);
863 [[nodiscard]] inline constexpr UInt128 operator*(UInt128 lhs, UInt128 rhs) noexcept {
864 using Native = unsigned __int128;
865 return static_cast<Native>(lhs) * static_cast<Native>(rhs);
872 [[nodiscard]] inline constexpr Int128 operator/(Int128 lhs, Int128 rhs) noexcept {
873 using Native = __int128;
874 return static_cast<Native>(lhs) / static_cast<Native>(rhs);
881 [[nodiscard]] inline constexpr UInt128 operator/(UInt128 lhs, UInt128 rhs) noexcept {
882 using Native = unsigned __int128;
883 return static_cast<Native>(lhs) / static_cast<Native>(rhs);
890 [[nodiscard]] inline constexpr Int128 operator%(Int128 lhs, Int128 rhs) noexcept {
891 using Native = __int128;
892 return static_cast<Native>(lhs) % static_cast<Native>(rhs);
899 [[nodiscard]] inline constexpr UInt128 operator%(UInt128 lhs, UInt128 rhs) noexcept {
900 using Native = unsigned __int128;
901 return static_cast<Native>(lhs) % static_cast<Native>(rhs);
907 [[nodiscard]] inline constexpr Int128 operator&(Int128 lhs, Int128 rhs) noexcept {
908 using Native = __int128;
909 return static_cast<Native>(lhs) & static_cast<Native>(rhs);
915 [[nodiscard]] inline constexpr UInt128 operator&(UInt128 lhs, UInt128 rhs) noexcept {
916 using Native = unsigned __int128;
917 return static_cast<Native>(lhs) & static_cast<Native>(rhs);
923 [[nodiscard]] inline constexpr Int128 operator|(Int128 lhs, Int128 rhs) noexcept {
924 using Native = __int128;
925 return static_cast<Native>(lhs) | static_cast<Native>(rhs);
931 [[nodiscard]] inline constexpr UInt128 operator|(UInt128 lhs, UInt128 rhs) noexcept {
932 using Native = unsigned __int128;
933 return static_cast<Native>(lhs) | static_cast<Native>(rhs);
939 [[nodiscard]] inline constexpr Int128 operator^(Int128 lhs, Int128 rhs) noexcept {
940 using Native = __int128;
941 return static_cast<Native>(lhs) ^ static_cast<Native>(rhs);
947 [[nodiscard]] inline constexpr UInt128 operator^(UInt128 lhs, UInt128 rhs) noexcept {
948 using Native = unsigned __int128;
949 return static_cast<Native>(lhs) ^ static_cast<Native>(rhs);
956 [[nodiscard]] inline constexpr Int128 operator<<(Int128 lhs, int rhs) noexcept {
957 using Native = __int128;
958 return static_cast<Native>(lhs) << rhs;
965 [[nodiscard]] inline constexpr UInt128 operator<<(UInt128 lhs, int rhs) noexcept {
966 using Native = unsigned __int128;
967 return static_cast<Native>(lhs) << rhs;
974 [[nodiscard]] inline constexpr Int128 operator>>(Int128 lhs, int rhs) noexcept {
975 using Native = __int128;
976 return static_cast<Native>(lhs) >> rhs;
983 [[nodiscard]] inline constexpr UInt128 operator>>(UInt128 lhs, int rhs) noexcept {
984 using Native = unsigned __int128;
985 return static_cast<Native>(lhs) >> rhs;
995 template<typename Hi, typename Low> [[nodiscard]] constexpr LargeInteger<Hi, Low> operator+(LargeInteger<Hi, Low> lhs) noexcept { return lhs; }
1002 template<typename Hi, typename Low> [[nodiscard]] constexpr LargeInteger<Hi, Low> operator-(LargeInteger<Hi, Low> lhs) noexcept {
1003 CE_DISABLE_WARNING_PUSH
1004 CE_DISABLE_WARNING_UNSIGNED_UNARY_MINUS
1005 return LargeInteger<Hi, Low>(-lhs.high - (lhs.low == 0 ? Hi(1) : Hi(0)), lhs.low);
1006 CE_DISABLE_WARNING_POP
1014 template<typename Hi, typename Low> [[nodiscard]] constexpr LargeInteger<Hi, Low> operator~(LargeInteger<Hi, Low> lhs) noexcept {
1015 return LargeInteger<Hi, Low>(~lhs.high, ~lhs.low);
1023 template<typename Hi, typename Low> [[nodiscard]] constexpr bool operator!(LargeInteger<Hi, Low> lhs) noexcept { return !bool(lhs); }
1030 template<typename Hi, typename Low> LargeInteger<Hi, Low>& operator++(LargeInteger<Hi, Low>& lhs) noexcept { return lhs = lhs + LargeInteger<Hi, Low>(1); }
1037 template<typename Hi, typename Low>
1038 LargeInteger<Hi, Low>
1039 operator++(LargeInteger<Hi, Low>& lhs, int) noexcept {
1040 LargeInteger tmp = lhs;
1050 template<typename Hi, typename Low> LargeInteger<Hi, Low>& operator--(LargeInteger<Hi, Low>& lhs) noexcept { return lhs = lhs - LargeInteger<Hi, Low>(1); }
1057 template<typename Hi, typename Low>
1058 LargeInteger<Hi, Low>
1059 operator--(LargeInteger<Hi, Low>& lhs, int) noexcept {
1060 LargeInteger tmp = lhs;
1065#if defined(CE_LARGE_INTEGER_HAS_INT128)
1069 [[nodiscard]] inline constexpr Int128 operator-(Int128 lhs) noexcept {
1070 using Native = __int128;
1071 return -static_cast<Native>(lhs);
1077 [[nodiscard]] inline constexpr UInt128 operator-(UInt128 lhs) noexcept {
1078 using Native = unsigned __int128;
1079 return -static_cast<Native>(lhs);
1085 [[nodiscard]] inline constexpr Int128 operator~(Int128 lhs) noexcept {
1086 using Native = __int128;
1087 return ~static_cast<Native>(lhs);
1093 [[nodiscard]] inline constexpr UInt128 operator~(UInt128 lhs) noexcept {
1094 using Native = unsigned __int128;
1095 return ~static_cast<Native>(lhs);
1107 template<typename Hi, typename Low>
1108 constexpr LargeInteger<Hi, Low>& operator+=(LargeInteger<Hi, Low>& lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
1109 return lhs = lhs + rhs;
1118 template<typename Hi, typename Low>
1119 constexpr LargeInteger<Hi, Low>& operator-=(LargeInteger<Hi, Low>& lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
1120 return lhs = lhs - rhs;
1129 template<typename Hi, typename Low>
1130 constexpr LargeInteger<Hi, Low>& operator*=(LargeInteger<Hi, Low>& lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
1131 return lhs = lhs * rhs;
1140 template<typename Hi, typename Low>
1141 constexpr LargeInteger<Hi, Low>& operator/=(LargeInteger<Hi, Low>& lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
1142 return lhs = lhs / rhs;
1152 template<typename Hi, typename Low>
1153 constexpr LargeInteger<Hi, Low>& operator%=(LargeInteger<Hi, Low>& lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
1154 return lhs = lhs % rhs;
1163 template<typename Hi, typename Low> constexpr LargeInteger<Hi, Low>& operator<<=(LargeInteger<Hi, Low>& lhs, int rhs) noexcept { return lhs = lhs << rhs; }
1171 template<typename Hi, typename Low> constexpr LargeInteger<Hi, Low>& operator>>=(LargeInteger<Hi, Low>& lhs, int rhs) noexcept { return lhs = lhs >> rhs; }
1179 template<typename Hi, typename Low>
1180 constexpr LargeInteger<Hi, Low>& operator&=(LargeInteger<Hi, Low>& lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
1181 return lhs = lhs & rhs;
1190 template<typename Hi, typename Low>
1191 constexpr LargeInteger<Hi, Low>& operator|=(LargeInteger<Hi, Low>& lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
1192 return lhs = lhs | rhs;
1201 template<typename Hi, typename Low>
1202 constexpr LargeInteger<Hi, Low>& operator^=(LargeInteger<Hi, Low>& lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
1203 return lhs = lhs ^ rhs;
1214 template<typename Hi, typename Low> [[nodiscard]] constexpr bool operator==(LargeInteger<Hi, Low> lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
1215 return lhs.high == rhs.high && lhs.low == rhs.low;
1224 template<typename Hi, typename Low> [[nodiscard]] constexpr bool operator!=(LargeInteger<Hi, Low> lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
1225 return !(lhs == rhs);
1234 template<typename Hi, typename Low> [[nodiscard]] constexpr bool operator<(LargeInteger<Hi, Low> lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
1235 return lhs.high < rhs.high || (lhs.high == rhs.high && lhs.low < rhs.low);
1244 template<typename Hi, typename Low> [[nodiscard]] constexpr bool operator<=(LargeInteger<Hi, Low> lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
1245 return !(rhs < lhs);
1254 template<typename Hi, typename Low> [[nodiscard]] constexpr bool operator>(LargeInteger<Hi, Low> lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
1264 template<typename Hi, typename Low> [[nodiscard]] constexpr bool operator>=(LargeInteger<Hi, Low> lhs, typename LargeInteger<Hi, Low>::Self rhs) noexcept {
1265 return !(lhs < rhs);
1268#if defined(CE_LARGE_INTEGER_HAS_INT128)
1273 [[nodiscard]] constexpr bool operator==(Int128 lhs, Int128 rhs) noexcept {
1274 using Native = __int128;
1275 return static_cast<Native>(lhs) == static_cast<Native>(rhs);
1282 [[nodiscard]] constexpr bool operator==(UInt128 lhs, UInt128 rhs) noexcept {
1283 using Native = unsigned __int128;
1284 return static_cast<Native>(lhs) == static_cast<Native>(rhs);
1291 [[nodiscard]] constexpr bool operator!=(Int128 lhs, Int128 rhs) noexcept {
1292 using Native = __int128;
1293 return static_cast<Native>(lhs) != static_cast<Native>(rhs);
1300 [[nodiscard]] constexpr bool operator!=(UInt128 lhs, UInt128 rhs) noexcept {
1301 using Native = unsigned __int128;
1302 return static_cast<Native>(lhs) != static_cast<Native>(rhs);
1309 [[nodiscard]] constexpr bool operator<(Int128 lhs, Int128 rhs) noexcept {
1310 using Native = __int128;
1311 return static_cast<Native>(lhs) < static_cast<Native>(rhs);
1318 [[nodiscard]] constexpr bool operator<(UInt128 lhs, UInt128 rhs) noexcept {
1319 using Native = unsigned __int128;
1320 return static_cast<Native>(lhs) < static_cast<Native>(rhs);
1327 [[nodiscard]] constexpr bool operator<=(Int128 lhs, Int128 rhs) noexcept {
1328 using Native = __int128;
1329 return static_cast<Native>(lhs) <= static_cast<Native>(rhs);
1336 [[nodiscard]] constexpr bool operator<=(UInt128 lhs, UInt128 rhs) noexcept {
1337 using Native = unsigned __int128;
1338 return static_cast<Native>(lhs) <= static_cast<Native>(rhs);
1345 [[nodiscard]] constexpr bool operator>(Int128 lhs, Int128 rhs) noexcept {
1346 using Native = __int128;
1347 return static_cast<Native>(lhs) > static_cast<Native>(rhs);
1354 [[nodiscard]] constexpr bool operator>(UInt128 lhs, UInt128 rhs) noexcept {
1355 using Native = unsigned __int128;
1356 return static_cast<Native>(lhs) > static_cast<Native>(rhs);
1363 [[nodiscard]] constexpr bool operator>=(Int128 lhs, Int128 rhs) noexcept {
1364 using Native = __int128;
1365 return static_cast<Native>(lhs) >= static_cast<Native>(rhs);
1372 [[nodiscard]] constexpr bool operator>=(UInt128 lhs, UInt128 rhs) noexcept {
1373 using Native = unsigned __int128;
1374 return static_cast<Native>(lhs) >= static_cast<Native>(rhs);
1385 template<typename Hi, typename Low> [[nodiscard]] constexpr LargeInteger<Hi, Low> abs(LargeInteger<Hi, Low> x) {
1386 if(x.high < Hi(0)) {
1387 return LargeInteger<Hi, Low>(-x.high - (x.low != 0), x.low);
1397template<typename Hi, typename Low> struct std::is_integral<CeresEngine::Math::LargeInteger<Hi, Low>> : std::true_type {};
1402template<typename Hi, typename Low> struct std::is_signed<CeresEngine::Math::LargeInteger<Hi, Low>> : std::is_signed<Hi> {};
1407template<typename Hi, typename Low> struct std::is_unsigned<CeresEngine::Math::LargeInteger<Hi, Low>> : std::is_unsigned<Hi> {};
1412template<typename Hi, typename Low> struct std::make_signed<CeresEngine::Math::LargeInteger<Hi, Low>> {
1413 typedef CeresEngine::Math::LargeInteger<typename std::make_signed<Hi>::type, Low> type;
1419template<typename Hi, typename Low> struct std::make_unsigned<CeresEngine::Math::LargeInteger<Hi, Low>> {
1420 typedef CeresEngine::Math::LargeInteger<typename std::make_unsigned<Hi>::type, Low> type;
1423template<typename H, typename L> struct std::hash<CeresEngine::Math::LargeInteger<H, L>> {
1424 using Type = CeresEngine::Math::LargeInteger<H, L>;
1425 constexpr size_t operator()(const Type& obj) const { return CeresEngine::hash(obj.high, obj.low); }
1432template<typename Hi, typename Low> struct std::numeric_limits<CeresEngine::Math::LargeInteger<Hi, Low>> {
1434 using Tp = CeresEngine::Math::LargeInteger<Hi, Low>;
1437 static inline constexpr bool is_specialized = true;
1440 static inline constexpr bool is_integer = true;
1443 static inline constexpr bool is_signed = numeric_limits<Hi>::is_signed;
1446 static inline constexpr bool is_exact = true;
1450 static inline constexpr bool has_infinity = false;
1454 static inline constexpr bool has_quiet_NaN = false;
1458 static inline constexpr bool has_signaling_NaN = false;
1461 static inline constexpr float_denorm_style has_denorm = denorm_absent;
1465 static inline constexpr bool has_denorm_loss = false;
1468 static inline constexpr float_round_style round_style = round_toward_zero;
1471 static inline constexpr bool is_iec559 = false;
1474 static inline constexpr bool is_bounded = true;
1477 static inline constexpr bool is_modulo = numeric_limits<Hi>::is_modulo;
1480 static inline constexpr int digits = static_cast<int>(sizeof(Tp) * 8 - is_signed);
1483 static inline constexpr int digits10 = digits * 3 / 10;
1487 static inline constexpr int max_digits10 = 0;
1490 static inline constexpr int radix = 2;
1494 static inline constexpr int min_exponent = 0;
1498 static inline constexpr int min_exponent10 = 0;
1502 static inline constexpr int max_exponent = 0;
1506 static inline constexpr int max_exponent10 = 0;
1509 static inline constexpr bool traps = numeric_limits<Hi>::traps;
1512 static inline constexpr bool tinyness_before = false;
1515 [[nodiscard]] static constexpr Tp min() { return is_signed ? Tp(1) << digits : Tp(0); }
1518 [[nodiscard]] static constexpr Tp lowest() { return min(); }
1521 [[nodiscard]] static constexpr Tp max() { return ~min(); }
1525 [[nodiscard]] static constexpr Tp epsilon() { return Tp(0); }
1528 [[nodiscard]] static constexpr Tp round_error() { return Tp(0); }
1531 [[nodiscard]] static constexpr Tp infinity() { return Tp(0); }
1534 [[nodiscard]] static constexpr Tp quiet_NaN() { return Tp(0); }
1537 [[nodiscard]] static constexpr Tp signaling_NaN() { return Tp(0); }
1541 [[nodiscard]] static constexpr Tp denorm_min() { return Tp(0); }
constexpr size_t hash(const T &v)
Generates a hash for the provided type.
Definition Hash.hpp:25
constexpr void multwide(T a, T b, T &hi, T &lo)
Definition LargeInteger.hpp:253
constexpr void mult128to256(U N, U M, U &H, U &L)
Definition LargeInteger.hpp:293
constexpr void mult128(T N, T M, T &Ans)
Definition LargeInteger.hpp:288
A wide integer type that uses Hi for the high-order bits in the integer data and Lo for the low-order...
Definition LargeInteger.hpp:53
constexpr LargeInteger(long double value) noexcept
Creates a new LargeInteger by converting from the floating point value.
Definition LargeInteger.hpp:210
constexpr LargeInteger(double value) noexcept
Creates a new LargeInteger by converting from the floating point value.
Definition LargeInteger.hpp:188
constexpr LargeInteger(Tp value) noexcept
Creates a new LargeInteger by converting from the native integer value.
Definition LargeInteger.hpp:109
constexpr LargeInteger() noexcept=default
Creates a new LargeInteger initialized to the value of 0.
constexpr LargeInteger(float value) noexcept
Creates a new LargeInteger by converting from the floating point value.
Definition LargeInteger.hpp:166