Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C++, is it better to cap a value using std::min or an if branch?

Tags:

A very common pattern in programming is to cap a value at a maximum after some kind of update. What I'd like to know, is if there's a difference between the following two pieces of code, and if one should be preferred:

value += increment; value = std::min(value, valueMax); 

vs

value += increment;  if (value > valueMax)     value = valueMax; 

My thinking is that this comes down to whether CPUs have instructions for taking two values and producing the minumum. If so, the call to std::min should result in this instruction and avoid an unnecessary branch. If not, the second version avoids an unnecessary assignment when value <= valueMax.

I'm not very good with this kind of thing, but I'm sure there's old-school assembly hackers who would know this. To them I ask: which is better?

like image 673
voltrevo Avatar asked Mar 21 '13 05:03

voltrevo


People also ask

Is there a min and max function in C++?

The C++ Standard Template Library (STL) declares the min and max functions in the standard C++ algorithm header. The C standard (C99) provides the fmin and fmax function in the standard C math.

Does C++ have a MIN function?

The min() function in C++ accepts two values and returns the smaller one. This function is available in <algorithm. h> .


2 Answers

Modern compilers are smart enough to generate the same code in both cases. For example, 32-bit GCC generates:

addl    %esi, %edi cmpl    %edx, %edi movl    %edi, %eax cmovgl  %edx, %eax 

64-bit Clang:

%1 = add nsw i32 %increment, %value %2 = icmp sgt i32 %1, %valueMax %value = select i1 %2, i32 %valueMax, i32 %1 
like image 60
grep Avatar answered Oct 19 '22 09:10

grep


On VC10 on Release for the following code we have the following assembly:

int main(int argc, char *argv[]) {    int dummyValue = 0, valueMax = 3000, value = valueMax + 1;    cin >> valueMax;   cin >> value;    dummyValue = std::min(value, valueMax);    cout << dummyValue;   cin >> valueMax;   cin >> value;    if (value > valueMax)     dummyValue = valueMax;    cout << dummyValue;   return 0; } 

Generated:

  24:   dummyValue = std::min(value, valueMax); 00E112AF  mov         eax,dword ptr [valueMax]   00E112B2  cmp         eax,dword ptr [value]   00E112B5  lea         edx,[value]   00E112B8  lea         ecx,[valueMax]   00E112BB  cmovge      ecx,edx     // <-- this is our conditional assignment 00E112BE  mov         esi,dword ptr [ecx]   

and

if (value > valueMax)   dummyValue = valueMax 00E112ED  mov         eax,dword ptr [valueMax]   00E112F0  cmp         dword ptr [value],eax   00E112F3  mov         ecx,dword ptr ds:[0E13038h]   00E112F9  cmovg       esi,eax   

So both cases optimized to either cmovge or cmovg instructions.

I would still go with std::min because it shows intent better than an if statement. It's optimized away and it's more readable.

like image 39
Ed Rowlett-Barbu Avatar answered Oct 19 '22 10:10

Ed Rowlett-Barbu