C++ 使用SSE内部函数时如何确保NAN传播?

C++ 使用SSE内部函数时如何确保NAN传播?,c++,c,floating-point,sse,nan,C++,C,Floating Point,Sse,Nan,我最近读到这篇关于SSE算术运算中的NaN值的文章: 作用于两个非数字(NAN)参数的算术运算结果未定义。因此,使用NAN参数的浮点操作将与相应汇编指令的预期行为不匹配 资料来源: 这是否意味着,例如,添加两个\uuum128值可能会将NaN转换为实数 如果计算依赖于NaN值,我需要最终结果也是NaN。有什么方法可以做到这一点吗?当我解释该文本时,它所说的是编译器提供了各种与SSE指令大致对应的内部函数。通常,您可以预期编译器将使用SSE指令来实现内部函数。然而,这并不严格。本质实际上指定了一些

我最近读到这篇关于SSE算术运算中的
NaN
值的文章:

作用于两个非数字(NAN)参数的算术运算结果未定义。因此,使用NAN参数的浮点操作将与相应汇编指令的预期行为不匹配

资料来源:

这是否意味着,例如,添加两个
\uuum128
值可能会将
NaN
转换为实数


如果计算依赖于
NaN
值,我需要最终结果也是
NaN
。有什么方法可以做到这一点吗?

当我解释该文本时,它所说的是编译器提供了各种与SSE指令大致对应的内部函数。通常,您可以预期编译器将使用SSE指令来实现内部函数。然而,这并不严格。本质实际上指定了一些抽象计算模型中的操作;它们不直接指定SSE指令。在该抽象模型中,对两个NaN进行操作的结果(奇怪的是,它似乎不允许一个NaN和一个数字)是未定义的。因此,例如,通过添加两个NaN得到的结果可能不是NaN

特别是,抽象模型中的操作将受到编译器优化的影响,这些优化可能会导致SSE指令以外的事情(编译时的计算,如果编译器可以推断存在NAN,则省略指令,这样就不需要实际执行add等)

看起来,如果您想保证为SSE指令指定的语义,您可能必须用汇编语言编写,而不是在Microsoft的编译器中使用内部函数


我真希望供应商不要再对浮点语义漠不关心。在没有明确规定的行为的情况下,很难进行工程设计。

@Mysticial:忽略那些说结果不能保证的文档是不明智的。@EricPostChil我不想暗示这里是这样的,但MSDN文档以前就知道有错误。(因此,即使是官方文件,我也总是持保留态度。)所以我一点也不会感到惊讶,因为写这段代码的人对这个主题的了解可能比我们少。@EricPostphil好吧,看。由于你显然没有其他建设性的话要说,我将以最后一点评论结束。我不轻易质疑官方文件。但当我这么做的时候,那是因为我有充分的理由这么做。考虑到我在编译器、SSE内部函数/指令方面的知识和经验,以及它们的实现方式,我可以说,关于NaNs的这句引用的话相当牵强(不是不可能,而是牵强)。也许它只适用于非常特殊的情况——在这种情况下,他们应该澄清这些问题,而不是让我们去猜测我们大多数人都认为是“安全”的情况use@EricPostpischil当然,结果不能保证;你最后一次看到没有提供“任何形式的无担保”的软件是什么时候?EricPostphil你真的在获得动力,不是吗?你在这次讨论中的反应更能说明你的性格,而不是你声称的年龄。有一种相对温和的可能性。它可能总是生成一个NaN,但不一定以任何一致的方式与输入NaN关联。如果是这种情况,将其记录下来会很有帮助。这听起来似乎只有当编译器能够证明两个值为
NaN
并且编译器有充分的理由利用它时,才会出现问题,伊姆霍:前者似乎不太可能,而后者很难想出一个……的例子@PatriciaShanahan:那似乎很可能。指令返回两个输入N中的哪一个通常取决于操作数顺序,编译器可能无法保持从内部函数到指令的顺序。这将导致需要记录返回的两个NAN中的哪一个未定义,如果处理不当,可能会导致记录表明在两个NAN上操作的结果未定义。尽管如此,文档还是这么说的。我觉得奇怪的是,许多语言不允许在没有显式强制转换的情况下将
double
转换为
float
,而是会在内部将内容提升为
double
,然后进行强制转换。如果我在设计一种语言,我会有“IEEE single”和“IEEE double”类型,它们的语义将完全按照IEEE标准执行,还有其他32位和64位浮点类型,它们的语义更有用(例如,让
==
在编译的情况下实现等价关系,使用32位类型计算f1=(f2+f3+f4)`使用64位中间结果,等等)