Пока signed long long intне проведут A*B, двое из них будут. Таким образом, A*Bможно разложить на три разных показателя степени, подходящих для любого из них signed long long int.
A1=A>>32;
A0=A & 0xffffffff;
B1=B>>32;
B0=B & 0xffffffff;
AB_0=A0*B0;
AB_1=A0*B1+A1*B0;
AB_2=A1*B1;
То же самое для C*D .
Следуя прямому пути, вычитание может быть выполнено для каждой пары, AB_iа CD_iтакже с использованием дополнительного бита переноса (точно 1-битное целое число) для каждой. Поэтому, если мы скажем E = A * BC * D, вы получите что-то вроде:
E_00=AB_0-CD_0
E_01=(AB_0 > CD_0) == (AB_0 - CD_0 < 0) ? 0 : 1 // carry bit if overflow
E_10=AB_1-CD_1
...
Мы продолжаем, перенося верхнюю половину E_10в E_20(сдвинуть на 32 и добавить, затем стереть верхнюю половину E_10).
Теперь вы можете избавиться от бита для переноса E_11, добавив его с нужным знаком (полученным из части без переноса) в E_20. Если это вызывает переполнение, результат не будет соответствовать.
E_10теперь достаточно места, чтобы взять верхнюю половину E_00 (сдвиг, добавление, стирание) и бит переносаE_01 .
E_10 может быть больше теперь снова, поэтому мы повторяем передачу E_20 .
В этот момент E_20должен стать ноль, иначе результат не будет соответствовать. В E_10результате переноса верхняя половина также пуста.
Последний шаг - перенести нижнюю половину E_20 в E_10снова.
Если ожидание, которое E=A*B+C*Dбудет соответствовать ожиданиям, у signed long long intнас теперь есть
E_20=0
E_10=0
E_00=E