Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saturating subtract/add for unsigned bytes

Imagine I have two unsigned bytes b and x. I need to calculate bsub as b - x and badd as b + x. However, I don't want underflow/overflow occur during these operations. For example (pseudo-code):

b = 3; x = 5; bsub = b - x; // bsub must be 0, not 254 

and

b = 250; x = 10; badd = b + x; // badd must be 255, not 4 

The obvious way to do this includes branching:

bsub = b - min(b, x); badd = b + min(255 - b, x); 

I just wonder if there are any better ways to do this, i.e. by some hacky bit manipulations?

like image 483
ovk Avatar asked Nov 02 '15 15:11

ovk


People also ask

Can you do unsigned subtraction?

Subtracting two unsigned values of the same size will result in an unsigned value. If the first operand is less than the second the result will be arithmetically in correct.

What is saturated add?

Saturation arithmetic is a version of arithmetic in which all operations such as addition and multiplication are limited to a fixed range between a minimum and maximum value.

What is signed saturation?

(signed-saturate n x) coerces the integer x into an n -bit signed integer by signed saturation, then returns the result as an n -bit unsigned number.


1 Answers

The article Branchfree Saturating Arithmetic provides strategies for this:

Their addition solution is as follows:

u32b sat_addu32b(u32b x, u32b y) {     u32b res = x + y;     res |= -(res < x);      return res; } 

modified for uint8_t:

uint8_t  sat_addu8b(uint8_t x, uint8_t y) {     uint8_t res = x + y;     res |= -(res < x);      return res; } 

and their subtraction solution is:

u32b sat_subu32b(u32b x, u32b y) {     u32b res = x - y;     res &= -(res <= x);      return res; } 

modified for uint8_t:

uint8_t sat_subu8b(uint8_t x, uint8_t y) {     uint8_t res = x - y;     res &= -(res <= x);      return res; } 
like image 159
Shafik Yaghmour Avatar answered Oct 05 '22 23:10

Shafik Yaghmour