我以前从未使用过GNU MPZ库。我想用它来计算大输入的模幂(结果不能存储在8个字节中)。因此,尝试使用gmp.h.
,但不知道如何在uint64_t和mpz_t
类型之间切换以及如何将结果转换回uint64_t
。我尝试使用gmp的一些内置函数,但返回错误分段错误:
代码:
#include <stdio.h>
#include <stdint.h>
#include <gmp.h>
void mpz_set_ull( mpz_t rop, uint64_t op ){
mpz_import(rop, 1, 1, sizeof(op), 0, 0, &op);
}
int powmod(mpz_t result, mpz_t a, mpz_t e, mpz_t n) {
// Use result as accum (temp variable)
if (mpz_cmp_si(e,0) == 0) { // If exponent is zero
mpz_set_ui(result, 1); // Set result to 1
return 1;
};
mpz_set(result, a); // Set value of accum to a
int bitptr = mpz_sizeinbase(e,2) - 1; // Find top bit in exponent
for(bitptr--; bitptr >= 0; bitptr--) {
mpz_mul(result,result,result); // result <-- result^2
mpz_fdiv_r(result,result,n); // result <-- result (mod n)
if(mpz_tstbit(e,bitptr)) { // Is bit e[bitptr] == 1?
mpz_mul(result,result,a); // result <-- result*a
mpz_fdiv_r(result,result,n); // result <-- result (mod n)
};
};
return 1;
}
int main() {
mpz_t mpz_g;
mpz_t mpz_l;
mpz_t mpz_p;
mpz_t mpz_r;
uint64_t r;
uint64_t p=1217409241131113809; //g^lm mod p
uint64_t g=1103362698;
uint64_t lm = 137911680;
mpz_set_ull( mpz_g, g );
mpz_set_ull( mpz_l, lm );
mpz_set_ull( mpz_p, p );
powmod(mpz_r,mpz_g,mpz_l,mpz_p );
r= mpz_get_ui (mpz_r);
printf("---> %ld\n",r);
return 0;
}
错误: 分段错误(核心已转储)
答案 0 :(得分:1)
在您的程序上使用GDB,我们可以看到在mpz_set_ull
中发生了分段错误:
$ gcc -g -lgmp test.c
$ gdb ./a.out
(gdb) run
Starting program: ./a.out
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7f12789 in __gmpz_import () from /usr/lib/libgmp.so.10
(gdb) bt
#0 0x00007ffff7f12789 in __gmpz_import () from /usr/lib/libgmp.so.10
#1 0x0000555555555209 in mpz_set_ull (rop=0x7fffffffe5e0, op=1103362698) at test.c:5
#2 0x0000555555555357 in main () at test.c:34
这是因为您传递给mpz_t
的{{1}}尚未初始化。 GMP希望您在致电mpz_import
之前先在mpz_init
上致电mpz_t
。
您可以通过在致电mpz_import
之前在main
中插入以下代码来解决此问题:
mpz_set_ull
根据您使用此代码的方式,您可能还需要调用
完成计算后, mpz_init(mpz_g);
mpz_init(mpz_l);
mpz_init(mpz_p);
mpz_init(mpz_r);
处理这些变量。
使用此修改来运行程序会给我:
mpz_clear
对于您输入的示例输入,这是正确的结果。