Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fastest way to clamp a real (fixed/floating point) value?

Is there a more efficient way to clamp real numbers than using if statements or ternary operators? I want to do this both for doubles and for a 32-bit fixpoint implementation (16.16). I'm not asking for code that can handle both cases; they will be handled in separate functions.

Obviously, I can do something like:

double clampedA; double a = calculate(); clampedA = a > MY_MAX ? MY_MAX : a; clampedA = a < MY_MIN ? MY_MIN : a; 

or

double a = calculate(); double clampedA = a; if(clampedA > MY_MAX)     clampedA = MY_MAX; else if(clampedA < MY_MIN)     clampedA = MY_MIN; 

The fixpoint version would use functions/macros for comparisons.

This is done in a performance-critical part of the code, so I'm looking for an as efficient way to do it as possible (which I suspect would involve bit-manipulation)

EDIT: It has to be standard/portable C, platform-specific functionality is not of any interest here. Also, MY_MIN and MY_MAX are the same type as the value I want clamped (doubles in the examples above).

like image 390
Niklas Avatar asked Jan 09 '09 09:01

Niklas


People also ask

How do you clamp integer so that it remains in range?

Suppose we wanted to limit an integer to stay within some arbitrary range, like 0-50. This can be easily achieved by testing the current value with an if statement and assigning the maximum or minimum value accordingly.

What does mathf clamp do?

Description. Clamps the given value between the given minimum float and maximum float values. Returns the given value if it is within the minimum and maximum range. Returns the minimum value if the given float value is less than the minimum.

How do you clamp an integer in C++?

std::clamp in C++ 17 Clamps a variable to a given range[high – low]. If num > high, num is assigned high. If num < low, num is assigned low. If num is already clamped, no modifications.

What is AC clamp used for?

A C-clamp or G-clamp or G-cramp is a type of clamp device typically used to hold a wood or metal workpiece, and often used in, but are not limited to, carpentry and welding.


1 Answers

Both GCC and clang generate beautiful assembly for the following simple, straightforward, portable code:

double clamp(double d, double min, double max) {   const double t = d < min ? min : d;   return t > max ? max : t; } 

> gcc -O3 -march=native -Wall -Wextra -Wc++-compat -S -fverbose-asm clamp_ternary_operator.c

GCC-generated assembly:

maxsd   %xmm0, %xmm1    # d, min movapd  %xmm2, %xmm0    # max, max minsd   %xmm1, %xmm0    # min, max ret 

> clang -O3 -march=native -Wall -Wextra -Wc++-compat -S -fverbose-asm clamp_ternary_operator.c

Clang-generated assembly:

maxsd   %xmm0, %xmm1 minsd   %xmm1, %xmm2 movaps  %xmm2, %xmm0 ret 

Three instructions (not counting the ret), no branches. Excellent.

This was tested with GCC 4.7 and clang 3.2 on Ubuntu 13.04 with a Core i3 M 350. On a side note, the straightforward C++ code calling std::min and std::max generated the same assembly.

This is for doubles. And for int, both GCC and clang generate assembly with five instructions (not counting the ret) and no branches. Also excellent.

I don't currently use fixed-point, so I will not give an opinion on fixed-point.

like image 68
Jorge Avatar answered Sep 19 '22 03:09

Jorge