快速乘法和减法模数为素数

时间:2011-10-27 10:29:40

标签: java performance optimization primes modulo

我需要优化一些代码,其中我将一个整数矢量(32位)乘以标量模p(其中p是素数(2 ^ 32)-5),然后从另一个矢量模p中减去该矢量。

代码如下所示:

public static void multiplyAndSubtract(long fragmentCoefficient, long[] equationToSubtractFrom, long[] equationToSubtract) {
    for (int i = 0; i < equationToSubtractFrom.length; i++) {
        equationToSubtractFrom[i] =  modP(equationToSubtractFrom[i] - multiplyModP(fragmentCoefficient, equationToSubtract[i]));
    }
}

我正在使用long,因为Java不支持无符号整数,但两个向量都是mod p,所以你可以期望每个数字都是0&lt; = x&lt; (2 ^ 32)-5

有什么想法来优化这个? mod p操作占用了大部分执行时间,因此优化这种方法的一种方法可能是在乘法后不知道怎么做modP并且只在减法后做。关于如何做到的任何想法?

3 个答案:

答案 0 :(得分:6)

e - (f * e mod p) mod p = (e-e f) mod p

请参阅Wolfram Alpha

答案 1 :(得分:4)

使用2 ^ 32 = 5(mod p)的事实可以加速计算并避免任何除法。

在乘法和减法之后,将结果分成低(x%2 ^ 32)和hi(x / 2 ^ 32)个部分。然后将hi部分乘以5并与低部分相加。然后再次重复此过程。如果结果大于p,则减去p。对于否定结果,请添加p。

编辑:由于组合的乘法和减法可能会溢出,因此乘法的结果也应该以p为模。但只有上述步骤中的一步就足够了:只需拆分,乘以5,然后添加。

答案 2 :(得分:1)

我知道有两种方法可以在不使用除法或模数的情况下完成此操作:

方法1:不变乘法 。 (see this paper

这里的基本思想是预先计算和近似p的倒数,这允许你只使用几个整数乘法进行整数除法。然后你可以向后乘以获得你的模数。这是更容易实现的方法。

方法2: (我经常使用的那个), 是使用浮点 。将数字转换为浮点数并乘以p的预先计算的倒数。然后舍入并转换回整数。这种方法很难做到正确,但根据我的经验,如果做得好,它会更快。

除了在整数或浮点中预计算倒数之外,这里的两种方法都不涉及任何除法。

这些方法中的任何一种方法是否比直接使用%更快,取决于您实施它们的程度。所以我不能保证任何一个会更快。