mpz_t в длинное длинное преобразование без знака (gmp lib) - PullRequest
5 голосов
/ 06 июня 2011

Есть ли способ преобразовать переменную mpz_t в long unsigned long в C? Как насчет обратного пути, от ull до mpz_t? Библиотека gmp не поддерживает это, поскольку ull являются частью C99.Я нашел это , но это на c ++, и я не знаю, как кодировать на c ++. Заранее спасибо.

Ответы [ 2 ]

7 голосов
/ 06 июня 2011

Вот некоторые функции для перевода между unsigned long long и mpz_t. Обратите внимание, что mpz2ull разбьет ваш стек, если число слишком велико, чтобы поместиться в unsigned long long:

unsigned long long mpz2ull(mpz_t z)
{
    unsigned long long result = 0;
    mpz_export(&result, 0, -1, sizeof result, 0, 0, z);
    return result;
}

void ull2mpz(mpz_t z, unsigned long long ull)
{
    mpz_import(z, 1, -1, sizeof ull, 0, 0, &ull);
}
5 голосов
/ 27 января 2013

Эти функции должны работать для преобразования между mpz_t и длинным подписанным / без знака.Они должны быть достаточно быстрыми, поскольку они избегают необходимости выполнять обработку строк:

void mpz_set_sll(mpz_t n, long long sll)
{
    mpz_set_si(n, (int)(sll >> 32));     /* n = (int)sll >> 32 */
    mpz_mul_2exp(n, n, 32 );             /* n <<= 32 */
    mpz_add_ui(n, n, (unsigned int)sll); /* n += (unsigned int)sll */
}

void mpz_set_ull(mpz_t n, unsigned long long ull)
{
    mpz_set_ui(n, (unsigned int)(ull >> 32)); /* n = (unsigned int)(ull >> 32) */
    mpz_mul_2exp(n, n, 32);                   /* n <<= 32 */
    mpz_add_ui(n, n, (unsigned int)ull);      /* n += (unsigned int)ull */
}

unsigned long long mpz_get_ull(mpz_t n)
{
    unsigned int lo, hi;
    mpz_t tmp;

    mpz_init( tmp );
    mpz_mod_2exp( tmp, n, 64 );   /* tmp = (lower 64 bits of n) */

    lo = mpz_get_ui( tmp );       /* lo = tmp & 0xffffffff */ 
    mpz_div_2exp( tmp, tmp, 32 ); /* tmp >>= 32 */
    hi = mpz_get_ui( tmp );       /* hi = tmp & 0xffffffff */

    mpz_clear( tmp );

    return (((unsigned long long)hi) << 32) + lo;
}

long long mpz_get_sll(mpz_t n)
{
    return (long long)mpz_get_ull(n); /* just use unsigned version */
}

Сигнатуры функций должны выглядеть как собственные функции GMP.Как и в случае других функций gmpz_set_, они предполагают, что переданные переменные уже инициализированы, но их легко изменить на функции стиля gmp_init_set_.

...