在线文档教程
C++
数字 | Numerics

std::fma

性病:FMA

Defined in header
float fma( float x, float y, float z (1)(since C++11)
double fma( double x, double y, double z (2)(since C++11)
long double fma( long double x, long double y, long double z (3)(since C++11)
Promoted fma( Arithmetic1 x, Arithmetic2 y, Arithmetic3 z (4)(since C++11)
#define FP_FAST_FMA /* implementation-defined */(5)(since C++11)
#define FP_FAST_FMAF /* implementation-defined */(6)(since C++11)
#define FP_FAST_FMAL /* implementation-defined */(7)(since C++11)

1-3%29次计算(x*y) + z好像要达到无限的精度,并且只舍入一次,以适应结果类型。

的所有参数组合的一组重载或函数模板算术类型不包括在1-3%29。如果有任何争论积分型,它被铸造成double.如果任何其他论点是long double,则返回类型为long double,否则就是double...

5-7%29如果宏常量FP_FAST_FMAF,,,FP_FAST_FMA,或FP_FAST_FMAL定义的函数std::fma除了比表达式更精确的%29之外,计算速度更快的%28x*y+zfloat,,,double,和long double分别争论。如果定义了这些宏,则这些宏将计算为整数。1...

参数

x, y, z-values of floating-point or integral types

返回值

如果成功,则返回(x*y) + z似乎计算到无限精度,并舍入一次以适应结果类型%28,或者,或者,计算为单个三元浮点操作%29。

如果溢出导致范围错误,±HUGE_VAL,,,±HUGE_VALF,或±HUGE_VALL会被归还。

如果由于下流发生范围错误,则返回舍入%29后的正确值%28。

错误处理

错误按数学[医]错误处理...

如果实现支持ieee浮点算法%28IEC 60559%29,

  • 如果x是零,y是无限的,或者x是无穷的,y是零,而z不是NaN,则NaN返回FE_INVALID提出来

  • 如果x是零,y是无穷的,或者x是无穷的,y是零,z是NaN,则NaN返回FE_INVALID可能被提高

  • 如果x%2Ay是一个精确的无穷大,z是带相反符号的无穷大,NaN返回,FE_INVALID提出来

  • 如果x或y为nan,则返回nan。

  • 如果z是nan,则x%2Ay=%27T0%2Ainf或inf%2A0,则NaN返回%28而不使用FE。[医]无效%29

注记

此操作通常在硬件中实现,如融合相加CPU指令。如果硬件支持,则适当的FP_FAST_FMA*宏是需要定义的,但是即使没有定义宏,许多实现也会使用CPU指令。

POSIX额外指定指定返回的情况FE_INVALID是域错误。

由于其无限的中间精度,fma是其他正确四舍五入的数学操作的一个常见的构建块,例如std::sqrt甚至分割%28,在CPU不提供的地方,例如Itanium%29。

与所有浮点表达式一样,表达式(x*y) + z可以编译为一个融合的乘法添加,除非#语用STDC FP_CONTRACT已经关机了。

二次

#include <iostream> #include <iomanip> #include <cmath> #include <cfenv> #pragma STDC FENV_ACCESS ON int main() { // demo the difference between fma and built-in operators double in = 0.1; std::cout << "0.1 double is " << std::setprecision(23) << in << " (" << std::hexfloat << in << std::defaultfloat << ")\n" << "0.1*10 is 1.0000000000000000555112 (0x8.0000000000002p-3), " << "or 1.0 if rounded to double\n"; double expr_result = 0.1 * 10 - 1; double fma_result = fma(0.1, 10, -1 std::cout << "0.1 * 10 - 1 = " << expr_result << " : 1 subtracted after intermediate rounding\n" << "fma(0.1, 10, -1) = " << std::setprecision(6) << fma_result << " (" << std::hexfloat << fma_result << std::defaultfloat << ")\n\n"; // fma is used in double-double arithmetic double high = 0.1 * 10; double low = fma(0.1, 10, -high std::cout << "in double-double arithmetic, 0.1 * 10 is representable as " << high << " + " << low << "\n\n"; // error handling std::feclearexcept(FE_ALL_EXCEPT std::cout << "fma(+Inf, 10, -Inf) = " << std::fma(INFINITY, 10, -INFINITY) << '\n'; if(std::fetestexcept(FE_INVALID)) std::cout << " FE_INVALID raised\n"; }

二次

可能的产出:

二次

0.1 double is 0.10000000000000000555112 (0x1.999999999999ap-4) 0.1*10 is 1.0000000000000000555112 (0x8.0000000000002p-3), or 1.0 if rounded to double 0.1 * 10 - 1 = 0 : 1 subtracted after intermediate rounding fma(0.1, 10, -1) = 5.55112e-17 (0x1p-54) in double-double arithmetic, 0.1 * 10 is representable as 1 + 5.55112e-17 fma(+Inf, 10, -Inf) = -nan FE_INVALID raised

二次

另见

remainder (C++11)signed remainder of the division operation (function)
remquo (C++11)signed remainder as well as the three last bits of the division operation (function)

c FMA文件

© cppreference.com

在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。

http://en.cppreference.com/w/cpp/数值/数学/fma