Есть важное различие между 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)
{
// 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 вызывает их из математической библиотеки. Сборка для clang для 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
.
person
Z boson
schedule
18.06.2015