Существует важное различие между 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
* * 1 028 * тогда +1029 *
fmax(Nan,x) = x
fmax(x,NaN) = x
fmin(Nan,x) = x
fmin(x,NaN) = x
fmax
можно эмулировать с помощью следующего кода
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);
}
Это показывает, что 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
.