[c++] Use of min and max functions in C++

From C++, are min and max preferable over fmin and fmax? For comparing two integers, do they provide basically the same functionality?

Do you tend to use one of these sets of functions or do you prefer to write your own (perhaps to improve efficiency, portability, flexibility, etc.)?

Notes:

  1. The C++ Standard Template Library (STL) declares the min and max functions in the standard C++ algorithm header.

  2. The C standard (C99) provides the fmin and fmax function in the standard C math.h header.

Thanks in advance!

This question is related to c++ c max min

The answer is


You're missing the entire point of fmin and fmax. It was included in C99 so that modern CPUs could use their native (read SSE) instructions for floating point min and max and avoid a test and branch (and thus a possibly mis-predicted branch). I've re-written code that used std::min and std::max to use SSE intrinsics for min and max in inner loops instead and the speed-up was significant.


If your implementation provides a 64-bit integer type, you may get a different (incorrect) answer by using fmin or fmax. Your 64-bit integers will be converted to doubles, which will (at least usually) have a significand that's smaller than 64-bits. When you convert such a number to a double, some of the least significant bits can/will be lost completely.

This means that two numbers that were really different could end up equal when converted to double -- and the result will be that incorrect number, that's not necessarily equal to either of the original inputs.


fmin and fmax, of fminl and fmaxl could be preferred when comparing signed and unsigned integers - you can take advantage of the fact that the entire range of signed and unsigned numbers and you don't have to worry about integer ranges and promotions.

unsigned int x = 4000000000;
int y = -1;

int z = min(x, y);
z = (int)fmin(x, y);

By the way, in cstdlib there are __min and __max you can use.

For more: http://msdn.microsoft.com/zh-cn/library/btkhtd8d.aspx


Use std::min and std::max.

If the other versions are faster then your implementation can add overloads for these and you'll get the benefit of performance and portability:

template <typename T>
T min (T, T) {
  // ... default
}

inline float min (float f1, float f2) {
 return fmin( f1, f2);
}    

I always use the min and max macros for ints. I'm not sure why anyone would use fmin or fmax for integer values.

The big gotcha with min and max is that they're not functions, even if they look like them. If you do something like:

min (10, BigExpensiveFunctionCall())

That function call may get called twice depending on the implementation of the macro. As such, its best practice in my org to never call min or max with things that aren't a literal or variable.


fmin and fmax are only for floating point and double variables.

min and max are template functions that allow comparison of any types, given a binary predicate. They can also be used with other algorithms to provide complex functionality.


I would prefer the C++ min/max functions, if you are using C++, because they are type-specific. fmin/fmax will force everything to be converted to/from floating point.

Also, the C++ min/max functions will work with user-defined types as long as you have defined operator< for those types.

HTH


std::min and std::max are templates. So, they can be used on a variety of types that provide the less than operator, including floats, doubles, long doubles. So, if you wanted to write generic C++ code you'd do something like this:

template<typename T>
T const& max3(T const& a, T const& b, T const& c)
{
   using std::max;
   return max(max(a,b),c); // non-qualified max allows ADL
}

As for performance, I don't think fmin and fmax differ from their C++ counterparts.


There is an important difference between std::min, std::max and fmin and fmax.

std::min(-0.0,0.0) = -0.0
std::max(-0.0,0.0) = -0.0

whereas

fmin(-0.0, 0.0) = -0.0
fmax(-0.0, 0.0) =  0.0

So std::min is not a 1-1 substitute for fmin. The functions std::min and std::max are not commutative. To get the same result with doubles with fmin and fmax one should swap the arguments

fmin(-0.0, 0.0) = std::min(-0.0,  0.0)
fmax(-0.0, 0.0) = std::max( 0.0, -0.0)

But as far as I can tell all these functions are implementation defined anyway in this case so to be 100% sure you have to test how they are implemented.


There is another important difference. For x ! = NaN:

std::max(Nan,x) = NaN
std::max(x,NaN) = x
std::min(Nan,x) = NaN
std::min(x,NaN) = x

whereas

fmax(Nan,x) = x
fmax(x,NaN) = x
fmin(Nan,x) = x
fmin(x,NaN) = x

fmax can be emulated with the following code

double myfmax(double x, double y)
{
   // z > nan for z != nan is required by C the standard
   int xnan = isnan(x), ynan = isnan(y);
   if(xnan || ynan) {
        if(xnan && !ynan) return y;
        if(!xnan && ynan) return x;
        return x;
   }
   // +0 > -0 is preferred by C the standard 
   if(x==0 && y==0) {
       int xs = signbit(x), ys = signbit(y);
       if(xs && !ys) return y;
       if(!xs && ys) return x;
       return x;
   }
   return std::max(x,y);
}

This shows that std::max is a subset of fmax.

Looking at the assembly shows that Clang uses builtin code for fmax and fmin whereas GCC calls them from a math library. The assembly for clang for fmax with -O3 is

movapd  xmm2, xmm0
cmpunordsd      xmm2, xmm2
movapd  xmm3, xmm2
andpd   xmm3, xmm1
maxsd   xmm1, xmm0
andnpd  xmm2, xmm1
orpd    xmm2, xmm3
movapd  xmm0, xmm2

whereas for std::max(double, double) it is simply

maxsd   xmm0, xmm1

However, for GCC and Clang using -Ofast fmax becomes simply

maxsd   xmm0, xmm1

So this shows once again that std::max is a subset of fmax and that when you use a looser floating point model which does not have nan or signed zero then fmax and std::max are the same. The same argument obviously applies to fmin and std::min.


As Richard Corden pointed, use C++ functions min and max defined in std namespace. They provide type safety, and help to avoid comparing mixed types (i.e. float point vs integer) what sometimes may be undesirable.

If you find that C++ library you use defines min/max as macros as well, it may cause conflicts, then you can prevent unwanted macro substitution calling the min/max functions this way (notice extra brackets):

(std::min)(x, y)
(std::max)(x, y)

Remember, this will effectively disable Argument Dependant Lookup (ADL, also called Koenig lookup), in case you want to rely on ADL.


Couldn't a C++ implementation targeted for processors with SSE instructions provide specializations of std::min and std::max for types float, double, and long double which do the equivalent of fminf, fmin, and fminl, respectively?

The specializations would provide better performance for floating-point types while the general template would handle non-floating-point types without attempting to coerce floating-point types into floating-point types that way the fmins and fmaxes would.


As you noted yourself, fmin and fmax were introduced in C99. Standard C++ library doesn't have fmin and fmax functions. Until C99 standard library gets incorporated into C++ (if ever), the application areas of these functions are cleanly separated. There's no situation where you might have to "prefer" one over the other.

You just use templated std::min/std::max in C++, and use whatever is available in C.


Examples related to c++

Method Call Chaining; returning a pointer vs a reference? How can I tell if an algorithm is efficient? Difference between opening a file in binary vs text How can compare-and-swap be used for a wait-free mutual exclusion for any shared data structure? Install Qt on Ubuntu #include errors detected in vscode Cannot open include file: 'stdio.h' - Visual Studio Community 2017 - C++ Error How to fix the error "Windows SDK version 8.1" was not found? Visual Studio 2017 errors on standard headers How do I check if a Key is pressed on C++

Examples related to c

conflicting types for 'outchar' Can't compile C program on a Mac after upgrade to Mojave Program to find largest and second largest number in array Prime numbers between 1 to 100 in C Programming Language In c, in bool, true == 1 and false == 0? How I can print to stderr in C? Visual Studio Code includePath "error: assignment to expression with array type error" when I assign a struct field (C) Compiling an application for use in highly radioactive environments How can you print multiple variables inside a string using printf?

Examples related to max

Min and max value of input in angular4 application numpy max vs amax vs maximum mongodb how to get max value from collections Python find min max and average of a list (array) Max length UITextField How to find the highest value of a column in a data frame in R? MAX function in where clause mysql Check if all values in list are greater than a certain number How do I get the max and min values from a set of numbers entered? SQL: Group by minimum value in one field while selecting distinct rows

Examples related to min

Min and max value of input in angular4 application Python find min max and average of a list (array) How do I get the max and min values from a set of numbers entered? SQL: Group by minimum value in one field while selecting distinct rows How to exclude 0 from MIN formula Excel Using std::max_element on a vector<double> How can I get the max (or min) value in a vector? Most efficient way to find smallest of 3 numbers Java? Find the smallest amongst 3 numbers in C++ Obtain smallest value from array in Javascript?