// 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, &copy);
  return copy;
}
inline _uint128 operator>>(const _uint128 &lft, const int shft) {
  _uint128 copy(lft);
  uint128shr(shft, &copy);
  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, &copy);
  return copy;
}
inline _int128 operator<<(const _uint128 &lft, const int shft) {
  _uint128 copy(lft);
  int128shl(shft, &copy);
  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, &copy, &rhs);
    return result;
  }
  _int128 operator%(const _int128 &rhs) const {
    _int128 result, copy(*this);
    int128rem(&result, &copy, &rhs);
    return result;
  };

  _int128 &operator+=(const _int128 &rhs) {
    const _int128 copy(*this);
    int128sum(this, &copy, &rhs);
    return *this;
  }
  _int128 &operator-=(const _int128 &rhs) {
    const _int128 copy(*this);
    int128dif(this, &copy, &rhs);
    return *this;
  }
  _int128 &operator*=(const _int128 &rhs) {
    const _int128 copy(*this);
    int128mul(this, &copy, &rhs);
    return *this;
  }
  _int128 &operator/=(const _int128 &rhs) {
    const _int128 copy(*this);
    int128div(this, &copy, &rhs);
    return *this;
  }
  _int128 &operator%=(const _int128 &rhs) {
    const _int128 copy(*this);
    int128rem(this, &copy, &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, &copy, &rhs);
    return result;
  }

  _uint128 operator%(const _uint128 &rhs) const {
    _uint128 result, copy(*this);
    uint128rem(&result, &copy, &rhs);
    return result;
  };

  _uint128 &operator+=(const _uint128 &rhs) {
    const _uint128 copy(*this);
    int128sum(this, &copy, &rhs);
    return *this;
  }
  _uint128 &operator-=(const _uint128 &rhs) {
    const _uint128 copy(*this);
    int128dif(this, &copy, &rhs);
    return *this;
  }
  _uint128 &operator*=(const _uint128 &rhs) {
    const _uint128 copy(*this);
    int128mul(this, &copy, &rhs);
    return *this;
  }
  _uint128 &operator/=(const _uint128 &rhs) {
    const _uint128 copy(*this);
    uint128div(this, &copy, &rhs);
    return *this;
  }
  _uint128 &operator%=(const _uint128 &rhs) {
    const _uint128 copy(*this);
    uint128rem(this, &copy, &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