As you know, in this reason, 64-bit C++ compilers are temporarily disabled.
In order to keep using __int128 (at least partially) in 32-bit compilers, I'm trying writing a template of the unsigned version of __int128.
UPD:
2024/3/14: added (maybe) all operators that an __int128 has except for operator/
/ fixed infinite-recursion bug in several operators
Here's it (not completed yet):
integer_128_impl.cpp
#include<tuple>
#include<iostream>
#include<climits>
namespace RedshiftShine{
using ll=unsigned long long;
const ll ulmx=ULLONG_MAX;
const ll shift=64;
ll min(ll x,ll y){
return x<y?x:y;
}
ll max(ll x,ll y){
return x>y?x:y;
}
bool detect_overflow_add(ll x,ll y){
return x+y<min(x,y);
}
bool detect_overflow_minus(ll x,ll y){
return x-y>max(x,y);
}
class Custom_Unsigned_int128{
private:
ll higherInt,lowerInt;
public:
Custom_Unsigned_int128(){}
template<typename _Tp>
Custom_Unsigned_int128(_Tp x):
higherInt(0),
lowerInt(x){}
template<typename _Tp>
Custom_Unsigned_int128(_Tp x,_Tp y):
higherInt(x),
lowerInt(y){}
Custom_Unsigned_int128
(const Custom_Unsigned_int128& ele):
higherInt(ele.higherInt),
lowerInt(ele.lowerInt){}
std::pair<ll,ll>
base_access(){
return std::pair<ll,ll>{
higherInt,
lowerInt
};
}
Custom_Unsigned_int128&
operator=(const Custom_Unsigned_int128& x){
higherInt=x.higherInt,
lowerInt=x.lowerInt;
return *this;
}
template<typename _Tp>
Custom_Unsigned_int128&
operator=(const _Tp& x){
*this=Custom_Unsigned_int128
{
0,x
};
return *this;
}
template<typename _Tp>
Custom_Unsigned_int128
operator+(const _Tp& x){
return Custom_Unsigned_int128
{
higherInt+
detect_overflow_add(lowerInt,x),
lowerInt+x
};
}
template<typename _Tp>
friend Custom_Unsigned_int128
operator+(const _Tp& x,const Custom_Unsigned_int128& ele){
return Custom_Unsigned_int128
{
ele.higherInt+
detect_overflow_add(ele.lowerInt,x),
ele.lowerInt+x
};
}
Custom_Unsigned_int128
operator+(const Custom_Unsigned_int128& x){
return Custom_Unsigned_int128
{
higherInt+x.higherInt+
detect_overflow_add(lowerInt,x.lowerInt),
lowerInt+x.lowerInt
};
}
template<typename _Tp>
bool
operator==(const _Tp& x)const{
return
(
!higherInt and
lowerInt==x
);
}
template<typename _Tp>
friend Custom_Unsigned_int128
operator==(const _Tp& x,const Custom_Unsigned_int128& ele){
return ele==x;
}
bool
operator==(const Custom_Unsigned_int128& x)const{
return
(
higherInt==x.higherInt and
lowerInt==x.lowerInt
);
}
template<typename _Tp>
bool
operator!=(const _Tp& x)const{
return !(*this==x);
}
template<typename _Tp>
friend Custom_Unsigned_int128
operator!=(const _Tp& x,const Custom_Unsigned_int128& ele){
return !(ele==x);
}
template<typename _Tp>
bool
operator<(const _Tp& x)const{
return
(
!higherInt and
lowerInt<x
);
}
template<typename _Tp>
friend Custom_Unsigned_int128
operator<(const _Tp& x,const Custom_Unsigned_int128& ele){
return ele<x;
}
bool
operator<(const Custom_Unsigned_int128& x)const{
return
(
higherInt<x.higherInt or
(
higherInt==x.higherInt and
lowerInt<x.lowerInt
)
);
}
template<typename _Tp>
bool
operator<=(const _Tp& x)const{
return
(
*this<x or
*this==x
);
}
template<typename _Tp>
friend Custom_Unsigned_int128
operator<=(const _Tp& x,const Custom_Unsigned_int128& ele){
return ele<=x;
}
bool
operator<=(const Custom_Unsigned_int128& x)const{
return
(
*this<x or
*this==x
);
}
template<typename _Tp>
bool
operator>(const _Tp& x)const{
return
!(
*this<=x
);
}
template<typename _Tp>
friend Custom_Unsigned_int128
operator>(const _Tp& x,const Custom_Unsigned_int128& ele){
return !(ele<=x);
}
bool
operator>(const Custom_Unsigned_int128& x)const{
return
!(
*this<=x
);
}
template<typename _Tp>
bool
operator>=(const _Tp& x)const{
return
!(
*this<x
);
}
template<typename _Tp>
friend Custom_Unsigned_int128
operator>=(const _Tp& x,const Custom_Unsigned_int128& ele){
return !(ele<x);
}
bool
operator>=(const Custom_Unsigned_int128& x)const{
return
!(
*this<x
);
}
template<typename _Tp>
Custom_Unsigned_int128&
operator+=(const _Tp& x){
return *this=*this+x;
}
template<typename _Tp>
Custom_Unsigned_int128
operator-(const _Tp& x){
return Custom_Unsigned_int128
{
higherInt-
detect_overflow_minus(lowerInt,x),
lowerInt-x
};
}
template<typename _Tp>
friend Custom_Unsigned_int128
operator-(const _Tp& x,const Custom_Unsigned_int128& ele){
return Custom_Unsigned_int128
{
-ele.higherInt+
detect_overflow_minus(x,ele.lowerInt),
x-ele.lowerInt
};
}
Custom_Unsigned_int128
operator-(const Custom_Unsigned_int128& x){
return Custom_Unsigned_int128
{
higherInt-x.higherInt-
detect_overflow_minus(lowerInt,x.lowerInt),
lowerInt-x.lowerInt
};
}
template<typename _Tp>
Custom_Unsigned_int128&
operator-=(const _Tp& x){
return *this=*this-x;
}
template<typename _Tp>
Custom_Unsigned_int128
operator&(const _Tp& x){
return Custom_Unsigned_int128
{
higherInt,
lowerInt&x
};
}
template<typename _Tp>
Custom_Unsigned_int128
friend operator&(const _Tp& x,const Custom_Unsigned_int128& ele){
return Custom_Unsigned_int128
{
ele.higherInt,
ele.lowerInt&x
};
}
Custom_Unsigned_int128
operator&(const Custom_Unsigned_int128& x){
return Custom_Unsigned_int128
{
higherInt&x.higherInt,
lowerInt&x.lowerInt
};
}
template<typename _Tp>
Custom_Unsigned_int128&
operator&=(const _Tp& x){
return *this=*this&x;
}
template<typename _Tp>
Custom_Unsigned_int128
operator|(const _Tp& x){
return Custom_Unsigned_int128
{
higherInt,
lowerInt|x
};
}
template<typename _Tp>
Custom_Unsigned_int128
friend operator|(const _Tp& x,const Custom_Unsigned_int128& ele){
return Custom_Unsigned_int128
{
ele.higherInt,
ele.lowerInt|x
};
}
Custom_Unsigned_int128
operator|(const Custom_Unsigned_int128& x){
return Custom_Unsigned_int128
{
higherInt|x.higherInt,
lowerInt|x.lowerInt
};
}
template<typename _Tp>
Custom_Unsigned_int128&
operator|=(const _Tp& x){
return *this=*this|x;
}
template<typename _Tp>
Custom_Unsigned_int128
operator^(const _Tp& x){
return Custom_Unsigned_int128
{
higherInt,
lowerInt^x
};
}
template<typename _Tp>
Custom_Unsigned_int128
friend operator^(const _Tp& x,const Custom_Unsigned_int128& ele){
return Custom_Unsigned_int128
{
ele.higherInt,
ele.lowerInt^x
};
}
Custom_Unsigned_int128
operator^(const Custom_Unsigned_int128& x){
return Custom_Unsigned_int128
{
higherInt^x.higherInt,
lowerInt^x.lowerInt
};
}
template<typename _Tp>
Custom_Unsigned_int128&
operator^=(const _Tp& x){
return *this=*this^x;
}
Custom_Unsigned_int128
operator~(){
return Custom_Unsigned_int128{
~higherInt,
~lowerInt
};
}
template<typename _Tp>
Custom_Unsigned_int128
operator<<(const _Tp& x){
return Custom_Unsigned_int128
{
higherInt<<x|(lowerInt>>(shift-x)),
lowerInt<<x
};
}
template<typename _Tp>
Custom_Unsigned_int128&
operator<<=(const _Tp& x){
return *this=*this<<x;
}
template<typename _Tp>
Custom_Unsigned_int128
operator>>(const _Tp& x){
return Custom_Unsigned_int128
{
higherInt>>x,
lowerInt>>x|(higherInt<<(shift-x))
};
}
template<typename _Tp>
Custom_Unsigned_int128&
operator>>=(const _Tp& x){
return *this=*this>>x;
}
template<typename _Tp>
Custom_Unsigned_int128
operator*(const _Tp& x)const{
Custom_Unsigned_int128 ret(0),pr(*this);
_Tp tm(x);
for(;tm;tm>>=1){
if(tm&1)ret+=pr;
pr+=pr;
}
return ret;
}
template<typename _Tp>
Custom_Unsigned_int128
friend operator*(const _Tp& x,const Custom_Unsigned_int128& ele){
return ele*x;
}
template<typename _Tp>
Custom_Unsigned_int128&
operator*=(const _Tp& x){
return *this=*this*x;
}
};
}
void test(){
RedshiftShine::Custom_Unsigned_int128 ci(1,1);
auto [a,b]=ci.base_access();
std::printf("%llu %llu\n",a,b);
}
int main(){
test();
}
Hope it helps.