我正试图在C中乘以两个128位整数。
这是我的算法:
将两个128位序列分成S1和S2。
然后将S1分成S11(前/后半部分)和S12(后/下半部分)并将S2分成S21(前/后半部分)和S22(后/下半部分)。
通过S22乘以S12 ... = S1222。
将S21乘以S11 ... = S1121,然后将其乘以2 ^ 128
进行位移将S1222和S1121组合为新阵列的前半部分和后半部分。我们称之为“Array1”。新数组的长度是S1的两倍。
然后我们必须将S12乘以S21并将S11乘以S22。我将这两个相乘得到S1221和S1122(并相应地对它们进行位移)。现在我必须将它们添加到Array1。这是我要求帮助的部分。我不知道如何将这些一个一个地添加到Array1。请记住,当你从Array1的3/4到Array1的1/4逐位时,可能会有1的进位,因为这是需要添加S1221和S1122的跨度。
我的问题是:如何将dstM1和dstM2添加到已填充的数组d中?
答案 0 :(得分:4)
如果您使用的是gcc或clang,则可以直接使用__int128
和unsigned __int128
。
答案 1 :(得分:3)
您陷入了无限循环,因为i += 1/32
与i += 0
相同。
另外:注意:memcpy(&d[3l/2-i], dstM1, 1/8);
为memcpy(&d[1-i], dstM1, 0);
答案 2 :(得分:1)
总结你的问题:如何添加两个传播进位的(无符号)整数数组。
uint16_t foo[4]; // 0000 aaaa FFFF cccc
uint16_t bar[4]; // dddd eeee FFFF 0000
好处是'FFFF + FFFF + 1'只是(1)FFFF。因此,总是可以在每个单词中添加进位而不产生额外的进位(就好像总和可能是20000)。
临时总和:sum = foo[3] + bar[3] + carry;
,最初为0,这个总和是否会产生新的进位。
(A+B) < A
((A + c) < A) || (((A + c) + B) < B)
另一种可能性是通过对列中的几个项进行求和来计算“多位进位”,这通常发生在bignum乘法中:
AAAA BBBB CCCC
DDDD EEEE FFFF ....
GGGG HHHH IIII .... ....
--------------------------
col4 col3 col2 col1 col0
现在每列产生32位或64位结果,并且进位不一定适合单个位。
uint32_t sum_low = carry_in_from_previous_column;
uint32_t sum_high = 0;
for (i = 0; i < N; i++) {
sum_low += matrix[i][column] & 0xffff;
sum_high += matrix[i][column] >> 16;
}
sum_high += sum_low >> 16; // add the multibit half carry
result = (sum_low & 0xffff) | (sum_high << 16);
carry_out = sum_high >> 16;