我担心以下情况
min(-0.0,0.0)
max(-0.0,0.0)
minmag(-x,x)
maxmag(-x,x)
根据维基百科 IEEE 754-2008说的是关于最小值和最大值
定义了最小和最大操作,但为输入值相等但表示不同的情况留有一些余地。尤其:
min(+0,−0) 或 min(−0,+0) 必须生成值为零的值,但可能始终返回第一个参数。
我做了一些测试比较fmin
, fmax
, 最小值和最大值定义如下
#define max(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
#define min(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
and _mm_min_ps
and _mm_max_ps
哪个叫上交所minps
and maxps
操作说明。
这是结果(我用来测试的代码发布在下面)
fmin(-0.0,0.0) = -0.0
fmax(-0.0,0.0) = 0.0
min(-0.0,0.0) = 0.0
max(-0.0,0.0) = 0.0
_mm_min_ps(-0.0,0.0) = 0.0
_mm_max_ps(-0.0,0.0) = -0.0
正如您所看到的,每种情况都会返回不同的结果。所以我的主要问题是 C 和 C++ 标准库说什么? Does fmin(-0.0,0.0)
必须等于-0.0
and fmax(-0.0,0.0)
必须等于0.0
或者不同的实现允许以不同的方式定义它?如果它是实现定义的,这是否意味着为了确保代码与 C 标准库的不同实现(例如来自不同编译器)兼容,必须进行检查以确定它们如何实现 min 和 max?
关于什么minmag(-x,x)
and maxmag(-x,x)
?这些均在 IEEE 754-2008 中定义。这些实现至少在 IEEE 754-2008 中定义吗?我从 Wikipdia 对 min 和 max 的评论推断,这些是实现定义的。但据我所知C标准库并没有定义这些函数。在OpenCL 这些函数定义为
maxmag 返回 x 如果 | x| > |y|,或 y 如果 |y| > |x|,否则为 fmax(x, y)。
minmag 返回 x 如果 |x|
x86 指令集没有 minmag 和 maxmag 指令,所以我不得不实施它们。但就我而言,我需要性能,并且在大小相等时为情况创建分支效率不高。
Itaninum 指令集有 minmag 和 maxmag 指令(famin
and famax
)并且在这种情况下据我所知(通过阅读)在这种情况下它返回第二个参数。那不是什么minps
and maxps
不过似乎正在做。奇怪的是_mm_min_ps(-0.0,0.0) = 0.0
and _mm_max_ps(-0.0,0.0) = -0.0
。我希望他们要么在这两种情况下返回第一个参数,要么返回第二个参数。为什么是minps
and maxps
指令是这样定义的吗?
#include <stdio.h>
#include <x86intrin.h>
#include <math.h>
#define max(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
#define min(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
int main(void) {
float a[4] = {-0.0, -1.0, -2.0, -3.0};
float b[4] = {0.0, 1.0, 2.0, 3.0};
__m128 a4 = _mm_load_ps(a);
__m128 b4 = _mm_load_ps(b);
__m128 c4 = _mm_min_ps(a4,b4);
__m128 d4 = _mm_max_ps(a4,b4);
{ float c[4]; _mm_store_ps(c,c4); printf("%f %f %f %f\n", c[0], c[1], c[2], c[3]); }
{ float c[4]; _mm_store_ps(c,d4); printf("%f %f %f %f\n", c[0], c[1], c[2], c[3]); }
printf("%f %f %f %f\n", fmin(a[0],b[0]), fmin(a[1],b[1]), fmin(a[2],b[2]), fmin(a[3],b[3]));
printf("%f %f %f %f\n", fmax(a[0],b[0]), fmax(a[1],b[1]), fmax(a[2],b[2]), fmax(a[3],b[3]));
printf("%f %f %f %f\n", min(a[0],b[0]), min(a[1],b[1]), min(a[2],b[2]), min(a[3],b[3]));
printf("%f %f %f %f\n", max(a[0],b[0]), max(a[1],b[1]), max(a[2],b[2]), max(a[3],b[3]));
}
//_mm_min_ps: 0.000000, -1.000000, -2.000000, -3.000000
//_mm_max_ps: -0.000000, 1.000000, 2.000000, 3.000000
//fmin: -0.000000, -1.000000, -2.000000, -3.000000
//fmax: 0.000000, 1.000000, 2.000000, 3.000000
//min: 0.000000, -1.000000, -2.000000, -3.000000
//max: 0.000000, 1.000000, 2.000000, 3.000000
Edit:
关于C++我测试过std::min(-0.0,0.0)
and std::max(-0.0,0.0)
两者都返回-0.0
。这表明std::min
不等于fmin
and std::max
不等于fmax
.