Пока 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