Podczas gdy jeden signed long long int
nie wytrzyma A*B
, dwóch z nich to zrobi. A*B
Można więc rozłożyć na trzy wyrażenia o różnych wykładnikach, z których każdy pasuje do jednego 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;
To samo dotyczy C*D
.
Idąc prostą drogą, można było dokonać subrakcji na każdej parze AB_i
i CD_i
podobnie, używając dodatkowego bitu przenoszenia (dokładnie 1-bitowej liczby całkowitej) dla każdej. Więc jeśli powiemy E = A * BC * D, otrzymasz coś takiego:
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
...
Kontynuujemy, przenosząc górną połowę E_10
do E_20
(przesuń o 32 i dodaj, a następnie usuń górną połowę E_10
).
Teraz możesz pozbyć się bitu przenoszonego E_11
, dodając go z odpowiednim znakiem (uzyskanym z części nienoszonej) do E_20
. Jeśli spowoduje to przepełnienie, wynik również nie będzie pasował.
E_10
teraz ma wystarczająco dużo miejsca, aby wziąć górną połowę z E_00
(przesuń, dodaj, wymaż) i przenoszoną część E_01
.
E_10
może być teraz ponownie większy, więc powtarzamy transfer do E_20
.
W tym momencie E_20
musi wynosić zero, w przeciwnym razie wynik nie będzie pasował. W górnej połowieE_10
jest również pusta w wyniku przeniesienia.
Ostatnim krokiem jest ponowne przeniesienie dolnej połowy E_20
do E_10
.
Jeśli oczekiwanie, E=A*B+C*D
które pasowałoby do signed long long int
blokad, mamy teraz
E_20=0
E_10=0
E_00=E