INT128

#include<bits/stdc++.h>
#define DEBUG cerr << "Call out: " << __func__ << "\t" << "Line: " << __LINE__ << "\t :"
using namespace std;

class INT128 {
public:
#define OPERATOR 9223372036854775808ull //(1 << 63)
#define HERE (*this)
    unsigned long long HighPart, LowPart;
    INT128() { HighPart = 0; LowPart = 0; }
    INT128(long long p)
    {
        HighPart = 0; LowPart = 0; if (p >= 0) LowPart = p; else LowPart = p, HERE.rev();
    }
    INT128(long long p, long long q) { HighPart = p; LowPart = q; }
    void print() { cout << (bitset<64>)HighPart << ' ' << (bitset<64>)LowPart; }
    void printH() { cout << hex << HighPart << LowPart << dec << endl; }
    INT128 operator | (INT128 b) { return ((HighPart | b.HighPart), (LowPart | b.LowPart)); }
    INT128 operator & (INT128 b) { return ((HighPart & b.HighPart), (LowPart & b.LowPart)); }
    INT128 operator ^ (INT128 b) { return ((HighPart ^ b.HighPart), (LowPart ^ b.LowPart)); }
    bool operator < (INT128 b) { return (HERE - b).HighPart & OPERATOR; }
    bool operator <= (INT128 b) { return (HERE == b) | (HERE < b); }
    bool operator == (INT128 b) { return (HighPart == b.HighPart) && (LowPart == b.LowPart); }
#define QAdd(a,b) \
    INT128(a.HighPart + b.HighPart + (a.LowPart >= 0-b.LowPart && (b.LowPart != 0)), a.LowPart + b.LowPart)
    inline INT128 rev() {
        INT128 p = HERE;
        p.HighPart = ~p.HighPart; p.LowPart = ~p.LowPart;
        return QAdd(p, (INT128(1)));
    }
    INT128 operator << (int st) {
        if (st == 0) return HERE;
        if (st >= 64) return INT128(LowPart << (st - 64), 0);
        else return INT128((HighPart << st | LowPart >> (64 - st)), LowPart << st);
    }
    INT128 operator >> (int st) {
        if (st == 0) return HERE;
        if (st >= 64) return INT128(0, HighPart >> (st - 64));
        else return INT128(HighPart >> st, (LowPart >> st | HighPart << (64 - st)));
    }
    bool operator [] (const int st) {
        return (st >= 64 ? ((HighPart >> (st - 64)) & 1) : ((LowPart >> (st)) & 1));
    }
    void change(int x, bool p) { // build successfully
        if (p) if (x >= 64) HighPart |= (1ll << (x - 64));
        else LowPart |= (1ll << (x));
        else if (x >= 64)
            if (((HighPart >> (x - 64)) & 1)) HighPart ^= (1ll << (x - 64)); else;
        else if (((LowPart >> (x)) & 1)) LowPart ^= (1ll << x);
    }
    INT128 operator / (long long st) { // build successfully
        INT128 nx = HERE;
        bool flag = (st & OPERATOR) ^ (HighPart & OPERATOR);
        if (st & OPERATOR) st = -st;
        if (HighPart & OPERATOR) nx = -nx;
        INT128 tmp = st; assert(st != 0);
        int len = log2(st) + 1; INT128 ret = 0;
        for (int i = 127 - len; i >= 0; i--) {
            if ((tmp << i) <= nx) ret.change(i, 1), nx = nx - (tmp << i);
        }
        if (flag) return -ret; else return ret;
    }
    long long operator % (long long st) {
        long long ret = 0;
        for (int i = 127; i >= 0; i--) {
            ret = ret * 2 + HERE[i];
            if (ret >= st) ret -= st;
        }
        return ret;
    }
    inline INT128 operator * (INT128 st) {
        register int flag;
        if ((HighPart & OPERATOR) ^ (st.HighPart & OPERATOR)) flag = 1;
        else flag = 0;
        register unsigned long long a1 = (unsigned int)LowPart, b1 = LowPart >> 32;
        register unsigned long long a2 = (unsigned int)st.LowPart, b2 = st.LowPart >> 32;
        INT128 ret = 
            (INT128)(a1 * a2) + // 0
            (((INT128)(a1 * b2) + (INT128)(a2 * b1)) << 32) + // 32
            (((INT128)(a1 * (unsigned int)st.HighPart + b1 * b2 + (unsigned int)HighPart * a2)) << 64) + // 32 * 2
            (((INT128)(a1 * (st.HighPart >> 32) + b1 * (unsigned int)st.HighPart +
                       (unsigned int)HighPart * b2 + (HighPart >> 32) * a2)) << 96); // 32 * 3
        if (flag) return -ret;
        else return ret;
    }
    friend ostream& operator << (ostream& st, INT128 t) {
        static int a[51]; int top = 0;
        if (t < 0) putchar('-'), t = -t;
        while (t.HighPart || t.LowPart) {
            a[top++] = t % 10;
            t = t / 10;
        }
        while (top) putchar(a[--top] + '0');
        return st;
    }
    INT128 operator + (INT128 p) { return QAdd(HERE, p); }
    INT128 operator - (INT128 p) { return QAdd(HERE, p.rev()); }
    INT128 operator - () { return HERE.rev(); }
    const INT128& operator=(const long long& p) { HERE = INT128(p); return HERE; }
    // operator long long(){ return LowPart; }
//#undef OPERATOR
#undef HERE
}; // IF you just want to add, PLEASE use QAdd()
INT128 time(INT128 a, INT128 st){
    register int flag;
    if ((a.HighPart & OPERATOR) ^ (st.HighPart & OPERATOR)) flag = 1;
    else flag = 0;
    register unsigned long long a1 = (unsigned int)a.LowPart, b1 = a.LowPart >> 32;
    register unsigned long long a2 = (unsigned int)st.LowPart, b2 = st.LowPart >> 32;
    INT128 ret = 
        (INT128)(a1 * a2) + // 0
        (((INT128)(a1 * b2) + (INT128)(a2 * b1)) << 32) + // 32
        (INT128)(((a1 * (unsigned int)st.HighPart + b1 * b2 + (unsigned int)a.HighPart * a2))  + // 32 * 2
        ((a1 * (st.HighPart >> 32) + b1 * (unsigned int)st.HighPart +
                   (unsigned int)a.HighPart * b2 + (a.HighPart >> 32) * a2)) << 32); // 32 * 3
    if (flag) return -ret;
    else return ret;
}
int main() {
    clock_t beg = clock();
    long long times = 0;
    INT128 a = 1000000ll, b = 10000000ll;
//  a * a * b;
    const int tx = 1000;
    while (clock() - beg <= CLOCKS_PER_SEC) {
        for (int i = 1; i <= tx; i++)
            time(a,b);
        times += tx;
    }
    cout << "time:\t" << times << endl;
    beg = clock();
    times = 0;
    while (clock() - beg <= CLOCKS_PER_SEC) {
        for (int i = 1; i <= tx; i++)
            QAdd(a,b);
        times += tx;
    }
    cout << "add:\t" << times << endl;
}
posted @ 2020-02-02 22:20  dgklr  阅读(217)  评论(0编辑  收藏  举报