在 GMP 的 mpz_t 和 NTL 的 ZZ 之间转换

问题描述 投票:0回答:2

我正在使用 NTL 和 GMP 扩展一个小型库。我使用 NTL 是为了方便(并符合现有 API),但我将切换到 GMP(和 MPFR)来处理真正对性能至关重要的内容。

我使用 GMP 作为 NTL 的长整数后端(使用

NTL_GMP_LIP=on
标志编译),我希望这意味着我可以从
mpz_t
对象访问底层
NTL::ZZ
。但是,我找不到任何文档或示例。

如果有人能给我一个小代码片段或解释如何在

NTL::ZZ
mpz_t
之间进行转换,我将永远感激不已。

(注意:我知道您可以使用字符串作为中间格式并使用字符串解析进行转换,但我想要更高性能的东西。)

c++ gmp ntl
2个回答
2
投票

您可以使用 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;

0
投票

这是一个避免了其他答案的二进制到十进制再转换的版本,因此速度明显更快(根据快速实验,速度约为 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;
}
© www.soinside.com 2019 - 2024. All rights reserved.