使用GNU MPZ库进行模块化指数

时间:2019-09-06 19:51:01

标签: c gmp mod exp

我以前从未使用过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;
}

错误: 分段错误(核心已转储)

1 个答案:

答案 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

对于您输入的示例输入,这是正确的结果。