我正在使用 NTL 和 GMP 扩展一个小型库。我使用 NTL 是为了方便(并符合现有 API),但我将切换到 GMP(和 MPFR)来处理真正对性能至关重要的内容。
我使用 GMP 作为 NTL 的长整数后端(使用
NTL_GMP_LIP=on
标志编译),我希望这意味着我可以从 mpz_t
对象访问底层 NTL::ZZ
。但是,我找不到任何文档或示例。
如果有人能给我一个小代码片段或解释如何在
NTL::ZZ
和 mpz_t
之间进行转换,我将永远感激不已。
(注意:我知道您可以使用字符串作为中间格式并使用字符串解析进行转换,但我想要更高性能的东西。)
您可以使用 sstream 或类似的字符串实用程序进行反之亦然。 以下代码用于从 NTL 传输到 ZZ。反过来也类似。
ZZ a, b;
cin >> a;
cin >> b;
mpz_t aa, bb;
mpz_init(aa);
mpz_init(bb);
std::stringstream ssa;
std::stringstream ssb;
ssa << a;
ssb << b;
mpz_set_str( aa, ssa.str().c_str(),10);
mpz_set_str( bb, ssb.str().c_str(),10);
gmp_printf ("%Zd-", aa);
gmp_printf ("%Zd\n", bb);
cout << a << "-" << b;
这是一个避免了其他答案的二进制到十进制再转换的版本,因此速度明显更快(根据快速实验,速度约为 4-5 倍):
#include <vector>
#include <cassert>
#include <gmp.h>
#include <NTL/ZZ.h>
void ntl2gmp(mpz_t out, NTL::ZZ const &num)
{
thread_local std::vector<unsigned char> bs;
if (NTL::IsZero(num)) {
mpz_set_ui(out, 0);
return;
}
size_t l = NTL::NumBytes(num);
if (l > bs.size())
bs.resize(l);
int sgn = NTL::sign(num);
assert(sgn == +1 || sgn == -1);
NTL::BytesFromZZ(bs.data(), num, l);
mpz_import(out, l, -1, 1, 0, 0, bs.data());
if (sgn < 0)
mpz_neg(out, out);
}
void gmp2ntl(NTL::ZZ &out, mpz_t const num)
{
thread_local std::vector<unsigned char> bs;
if (!mpz_cmp_ui(num, 0)) {
NTL::clear(out);
return;
}
size_t l = (mpz_sizeinbase(num, 2) + 7) / 8;
if (l > bs.size())
bs.resize(l);
int sgn = mpz_sgn(num);
assert(sgn == +1 || sgn == -1);
size_t ll;
mpz_export(bs.data(), &ll, -1, 1, 0, 0, num);
assert(ll <= l);
NTL::ZZFromBytes(out, bs.data(), ll);
if (sgn < 0)
out = -out;
}