Існує важлива різниця між std::min, std::maxі fminта fmax.
std::min(-0.0,0.0) = -0.0
std::max(-0.0,0.0) = -0.0
тоді як
fmin(-0.0, 0.0) = -0.0
fmax(-0.0, 0.0) = 0.0
Тож std::minне є заміною 1-1 fmin. Функції std::minі std::maxне є комутативними. Для того, щоб отримати той же результат з двійниками з fminі fmaxодин повинен поміняти місцями аргументи
fmin(-0.0, 0.0) = std::min(-0.0, 0.0)
fmax(-0.0, 0.0) = std::max( 0.0, -0.0)
Але, наскільки я можу зрозуміти, усі ці функції в даному випадку визначені в будь-якому випадку, щоб бути на 100% впевненим, що ви повинні перевірити, як вони реалізовані.
Є ще одна важлива різниця. Для x ! = NaN:
std::max(Nan,x) = NaN
std::max(x,NaN) = x
std::min(Nan,x) = NaN
std::min(x,NaN) = x
тоді як
fmax(Nan,x) = x
fmax(x,NaN) = x
fmin(Nan,x) = x
fmin(x,NaN) = x
fmax можна емулювати за допомогою наступного коду
double myfmax(double x, double y)
{
int xnan = isnan(x), ynan = isnan(y);
if(xnan || ynan) {
if(xnan && !ynan) return y;
if(!xnan && ynan) return x;
return x;
}
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);
}
Це показує, що std::maxце підмножина fmax.
Перегляд збірки показує, що Clang використовує вбудований код, fmaxа fminтоді як GCC викликає їх із математичної бібліотеки. Збірка для клакання для fmaxз -O3є
movapd xmm2, xmm0
cmpunordsd xmm2, xmm2
movapd xmm3, xmm2
andpd xmm3, xmm1
maxsd xmm1, xmm0
andnpd xmm2, xmm1
orpd xmm2, xmm3
movapd xmm0, xmm2
тоді як для std::max(double, double)цього просто
maxsd xmm0, xmm1
Однак для GCC та Clang використання -Ofast fmaxстає просто
maxsd xmm0, xmm1
Отже, це ще раз показує, що std::maxце підмножина, fmaxі що коли ви використовуєте більш вільну модель із плаваючою комою, яка тоді не має nanабо не підписана нулем, fmaxі std::maxвони однакові. Очевидно, той самий аргумент стосується fminі std::min.