【发布时间】:2019-04-04 05:53:07
【问题描述】:
我正在阅读 IEEE-754 数学函数在 glibc 中的实现。
这是floor 的实现。
float
__floorf(float x)
{
int32_t i0,j0;
uint32_t i;
GET_FLOAT_WORD(i0,x);
j0 = ((i0>>23)&0xff)-0x7f;
if(j0<23) {
if(j0<0) {
/* return 0*sign(x) if |x|<1 */
if(i0>=0) {i0=0;}
else if((i0&0x7fffffff)!=0)
{ i0=0xbf800000;}
} else {
i = (0x007fffff)>>j0;
if((i0&i)==0) return x; /* x is integral */
if(i0<0) i0 += (0x00800000)>>j0;
i0 &= (~i);
}
} else {
if(__builtin_expect(j0==0x80, 0)) return x+x; /* inf or NaN */
else return x; /* x is integral */
}
SET_FLOAT_WORD(x,i0);
return x;
}
有趣的部分是if(__builtin_expect(j0==0x80, 0)) return x+x; /* inf or NaN */。
为什么当x 是inf 或NaN 时返回x+x?
为什么不直接返回x?
编辑
我从https://github.com/lattera/glibc/blob/895ef79e04a953cac1493863bcae29ad85657ee1/sysdeps/ieee754/flt-32/s_floorf.c 得到我的代码,并假设它是来自 glibc 的 fork。
【问题讨论】:
-
代码的格式看起来不是 GNUish。你确定它来自glibc?你应该ask the author of that code,我通过谷歌搜索
"float __floorf"找到了他。 -
您应该在您的问题中添加您搜索答案的链接。知道此代码来自 1993 年的 SUN 可能有助于最终回答这个问题。
-
对标准不是很熟悉,但 IIRC NaN 可以发出或不发出信号,也许这是为了处理这个问题。从@RolandIllig 的结果进一步搜索,commit adding similar code 到 glibc 说:“地板的 alpha 版本错误地为 sNaN 输入返回 sNaN。通过检查 NaN 并在这种情况下返回与自身相加的输入值来解决这个问题。”跨度>
-
@muru:是的,我认为是设置 FP 异常标志,例如
ceil需要在无限输入上设置或引发溢出,或者在 NaN 输入上无效。 -
是的,inf 和 NaN 会保持不变,但可能会出现一些副作用,至少对于发出 NaN 信号:浮点异常。