gcc 将一个'__int128'添加到GMP库的一个'mpz_class'或'mpz_t'中的更快的方法是什么?

lvmkulzt  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(180)

我想用一个128 bit integer using g++GMPmpz_class(或mpz_t)来做这个:

typedef unsigned __int128 tw_limb_t;

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

我可以执行以下操作,但首先将__int128转换为mpz_t似乎很慢:

typedef unsigned __int128 tw_limb_t;

inline mpz_class& operator+=(mpz_class &lhs, const tw_limb_t &rhs) {
    if (sizeof(tw_limb_t) != 2 * sizeof(mp_limb_t)) {
        throw std::runtime_error("sizeof(tw_limb_t) is not twice 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;
}

如何从中获得更高的性能?

ttp71kqs

ttp71kqs1#

这是我目前使用Marc Glisse建议的mpz_roinit_n的最佳解决方案。

typedef unsigned __int128 tw_limb_t;

inline mpz_class& operator+=(mpz_class &lhs, const tw_limb_t &rhs) {
    if (sizeof(tw_limb_t) != 2 * sizeof(mp_limb_t)) {
        throw std::runtime_error("sizeof(tw_limb_t) is not twice 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 tw_limb_t &rhs) {
    lhs += rhs;
    return lhs;
}

相关问题