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?
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.
The min() function in C++ accepts two values and returns the smaller one. This function is available in <algorithm. h> .
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With