这个问题是关于Apple libm C数学库中sin函数的实现,可用here. 主罪功能从line 736开始. 简而言之:当x足够小,以至于距离sin(x)最近的浮点数只有x时,为什么该函数要执行其结果从未被使用的浮点相乘,然后返回x,而不是立即返回x

该功能根据输入x的幅度xk使用不同的方法.我感兴趣的情况是,当xk足够小时,与sin(x)最近的浮点数只是xlines 809-829. 我猜在这种情况下,该函数只会执行return x. 它的作用如下:

/*  Make t0 volatile to force compiler to fetch it at run-time
    rather than optimizing away the multiplication.
*/
static volatile const double t0 = 1/3.;

/*  Get t0 once.  If we wrote "t0*t0", the compiler would load it
    twice, since it is volatile.
*/
const double t1 = t0;

/*  Perform a multiplication and pass it into an assembly construct to
    prevent the compiler from knowing we do not use the result and
    optimizing away the multiplication.
*/
__asm__("" : : "X" (t1*t1));

// Return the floating-point number nearest sine(x), which is x.
return x;

因此,它创建了一个新的静态volatile const double t0等于1/3.,另一个具有相同值的const double t1,以一种声称编译器无法优化的方式将t1乘以本身..然后返回x.Why does it do this, instead of just returning 104 at the start?

推荐答案

.为什么该函数要执行一个结果从未被使用的浮点相乘然后返回x.

浮点乘运算有两个输出.一个是浮点寄存器中的数值,另一个是浮点状态位中的更新标志.在您询问的代码中,x太小了,以至于与sin x最近的可表示值是x,因此它将是函数的返回值.然而,x的sin并不完全是x,因此我们希望升起不精确标志.将1/3.乘以本身即可实现这一目标.

您会在803行的return x * (1 - 0x1p-53);中注意到类似的护理.此时,已知x处于次正常范围(它说"非正常",但"次正常"更合适),因此由于四舍五入,x * (1 - 0x1p-53)x具有相同的值.但如果x不为零,它也会引发不精确标志.(而且零的sin是精确的,所以当x为零时,最好不要升起不精确标志.)

C++相关问答推荐

librsvg rsvg_handle_get_dimensions获取像素大小与浏览器中的渲染大小没有不同

如何通过Zephyr(Devicetree)在PR Pico上设置UTE 1?

为什么在C中设置文件的位置并写入文件,填充空字符?

当main函数调用被重构时,C函数给出错误的结果

单指针和空参数列表之间的函数指针兼容性

由Go调用E.C.引起的内存快速增长

为什么可以通过指向常量int的指针间接地改变整数的值?

为什么net/if.h在ifaddrs.h之前?

Clang:如何强制运行时错误的崩溃/异常由于-fsanitize=undefined

为静态库做准备中的奇怪行为

文件权限为0666,但即使以超级用户身份也无法打开

在句子中转换单词的问题

为什么双精度d=flt_max+flt_max;在c语言中得到inf的结果

编译器如何处理具有更复杂值的枚举?

致命错误:ASM/rwan ce.h:没有这样的文件或目录.符号链接还不够

如何在c中使用具有不同变量类型的内存分配?

正在try 理解C++中的`正在释放的指针未被分配‘错误

问题:C#Define上的初始值设定项元素不是常量

如何正确探测平台设备?

Zig 中 C 的system函数的惯用替代方案