2563 lines
72 KiB
C++
2563 lines
72 KiB
C++
// File:Int128.h
|
|
// https://stackoverflow.com/questions/6759592/how-to-enable-int128-on-visual-studio
|
|
|
|
#ifndef Int128_h
|
|
#define Int128_h
|
|
|
|
#pragma once
|
|
|
|
#include <limits>
|
|
//#include <CommonHashFunctions.h>
|
|
//#include "PragmaLib.h"
|
|
|
|
typedef struct {
|
|
unsigned __int64 i[2];
|
|
} _S2;
|
|
|
|
typedef struct {
|
|
unsigned int i[4];
|
|
} _S4;
|
|
|
|
typedef struct {
|
|
unsigned short s[8];
|
|
} _S8;
|
|
|
|
typedef struct {
|
|
unsigned char b[16];
|
|
} _S16;
|
|
|
|
#define HI64(n) (n).s2.i[1]
|
|
#define LO64(n) (n).s2.i[0]
|
|
|
|
extern "C" {
|
|
void int128add( void *dst, const void *x);
|
|
void int128sub( void *dst, const void *x);
|
|
void int128mul( void *dst, const void *x);
|
|
void int128div( void *dst, void *x);
|
|
void int128rem( void *dst, void *x);
|
|
void int128neg( void *x);
|
|
void int128inc( void *x);
|
|
void int128dec( void *x);
|
|
void int128shr( int shft, void *x );
|
|
void int128shl( int shft, void *x );
|
|
int int128cmp( const void *x1, const void *x2);
|
|
void uint128div(void *dst, const void *x);
|
|
void uint128rem(void *dst, const void *x);
|
|
void uint128shr(int shft, void *x );
|
|
int uint128cmp(const void *x1, const void *x2);
|
|
};
|
|
|
|
class _int128 {
|
|
public:
|
|
union {
|
|
_S2 s2;
|
|
_S4 s4;
|
|
_S8 s8;
|
|
_S16 s16;
|
|
};
|
|
|
|
// constructors
|
|
inline _int128() {}
|
|
inline _int128(const unsigned __int64 &n) {
|
|
HI64(*this) = 0;
|
|
LO64(*this) = n;
|
|
}
|
|
inline _int128(const __int64 &n) {
|
|
HI64(*this) = n < 0 ? -1 : 0;
|
|
LO64(*this) = n;
|
|
}
|
|
inline _int128(unsigned long n) {
|
|
HI64(*this) = 0;
|
|
LO64(*this) = n;
|
|
}
|
|
inline _int128(long n) {
|
|
HI64(*this) = n < 0 ? -1 : 0;
|
|
LO64(*this) = n;
|
|
}
|
|
inline _int128(unsigned int n) {
|
|
HI64(*this) = 0;
|
|
LO64(*this) = n;
|
|
}
|
|
inline _int128(int n) {
|
|
HI64(*this) = n < 0 ? -1 : 0;
|
|
LO64(*this) = n;
|
|
}
|
|
inline _int128(unsigned short n) {
|
|
HI64(*this) = 0;
|
|
LO64(*this) = n;
|
|
}
|
|
inline _int128(short n) {
|
|
HI64(*this) = n < 0 ? -1 : 0;
|
|
LO64(*this) = n;
|
|
}
|
|
explicit inline _int128(const unsigned __int64 &hi, const unsigned __int64 &lo) {
|
|
HI64(*this) = hi;
|
|
LO64(*this) = lo;
|
|
}
|
|
|
|
// type operators
|
|
inline operator unsigned __int64() const {
|
|
return LO64(*this);
|
|
}
|
|
inline operator __int64() const {
|
|
return LO64(*this);
|
|
}
|
|
inline operator unsigned long() const {
|
|
return (unsigned long)LO64(*this);
|
|
}
|
|
inline operator long() const {
|
|
return (long)LO64(*this);
|
|
}
|
|
inline operator unsigned int() const {
|
|
return (unsigned int)LO64(*this);
|
|
}
|
|
inline operator int() const {
|
|
return (int)LO64(*this);
|
|
}
|
|
inline operator unsigned short() const {
|
|
return (unsigned short)LO64(*this);
|
|
}
|
|
inline operator short() const {
|
|
return (short)LO64(*this);
|
|
}
|
|
inline operator unsigned char() const {
|
|
return (unsigned char)LO64(*this);
|
|
}
|
|
inline operator char() const {
|
|
return (char)LO64(*this);
|
|
}
|
|
inline operator bool() const {
|
|
return LO64(*this) || HI64(*this);
|
|
}
|
|
|
|
// assign operators
|
|
inline _int128 &operator++() { // prefix-form
|
|
int128inc(this);
|
|
return *this;
|
|
}
|
|
inline _int128 &operator--() { // prefix-form
|
|
int128dec(this);
|
|
return *this;
|
|
}
|
|
|
|
inline _int128 operator++(int) { // postfix-form
|
|
const _int128 result(*this);
|
|
int128inc(this);
|
|
return result;
|
|
}
|
|
inline _int128 operator--(int) { // postfix-form
|
|
const _int128 result(*this);
|
|
int128dec(this);
|
|
return result;
|
|
}
|
|
|
|
inline bool isNegative() const {
|
|
return ((int)s4.i[3] < 0);
|
|
}
|
|
inline bool isZero() const {
|
|
return LO64(*this) == 0 && HI64(*this) == 0;
|
|
}
|
|
};
|
|
|
|
class _uint128 {
|
|
public:
|
|
union {
|
|
_S2 s2;
|
|
_S4 s4;
|
|
_S8 s8;
|
|
_S16 s16;
|
|
};
|
|
|
|
// constructors
|
|
inline _uint128() {}
|
|
|
|
inline _uint128(const _int128 &n) {
|
|
HI64(*this) = HI64(n);
|
|
LO64(*this) = LO64(n);
|
|
}
|
|
inline _uint128(const unsigned __int64 &n) {
|
|
HI64(*this) = 0;
|
|
LO64(*this) = n;
|
|
}
|
|
inline _uint128(const __int64 &n) {
|
|
HI64(*this) = n < 0 ? -1 : 0;
|
|
LO64(*this) = n;
|
|
}
|
|
inline _uint128(unsigned long n) {
|
|
HI64(*this) = 0;
|
|
LO64(*this) = n;
|
|
}
|
|
inline _uint128(long n) {
|
|
HI64(*this) = n < 0 ? -1 : 0;
|
|
LO64(*this) = n;
|
|
}
|
|
inline _uint128(unsigned int n) {
|
|
HI64(*this) = 0;
|
|
LO64(*this) = n;
|
|
}
|
|
inline _uint128(int n) {
|
|
HI64(*this) = n < 0 ? -1 : 0;
|
|
LO64(*this) = n;
|
|
}
|
|
inline _uint128(unsigned short n) {
|
|
HI64(*this) = n < 0 ? -1 : 0;
|
|
LO64(*this) = n;
|
|
}
|
|
inline _uint128(short n) {
|
|
HI64(*this) = n < 0 ? -1 : 0;
|
|
LO64(*this) = n;
|
|
}
|
|
inline _uint128(const unsigned __int64 &hi, const unsigned __int64 &lo) {
|
|
HI64(*this) = hi;
|
|
LO64(*this) = lo;
|
|
}
|
|
|
|
// type operators
|
|
inline operator _int128() const {
|
|
return *(_int128*)(void*)this;
|
|
}
|
|
inline operator unsigned __int64() const {
|
|
return LO64(*this);
|
|
}
|
|
inline operator __int64() const {
|
|
return LO64(*this);
|
|
}
|
|
inline operator unsigned long() const {
|
|
return (unsigned long)LO64(*this);
|
|
}
|
|
inline operator long() const {
|
|
return (long)LO64(*this);
|
|
}
|
|
inline operator unsigned int() const {
|
|
return (unsigned int)LO64(*this);
|
|
}
|
|
inline operator int() const {
|
|
return (int)LO64(*this);
|
|
}
|
|
inline operator unsigned short() const {
|
|
return (unsigned short)LO64(*this);
|
|
}
|
|
inline operator short() const {
|
|
return (short)LO64(*this);
|
|
}
|
|
inline operator unsigned char() const {
|
|
return (unsigned char)LO64(*this);
|
|
}
|
|
inline operator char() const {
|
|
return (char)LO64(*this);
|
|
}
|
|
inline operator bool() const {
|
|
return LO64(*this) || HI64(*this);
|
|
}
|
|
|
|
inline _uint128 &operator++() { // prefix-form
|
|
int128inc(this);
|
|
return *this;
|
|
}
|
|
inline _uint128 &operator--() { // prefix-form
|
|
int128dec(this);
|
|
return *this;
|
|
}
|
|
|
|
inline _uint128 operator++(int) { // postfix-form
|
|
const _uint128 result(*this);
|
|
int128inc(this);
|
|
return result;
|
|
}
|
|
inline _uint128 operator--(int) { // postfix-form
|
|
const _uint128 result(*this);
|
|
int128dec(this);
|
|
return result;
|
|
}
|
|
|
|
inline bool isNegative() const {
|
|
return false;
|
|
}
|
|
inline bool isZero() const {
|
|
return LO64(*this) == 0 && HI64(*this) == 0;
|
|
}
|
|
};
|
|
|
|
// 4 version of all 5 binary arithmetic operators,
|
|
// 3 binary logical operators and 6 compare-operators
|
|
// signed op signed
|
|
// signed op unsigned
|
|
// unsigned op signed
|
|
// unsigned op unsigned
|
|
// For +,-,*,&,|,^,==,!= the called function is the same
|
|
// regardless of signed/unsigned combinations.
|
|
// For /,%,<,>,<=,>= however the signed function is used
|
|
// only for the "signed op signed" combination.
|
|
// For left shift (<<) there is no difference for
|
|
// signed and unsigned function, but for right shift (>>)
|
|
// the leftmost bit (bit 127) indicates the sign, and will
|
|
// be copied to all new bits comming in from left for _int128
|
|
// and 0-bits will be shifted in for _uint128 (because there
|
|
// is no sign).
|
|
// For assign-operators (+=,-=...) the same rules apply.
|
|
// Vesions for built in integral types are then defined
|
|
// on top of these
|
|
|
|
// 4 basic combination of operator+ (128-bit integers - dont care about signed/unsigned)
|
|
inline _int128 operator+(const _int128 &lft, const _int128 &rhs) {
|
|
_int128 result(lft);
|
|
int128add(&result, &rhs);
|
|
return result;
|
|
}
|
|
inline _int128 operator+(const _int128 &lft, const _uint128 &rhs) {
|
|
_int128 result(lft);
|
|
int128add(&result, &rhs);
|
|
return result;
|
|
}
|
|
inline _uint128 operator+(const _uint128 &lft, const _int128 &rhs) {
|
|
_uint128 result(lft);
|
|
int128add(&result, &rhs);
|
|
return result;
|
|
}
|
|
inline _uint128 operator+(const _uint128 &lft, const _uint128 &rhs) {
|
|
_uint128 result(lft);
|
|
int128add(&result, &rhs);
|
|
return result;
|
|
}
|
|
|
|
// 4 basic combination of operator- (128-bit integers - dont care about signed/unsigned)
|
|
inline _int128 operator-(const _int128 &lft, const _int128 &rhs) {
|
|
_int128 result(lft);
|
|
int128sub(&result, &rhs);
|
|
return result;
|
|
}
|
|
inline _int128 operator-(const _int128 &lft, const _uint128 &rhs) {
|
|
_int128 result(lft);
|
|
int128sub(&result, &rhs);
|
|
return result;
|
|
}
|
|
inline _uint128 operator-(const _uint128 &lft, const _int128 &rhs) {
|
|
_uint128 result(lft);
|
|
int128sub(&result, &rhs);
|
|
return result;
|
|
}
|
|
inline _uint128 operator-(const _uint128 &lft, const _uint128 &rhs) {
|
|
_uint128 result(lft);
|
|
int128sub(&result, &rhs);
|
|
return result;
|
|
}
|
|
|
|
// 4 basic combination of operator* (128-bit integers - dont care about signed/unsigned)
|
|
inline _int128 operator*(const _int128 &lft, const _int128 &rhs) {
|
|
_int128 result(lft);
|
|
int128mul(&result, &rhs);
|
|
return result;
|
|
}
|
|
inline _int128 operator*(const _int128 &lft, const _uint128 &rhs) {
|
|
_int128 result(lft);
|
|
int128mul(&result, &rhs);
|
|
return result;
|
|
}
|
|
inline _uint128 operator*(const _uint128 &lft, const _int128 &rhs) {
|
|
_uint128 result(lft);
|
|
int128mul(&result, &rhs);
|
|
return result;
|
|
}
|
|
inline _uint128 operator*(const _uint128 &lft, const _uint128 &rhs) {
|
|
_uint128 result(lft);
|
|
int128mul(&result, &rhs);
|
|
return result;
|
|
}
|
|
|
|
// 4 basic combination of operator/ - signed division only if both are signed
|
|
inline _int128 operator/(const _int128 &lft, const _int128 &rhs) {
|
|
_int128 result(lft), tmp(rhs);
|
|
int128div(&result, &tmp);
|
|
return result;
|
|
}
|
|
inline _int128 operator/(const _int128 &lft, const _uint128 &rhs) {
|
|
_int128 result(lft);
|
|
uint128div(&result, &rhs);
|
|
return result;
|
|
}
|
|
inline _uint128 operator/(const _uint128 &lft, const _int128 &rhs) {
|
|
_uint128 result(lft);
|
|
uint128div(&result, &rhs);
|
|
return result;
|
|
}
|
|
inline _uint128 operator/(const _uint128 &lft, const _uint128 &rhs) {
|
|
_uint128 result(lft);
|
|
uint128div(&result, &rhs);
|
|
return result;
|
|
}
|
|
|
|
// 4 basic combination of operator% - signed % only if both are signed
|
|
inline _int128 operator%(const _int128 &lft, const _int128 &rhs) {
|
|
_int128 result(lft), tmp(rhs);
|
|
int128rem(&result, &tmp);
|
|
return result;
|
|
}
|
|
inline _int128 operator%(const _int128 &lft, const _uint128 &rhs) {
|
|
_int128 result(lft);
|
|
uint128rem(&result, &rhs);
|
|
return result;
|
|
}
|
|
inline _uint128 operator%(const _uint128 &lft, const _int128 &rhs) {
|
|
_uint128 result(lft);
|
|
uint128rem(&result, &rhs);
|
|
return result;
|
|
}
|
|
inline _uint128 operator%(const _uint128 &lft, const _uint128 &rhs) {
|
|
_uint128 result(lft);
|
|
uint128rem(&result, &rhs);
|
|
return result;
|
|
}
|
|
|
|
// 2 version of unary - (dont care about signed/unsigned)
|
|
inline _int128 operator-(const _int128 &x) { // unary minus
|
|
_int128 result(x);
|
|
int128neg(&result);
|
|
return result;
|
|
}
|
|
inline _uint128 operator-(const _uint128 &x) {
|
|
_uint128 result(x);
|
|
int128neg(&result);
|
|
return result;
|
|
}
|
|
|
|
// Basic bit operators
|
|
// 4 basic combinations of operator&
|
|
inline _int128 operator&(const _int128 &lft, const _int128 &rhs) {
|
|
return _int128(HI64(lft) & HI64(rhs), LO64(lft) & LO64(rhs));
|
|
}
|
|
inline _int128 operator&(const _int128 &lft, const _uint128 &rhs) {
|
|
return _int128(HI64(lft) & HI64(rhs), LO64(lft) & LO64(rhs));
|
|
}
|
|
inline _uint128 operator&(const _uint128 &lft, const _int128 &rhs) {
|
|
return _uint128(HI64(lft) & HI64(rhs), LO64(lft) & LO64(rhs));
|
|
}
|
|
inline _uint128 operator&(const _uint128 &lft, const _uint128 &rhs) {
|
|
return _int128(HI64(lft) & HI64(rhs), LO64(lft) & LO64(rhs));
|
|
}
|
|
|
|
// 4 basic combinations of operator|
|
|
inline _int128 operator|(const _int128 &lft, const _int128 &rhs) {
|
|
return _int128(HI64(lft) | HI64(rhs), LO64(lft) | LO64(rhs));
|
|
}
|
|
inline _int128 operator|(const _int128 &lft, const _uint128 &rhs) {
|
|
return _int128(HI64(lft) | HI64(rhs), LO64(lft) | LO64(rhs));
|
|
}
|
|
inline _uint128 operator|(const _uint128 &lft, const _int128 &rhs) {
|
|
return _uint128(HI64(lft) | HI64(rhs), LO64(lft) | LO64(rhs));
|
|
}
|
|
inline _uint128 operator|(const _uint128 &lft, const _uint128 &rhs) {
|
|
return _uint128(HI64(lft) | HI64(rhs), LO64(lft) | LO64(rhs));
|
|
}
|
|
|
|
// 4 basic combinations of operator^
|
|
inline _int128 operator^(const _int128 &lft, const _int128 &rhs) {
|
|
return _int128(HI64(lft) ^ HI64(rhs), LO64(lft) ^ LO64(rhs));
|
|
}
|
|
inline _int128 operator^(const _int128 &lft, const _uint128 &rhs) {
|
|
return _int128(HI64(lft) ^ HI64(rhs), LO64(lft) ^ LO64(rhs));
|
|
}
|
|
inline _uint128 operator^(const _uint128 &lft, const _int128 &rhs) {
|
|
return _uint128(HI64(lft) ^ HI64(rhs), LO64(lft) ^ LO64(rhs));
|
|
}
|
|
inline _uint128 operator^(const _uint128 &lft, const _uint128 &rhs) {
|
|
return _uint128(HI64(lft) ^ HI64(rhs), LO64(lft) ^ LO64(rhs));
|
|
}
|
|
|
|
// 2 versions of operator~
|
|
inline _int128 operator~(const _int128 &n) {
|
|
return _int128(~HI64(n), ~LO64(n));
|
|
}
|
|
inline _uint128 operator~(const _uint128 &n) {
|
|
return _uint128(~HI64(n), ~LO64(n));
|
|
}
|
|
|
|
// 2 version of operator>> (arithmetic shift for signed, logical shift for unsigned)
|
|
inline _int128 operator>>(const _int128 &lft, const int shft) {
|
|
_int128 copy(lft);
|
|
int128shr(shft, ©);
|
|
return copy;
|
|
}
|
|
inline _uint128 operator>>(const _uint128 &lft, const int shft) {
|
|
_uint128 copy(lft);
|
|
uint128shr(shft, ©);
|
|
return copy;
|
|
}
|
|
|
|
// 2 version of operator<< (dont care about signed/unsigned)
|
|
inline _int128 operator<<(const _int128 &lft, const int shft) {
|
|
_int128 copy(lft);
|
|
int128shl(shft, ©);
|
|
return copy;
|
|
}
|
|
inline _int128 operator<<(const _uint128 &lft, const int shft) {
|
|
_uint128 copy(lft);
|
|
int128shl(shft, ©);
|
|
return copy;
|
|
}
|
|
|
|
|
|
// 4 basic combinations of operator==. (dont care about signed/unsigned)
|
|
inline bool operator==(const _int128 &lft, const _int128 &rhs) {
|
|
return (LO64(lft) == LO64(rhs)) && (HI64(lft) == HI64(rhs));
|
|
}
|
|
inline bool operator==(const _int128 &lft, const _uint128 &rhs) {
|
|
return (LO64(lft) == LO64(rhs)) && (HI64(lft) == HI64(rhs));
|
|
}
|
|
inline bool operator==(const _uint128 &lft, const _int128 &rhs) {
|
|
return (LO64(lft) == LO64(rhs)) && (HI64(lft) == HI64(rhs));
|
|
}
|
|
inline bool operator==(const _uint128 &lft, const _uint128 &rhs) {
|
|
return (LO64(lft) == LO64(rhs)) && (HI64(lft) == HI64(rhs));
|
|
}
|
|
|
|
// 4 basic combinations of operator!= (dont care about signed/unsigned)
|
|
inline bool operator!=(const _int128 &lft, const _int128 &rhs) {
|
|
return (LO64(lft) != LO64(rhs)) || (HI64(lft) != HI64(rhs));
|
|
}
|
|
inline bool operator!=(const _int128 &lft, const _uint128 &rhs) {
|
|
return (LO64(lft) != LO64(rhs)) || (HI64(lft) != HI64(rhs));
|
|
}
|
|
inline bool operator!=(const _uint128 &lft, const _int128 &rhs) {
|
|
return (LO64(lft) != LO64(rhs)) || (HI64(lft) != HI64(rhs));
|
|
}
|
|
inline bool operator!=(const _uint128 &lft, const _uint128 &rhs) {
|
|
return (LO64(lft) != LO64(rhs)) || (HI64(lft) != HI64(rhs));
|
|
}
|
|
|
|
// 4 basic combinations of operator> (signed compare only if both are signed)
|
|
inline bool operator>(const _int128 &lft, const _int128 &rhs) {
|
|
return int128cmp(&lft, &rhs) > 0;
|
|
}
|
|
inline bool operator>(const _int128 &lft, const _uint128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) > 0;
|
|
}
|
|
inline bool operator>(const _uint128 &lft, const _int128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) > 0;
|
|
}
|
|
inline bool operator>(const _uint128 &lft, const _uint128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) > 0;
|
|
}
|
|
|
|
// 4 basic combinations of operator>= (signed compare only if both are signed)
|
|
inline bool operator>=(const _int128 &lft, const _int128 &rhs) {
|
|
return int128cmp(&lft, &rhs) >= 0;
|
|
}
|
|
inline bool operator>=(const _int128 &lft, const _uint128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) >= 0;
|
|
}
|
|
inline bool operator>=(const _uint128 &lft, const _int128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) >= 0;
|
|
}
|
|
inline bool operator>=(const _uint128 &lft, const _uint128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) >= 0;
|
|
}
|
|
|
|
// 4 basic combinations of operator< (signed compare only if both are signed)
|
|
inline bool operator<(const _int128 &lft, const _int128 &rhs) {
|
|
return int128cmp(&lft, &rhs) < 0;
|
|
}
|
|
inline bool operator<(const _int128 &lft, const _uint128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) < 0;
|
|
}
|
|
inline bool operator<(const _uint128 &lft, const _int128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) < 0;
|
|
}
|
|
inline bool operator<(const _uint128 &lft, const _uint128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) < 0;
|
|
}
|
|
|
|
// 4 basic combinations of operator<= (signed compare only if both are signed)
|
|
inline bool operator<=(const _int128 &lft, const _int128 &rhs) {
|
|
return int128cmp(&lft, &rhs) <= 0;
|
|
}
|
|
inline bool operator<=(const _int128 &lft, const _uint128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) <= 0;
|
|
}
|
|
inline bool operator<=(const _uint128 &lft, const _int128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) <= 0;
|
|
}
|
|
inline bool operator<=(const _uint128 &lft, const _uint128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) <= 0;
|
|
}
|
|
|
|
// Assign operators
|
|
// operator+= (dont care about sign)
|
|
inline _int128 &operator+=(_int128 &lft, const _int128 &rhs) {
|
|
int128add(&lft, &rhs);
|
|
return lft;
|
|
}
|
|
inline _int128 &operator+=(_int128 &lft, const _uint128 &rhs) {
|
|
int128add(&lft, &rhs);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator+=(_uint128 &lft, const _int128 &rhs) {
|
|
int128add(&lft, &rhs);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator+=(_uint128 &x, const _uint128 &rhs) {
|
|
int128add(&x, &rhs);
|
|
return x;
|
|
}
|
|
|
|
// operator-= (dont care about sign)
|
|
inline _int128 &operator-=(_int128 &lft, const _int128 &rhs) {
|
|
int128sub(&lft, &rhs);
|
|
return lft;
|
|
}
|
|
inline _int128 &operator-=(_int128 &lft, const _uint128 &rhs) {
|
|
int128sub(&lft, &rhs);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator-=(_uint128 &lft, const _int128 &rhs) {
|
|
int128sub(&lft, &rhs);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator-=(_uint128 &lft, const _uint128 &rhs) {
|
|
int128sub(&lft, &rhs);
|
|
return lft;
|
|
}
|
|
|
|
// operator*= (dont care about sign)
|
|
inline _int128 &operator*=(_int128 &lft, const _int128 &rhs) {
|
|
int128mul(&lft, &rhs);
|
|
return lft;
|
|
}
|
|
inline _int128 &operator*=(_int128 &lft, const _uint128 &rhs) {
|
|
int128mul(&lft, &rhs);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator*=(_uint128 &lft, const _int128 &rhs) {
|
|
int128mul(&lft, &rhs);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator*=(_uint128 &lft, const _uint128 &rhs) {
|
|
int128mul(&lft, &rhs);
|
|
return lft;
|
|
}
|
|
|
|
// operator/= (use signed div only if both are signed)
|
|
inline _int128 &operator/=(_int128 &lft, const _int128 &rhs) {
|
|
_int128 tmp(rhs);
|
|
int128div(&lft, &tmp);
|
|
return lft;
|
|
}
|
|
inline _int128 &operator/=(_int128 &lft, const _uint128 &rhs) {
|
|
uint128div(&lft, &rhs);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator/=(_uint128 &lft, const _int128 &rhs) {
|
|
uint128div(&lft, &rhs);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator/=(_uint128 &lft, const _uint128 &rhs) {
|
|
uint128div(&lft, &rhs);
|
|
return lft;
|
|
}
|
|
|
|
// operator%= (use signed % only if both are signed)
|
|
inline _int128 &operator%=(_int128 &lft, const _int128 &rhs) {
|
|
_int128 tmp(rhs);
|
|
int128rem(&lft, &tmp);
|
|
return lft;
|
|
}
|
|
inline _int128 &operator%=(_int128 &lft, const _uint128 &rhs) {
|
|
uint128rem(&lft, &rhs);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator%=(_uint128 &lft, const _int128 &rhs) {
|
|
uint128rem(&lft, &rhs);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator%=(_uint128 &lft, const _uint128 &rhs) {
|
|
uint128rem(&lft, &rhs);
|
|
return lft;
|
|
}
|
|
|
|
// operator&= (dont care about sign)
|
|
inline _int128 &operator&=(_int128 &lft, const _int128 &rhs) {
|
|
LO64(lft) &= LO64(rhs); HI64(lft) &= HI64(rhs);
|
|
return lft;
|
|
}
|
|
inline _int128 &operator&=(_int128 &lft, const _uint128 &rhs) {
|
|
LO64(lft) &= LO64(rhs); HI64(lft) &= HI64(rhs);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator&=(_uint128 &lft, const _int128 &rhs) {
|
|
LO64(lft) &= LO64(rhs); HI64(lft) &= HI64(rhs);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator&=(_uint128 &lft, const _uint128 &rhs) {
|
|
LO64(lft) &= LO64(rhs); HI64(lft) &= HI64(rhs);
|
|
return lft;
|
|
}
|
|
|
|
// operator|= (dont care about sign)
|
|
inline _int128 &operator|=(_int128 &lft, const _int128 &rhs) {
|
|
LO64(lft) |= LO64(rhs); HI64(lft) |= HI64(rhs);
|
|
return lft;
|
|
}
|
|
inline _int128 &operator|=(_int128 &lft, const _uint128 &rhs) {
|
|
LO64(lft) |= LO64(rhs); HI64(lft) |= HI64(rhs);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator|=(_uint128 &lft, const _int128 &rhs) {
|
|
LO64(lft) |= LO64(rhs); HI64(lft) |= HI64(rhs);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator|=(_uint128 &lft, const _uint128 &rhs) {
|
|
LO64(lft) |= LO64(rhs); HI64(lft) |= HI64(rhs);
|
|
return lft;
|
|
}
|
|
|
|
// operator^= (dont care about sign)
|
|
inline _int128 &operator^=(_int128 &lft, const _int128 &rhs) {
|
|
LO64(lft) ^= LO64(rhs); HI64(lft) ^= HI64(rhs);
|
|
return lft;
|
|
}
|
|
inline _int128 &operator^=(_int128 &lft, const _uint128 &rhs) {
|
|
LO64(lft) ^= LO64(rhs); HI64(lft) ^= HI64(rhs);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator^=(_uint128 &lft, const _int128 &rhs) {
|
|
LO64(lft) ^= LO64(rhs); HI64(lft) ^= HI64(rhs);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator^=(_uint128 &lft, const _uint128 &rhs) {
|
|
LO64(lft) ^= LO64(rhs); HI64(lft) ^= HI64(rhs);
|
|
return lft;
|
|
}
|
|
|
|
inline _int128 &operator>>=(_int128 &lft, int shft) {
|
|
int128shr(shft, &lft);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator>>=(_uint128 &lft, int shft) {
|
|
uint128shr(shft, &lft);
|
|
return lft;
|
|
}
|
|
inline _int128 &operator<<=(_int128 &lft, int shft) {
|
|
int128shl(shft, &lft);
|
|
return lft;
|
|
}
|
|
inline _uint128 &operator<<=(_uint128 &lft, int shft) {
|
|
int128shl(shft, &lft);
|
|
return lft;
|
|
}
|
|
|
|
// Now all combinations of binary operators for lft = 128-bit and rhs is built in integral type
|
|
// operator+ for built in integral types as second argument
|
|
inline _int128 operator+(const _int128 &lft, __int64 rhs) {
|
|
return lft + (_int128)rhs;
|
|
}
|
|
inline _int128 operator+(const _int128 &lft, unsigned __int64 rhs) {
|
|
return lft + (_uint128)rhs;
|
|
}
|
|
inline _int128 operator+(const _int128 &lft, long rhs) {
|
|
return lft + (_int128)rhs;
|
|
}
|
|
inline _int128 operator+(const _int128 &lft, unsigned long rhs) {
|
|
return lft + (_uint128)rhs;
|
|
}
|
|
inline _int128 operator+(const _int128 &lft, int rhs) {
|
|
return lft + (_int128)rhs;
|
|
}
|
|
inline _int128 operator+(const _int128 &lft, unsigned int rhs) {
|
|
return lft + (_uint128)rhs;
|
|
}
|
|
inline _int128 operator+(const _int128 &lft, short rhs) {
|
|
return lft + (_int128)rhs;
|
|
}
|
|
inline _int128 operator+(const _int128 &lft, unsigned short rhs) {
|
|
return lft + (_uint128)rhs;
|
|
}
|
|
|
|
inline _uint128 operator+(const _uint128 &lft, __int64 rhs) {
|
|
return lft + (_int128)rhs;
|
|
}
|
|
inline _uint128 operator+(const _uint128 &lft, unsigned __int64 rhs) {
|
|
return lft + (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator+(const _uint128 &lft, long rhs) {
|
|
return lft + (_int128)rhs;
|
|
}
|
|
inline _uint128 operator+(const _uint128 &lft, unsigned long rhs) {
|
|
return lft + (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator+(const _uint128 &lft, int rhs) {
|
|
return lft + (_int128)rhs;
|
|
}
|
|
inline _uint128 operator+(const _uint128 &lft, unsigned int rhs) {
|
|
return lft + (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator+(const _uint128 &lft, short rhs) {
|
|
return lft + (_int128)rhs;
|
|
}
|
|
inline _uint128 operator+(const _uint128 &lft, unsigned short rhs) {
|
|
return lft + (_uint128)rhs;
|
|
}
|
|
|
|
|
|
// operator- for built in integral types as second argument
|
|
inline _int128 operator-(const _int128 &lft, __int64 rhs) {
|
|
return lft - (_int128)rhs;
|
|
}
|
|
inline _int128 operator-(const _int128 &lft, unsigned __int64 rhs) {
|
|
return lft - (_uint128)rhs;
|
|
}
|
|
inline _int128 operator-(const _int128 &lft, long rhs) {
|
|
return lft - (_int128)rhs;
|
|
}
|
|
inline _int128 operator-(const _int128 &lft, unsigned long rhs) {
|
|
return lft - (_uint128)rhs;
|
|
}
|
|
inline _int128 operator-(const _int128 &lft, int rhs) {
|
|
return lft - (_int128)rhs;
|
|
}
|
|
inline _int128 operator-(const _int128 &lft, unsigned int rhs) {
|
|
return lft - (_uint128)rhs;
|
|
}
|
|
inline _int128 operator-(const _int128 &lft, short rhs) {
|
|
return lft - (_int128)rhs;
|
|
}
|
|
inline _int128 operator-(const _int128 &lft, unsigned short rhs) {
|
|
return lft - (_uint128)rhs;
|
|
}
|
|
|
|
inline _uint128 operator-(const _uint128 &lft, __int64 rhs) {
|
|
return lft - (_int128)rhs;
|
|
}
|
|
inline _uint128 operator-(const _uint128 &lft, unsigned __int64 rhs) {
|
|
return lft - (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator-(const _uint128 &lft, long rhs) {
|
|
return lft - (_int128)rhs;
|
|
}
|
|
inline _uint128 operator-(const _uint128 &lft, unsigned long rhs) {
|
|
return lft - (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator-(const _uint128 &lft, int rhs) {
|
|
return lft - (_int128)rhs;
|
|
}
|
|
inline _uint128 operator-(const _uint128 &lft, unsigned int rhs) {
|
|
return lft - (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator-(const _uint128 &lft, short rhs) {
|
|
return lft - (_int128)rhs;
|
|
}
|
|
inline _uint128 operator-(const _uint128 &lft, unsigned short rhs) {
|
|
return lft - (_uint128)rhs;
|
|
}
|
|
|
|
|
|
// operator* for built in integral types as second argument
|
|
inline _int128 operator*(const _int128 &lft, __int64 rhs) {
|
|
return lft * (_int128)rhs;
|
|
}
|
|
inline _int128 operator*(const _int128 &lft, unsigned __int64 rhs) {
|
|
return lft * (_uint128)rhs;
|
|
}
|
|
inline _int128 operator*(const _int128 &lft, long rhs) {
|
|
return lft * (_int128)rhs;
|
|
}
|
|
inline _int128 operator*(const _int128 &lft, unsigned long rhs) {
|
|
return lft * (_uint128)rhs;
|
|
}
|
|
inline _int128 operator*(const _int128 &lft, int rhs) {
|
|
return lft * (_int128)rhs;
|
|
}
|
|
inline _int128 operator*(const _int128 &lft, unsigned int rhs) {
|
|
return lft * (_uint128)rhs;
|
|
}
|
|
inline _int128 operator*(const _int128 &lft, short rhs) {
|
|
return lft * (_int128)rhs;
|
|
}
|
|
inline _int128 operator*(const _int128 &lft, unsigned short rhs) {
|
|
return lft * (_uint128)rhs;
|
|
}
|
|
|
|
inline _uint128 operator*(const _uint128 &lft, __int64 rhs) {
|
|
return lft * (_int128)rhs;
|
|
}
|
|
inline _uint128 operator*(const _uint128 &lft, unsigned __int64 rhs) {
|
|
return lft * (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator*(const _uint128 &lft, long rhs) {
|
|
return lft * (_int128)rhs;
|
|
}
|
|
inline _uint128 operator*(const _uint128 &lft, unsigned long rhs) {
|
|
return lft * (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator*(const _uint128 &lft, int rhs) {
|
|
return lft * (_int128)rhs;
|
|
}
|
|
inline _uint128 operator*(const _uint128 &lft, unsigned int rhs) {
|
|
return lft * (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator*(const _uint128 &lft, short rhs) {
|
|
return lft * (_int128)rhs;
|
|
}
|
|
inline _uint128 operator*(const _uint128 &lft, unsigned short rhs) {
|
|
return lft * (_uint128)rhs;
|
|
}
|
|
|
|
|
|
// operator/ for built in integral types as second argument
|
|
inline _int128 operator/(const _int128 &lft, __int64 rhs) {
|
|
return lft / (_int128)rhs;
|
|
}
|
|
inline _int128 operator/(const _int128 &lft, unsigned __int64 rhs) {
|
|
return lft / (_int128)rhs;
|
|
}
|
|
inline _int128 operator/(const _int128 &lft, long rhs) {
|
|
return lft / (_int128)rhs;
|
|
}
|
|
inline _int128 operator/(const _int128 &lft, unsigned long rhs) {
|
|
return lft / (_int128)rhs;
|
|
}
|
|
inline _int128 operator/(const _int128 &lft, int rhs) {
|
|
return lft / (_int128)rhs;
|
|
}
|
|
inline _int128 operator/(const _int128 &lft, unsigned int rhs) {
|
|
return lft / (_int128)rhs;
|
|
}
|
|
inline _int128 operator/(const _int128 &lft, short rhs) {
|
|
return lft / (_int128)rhs;
|
|
}
|
|
inline _int128 operator/(const _int128 &lft, unsigned short rhs) {
|
|
return lft / (_int128)rhs;
|
|
}
|
|
|
|
inline _uint128 operator/(const _uint128 &lft, __int64 rhs) {
|
|
return lft / (_int128)rhs;
|
|
}
|
|
inline _uint128 operator/(const _uint128 &lft, unsigned __int64 rhs) {
|
|
return lft / (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator/(const _uint128 &lft, long rhs) {
|
|
return lft / (_int128)rhs;
|
|
}
|
|
inline _uint128 operator/(const _uint128 &lft, unsigned long rhs) {
|
|
return lft / (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator/(const _uint128 &lft, int rhs) {
|
|
return lft / (_int128)rhs;
|
|
}
|
|
inline _uint128 operator/(const _uint128 &lft, unsigned int rhs) {
|
|
return lft / (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator/(const _uint128 &lft, short rhs) {
|
|
return lft / (_int128)rhs;
|
|
}
|
|
inline _uint128 operator/(const _uint128 &lft, unsigned short rhs) {
|
|
return lft / (_uint128)rhs;
|
|
}
|
|
|
|
|
|
// operator% for built in integral types as second argument
|
|
inline _int128 operator%(const _int128 &lft, __int64 rhs) {
|
|
return lft % (_int128)rhs;
|
|
}
|
|
inline _int128 operator%(const _int128 &lft, unsigned __int64 rhs) {
|
|
return lft % (_int128)rhs;
|
|
}
|
|
inline _int128 operator%(const _int128 &lft, long rhs) {
|
|
return lft % (_int128)rhs;
|
|
}
|
|
inline _int128 operator%(const _int128 &lft, unsigned long rhs) {
|
|
return lft % (_int128)rhs;
|
|
}
|
|
inline _int128 operator%(const _int128 &lft, int rhs) {
|
|
return lft % (_int128)rhs;
|
|
}
|
|
inline _int128 operator%(const _int128 &lft, unsigned int rhs) {
|
|
return lft % (_int128)rhs;
|
|
}
|
|
inline _int128 operator%(const _int128 &lft, short rhs) {
|
|
return lft % (_int128)rhs;
|
|
}
|
|
inline _int128 operator%(const _int128 &lft, unsigned short rhs) {
|
|
return lft % (_int128)rhs;
|
|
}
|
|
|
|
inline _uint128 operator%(const _uint128 &lft, __int64 rhs) {
|
|
return lft % (_int128)rhs;
|
|
}
|
|
inline _uint128 operator%(const _uint128 &lft, unsigned __int64 rhs) {
|
|
return lft % (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator%(const _uint128 &lft, long rhs) {
|
|
return lft % (_int128)rhs;
|
|
}
|
|
inline _uint128 operator%(const _uint128 &lft, unsigned long rhs) {
|
|
return lft % (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator%(const _uint128 &lft, int rhs) {
|
|
return lft % (_int128)rhs;
|
|
}
|
|
inline _uint128 operator%(const _uint128 &lft, unsigned int rhs) {
|
|
return lft % (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator%(const _uint128 &lft, short rhs) {
|
|
return lft % (_int128)rhs;
|
|
}
|
|
inline _uint128 operator%(const _uint128 &lft, unsigned short rhs) {
|
|
return lft % (_uint128)rhs;
|
|
}
|
|
|
|
|
|
// operator& for built in integral types as second argument
|
|
inline _int128 operator&(const _int128 &lft, __int64 rhs) {
|
|
return lft & (_int128)rhs;
|
|
}
|
|
inline _int128 operator&(const _int128 &lft, unsigned __int64 rhs) {
|
|
return lft & (_int128)rhs;
|
|
}
|
|
inline _int128 operator&(const _int128 &lft, long rhs) {
|
|
return lft & (_int128)rhs;
|
|
}
|
|
inline _int128 operator&(const _int128 &lft, unsigned long rhs) {
|
|
return lft & (_int128)rhs;
|
|
}
|
|
inline _int128 operator&(const _int128 &lft, int rhs) {
|
|
return lft & (_int128)rhs;
|
|
}
|
|
inline _int128 operator&(const _int128 &lft, unsigned int rhs) {
|
|
return lft & (_int128)rhs;
|
|
}
|
|
inline _int128 operator&(const _int128 &lft, short rhs) {
|
|
return lft & (_int128)rhs;
|
|
}
|
|
inline _int128 operator&(const _int128 &lft, unsigned short rhs) {
|
|
return lft & (_int128)rhs;
|
|
}
|
|
|
|
inline _uint128 operator&(const _uint128 &lft, __int64 rhs) {
|
|
return lft & (_int128)rhs;
|
|
}
|
|
inline _uint128 operator&(const _uint128 &lft, unsigned __int64 rhs) {
|
|
return lft & (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator&(const _uint128 &lft, long rhs) {
|
|
return lft & (_int128)rhs;
|
|
}
|
|
inline _uint128 operator&(const _uint128 &lft, unsigned long rhs) {
|
|
return lft & (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator&(const _uint128 &lft, int rhs) {
|
|
return lft & (_int128)rhs;
|
|
}
|
|
inline _uint128 operator&(const _uint128 &lft, unsigned int rhs) {
|
|
return lft & (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator&(const _uint128 &lft, short rhs) {
|
|
return lft & (_int128)rhs;
|
|
}
|
|
inline _uint128 operator&(const _uint128 &lft, unsigned short rhs) {
|
|
return lft & (_uint128)rhs;
|
|
}
|
|
|
|
|
|
// operator| for built in integral types as second argument
|
|
inline _int128 operator|(const _int128 &lft, __int64 rhs) {
|
|
return lft | (_int128)rhs;
|
|
}
|
|
inline _int128 operator|(const _int128 &lft, unsigned __int64 rhs) {
|
|
return lft | (_int128)rhs;
|
|
}
|
|
inline _int128 operator|(const _int128 &lft, long rhs) {
|
|
return lft | (_int128)rhs;
|
|
}
|
|
inline _int128 operator|(const _int128 &lft, unsigned long rhs) {
|
|
return lft | (_int128)rhs;
|
|
}
|
|
inline _int128 operator|(const _int128 &lft, int rhs) {
|
|
return lft | (_int128)rhs;
|
|
}
|
|
inline _int128 operator|(const _int128 &lft, unsigned int rhs) {
|
|
return lft | (_int128)rhs;
|
|
}
|
|
inline _int128 operator|(const _int128 &lft, short rhs) {
|
|
return lft | (_int128)rhs;
|
|
}
|
|
inline _int128 operator|(const _int128 &lft, unsigned short rhs) {
|
|
return lft | (_int128)rhs;
|
|
}
|
|
|
|
inline _uint128 operator|(const _uint128 &lft, __int64 rhs) {
|
|
return lft | (_int128)rhs;
|
|
}
|
|
inline _uint128 operator|(const _uint128 &lft, unsigned __int64 rhs) {
|
|
return lft | (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator|(const _uint128 &lft, long rhs) {
|
|
return lft | (_int128)rhs;
|
|
}
|
|
inline _uint128 operator|(const _uint128 &lft, unsigned long rhs) {
|
|
return lft | (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator|(const _uint128 &lft, int rhs) {
|
|
return lft | (_int128)rhs;
|
|
}
|
|
inline _uint128 operator|(const _uint128 &lft, unsigned int rhs) {
|
|
return lft | (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator|(const _uint128 &lft, short rhs) {
|
|
return lft | (_int128)rhs;
|
|
}
|
|
inline _uint128 operator|(const _uint128 &lft, unsigned short rhs) {
|
|
return lft | (_uint128)rhs;
|
|
}
|
|
|
|
|
|
// operator^ for built in integral types as second argument
|
|
inline _int128 operator^(const _int128 &lft, __int64 rhs) {
|
|
return lft ^ (_int128)rhs;
|
|
}
|
|
inline _int128 operator^(const _int128 &lft, unsigned __int64 rhs) {
|
|
return lft ^ (_int128)rhs;
|
|
}
|
|
inline _int128 operator^(const _int128 &lft, long rhs) {
|
|
return lft ^ (_int128)rhs;
|
|
}
|
|
inline _int128 operator^(const _int128 &lft, unsigned long rhs) {
|
|
return lft ^ (_int128)rhs;
|
|
}
|
|
inline _int128 operator^(const _int128 &lft, int rhs) {
|
|
return lft ^ (_int128)rhs;
|
|
}
|
|
inline _int128 operator^(const _int128 &lft, unsigned int rhs) {
|
|
return lft ^ (_int128)rhs;
|
|
}
|
|
inline _int128 operator^(const _int128 &lft, short rhs) {
|
|
return lft ^ (_int128)rhs;
|
|
}
|
|
inline _int128 operator^(const _int128 &lft, unsigned short rhs) {
|
|
return lft ^ (_int128)rhs;
|
|
}
|
|
|
|
inline _uint128 operator^(const _uint128 &lft, __int64 rhs) {
|
|
return lft ^ (_int128)rhs;
|
|
}
|
|
inline _uint128 operator^(const _uint128 &lft, unsigned __int64 rhs) {
|
|
return lft ^ (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator^(const _uint128 &lft, long rhs) {
|
|
return lft ^ (_int128)rhs;
|
|
}
|
|
inline _uint128 operator^(const _uint128 &lft, unsigned long rhs) {
|
|
return lft ^ (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator^(const _uint128 &lft, int rhs) {
|
|
return lft ^ (_int128)rhs;
|
|
}
|
|
inline _uint128 operator^(const _uint128 &lft, unsigned int rhs) {
|
|
return lft ^ (_uint128)rhs;
|
|
}
|
|
inline _uint128 operator^(const _uint128 &lft, short rhs) {
|
|
return lft ^ (_int128)rhs;
|
|
}
|
|
inline _uint128 operator^(const _uint128 &lft, unsigned short rhs) {
|
|
return lft ^ (_uint128)rhs;
|
|
}
|
|
|
|
// Compare operators where second argument is built in integral type
|
|
// operator== for built in integral types as second argument
|
|
inline bool operator==(const _int128 &lft, __int64 rhs) {
|
|
return lft == _int128(rhs);
|
|
}
|
|
inline bool operator==(const _int128 &lft, unsigned __int64 rhs) {
|
|
return lft == _int128(rhs);
|
|
}
|
|
inline bool operator==(const _int128 &lft, long rhs) {
|
|
return lft == _int128(rhs);
|
|
}
|
|
inline bool operator==(const _int128 &lft, unsigned long rhs) {
|
|
return lft == _int128(rhs);
|
|
}
|
|
inline bool operator==(const _int128 &lft, int rhs) {
|
|
return lft == _int128(rhs);
|
|
}
|
|
inline bool operator==(const _int128 &lft, unsigned int rhs) {
|
|
return lft == _int128(rhs);
|
|
}
|
|
inline bool operator==(const _int128 &lft, short rhs) {
|
|
return lft == _int128(rhs);
|
|
}
|
|
inline bool operator==(const _int128 &lft, unsigned short rhs) {
|
|
return lft == _int128(rhs);
|
|
}
|
|
inline bool operator==(const _int128 &lft, char rhs) {
|
|
return lft == _int128(rhs);
|
|
}
|
|
inline bool operator==(const _int128 &lft, unsigned char rhs) {
|
|
return lft == _int128(rhs);
|
|
}
|
|
|
|
inline bool operator==(const _uint128 &lft, __int64 rhs) {
|
|
return lft == _int128(rhs);
|
|
}
|
|
inline bool operator==(const _uint128 &lft, unsigned __int64 rhs) {
|
|
return lft == _uint128(rhs);
|
|
}
|
|
inline bool operator==(const _uint128 &lft, long rhs) {
|
|
return lft == _int128(rhs);
|
|
}
|
|
inline bool operator==(const _uint128 &lft, unsigned long rhs) {
|
|
return lft == _uint128(rhs);
|
|
}
|
|
inline bool operator==(const _uint128 &lft, int rhs) {
|
|
return lft == _int128(rhs);
|
|
}
|
|
inline bool operator==(const _uint128 &lft, unsigned int rhs) {
|
|
return lft == _uint128(rhs);
|
|
}
|
|
inline bool operator==(const _uint128 &lft, short rhs) {
|
|
return lft == _int128(rhs);
|
|
}
|
|
inline bool operator==(const _uint128 &lft, unsigned short rhs) {
|
|
return lft == _uint128(rhs);
|
|
}
|
|
inline bool operator==(const _uint128 &lft, char rhs) {
|
|
return lft == _int128(rhs);
|
|
}
|
|
inline bool operator==(const _uint128 &lft, unsigned char rhs) {
|
|
return lft == _uint128(rhs);
|
|
}
|
|
|
|
|
|
// operator!= for built in integral types as second argument
|
|
inline bool operator!=(const _int128 &lft, __int64 rhs) {
|
|
return lft != _int128(rhs);
|
|
}
|
|
inline bool operator!=(const _int128 &lft, unsigned __int64 rhs) {
|
|
return lft != _int128(rhs);
|
|
}
|
|
inline bool operator!=(const _int128 &lft, long rhs) {
|
|
return lft != _int128(rhs);
|
|
}
|
|
inline bool operator!=(const _int128 &lft, unsigned long rhs) {
|
|
return lft != _int128(rhs);
|
|
}
|
|
inline bool operator!=(const _int128 &lft, int rhs) {
|
|
return lft != _int128(rhs);
|
|
}
|
|
inline bool operator!=(const _int128 &lft, unsigned int rhs) {
|
|
return lft != _int128(rhs);
|
|
}
|
|
inline bool operator!=(const _int128 &lft, short rhs) {
|
|
return lft != _int128(rhs);
|
|
}
|
|
inline bool operator!=(const _int128 &lft, unsigned short rhs) {
|
|
return lft != _int128(rhs);
|
|
}
|
|
inline bool operator!=(const _int128 &lft, char rhs) {
|
|
return lft != _int128(rhs);
|
|
}
|
|
inline bool operator!=(const _int128 &lft, unsigned char rhs) {
|
|
return lft != _int128(rhs);
|
|
}
|
|
|
|
inline bool operator!=(const _uint128 &lft, __int64 rhs) {
|
|
return lft != _int128(rhs);
|
|
}
|
|
inline bool operator!=(const _uint128 &lft, unsigned __int64 rhs) {
|
|
return lft != _uint128(rhs);
|
|
}
|
|
inline bool operator!=(const _uint128 &lft, long rhs) {
|
|
return lft != _int128(rhs);
|
|
}
|
|
inline bool operator!=(const _uint128 &lft, unsigned long rhs) {
|
|
return lft != _uint128(rhs);
|
|
}
|
|
inline bool operator!=(const _uint128 &lft, int rhs) {
|
|
return lft != _int128(rhs);
|
|
}
|
|
inline bool operator!=(const _uint128 &lft, unsigned int rhs) {
|
|
return lft != _uint128(rhs);
|
|
}
|
|
inline bool operator!=(const _uint128 &lft, short rhs) {
|
|
return lft != _int128(rhs);
|
|
}
|
|
inline bool operator!=(const _uint128 &lft, unsigned short rhs) {
|
|
return lft != _uint128(rhs);
|
|
}
|
|
inline bool operator!=(const _uint128 &lft, char rhs) {
|
|
return lft != _int128(rhs);
|
|
}
|
|
inline bool operator!=(const _uint128 &lft, unsigned char rhs) {
|
|
return lft != _uint128(rhs);
|
|
}
|
|
|
|
|
|
// operator> for built in integral types as second argument
|
|
inline bool operator>(const _int128 &lft, __int64 rhs) {
|
|
return lft > _int128(rhs);
|
|
}
|
|
inline bool operator>(const _int128 &lft, unsigned __int64 rhs) {
|
|
return lft > _uint128(rhs);
|
|
}
|
|
inline bool operator>(const _int128 &lft, long rhs) {
|
|
return lft > _int128(rhs);
|
|
}
|
|
inline bool operator>(const _int128 &lft, unsigned long rhs) {
|
|
return lft > _uint128(rhs);
|
|
}
|
|
inline bool operator>(const _int128 &lft, int rhs) {
|
|
return lft > _int128(rhs);
|
|
}
|
|
inline bool operator>(const _int128 &lft, unsigned int rhs) {
|
|
return lft > _uint128(rhs);
|
|
}
|
|
inline bool operator>(const _int128 &lft, short rhs) {
|
|
return lft > _int128(rhs);
|
|
}
|
|
inline bool operator>(const _int128 &lft, unsigned short rhs) {
|
|
return lft > _uint128(rhs);
|
|
}
|
|
inline bool operator>(const _int128 &lft, char rhs) {
|
|
return lft > _int128(rhs);
|
|
}
|
|
inline bool operator>(const _int128 &lft, unsigned char rhs) {
|
|
return lft > _uint128(rhs);
|
|
}
|
|
|
|
inline bool operator>(const _uint128 &lft, __int64 rhs) {
|
|
return lft > _int128(rhs);
|
|
}
|
|
inline bool operator>(const _uint128 &lft, unsigned __int64 rhs) {
|
|
return lft > _uint128(rhs);
|
|
}
|
|
inline bool operator>(const _uint128 &lft, long rhs) {
|
|
return lft > _int128(rhs);
|
|
}
|
|
inline bool operator>(const _uint128 &lft, unsigned long rhs) {
|
|
return lft > _uint128(rhs);
|
|
}
|
|
inline bool operator>(const _uint128 &lft, int rhs) {
|
|
return lft > _int128(rhs);
|
|
}
|
|
inline bool operator>(const _uint128 &lft, unsigned int rhs) {
|
|
return lft > _uint128(rhs);
|
|
}
|
|
inline bool operator>(const _uint128 &lft, short rhs) {
|
|
return lft > _int128(rhs);
|
|
}
|
|
inline bool operator>(const _uint128 &lft, unsigned short rhs) {
|
|
return lft > _uint128(rhs);
|
|
}
|
|
inline bool operator>(const _uint128 &lft, char rhs) {
|
|
return lft > _int128(rhs);
|
|
}
|
|
inline bool operator>(const _uint128 &lft, unsigned char rhs) {
|
|
return lft > _uint128(rhs);
|
|
}
|
|
|
|
|
|
// operator>= for built in integral types as second argument
|
|
inline bool operator>=(const _int128 &lft, __int64 rhs) {
|
|
return lft >= _int128(rhs);
|
|
}
|
|
inline bool operator>=(const _int128 &lft, unsigned __int64 rhs) {
|
|
return lft >= _uint128(rhs);
|
|
}
|
|
inline bool operator>=(const _int128 &lft, long rhs) {
|
|
return lft >= _int128(rhs);
|
|
}
|
|
inline bool operator>=(const _int128 &lft, unsigned long rhs) {
|
|
return lft >= _uint128(rhs);
|
|
}
|
|
inline bool operator>=(const _int128 &lft, int rhs) {
|
|
return lft >= _int128(rhs);
|
|
}
|
|
inline bool operator>=(const _int128 &lft, unsigned int rhs) {
|
|
return lft >= _uint128(rhs);
|
|
}
|
|
inline bool operator>=(const _int128 &lft, short rhs) {
|
|
return lft >= _int128(rhs);
|
|
}
|
|
inline bool operator>=(const _int128 &lft, unsigned short rhs) {
|
|
return lft >= _uint128(rhs);
|
|
}
|
|
inline bool operator>=(const _int128 &lft, char rhs) {
|
|
return lft >= _int128(rhs);
|
|
}
|
|
inline bool operator>=(const _int128 &lft, unsigned char rhs) {
|
|
return lft >= _uint128(rhs);
|
|
}
|
|
|
|
inline bool operator>=(const _uint128 &lft, __int64 rhs) {
|
|
return lft >= _int128(rhs);
|
|
}
|
|
inline bool operator>=(const _uint128 &lft, unsigned __int64 rhs) {
|
|
return lft >= _uint128(rhs);
|
|
}
|
|
inline bool operator>=(const _uint128 &lft, long rhs) {
|
|
return lft >= _int128(rhs);
|
|
}
|
|
inline bool operator>=(const _uint128 &lft, unsigned long rhs) {
|
|
return lft >= _uint128(rhs);
|
|
}
|
|
inline bool operator>=(const _uint128 &lft, int rhs) {
|
|
return lft >= _int128(rhs);
|
|
}
|
|
inline bool operator>=(const _uint128 &lft, unsigned int rhs) {
|
|
return lft >= _uint128(rhs);
|
|
}
|
|
inline bool operator>=(const _uint128 &lft, short rhs) {
|
|
return lft >= _int128(rhs);
|
|
}
|
|
inline bool operator>=(const _uint128 &lft, unsigned short rhs) {
|
|
return lft >= _uint128(rhs);
|
|
}
|
|
inline bool operator>=(const _uint128 &lft, char rhs) {
|
|
return lft >= _int128(rhs);
|
|
}
|
|
inline bool operator>=(const _uint128 &lft, unsigned char rhs) {
|
|
return lft >= _uint128(rhs);
|
|
}
|
|
|
|
|
|
// operator< for built in integral types as second argument
|
|
inline bool operator<(const _int128 &lft, __int64 rhs) {
|
|
return lft < _int128(rhs);
|
|
}
|
|
inline bool operator<(const _int128 &lft, unsigned __int64 rhs) {
|
|
return lft < _uint128(rhs);
|
|
}
|
|
inline bool operator<(const _int128 &lft, long rhs) {
|
|
return lft < _int128(rhs);
|
|
}
|
|
inline bool operator<(const _int128 &lft, unsigned long rhs) {
|
|
return lft < _uint128(rhs);
|
|
}
|
|
inline bool operator<(const _int128 &lft, int rhs) {
|
|
return lft < _int128(rhs);
|
|
}
|
|
inline bool operator<(const _int128 &lft, unsigned int rhs) {
|
|
return lft < _uint128(rhs);
|
|
}
|
|
inline bool operator<(const _int128 &lft, short rhs) {
|
|
return lft < _int128(rhs);
|
|
}
|
|
inline bool operator<(const _int128 &lft, unsigned short rhs) {
|
|
return lft < _uint128(rhs);
|
|
}
|
|
inline bool operator<(const _int128 &lft, char rhs) {
|
|
return lft < _int128(rhs);
|
|
}
|
|
inline bool operator<(const _int128 &lft, unsigned char rhs) {
|
|
return lft < _uint128(rhs);
|
|
}
|
|
|
|
inline bool operator<(const _uint128 &lft, __int64 rhs) {
|
|
return lft < _int128(rhs);
|
|
}
|
|
inline bool operator<(const _uint128 &lft, unsigned __int64 rhs) {
|
|
return lft < _uint128(rhs);
|
|
}
|
|
inline bool operator<(const _uint128 &lft, long rhs) {
|
|
return lft < _int128(rhs);
|
|
}
|
|
inline bool operator<(const _uint128 &lft, unsigned long rhs) {
|
|
return lft < _uint128(rhs);
|
|
}
|
|
inline bool operator<(const _uint128 &lft, int rhs) {
|
|
return lft < _int128(rhs);
|
|
}
|
|
inline bool operator<(const _uint128 &lft, unsigned int rhs) {
|
|
return lft < _uint128(rhs);
|
|
}
|
|
inline bool operator<(const _uint128 &lft, short rhs) {
|
|
return lft < _int128(rhs);
|
|
}
|
|
inline bool operator<(const _uint128 &lft, unsigned short rhs) {
|
|
return lft < _uint128(rhs);
|
|
}
|
|
inline bool operator<(const _uint128 &lft, char rhs) {
|
|
return lft < _int128(rhs);
|
|
}
|
|
inline bool operator<(const _uint128 &lft, unsigned char rhs) {
|
|
return lft < _uint128(rhs);
|
|
}
|
|
|
|
|
|
// operator<= for built in integral types as second argument
|
|
inline bool operator<=(const _int128 &lft, __int64 rhs) {
|
|
return lft <= _int128(rhs);
|
|
}
|
|
inline bool operator<=(const _int128 &lft, unsigned __int64 rhs) {
|
|
return lft <= _uint128(rhs);
|
|
}
|
|
inline bool operator<=(const _int128 &lft, long rhs) {
|
|
return lft <= _int128(rhs);
|
|
}
|
|
inline bool operator<=(const _int128 &lft, unsigned long rhs) {
|
|
return lft <= _uint128(rhs);
|
|
}
|
|
inline bool operator<=(const _int128 &lft, int rhs) {
|
|
return lft <= _int128(rhs);
|
|
}
|
|
inline bool operator<=(const _int128 &lft, unsigned int rhs) {
|
|
return lft <= _uint128(rhs);
|
|
}
|
|
inline bool operator<=(const _int128 &lft, short rhs) {
|
|
return lft <= _int128(rhs);
|
|
}
|
|
inline bool operator<=(const _int128 &lft, unsigned short rhs) {
|
|
return lft <= _uint128(rhs);
|
|
}
|
|
inline bool operator<=(const _int128 &lft, char rhs) {
|
|
return lft <= _int128(rhs);
|
|
}
|
|
inline bool operator<=(const _int128 &lft, unsigned char rhs) {
|
|
return lft <= _uint128(rhs);
|
|
}
|
|
|
|
inline bool operator<=(const _uint128 &lft, __int64 rhs) {
|
|
return lft <= _int128(rhs);
|
|
}
|
|
inline bool operator<=(const _uint128 &lft, unsigned __int64 rhs) {
|
|
return lft <= _uint128(rhs);
|
|
}
|
|
inline bool operator<=(const _uint128 &lft, long rhs) {
|
|
return lft <= _int128(rhs);
|
|
}
|
|
inline bool operator<=(const _uint128 &lft, unsigned long rhs) {
|
|
return lft <= _uint128(rhs);
|
|
}
|
|
inline bool operator<=(const _uint128 &lft, int rhs) {
|
|
return lft <= _int128(rhs);
|
|
}
|
|
inline bool operator<=(const _uint128 &lft, unsigned int rhs) {
|
|
return lft <= _uint128(rhs);
|
|
}
|
|
inline bool operator<=(const _uint128 &lft, short rhs) {
|
|
return lft <= _int128(rhs);
|
|
}
|
|
inline bool operator<=(const _uint128 &lft, unsigned short rhs) {
|
|
return lft <= _uint128(rhs);
|
|
}
|
|
inline bool operator<=(const _uint128 &lft, char rhs) {
|
|
return lft <= _int128(rhs);
|
|
}
|
|
inline bool operator<=(const _uint128 &lft, unsigned char rhs) {
|
|
return lft <= _uint128(rhs);
|
|
}
|
|
|
|
// Assign operators where second argument is built in integral type
|
|
// operator+= for built in integral types as second argument
|
|
inline _int128 &operator+=(_int128 &lft, __int64 rhs) {
|
|
return lft += (_int128)rhs;
|
|
}
|
|
inline _int128 &operator+=(_int128 &lft, unsigned __int64 rhs) {
|
|
return lft += (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator+=(_int128 &lft, long rhs) {
|
|
return lft += (_int128)rhs;
|
|
}
|
|
inline _int128 &operator+=(_int128 &lft, unsigned long rhs) {
|
|
return lft += (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator+=(_int128 &lft, int rhs) {
|
|
return lft += (_int128)rhs;
|
|
}
|
|
inline _int128 &operator+=(_int128 &lft, unsigned int rhs) {
|
|
return lft += (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator+=(_int128 &lft, short rhs) {
|
|
return lft += (_int128)rhs;
|
|
}
|
|
inline _int128 &operator+=(_int128 &lft, unsigned short rhs) {
|
|
return lft += (_uint128)rhs;
|
|
}
|
|
|
|
inline _uint128 &operator+=(_uint128 &lft, __int64 rhs) {
|
|
return lft += (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator+=(_uint128 &lft, unsigned __int64 rhs) {
|
|
return lft += (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator+=(_uint128 &lft, long rhs) {
|
|
return lft += (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator+=(_uint128 &lft, unsigned long rhs) {
|
|
return lft += (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator+=(_uint128 &lft, int rhs) {
|
|
return lft += (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator+=(_uint128 &lft, unsigned int rhs) {
|
|
return lft += (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator+=(_uint128 &lft, short rhs) {
|
|
return lft += (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator+=(_uint128 &lft, unsigned short rhs) {
|
|
return lft += (_uint128)rhs;
|
|
}
|
|
|
|
|
|
// operator-= for built in integral types as second argument
|
|
inline _int128 &operator-=(_int128 &lft, __int64 rhs) {
|
|
return lft -= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator-=(_int128 &lft, unsigned __int64 rhs) {
|
|
return lft -= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator-=(_int128 &lft, long rhs) {
|
|
return lft -= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator-=(_int128 &lft, unsigned long rhs) {
|
|
return lft -= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator-=(_int128 &lft, int rhs) {
|
|
return lft -= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator-=(_int128 &lft, unsigned int rhs) {
|
|
return lft -= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator-=(_int128 &lft, short rhs) {
|
|
return lft -= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator-=(_int128 &lft, unsigned short rhs) {
|
|
return lft -= (_uint128)rhs;
|
|
}
|
|
|
|
inline _uint128 &operator-=(_uint128 &lft, __int64 rhs) {
|
|
return lft -= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator-=(_uint128 &lft, unsigned __int64 rhs) {
|
|
return lft -= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator-=(_uint128 &lft, long rhs) {
|
|
return lft -= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator-=(_uint128 &lft, unsigned long rhs) {
|
|
return lft -= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator-=(_uint128 &lft, int rhs) {
|
|
return lft -= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator-=(_uint128 &lft, unsigned int rhs) {
|
|
return lft -= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator-=(_uint128 &lft, short rhs) {
|
|
return lft -= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator-=(_uint128 &lft, unsigned short rhs) {
|
|
return lft -= (_uint128)rhs;
|
|
}
|
|
|
|
|
|
// operator*= for built in integral types as second argument
|
|
inline _int128 &operator*=(_int128 &lft, __int64 rhs) {
|
|
return lft *= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator*=(_int128 &lft, unsigned __int64 rhs) {
|
|
return lft *= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator*=(_int128 &lft, long rhs) {
|
|
return lft *= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator*=(_int128 &lft, unsigned long rhs) {
|
|
return lft *= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator*=(_int128 &lft, int rhs) {
|
|
return lft *= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator*=(_int128 &lft, unsigned int rhs) {
|
|
return lft *= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator*=(_int128 &lft, short rhs) {
|
|
return lft *= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator*=(_int128 &lft, unsigned short rhs) {
|
|
return lft *= (_uint128)rhs;
|
|
}
|
|
|
|
inline _uint128 &operator*=(_uint128 &lft, __int64 rhs) {
|
|
return lft *= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator*=(_uint128 &lft, unsigned __int64 rhs) {
|
|
return lft *= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator*=(_uint128 &lft, long rhs) {
|
|
return lft *= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator*=(_uint128 &lft, unsigned long rhs) {
|
|
return lft *= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator*=(_uint128 &lft, int rhs) {
|
|
return lft *= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator*=(_uint128 &lft, unsigned int rhs) {
|
|
return lft *= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator*=(_uint128 &lft, short rhs) {
|
|
return lft *= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator*=(_uint128 &lft, unsigned short rhs) {
|
|
return lft *= (_uint128)rhs;
|
|
}
|
|
|
|
|
|
// operator/= for built in integral types as second argument
|
|
inline _int128 &operator/=(_int128 &lft, __int64 rhs) {
|
|
return lft /= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator/=(_int128 &lft, unsigned __int64 rhs) {
|
|
return lft /= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator/=(_int128 &lft, long rhs) {
|
|
return lft /= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator/=(_int128 &lft, unsigned long rhs) {
|
|
return lft /= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator/=(_int128 &lft, int rhs) {
|
|
return lft /= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator/=(_int128 &lft, unsigned int rhs) {
|
|
return lft /= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator/=(_int128 &lft, short rhs) {
|
|
return lft /= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator/=(_int128 &lft, unsigned short rhs) {
|
|
return lft /= (_uint128)rhs;
|
|
}
|
|
|
|
inline _uint128 &operator/=(_uint128 &lft, __int64 rhs) {
|
|
return lft /= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator/=(_uint128 &lft, unsigned __int64 rhs) {
|
|
return lft /= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator/=(_uint128 &lft, long rhs) {
|
|
return lft /= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator/=(_uint128 &lft, unsigned long rhs) {
|
|
return lft /= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator/=(_uint128 &lft, int rhs) {
|
|
return lft /= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator/=(_uint128 &lft, unsigned int rhs) {
|
|
return lft /= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator/=(_uint128 &lft, short rhs) {
|
|
return lft /= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator/=(_uint128 &lft, unsigned short rhs) {
|
|
return lft /= (_uint128)rhs;
|
|
}
|
|
|
|
|
|
// operator%= for built in integral types as second argument
|
|
inline _int128 &operator%=(_int128 &lft, __int64 rhs) {
|
|
return lft %= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator%=(_int128 &lft, unsigned __int64 rhs) {
|
|
return lft %= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator%=(_int128 &lft, long rhs) {
|
|
return lft %= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator%=(_int128 &lft, unsigned long rhs) {
|
|
return lft %= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator%=(_int128 &lft, int rhs) {
|
|
return lft %= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator%=(_int128 &lft, unsigned int rhs) {
|
|
return lft %= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator%=(_int128 &lft, short rhs) {
|
|
return lft %= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator%=(_int128 &lft, unsigned short rhs) {
|
|
return lft %= (_uint128)rhs;
|
|
}
|
|
|
|
inline _uint128 &operator%=(_uint128 &lft, __int64 rhs) {
|
|
return lft %= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator%=(_uint128 &lft, unsigned __int64 rhs) {
|
|
return lft %= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator%=(_uint128 &lft, long rhs) {
|
|
return lft %= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator%=(_uint128 &lft, unsigned long rhs) {
|
|
return lft %= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator%=(_uint128 &lft, int rhs) {
|
|
return lft %= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator%=(_uint128 &lft, unsigned int rhs) {
|
|
return lft %= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator%=(_uint128 &lft, short rhs) {
|
|
return lft %= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator%=(_uint128 &lft, unsigned short rhs) {
|
|
return lft %= (_uint128)rhs;
|
|
}
|
|
|
|
|
|
// operator&= for built in integral types as second argument
|
|
inline _int128 &operator&=(_int128 &lft, __int64 rhs) {
|
|
return lft &= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator&=(_int128 &lft, unsigned __int64 rhs) {
|
|
return lft &= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator&=(_int128 &lft, long rhs) {
|
|
return lft &= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator&=(_int128 &lft, unsigned long rhs) {
|
|
return lft &= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator&=(_int128 &lft, int rhs) {
|
|
return lft &= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator&=(_int128 &lft, unsigned int rhs) {
|
|
return lft &= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator&=(_int128 &lft, short rhs) {
|
|
return lft &= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator&=(_int128 &lft, unsigned short rhs) {
|
|
return lft &= (_uint128)rhs;
|
|
}
|
|
|
|
inline _uint128 &operator&=(_uint128 &lft, __int64 rhs) {
|
|
return lft &= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator&=(_uint128 &lft, unsigned __int64 rhs) {
|
|
return lft &= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator&=(_uint128 &lft, long rhs) {
|
|
return lft &= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator&=(_uint128 &lft, unsigned long rhs) {
|
|
return lft &= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator&=(_uint128 &lft, int rhs) {
|
|
return lft &= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator&=(_uint128 &lft, unsigned int rhs) {
|
|
return lft &= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator&=(_uint128 &lft, short rhs) {
|
|
return lft &= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator&=(_uint128 &lft, unsigned short rhs) {
|
|
return lft &= (_uint128)rhs;
|
|
}
|
|
|
|
|
|
// operator|= for built in integral types as second argument
|
|
inline _int128 &operator|=(_int128 &lft, __int64 rhs) {
|
|
return lft |= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator|=(_int128 &lft, unsigned __int64 rhs) {
|
|
return lft |= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator|=(_int128 &lft, long rhs) {
|
|
return lft |= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator|=(_int128 &lft, unsigned long rhs) {
|
|
return lft |= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator|=(_int128 &lft, int rhs) {
|
|
return lft |= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator|=(_int128 &lft, unsigned int rhs) {
|
|
return lft |= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator|=(_int128 &lft, short rhs) {
|
|
return lft |= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator|=(_int128 &lft, unsigned short rhs) {
|
|
return lft |= (_uint128)rhs;
|
|
}
|
|
|
|
inline _uint128 &operator|=(_uint128 &lft, __int64 rhs) {
|
|
return lft |= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator|=(_uint128 &lft, unsigned __int64 rhs) {
|
|
return lft |= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator|=(_uint128 &lft, long rhs) {
|
|
return lft |= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator|=(_uint128 &lft, unsigned long rhs) {
|
|
return lft |= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator|=(_uint128 &lft, int rhs) {
|
|
return lft |= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator|=(_uint128 &lft, unsigned int rhs) {
|
|
return lft |= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator|=(_uint128 &lft, short rhs) {
|
|
return lft |= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator|=(_uint128 &lft, unsigned short rhs) {
|
|
return lft |= (_uint128)rhs;
|
|
}
|
|
|
|
|
|
// operator^= for built in integral types as second argument
|
|
inline _int128 &operator^=(_int128 &lft, __int64 rhs) {
|
|
return lft ^= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator^=(_int128 &lft, unsigned __int64 rhs) {
|
|
return lft ^= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator^=(_int128 &lft, long rhs) {
|
|
return lft ^= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator^=(_int128 &lft, unsigned long rhs) {
|
|
return lft ^= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator^=(_int128 &lft, int rhs) {
|
|
return lft ^= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator^=(_int128 &lft, unsigned int rhs) {
|
|
return lft ^= (_uint128)rhs;
|
|
}
|
|
inline _int128 &operator^=(_int128 &lft, short rhs) {
|
|
return lft ^= (_int128)rhs;
|
|
}
|
|
inline _int128 &operator^=(_int128 &lft, unsigned short rhs) {
|
|
return lft ^= (_uint128)rhs;
|
|
}
|
|
|
|
inline _uint128 &operator^=(_uint128 &lft, __int64 rhs) {
|
|
return lft ^= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator^=(_uint128 &lft, unsigned __int64 rhs) {
|
|
return lft ^= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator^=(_uint128 &lft, long rhs) {
|
|
return lft ^= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator^=(_uint128 &lft, unsigned long rhs) {
|
|
return lft ^= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator^=(_uint128 &lft, int rhs) {
|
|
return lft ^= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator^=(_uint128 &lft, unsigned int rhs) {
|
|
return lft ^= (_uint128)rhs;
|
|
}
|
|
inline _uint128 &operator^=(_uint128 &lft, short rhs) {
|
|
return lft ^= (_int128)rhs;
|
|
}
|
|
inline _uint128 &operator^=(_uint128 &lft, unsigned short rhs) {
|
|
return lft ^= (_uint128)rhs;
|
|
}
|
|
|
|
_int128 _strtoi128_l( const char *str, char **end, int radix, _locale_t locale);
|
|
_uint128 _strtoui128_l(const char *str, char **end, int radix, _locale_t locale);
|
|
_int128 _wcstoi128_l( const wchar_t *str, wchar_t **end, int radix, _locale_t locale);
|
|
_uint128 _wcstoui128_l(const wchar_t *str, wchar_t **end, int radix, _locale_t locale);
|
|
|
|
inline _int128 _strtoi128( const char *str, char **end, int radix) {
|
|
return _strtoi128_l(str, end, radix, _get_current_locale());
|
|
}
|
|
inline _uint128 _strtoui128(const char *str, char **end, int radix) {
|
|
return _strtoui128_l(str, end, radix, _get_current_locale());
|
|
}
|
|
inline _int128 _wcstoi128(const wchar_t *str, wchar_t **end, int radix) {
|
|
return _wcstoi128_l(str, end, radix, _get_current_locale());
|
|
}
|
|
inline _uint128 _wcstoui128(const wchar_t *str, wchar_t **end, int radix) {
|
|
return _wcstoui128_l(str, end, radix, _get_current_locale());
|
|
}
|
|
|
|
char *_i128toa( _int128 value, char *str , int radix);
|
|
char *_ui128toa( _uint128 value, char *str , int radix);
|
|
wchar_t *_i128tow( _int128 value, wchar_t *str , int radix);
|
|
wchar_t *_ui128tow( _uint128 value, wchar_t *str , int radix);
|
|
|
|
String toString(const _int128 &n , StreamSize precision = 0, StreamSize width = 0, FormatFlags flags = 0);
|
|
String toString(const _uint128 &n , StreamSize precision = 0, StreamSize width = 0, FormatFlags flags = 0);
|
|
|
|
#ifdef _UNICODE
|
|
#define _tcstoi128 _wcstoi128
|
|
#define _tcstoui128 _wcstoui128
|
|
#define _i128tot _i128tow
|
|
#define _ui128tot _ui128tow
|
|
#else
|
|
#define _tcstoi128 _strtoi128
|
|
#define _tcstoui128 _strtoui128
|
|
#define _i128tot _i128toa
|
|
#define _ui128tot _ui128toa
|
|
#endif // _UNICODE
|
|
|
|
inline char radixLetter(unsigned int c) {
|
|
return (c < 10) ? ('0' + c) : ('a' + (c-10));
|
|
}
|
|
|
|
inline bool iswodigit(wchar_t ch) {
|
|
return ('0' <= ch) && (ch < '8');
|
|
}
|
|
|
|
extern const _int128 _I128_MIN, _I128_MAX;
|
|
extern const _uint128 _UI128_MAX;
|
|
|
|
// use _standardRandomGenerator if rnd == NULL
|
|
inline _uint128 randInt128(Random *rnd = NULL) {
|
|
if (rnd == NULL) rnd = _standardRandomGenerator;
|
|
return _uint128(rnd->nextInt64(), rnd->nextInt64());
|
|
}
|
|
|
|
inline _uint128 randInt128(const _uint128 &n, Random *rnd = NULL) {
|
|
return randInt128(rnd) % n;
|
|
}
|
|
|
|
inline _int128 randInt128(const _int128 &from, const _int128 &to, Random *rnd = NULL) {
|
|
return randInt128(to-from+1, rnd) + from;
|
|
}
|
|
|
|
inline unsigned long int128Hash(const _int128 &n) {
|
|
return uint64Hash(LO64(n) ^ HI64(n));
|
|
}
|
|
|
|
inline unsigned long uint128Hash(const _uint128 &n) {
|
|
return uint64Hash(LO64(n) ^ HI64(n));
|
|
}
|
|
|
|
inline int int128HashCmp(const _int128 &n1, const _int128 &n2) {
|
|
return int128cmp(&n1, &n2);
|
|
}
|
|
|
|
inline int uint128HashCmp(const _uint128 &n1, const _uint128 &n2) {
|
|
return uint128cmp(&n1, &n2);
|
|
}
|
|
|
|
std::istream &operator>>(std::istream &s, _int128 &n);
|
|
std::ostream &operator<<(std::ostream &s, const _int128 &n);
|
|
std::istream &operator>>(std::istream &s, _uint128 &n);
|
|
std::ostream &operator<<(std::ostream &s, const _uint128 &n);
|
|
|
|
std::wistream &operator>>(std::wistream &s, _int128 &n);
|
|
std::wostream &operator<<(std::wostream &s, const _int128 &n);
|
|
std::wistream &operator>>(std::wistream &s, _uint128 &n);
|
|
std::wostream &operator<<(std::wostream &s, const _uint128 &n);
|
|
|
|
Packer &operator<<(Packer &p, const _int128 &n);
|
|
Packer &operator>>(Packer &p, _int128 &n);
|
|
Packer &operator<<(Packer &p, const _uint128 &n);
|
|
Packer &operator>>(Packer &p, _uint128 &n);
|
|
|
|
inline bool isChar( _int128 v) { return v == (char )v; }
|
|
inline bool isChar( _uint128 v) { return v == (char )v; }
|
|
inline bool isUchar( _int128 v) { return v == (UCHAR )v; }
|
|
inline bool isUchar( _uint128 v) { return v == (UCHAR )v; }
|
|
inline bool isShort( _int128 v) { return v == (short )v; }
|
|
inline bool isShort( _uint128 v) { return v == (short )v; }
|
|
inline bool isUshort( _int128 v) { return v == (USHORT)v; }
|
|
inline bool isUshort( _uint128 v) { return v == (USHORT)v; }
|
|
inline bool isInt( _int128 v) { return v == (int )v; }
|
|
inline bool isInt( _uint128 v) { return v == (int )v; }
|
|
inline bool isUint( _int128 v) { return v == (UINT )v; }
|
|
inline bool isUint( _uint128 v) { return v == (UINT )v; }
|
|
inline bool isInt64( _int128 v) { return v == (INT64 )v; }
|
|
inline bool isInt64( _uint128 v) { return v == (INT64 )v; }
|
|
inline bool isUint64( _int128 v) { return v == (UINT64)v; }
|
|
inline bool isUint64( _uint128 v) { return v == (UINT64)v; }
|
|
|
|
template<> class std::numeric_limits<_int128>
|
|
: public _Num_int_base
|
|
{ // limits for type _int128
|
|
public:
|
|
_NODISCARD static _int128 (min)() noexcept
|
|
{ // return minimum value
|
|
return (_I128_MIN);
|
|
}
|
|
_NODISCARD static _int128 (max)() noexcept
|
|
{ // return maximum value
|
|
return (_I128_MAX);
|
|
}
|
|
|
|
_NODISCARD static _int128 lowest() noexcept
|
|
{ // return most negative value
|
|
return ((min)());
|
|
}
|
|
|
|
_NODISCARD static _int128 epsilon() noexcept
|
|
{ // return smallest effective increment from 1.0
|
|
return (0);
|
|
}
|
|
|
|
_NODISCARD static _int128 round_error() noexcept
|
|
{ // return largest rounding error
|
|
return (0);
|
|
}
|
|
|
|
_NODISCARD static _int128 denorm_min() noexcept
|
|
{ // return minimum denormalized value
|
|
return (0);
|
|
}
|
|
|
|
_NODISCARD static _int128 infinity() noexcept
|
|
{ // return positive infinity
|
|
return (0);
|
|
}
|
|
|
|
_NODISCARD static _int128 quiet_NaN() noexcept
|
|
{ // return non-signaling NaN
|
|
return (0);
|
|
}
|
|
|
|
_NODISCARD static _int128 signaling_NaN() noexcept
|
|
{ // return signaling NaN
|
|
return (0);
|
|
}
|
|
|
|
static constexpr bool is_signed = true;
|
|
static constexpr int digits = 127;
|
|
static constexpr int digits10 = 39;
|
|
};
|
|
|
|
// CLASS numeric_limits<unsigned long long>
|
|
template<> class std::numeric_limits<_uint128>
|
|
: public _Num_int_base
|
|
{ // limits for type _uint128
|
|
public:
|
|
_NODISCARD static _uint128 (min)() noexcept
|
|
{ // return minimum value
|
|
return (0);
|
|
}
|
|
|
|
_NODISCARD static _uint128 (max)() noexcept
|
|
{ // return maximum value
|
|
return (_UI128_MAX);
|
|
}
|
|
|
|
_NODISCARD static _uint128 lowest() noexcept
|
|
{ // return most negative value
|
|
return ((min)());
|
|
}
|
|
|
|
_NODISCARD static _uint128 epsilon() noexcept
|
|
{ // return smallest effective increment from 1.0
|
|
return (0);
|
|
}
|
|
|
|
_NODISCARD static _uint128 round_error() noexcept
|
|
{ // return largest rounding error
|
|
return (0);
|
|
}
|
|
|
|
_NODISCARD static _uint128 denorm_min() noexcept
|
|
{ // return minimum denormalized value
|
|
return (0);
|
|
}
|
|
|
|
_NODISCARD static _uint128 infinity() noexcept
|
|
{ // return positive infinity
|
|
return (0);
|
|
}
|
|
|
|
_NODISCARD static _uint128 quiet_NaN() noexcept
|
|
{ // return non-signaling NaN
|
|
return (0);
|
|
}
|
|
|
|
_NODISCARD static _uint128 signaling_NaN() noexcept
|
|
{ // return signaling NaN
|
|
return (0);
|
|
}
|
|
|
|
static constexpr bool is_modulo = true;
|
|
static constexpr int digits = 128;
|
|
static constexpr int digits10 = 39;
|
|
};
|
|
|
|
#if 0
|
|
|
|
// Int128 is available only in x64 arhcitecture
|
|
|
|
#if defined(_M_X64) && defined(__cplusplus)
|
|
|
|
class _int128;
|
|
class _uint128;
|
|
extern "C" {
|
|
void int128sum( void *dst, const void *x, const void *y);
|
|
void int128dif( void *dst, const void *x, const void *y);
|
|
void int128mul( void *dst, const void *x, const void *y);
|
|
void int128div( void *dst, const void *x, const void *y);
|
|
void int128rem( void *dst, const void *x, const void *y);
|
|
void int128neg( void *dst, const void *x);
|
|
int int128cmp(const void *n1, const void *n2);
|
|
void uint128div( void *dst, const void *x, const void *y);
|
|
void uint128rem( void *dst, const void *x, const void *y);
|
|
int uint128cmp(const void *n1, const void *n2);
|
|
};
|
|
|
|
class _int128 {
|
|
private:
|
|
_int128(unsigned __int64 _lo, const unsigned __int64 _hi) : lo(_lo), hi(_hi) {
|
|
}
|
|
public:
|
|
unsigned __int64 lo;
|
|
unsigned __int64 hi;
|
|
#pragma warning(disable:26495)
|
|
_int128() {
|
|
}
|
|
_int128(unsigned __int64 n) : lo(n), hi(0) {
|
|
}
|
|
_int128(__int64 n) : lo(n), hi(n>=0 ? 0:-1) { // remember signextend hi if n < 0 (2-complement)
|
|
}
|
|
_int128(unsigned int n) : lo(n), hi(0) {
|
|
}
|
|
_int128(int n) : lo(n), hi(n>=0 ? 0:-1) {
|
|
}
|
|
_int128(unsigned short n) : lo(n), hi(0) {
|
|
}
|
|
_int128(short n) : lo(n), hi(n>=0 ? 0:-1) {
|
|
}
|
|
explicit _int128(const char *str);
|
|
|
|
operator unsigned __int64() const {
|
|
return lo;
|
|
}
|
|
operator __int64() const {
|
|
return lo;
|
|
}
|
|
operator unsigned int() const {
|
|
return (unsigned int)lo;
|
|
}
|
|
operator int() const {
|
|
return (int)lo;
|
|
}
|
|
_int128 operator+(const _int128 &rhs) const {
|
|
_int128 result;
|
|
int128sum(&result, this, &rhs);
|
|
return result;
|
|
}
|
|
|
|
_int128 operator-(const _int128 &rhs) const {
|
|
_int128 result;
|
|
int128dif(&result, this, &rhs);
|
|
return result;
|
|
}
|
|
|
|
_int128 operator-() const {
|
|
_int128 result;
|
|
int128neg(&result, this);
|
|
return result;
|
|
}
|
|
_int128 operator*(const _int128 &rhs) const {
|
|
_int128 result;
|
|
int128mul(&result, this, &rhs);
|
|
return result;
|
|
}
|
|
|
|
_int128 operator/(const _int128 &rhs) const {
|
|
_int128 result, copy(*this);
|
|
int128div(&result, ©, &rhs);
|
|
return result;
|
|
}
|
|
_int128 operator%(const _int128 &rhs) const {
|
|
_int128 result, copy(*this);
|
|
int128rem(&result, ©, &rhs);
|
|
return result;
|
|
};
|
|
|
|
_int128 &operator+=(const _int128 &rhs) {
|
|
const _int128 copy(*this);
|
|
int128sum(this, ©, &rhs);
|
|
return *this;
|
|
}
|
|
_int128 &operator-=(const _int128 &rhs) {
|
|
const _int128 copy(*this);
|
|
int128dif(this, ©, &rhs);
|
|
return *this;
|
|
}
|
|
_int128 &operator*=(const _int128 &rhs) {
|
|
const _int128 copy(*this);
|
|
int128mul(this, ©, &rhs);
|
|
return *this;
|
|
}
|
|
_int128 &operator/=(const _int128 &rhs) {
|
|
const _int128 copy(*this);
|
|
int128div(this, ©, &rhs);
|
|
return *this;
|
|
}
|
|
_int128 &operator%=(const _int128 &rhs) {
|
|
const _int128 copy(*this);
|
|
int128rem(this, ©, &rhs);
|
|
return *this;
|
|
}
|
|
|
|
_int128 operator&(const _int128 &rhs) const {
|
|
return _int128(lo&rhs.lo, hi&rhs.hi);
|
|
}
|
|
_int128 operator|(const _int128 &rhs) const {
|
|
return _int128(lo|rhs.lo, hi|rhs.hi);
|
|
}
|
|
_int128 operator^(const _int128 &rhs) const {
|
|
return _int128(lo^rhs.lo, hi^rhs.hi);
|
|
}
|
|
|
|
const char *parseDec(const char *str); // return pointer to char following the number
|
|
const char *parseHex(const char *str); // do
|
|
const char *parseOct(const char *str); // do
|
|
};
|
|
|
|
class _uint128 {
|
|
public:
|
|
unsigned __int64 lo;
|
|
unsigned __int64 hi;
|
|
|
|
_uint128() {
|
|
}
|
|
_uint128(const _int128 &n) : lo(n.lo), hi(n.hi) {
|
|
}
|
|
_uint128(unsigned __int64 n) : lo(n), hi(0) {
|
|
}
|
|
_uint128(__int64 n) : lo(n), hi(n>=0 ? 0:-1) {
|
|
}
|
|
_uint128(unsigned int n) : lo(n), hi(0) {
|
|
}
|
|
_uint128(int n) : lo(n), hi(n>=0 ? 0:-1) {
|
|
}
|
|
_uint128(unsigned short n) : lo(n), hi(0) {
|
|
}
|
|
_uint128(short n) : lo(n), hi(n>=0 ? 0:-1) {
|
|
}
|
|
explicit _uint128(const char *str);
|
|
|
|
operator _int128() const {
|
|
return *(_int128*)(void*)this;
|
|
}
|
|
operator unsigned __int64() const {
|
|
return lo;
|
|
}
|
|
operator __int64() const {
|
|
return lo;
|
|
}
|
|
operator unsigned int() const {
|
|
return (unsigned int)lo;
|
|
}
|
|
operator int() const {
|
|
return (int)lo;
|
|
}
|
|
|
|
_uint128 operator+(const _uint128 &rhs) const {
|
|
_uint128 result;
|
|
int128sum(&result, this, &rhs);
|
|
return result;
|
|
}
|
|
|
|
_uint128 operator-(const _uint128 &rhs) const {
|
|
_uint128 result;
|
|
int128dif(&result, this, &rhs);
|
|
return result;
|
|
}
|
|
|
|
_uint128 operator*(const _uint128 &rhs) const {
|
|
_uint128 result;
|
|
int128mul(&result, this, &rhs);
|
|
return result;
|
|
}
|
|
|
|
_uint128 operator/(const _uint128 &rhs) const {
|
|
_uint128 result, copy(*this);
|
|
uint128div(&result, ©, &rhs);
|
|
return result;
|
|
}
|
|
|
|
_uint128 operator%(const _uint128 &rhs) const {
|
|
_uint128 result, copy(*this);
|
|
uint128rem(&result, ©, &rhs);
|
|
return result;
|
|
};
|
|
|
|
_uint128 &operator+=(const _uint128 &rhs) {
|
|
const _uint128 copy(*this);
|
|
int128sum(this, ©, &rhs);
|
|
return *this;
|
|
}
|
|
_uint128 &operator-=(const _uint128 &rhs) {
|
|
const _uint128 copy(*this);
|
|
int128dif(this, ©, &rhs);
|
|
return *this;
|
|
}
|
|
_uint128 &operator*=(const _uint128 &rhs) {
|
|
const _uint128 copy(*this);
|
|
int128mul(this, ©, &rhs);
|
|
return *this;
|
|
}
|
|
_uint128 &operator/=(const _uint128 &rhs) {
|
|
const _uint128 copy(*this);
|
|
uint128div(this, ©, &rhs);
|
|
return *this;
|
|
}
|
|
_uint128 &operator%=(const _uint128 &rhs) {
|
|
const _uint128 copy(*this);
|
|
uint128rem(this, ©, &rhs);
|
|
return *this;
|
|
}
|
|
const char *parseDec(const char *str); // return pointer to char following the number
|
|
const char *parseHex(const char *str); // do
|
|
const char *parseOct(const char *str); // do
|
|
|
|
};
|
|
|
|
inline
|
|
bool operator==(const _int128 &lft, const _int128 &rhs) {
|
|
return (lft.lo == rhs.lo) && (lft.hi == rhs.hi);
|
|
}
|
|
|
|
inline
|
|
bool operator==(const _int128 &lft, const _uint128 &rhs) {
|
|
return (lft.lo == rhs.lo) && (lft.hi == rhs.hi);
|
|
}
|
|
|
|
inline
|
|
bool operator==(const _uint128 &lft, const _int128 &rhs) {
|
|
return (lft.lo == rhs.lo) && (lft.hi == rhs.hi);
|
|
}
|
|
|
|
inline
|
|
bool operator==(const _uint128 &lft, const _uint128 &rhs) {
|
|
return (lft.lo == rhs.lo) && (lft.hi == rhs.hi);
|
|
}
|
|
|
|
inline
|
|
bool operator!=(const _int128 &lft, const _int128 &rhs) {
|
|
return (lft.lo != rhs.lo) || (lft.hi != rhs.hi);
|
|
}
|
|
|
|
inline
|
|
bool operator!=(const _int128 &lft, const _uint128 &rhs) {
|
|
return (lft.lo != rhs.lo) || (lft.hi != rhs.hi);
|
|
}
|
|
|
|
inline
|
|
bool operator!=(const _uint128 &lft, const _int128 &rhs) {
|
|
return (lft.lo != rhs.lo) || (lft.hi != rhs.hi);
|
|
}
|
|
|
|
inline
|
|
bool operator!=(const _uint128 &lft, const _uint128 &rhs) {
|
|
return (lft.lo != rhs.lo) || (lft.hi != rhs.hi);
|
|
}
|
|
|
|
inline
|
|
bool operator>(const _int128 &lft, const _int128 &rhs) {
|
|
return int128cmp(&lft, &rhs) > 0;
|
|
}
|
|
|
|
inline
|
|
bool operator>(const _int128 &lft, const _uint128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) > 0;
|
|
}
|
|
|
|
inline
|
|
bool operator>(const _uint128 &lft, const _int128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) > 0;
|
|
}
|
|
|
|
inline
|
|
bool operator>(const _uint128 &lft, const _uint128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) > 0;
|
|
}
|
|
|
|
inline
|
|
bool operator>=(const _int128 &lft, const _int128 &rhs) {
|
|
return int128cmp(&lft, &rhs) >= 0;
|
|
}
|
|
|
|
inline
|
|
bool operator>=(const _int128 &lft, const _uint128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) >= 0;
|
|
}
|
|
|
|
inline
|
|
bool operator>=(const _uint128 &lft, const _int128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) >= 0;
|
|
}
|
|
|
|
inline
|
|
bool operator>=(const _uint128 &lft, const _uint128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) >= 0;
|
|
}
|
|
|
|
inline
|
|
bool operator<(const _int128 &lft, const _int128 &rhs) {
|
|
return int128cmp(&lft, &rhs) < 0;
|
|
}
|
|
|
|
inline
|
|
bool operator<(const _int128 &lft, const _uint128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) < 0;
|
|
}
|
|
|
|
inline
|
|
bool operator<(const _uint128 &lft, const _int128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) < 0;
|
|
}
|
|
|
|
inline
|
|
bool operator<(const _uint128 &lft, const _uint128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) < 0;
|
|
}
|
|
|
|
inline
|
|
bool operator<=(const _int128 &lft, const _int128 &rhs) {
|
|
return int128cmp(&lft, &rhs) <= 0;
|
|
}
|
|
|
|
inline
|
|
bool operator<=(const _int128 &lft, const _uint128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) <= 0;
|
|
}
|
|
|
|
inline
|
|
bool operator<=(const _uint128 &lft, const _int128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) <= 0;
|
|
}
|
|
|
|
inline
|
|
bool operator<=(const _uint128 &lft, const _uint128 &rhs) {
|
|
return uint128cmp(&lft, &rhs) <= 0;
|
|
}
|
|
|
|
char * _i128toa(_int128 value, char *str, int radix);
|
|
char * _ui128toa(_uint128 value, char *str, int radix);
|
|
wchar_t * _i128tow(_int128 value, wchar_t *str, int radix);
|
|
wchar_t * _ui128tow(_uint128 value, wchar_t *str, int radix);
|
|
|
|
inline
|
|
char radixLetter(unsigned int c) {
|
|
return (c < 10) ? ('0' + c) : ('a' + (c-10));
|
|
}
|
|
|
|
inline
|
|
wchar_t wradixLetter(unsigned int c) {
|
|
return (c < 10) ? ('0' + c) : ('a' + (c-10));
|
|
}
|
|
|
|
inline
|
|
bool isodigit(unsigned char ch) {
|
|
return ('0' <= ch) && (ch < '8');
|
|
}
|
|
|
|
unsigned int convertNumberChar(char digit);
|
|
#define __int128 _int128
|
|
#define __uint128 _uint128
|
|
|
|
#endif
|
|
|
|
#pragma warning(default:26495)
|
|
#endif
|
|
|
|
#endif |