将“__int128”添加到GMP库的“mpz_class”或“mpz_t”的更快方法?

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

提问人:Daniel S. 提问时间:8/22/2022 最后编辑:Daniel S. 更新时间:9/15/2022 访问量:248

问:

我想使用 g++GMP(或):mpz_classmpz_t

typedef unsigned __int128 tw_limb_t;

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

我可以执行以下操作,但是首先将其转换为:__int128mpz_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;
}

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

C GCC G++ GMP int128

评论

0赞 Marc Glisse 8/22/2022
您可以手动创建假mpz_t以避免rhs_mpz分配,但代码可能会在将来的 GMP 更新中中断。
0赞 Marc Glisse 8/24/2022
(例如,请参阅文档中的mpz_roinit_n)
0赞 Daniel S. 8/24/2022
@MarcGlisse 谢谢,这让我的机器速度更快一些。

答:

1赞 Daniel S. 8/24/2022 #1

这是我目前使用的最佳解决方案,正如 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;
}