C – Saturating Signed Integer Multiplication with Bitwise Operators

bit-manipulationcmultiplicationsaturation-arithmetic

Alright, so the assignment I have to do is to multiply a signed integer by 2 and return the value. If the value overflows then saturate it by returning Tmin or Tmax instead. The challenge is using only these logical operators (! ~ & ^ | + << >>) with no (if statements, loops, etc.) and only allowed a maximum of 20 logical operators.

Now my thought process to tackle this problem was first to find the limits. So I divided Tmin/max by 2 to get the boundaries. Here's what I have:

Positive

This and higher works:

1100000...

This and lower doesn't:

1011111...

If it doesn't work I need to return this:

100000...

Negative

This and lower works:

0011111...

This and higher doesn't:

0100000...

If it doesn't work I need to return this:

011111...

Otherwise I have to return:

2 * x;

(the integers are 32-bit by the way)

I see that the first two bits are important in determining whether or not the problem should return 2*x or the limits. For example an XOR would do since if the first to bits are the same then 2*x should be returned otherwise the limits should be returned. Another if statement is then needed for the sign of the integer for it is negative Tmin needs to be returned, otherwise Tmax needs to be.

Now my question is, how do you do this without using if statements? xD Or a better question is the way I am planning this out going to work or even feasible under the constraints? Or even better question is whether there is an easier way to solve this, and if so how? Any help would be greatly appreciated!

Best Answer

a = (x>>31); // fills the integer with the sign bit 
b = (x<<1) >> 31; // fills the integer with the MSB 
x <<= 1; // multiplies by 2
x ^= (a^b)&(x^b^0x80000000); // saturate

So how does this work. The first two lines use the arithmetic right shift to fill the whole integer with a selected bit.

The last line is basically the "if statement". If a==b then the right hand side evaluates to 0 and none of the bits in x are flipped. Otherwise it must be the case that a==~b and the right hand side evaluates to x^b^0x80000000. After the statement is applied x will equal x^x^b^0x80000000 => b^0x80000000 which is exactly the saturation value.

Edit:

Here is it in the context of an actual program.

#include<stdio.h>
main(){
    int i = 0xFFFF;
    while(i<<=1){
        int a = i >> 31;
        int b = (i << 1) >> 31;
        int x = i << 1;
        x ^= (a^b) & (x ^ b ^ 0x80000000);
        printf("%d, %d\n", i, x);
    }
}
Related Topic