我使用OpenCL进行GPGPU编程,但是不幸的是,没有 native 256位整数支持。我决定将256位整数分成四个64位整数。基本操作的很好解决方案,但是如何获得它们的模数呢?
我需要这样做:
(uint256) % (uint256)
但是使用OpenCL,我只能拥有:
[ (uint64), (uint64), (uint64), (uint64) ] % [ (uint64), (uint64), (uint64), (uint64) ]
那么我该如何实现呢?我应该使用哪种算法,最重要的是-最容易实现的算法是什么?
附言对于公钥加密,我需要它。
编辑:我既没有实现加法,也没有实现减法。
最佳答案
这是一个简单(相当有效)的算法,仅使用减法,乘以2,除以2和比较(所有这些对于uint256都很容易实现)来计算a % b
。
uint256 modulo(uint256 a, uint256 b) {
int i = 0;
while (b <= a) {
b = b * 2; // watch out for overflow!
i++;
}
while (i--) {
b = b / 2;
if (b <= a) {
a = a - b;
}
}
return a;
}
这是一个例子:
start: a = 40, b = 7
i = 1, a = 40, b = 14
i = 2, a = 40, b = 28
i = 3, a = 40, b = 56
i = 3, b = 28, a = 40 - 28 = 12
i = 2, b = 14, a = 12 (b > a so nothing happens)
i = 1, b = 7, a = 12 - 7 = 5
i = 0, so we stop and return a = 5
编辑:为什么这有效?
如果满足以下条件,则可计算模余数的简单方法:
int modulo(int a, int b) {
while (a >= b) {
a -= b;
}
return a;
}
提出的解决方案使用相同的想法,但是效率更高。我们知道,最终我们将从
b
中减去a
精确地达到k
时间。通过我们我们不知道k
的值。 k
可以二进制形式表示为2^0 * k_0 + 2^1 * k_1 + 2^2 * k_2 + ...
。该算法从2 ^ i的最大值开始,尝试减去2^i * b
。因此,我们实现了对数时间复杂度,而不是线性。免责声明:我不会使用此实现,而是真正的密码实现,因为它容易受到旁道攻击(不同的执行时间取决于输入)。