GCC的__builtin_isnan除了做isnan之外还做什么?

jtoj6r0c  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(151)

GCC built-ins description中,它说:
GCC提供了ISO C99浮点比较宏的内置版本,避免了对无序操作数引发异常。它们与标准宏具有相同的名称(isgreater,isgreaterequal,isless,islessequal,islessgreater,and isunordered),加上_builtin 前缀。我们希望库实现者能够简单地将每个标准宏定义为其内置等效宏。以同样的方式,GCC提供了fpclassify、isfinite、isinf_sign、isnormal和signbit内置函数,这些内置函数使用_builtin 前缀。isinf和isnan内置函数既可以使用_builtin 前缀,也可以不使用_builtin 前缀。
所以,我不太能解析这个。浮点数比较什么时候应该引发异常?C标准强制它们这样做吗?强制它们不这样做吗?没有强制任何东西吗?__builtin_isnan()的行为与isnan()不同吗?

jfgube3f

jfgube3f1#

这里的异常,GCC文档指的是IEEE 754浮点异常。

a < b

字符串
并且其中一个操作数是NaN,将引发FP异常(无效)。这意味着FPU中的一个位将保持设置状态,直到程序员显式清除它。通过使用isgreater/isless/etc。程序员可以避免触发FP异常。

nxowjjhe

nxowjjhe2#

GCC内置的标准库函数主要用于优化,当某些参数或环境约束可以在编译时知道时。
__builtin_isnan()的主要目的是允许在禁用NaN支持时将isnan(x)优化为(x != x)(即-fno-signaling-nans,默认值)。
isnan(x)(x != x)的行为并不相同。在评估信令NaN时存在差异。
(以上是问题的主要答案。以下是更多的技术细节。)
IEEE754(标准)定义了“安静”的NaN和“信令”的NaN,这可能是一个令人头痛的问题,让你彻底了解它们。(我是认真的。)
如果你是IEEE浮点运算及其比较运算的新手,这里有一些基础知识:

  • 有四种可能的结果用于比较两个IEEE 754浮点数的关系:“小于”、“等于”、“大于”和“无序”。当一个或两个操作数都是NaN时,会出现“无序”结果。这也意味着,例如,!(x > y)在浮点数中不等同于(x <= y)。(但是,!(x == y)(x != y)是等价的。)
  • IEEE 754定义了“安静”和“信令”比较操作,区别在于它们是否以及何时会生成浮点异常。

“安静”和“信号”术语是相对的,我把它们加在吓人的引号里,因为“安静”的比较并不总是安静的,而“信号”并不总是信号。
IEEE 754中的“安静”比较Map到C中的这些:(x == y)isgreaterisgreaterequalislessislessequalisunordered
IEEE 754中的“信令”比较Map到C中的这些:iseqsig(x > y)(x >= y)(x < y)(x <= y)。没有isunordered的“信令”变体,因为这没有意义。
对于“安静”比较,它们不会抛出带有安静NaN操作数的FP异常。* 但是 * 当任何操作数是一个信号NaN时,它们会抛出“无效操作”(FE_INVALID)异常。
对于“信号”比较,当任何一个操作数是NaN时,不管它的信号位是多少,它们都会抛出异常(也就是说,它们也会在安静的NaN上抛出异常)。
还有一些函数,即使存在NaN信号,也不会抛出异常。fpclassify函数,包括isnan,就是这种类型。(这些也是IEEE 754中的标准操作,尽管不同的语言为这些提供了不同的API。)
this Stack Overflow answer about isnan() and (x != x)中,我做了一个快速比较表:

| isnan(x) | (x != x)  | (x >= x)   | isgreaterequal(x,x)
--------------+----------+-----------+------------+--------------------
-Wfloat-equal | no warn  | warn      | no warn    | no warn
--------------+----------+-----------+------------+--------------------
Finite number | false    | false     | true       | true
Infinity      | false    | false     | true       | true
NaN (quiet)   | true     | true      | FPE; false | false
SNaN          | true     | FPE; true | FPE; false | FPE; false

字符串

  • 备注:表中的truefalse分别指宏的非零和0返回值(它们的返回类型是int,而不是bool)。“FPE”表示宏或表达式产生“无效操作”异常。*

因此,您可以了解isnan!=>=isgreaterequal在不同类型的浮点值上的行为。

相关问题