ein*_*ica 6 c++ floating-point fma
浮点表达式有时可以在处理硬件上收缩,例如使用融合乘法和加法作为单个硬件操作.
显然,使用这些不仅仅是一个实现细节,而是由编程语言规范控制.具体来说,C89标准不允许这样的收缩,而在C99中,只要定义了某些宏,就允许它们.请参阅此SO答案中的详细信息.
但是C++怎么样?浮点收缩是不允许的?某些标准允许吗?普遍允许吗?
允许收缩,但为用户提供了禁用收缩的设施。标准云中的语言不清楚禁用它们是否会提供预期结果的问题。
\n\n我在官方 C++ 2003 标准和 2017 年 n4659 草案中对此进行了调查。除非另有说明,C++ 引文均来自 2003 年。
\n\n文本 \xe2\x80\x9ccontract\xe2\x80\x9d 未出现在这两个文档中。然而,第 5 条表达式 [expr] 第 10 段(2017\xe2\x80\x99s 8 [expr] 13 中的相同文本)表示:
\n\n\n\n\n浮点操作数的值和浮点表达式的结果可以用比类型所要求的更高的精度和范围来表示;类型不会因此改变。
\n
我更喜欢这个声明明确说明是否可以自由使用这个额外的精度和范围(实现可以在某些表达式中使用它,包括子表达式,而在其他表达式中不使用它)或者必须统一使用(如果实现使用额外的精度) ,它必须在每个浮点表达式中使用它)或根据一些其他规则(例如它可以使用一种精度用于float,另一种精度用于double)。
如果我们宽容地解释它,则意味着,a*b+c可以a*b以无限的精度和范围来计算,然后可以以实现正常的任何精度和范围来计算加法。这在数学上相当于收缩,因为它a*b+c与使用融合乘加指令求值具有相同的结果。
因此,通过这种解释,实现可以收缩表达式。
\n\n17.4.1.2 [lib.headers] 3(2017\xe2\x80\x99s 20.5.1.2 [headers] 3中的类似文本)说:
\n\n\n\n\n标准 C 库的功能由 18 个附加头文件提供,如表 12\xe2\x80\xa6 所示
\n
表 12 包括<cmath>,第 4 段表示这对应于math.h。从技术上讲,C++ 2003标准指的是C 1990标准,但我没有电子形式,也不知道我的纸质副本在哪里,所以我将使用C 2011标准(但非官方草案N1570),C++ 2017年草案参考。
C 标准在 中定义了<math.h>一个 pragma FP_CONTRACT:
#pragma STDC FP_CONTRACT on-off-switch\nRun Code Online (Sandbox Code Playgroud)\n\n其中on-off-switch是on允许或off禁止表达式的收缩。它还表示编译指示的默认状态是实现定义的。
C++ 标准未定义 \xe2\x80\x9cfacility\xe2\x80\x9d 或 \xe2\x80\x9cfacilities。\xe2\x80\x9d \xe2\x80\x9cfacility\xe2\x80\x9d 的字典定义为 \ xe2\x80\x9ca 为特定目的而提供的场所、便利设施或设备\xe2\x80\x9d(新牛津美国词典、Apple 词典应用程序版本 2.2.2 (203))。设施是 \xe2\x80\x9ca 建筑物或场所的理想或有用的功能或设施。\xe2\x80\x9d 编译指示是为特定目的提供的有用功能,因此它似乎是设施,因此它是包括在<cmath>。
因此,使用这个编译指示应该允许或禁止收缩。
\n\n启用时允许收缩FP_CONTRACT,并且默认情况下可能会启用。
8 [expr] 13 的文本可以被解释为有效地允许收缩,即使是FP_CONTRACT关闭的,但对于最终解释来说还不够清晰。