将两个128位整数相乘

时间:2014-02-28 03:19:12

标签: c integer-arithmetic

我正试图在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中?

3 个答案:

答案 0 :(得分:4)

如果您使用的是gcc或clang,则可以直接使用__int128unsigned __int128

答案 1 :(得分:3)

您陷入了无限循环,因为i += 1/32i += 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 + B)生成进位
  • 当求和(A + B + c)时,如果((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;