I'm trying to find a way to catch overflow/underflow accurately when multiplying two signed binary numbers (a
and b
) of n
arbitrary bits in an efficient manner. I'm using 2's complement.
Is there a way to do so during execution of the booth's algorithm? If so, how?
Things that I considered but can't use:
GCC's built-in overflow detection: as my use case deals with arbitrary bit lengths which may or may not be castable to base signed integer types.
Post-multiplication check using division: I don't want to be using division afterwards to check result
r
withr / b == a
. That would be too computationally expensive.Traditional multiplication by adding: Too computationally inefficient.
To make it a little clearer on how I've approached Booth's algo here the step-by-step on a couple of examples using n=8bits big-endian to keep things readable.
The 'booth' bit is added to the register on the right and an extra bit to handle the negative integer limit case is added on the left.
so the register structure is:
x q
|.|.... ....|.... ....|.|
where x
= extra bit and q
the "booth" bit. So the total size ends up as 8+8+2 bits.
e.g.1:
a: 0000 0101 (5)
b: 1111 1101 (-3)
m: 0|0000 0101|0000 0000|0 (a)
-m: 0|1111 1011|0000 0000|0 (negated a)
register: 0|0000 0000|1111 1101|0 (initialized register with b)
step 1 (p+=-m): 0|1111 1011|1111 1101|0
step 1 (shift): 0|0111 1101|1111 1110|1
step 2 (p+=+m): 0|1000 0010|1111 1110|1
step 2 (shift): 0|0100 0001|0111 1111|0
step 3 (p+=-m): 1|0011 1100|0111 1111|0
step 3 (shift): 0|1001 1110|0011 1111|1
step 4 (shift): 0|0100 1111|0001 1111|1
step 5 (shift): 0|0010 0111|1000 1111|1
step 6 (shift): 0|0001 0011|1100 0111|1
step 7 (shift): 0|0000 1001|1110 0011|1
step 8 (shift): 0|0000 0100|1111 0001|1
result: .|.... ....|1111 0001|. = -15 //Cool
e.g.2:
a: 0011 1111 (63)
b: 1111 1101 (-3)
m: 0|0011 1111|0000 0000|0 (a)
-m: 0|1100 0001|0000 0000|0 (negated a)
register: 0|0000 0000|1111|1101|0 (initialized register with b)
step 1 (p+=-m): 0|1100 0001|1111 1101|0
step 1 (shift): 0|0110 0000|1111 1110|1
step 2 (p+=+m): 0|1001 1111|1111 1110|1
step 2 (shift): 0|0100 1111|1111 1111|0
step 3 (p+=-m): 1|0001 0000|1111 1111|0
step 3 (shift): 0|1000 1000|0111 1111|1
step 4 (shift): 0|0100 0100|0011 1111|1
step 5 (shift): 0|0010 0010|0001 1111|1
step 6 (shift): 0|0001 0001|0000 1111|1
step 7 (shift): 0|0000 1000|1000 0111|1
step 8 (shift): 0|0000 0100|0100 0011|1
result: .|.... ....|0100 0011|. = 35 //Wrong! underflow.
Thanks.