Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I write a 'clamp' / 'clip' / 'bound' macro for returning a value in a given range?

I often find myself writing something like

int computedValue = ...;
return MAX(0, MIN(5, computedValue));

I would like to be able to write this as a single one-line macro. It must be free of side effects, in the same way that the existing system macros MIN and MAX are, and should work for the same data types as MIN and MAX.

Can anyone show me how to turn this into a single macro?

like image 553
hfossli Avatar asked Feb 08 '13 09:02

hfossli


1 Answers

This is without side effects and works for any primitive number:

#define MIN(A,B)    ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __a : __b; })
#define MAX(A,B)    ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __b : __a; })

#define CLAMP(x, low, high) ({\
  __typeof__(x) __x = (x); \
  __typeof__(low) __low = (low);\
  __typeof__(high) __high = (high);\
  __x > __high ? __high : (__x < __low ? __low : __x);\
  })

Can be used like so

int clampedInt = CLAMP(computedValue, 3, 7);
double clampedDouble = CLAMP(computedValue, 0.5, 1.0);

Other suggested names instead of CLAMP can be VALUE_CONSTRAINED_LOW_HIGH, BOUNDS, CLIPPED.

like image 114
hfossli Avatar answered Oct 12 '22 23:10

hfossli