Умножение двух 128-битных интов
Я пытаюсь умножить два 128-битных целых числа в C.
вот мой алгоритм:
разделить две 128-битные последовательности на S1 и S2.
затем разделить на С1 С11 (передняя/верхняя) и S12 (задняя/нижняя половина) и сплит S2 В типа S21 (передняя/верхняя) и S22 (задняя/нижняя половина).
умножьте S12 на S22... = S1222.
умножьте S11 на S21... = S1121, а затем бит сдвигает его, умножая его на 2^128
Объединить S1222 и S1121 будет передней и задней половинами нового массива. Назовем его "Array1". Длина нового массива в два раза больше длины S1.
тогда мы должны умножить S12 на S21 и S11 на S22. Я умножил эти два, чтобы получить s1221 и S1122 соответственно (и бит-сдвинул их соответственно). Теперь я должен добавить их в Array1. Это та часть, где я прошу о помощи. Я не уверен, как добавить их один за другим в Array1. Имейте в виду, что может быть перенос 1, Когда вы идете по кусочкам от 3/4 от Array1 до 1/4 от Array1, так как это промежуток, где необходимо добавить S1221 и S1122.
мой вопрос: Как добавить dstM1 и dstM2 в массив d, который уже заполнен?
3 ответов
суммируя ваш вопрос: Как вы можете добавить два массива (без знака) целых чисел, распространяющих перенос.
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, либо эта сумма производит новый перенос, либо нет.
- Carry производится из (A+B), если
(A+B) < A
- при суммировании (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;
вы застряли в бесконечном цикле, потому что i += 1/32
Это то же самое, что i += 0
.
также: Примечание:memcpy(&d[3l/2-i], dstM1, 1/8);
и memcpy(&d[1-i], dstM1, 0);