Mentre un signed long long int
non regge A*B
, due lo faranno. Quindi A*B
potrebbe essere scomposto in termini dell'albero di esponente diverso, ognuno dei quali si adatta a uno 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;
Lo stesso per C*D
.
Seguendo la strada diritta, la sottrazione potrebbe essere fatta per ogni coppia di AB_i
e CD_i
allo stesso modo, usando un bit di carry aggiuntivo (esattamente un numero intero di 1 bit) per ciascuno. Quindi se diciamo E = A * BC * D ottieni qualcosa del tipo:
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
...
Continuiamo trasferendo la metà superiore di E_10
a E_20
(sposta di 32 e aggiungi, quindi cancella la metà superiore di E_10
).
Ora puoi eliminare il bit di riporto E_11
aggiungendolo con il segno giusto (ottenuto dalla parte non riporto) a E_20
. Se questo innesca un overflow, il risultato non si adatterebbe neanche.
E_10
ora ha abbastanza 'spazio' per prelevare la metà superiore da E_00
(sposta, aggiungi, cancella) e il bit di trasporto E_01
.
E_10
potrebbe essere di nuovo più grande, quindi ripetiamo il trasferimento a E_20
.
A questo punto, E_20
deve diventare zero, altrimenti il risultato non si adatta. La metà superiore diE_10
è vuota a seguito del trasferimento.
Il passo finale è quello di trasferire la metà inferiore E_20
in E_10
nuovamente.
Se l'aspettativa che E=A*B+C*D
si adatterebbe alle signed long long int
prese, ora abbiamo
E_20=0
E_10=0
E_00=E