Alternative __int128 without 64-bit compiler
Difference between en1 and en2, changed 10,726 character(s)
As you know, in [this](https://codeforces.net/blog/entry/126654) 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):↵

<spoiler summary="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=
3264;↵

    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){}↵
        ↵
        
template<typename _Tp>↵
        Custom_Unsigned_int128↵
        operator=(const _Tp& x){↵
            higherInt=0;↵
            lowerInt=x;↵
        }↵

        Custom_Unsigned_int128↵
        operator=(const Custom_Unsigned_int128& x){↵
            higherInt=x.higherInt;↵
            lowerInt=x.lowerInt;↵
        }↵

        template<typename _Tp>↵
        Custom_Unsigned_int128↵
        operator+(const _Tp& x){↵
            return Custom_Unsigned_int128↵
            {↵
                higherInt+↵
                detect_overflow_add(lowerInt,x),↵
                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>↵
        Custom_Unsigned_int128↵
        operator-(const _Tp& x){↵
            return Custom_Unsigned_int128↵
            {↵
                higherInt-↵
                detect_overflow_minus(lowerInt,x),↵
                lowerInt-x
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↵
            };↵
        }↵

        
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↵
        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();

}↵
~~~~~↵


</spoiler>↵

Hope it helps.

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
en4 English shiny_shine 2024-03-22 15:45:49 21 Revision 3 / Alpha version
en3 English shiny_shine 2024-03-15 09:14:17 3016 Revision 2 / Alpha version
en2 English shiny_shine 2024-03-14 09:11:41 10726 Revision 1
en1 English shiny_shine 2024-03-13 12:59:06 4429 Initial revision (published)