简体   繁体   中英

Faster way to add an `__int128` to an `mpz_class` or `mpz_t` of the GMP library?

I want to do this with a 128 bit integer using g++ and GMP 's mpz_class (or mpz_t ):

typedef unsigned __int128 dbl_limb_t;

mpz_class a = "1234567890123456789012345678901234567890";
dbl_limb_t b = ...;
a += b;

I can do the following, but it seems slow to first convert the __int128 to mpz_t :

typedef unsigned __int128 dbl_limb_t;

inline mpz_class& operator+=(mpz_class &lhs, const dbl_limb_t &rhs) {
    if (sizeof(dbl_limb_t) != 2 * sizeof(mp_limb_t)) {
        throw std::runtime_error("sizeof(dbl_limb_t) is not double of sizeof(mp_limb_t)");
    }

    const int LIMB_BITLEN = sizeof(mp_limb_t) * 8;

    mpz_class rhs_mpz = (mp_limb_t) (rhs >> LIMB_BITLEN);
    rhs_mpz <<= LIMB_BITLEN;
    rhs_mpz += (mp_limb_t) rhs;

    lhs += rhs_mpz;

    return lhs;
}

How to get more performance out of this?

This is my current best solution using mpz_roinit_n as suggested by Marc Glisse.

typedef unsigned __int128 dbl_limb_t;

inline mpz_class& operator+=(mpz_class &lhs, const dbl_limb_t &rhs) {
    if (sizeof(dbl_limb_t) != 2 * sizeof(mp_limb_t)) {
        throw std::runtime_error("sizeof(dbl_limb_t) is not double of sizeof(mp_limb_t)");
    }

    mpz_t rhs_mpz;
    mpz_roinit_n(rhs_mpz, reinterpret_cast<const mp_limb_t*>(&rhs), 2);

    mpz_add(lhs.get_mpz_t(), lhs.get_mpz_t(), rhs_mpz);

    return lhs;
}

inline mpz_class operator+(mpz_class lhs, const dbl_limb_t &rhs) {
    lhs += rhs;
    return lhs;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM