我在Mathematica中实现了一个使用PowerMod查找模块化逆的算法。我现在需要在C中实现这个算法,并且我决定使用gmp及其函数 mpz_powm ,这显然做了同样的事情。问题是,我没有得到相同的值。例如,在Mathematica上运行时,它会给出:
PowerMod[30030, -1, 43] = 35
而 mpz_pwm 给出16.并且:
PowerMod[30030, -1, 71] = 8
而 mpz_pwm 给出了46.(我希望这些是足够的例子。)我也尝试了各种模块化逆算法,我设法在网上找到它们,它们也提供不同的值。不过,我怀疑Mathematica是对的。有谁知道这里发生了什么?
答案 0 :(得分:2)
this link有一些似乎相关的东西。
简而言之,似乎mpz_pwm将-1解释为无符号短路2 ^ 16-1。此链接的线程中的一个响应来自GMP开发人员,以及这是文档中的错误。
对于2 ^ 16-1,我通过一些实验来得到它。
PowerMod[30030,2^16-1,43]
(* Out[5]= 16 *)
到目前为止一切顺利。当第三个参数是71时,它就会崩溃。但是PowerMod[30030, -1, 71]
实际上不是8.当第三个参数是79时,它就成立。而我们仍然没有得到PowerMod[30030, 2^16-1,79]
等于46:当第三个参数是73.所以我猜这些是你实际上分别提供给powerMod
和mpz_pwm的参数。
如果GMP没有直接执行您需要的功能,您可以从扩展GCD获得模块化反转。我将展示在Mathematica中使用的代码,但我确信它可以适应手头的目的。
myModularInverse[n_,p_] := With[{inv=ExtendedGCD[n,p][[2,1]]},
If[inv>0, inv, inv+p]]
快速举例:
myModularInverse[30030, 43]
(* Out[28]= 35 *)
myModularInverse[30030, 79]
(* Out[29]= 8 *)
编辑:更多挖掘表明GMP有一个函数mpz_invert,似乎在这里做了所需的事情。请参阅GMP number theory functions。还有一个gmp_invert函数,我猜在gmp层次结构中处于更高级别。
答案 1 :(得分:1)
原生GMP mpz_powm
不会直接处理负指数。您需要使用mpz_invert
计算逆。
我在gmpy2(GMP的Python包装器)中实现了你想要的行为。我的代码在:
https://code.google.com/p/gmpy/source/browse/trunk/src/gmpy2_pow.c
注意代码:mpz_inoc和mpz_cloc是mpz_init和mpz_clear的替换,用于在幕后缓存对象。