?
This document uses PHP Chinese website manual Release
在頭文件<math.h>中定義 | ||
---|---|---|
float fmaf( float x, float y, float z ); | (1) | (自C99) |
double fma( double x, double y, double z ); | (2) | (自 C99) |
long double fmal( long double x, long double y, long double z ); | (3) | (自 C99) |
#define FP_FAST_FMA /* implementation-defined */ | (4) | (自C99) |
#define FP_FAST_FMAF /* implementation-defined */ | (5) | (自C99) |
#define FP_FAST_FMAL /* implementation-defined */ | (6) | (自C99) |
Defined in header <tgmath.h> | ||
#define fma( x, y, z ) | (7) | (自C99) |
1-3)計算(x * y)+ z,就像無限精度一樣,只舍入一次以適應結(jié)果類型。
4-6)如果定義了宏常量FP_FAST_FMAF,F(xiàn)P_FAST_FMA或FP_FAST_FMAL,則相應函數(shù)fmaf,fma或fmal的計算速度(除了更精確之外)的計算結(jié)果要高于float,double和x * y + z的表達式 長雙重論點,分別。 如果定義,這些宏評估為整數(shù)1。
7)類型泛型宏:如果任何參數(shù)的類型為long double,則調(diào)用fmal。 否則,如果任何參數(shù)具有整數(shù)類型或類型為double,則調(diào)用fma。 否則,調(diào)用fmaf。
x, y, z | - | floating point values |
---|
如果成功,則返回(x * y)+ z的值,如同計算為無限精度一樣,并舍入一次以適合結(jié)果類型(或者,也可以計算為單個三元浮點運算)。
如果發(fā)生由溢出引起的范圍錯誤,則返回±HUGE_VAL,±HUGE_VALF或±HUGE_VALL。
如果發(fā)生由于下溢導致的范圍錯誤,則返回正確的值(舍入后)。
按照math_errhandling中的指定報告錯誤。
如果實現(xiàn)支持IEEE浮點運算(IEC 60559),
如果x是零并且y是無限的或者如果x是無限的并且y是零并且z不是NaN,則返回NaN并且引發(fā)FE_INVALID
如果x是零并且y是無限的或者如果x是無限的并且y是零并且z是NaN,則返回NaN并且可以提升FE_INVALID
如果x * y是一個精確的無窮大而z是一個具有相反符號的無窮大,則返回NaN并且引發(fā)FE_INVALID
如果x或y是NaN,則返回NaN
如果z是NaN,并且x * y不是0 * Inf或Inf * 0,則返回NaN(不含F(xiàn)E_INVALID)
這種操作通常以硬件實現(xiàn)為融合乘加CPU指令。 如果硬件支持,則應該定義適當?shù)腇P_FAST_FMA *宏,但是即使未定義宏,許多實現(xiàn)也會使用CPU指令。
POSIX指定值x * y無效且z是NaN的情況是域錯誤。
由于其無限的中間精度,fma是其他正確舍入的數(shù)學運算的常見構(gòu)建模塊,例如sqrt或甚至除CPU之外的分區(qū)(例如Itanium)。
與所有浮點表達式一樣,除非#pragma STDC FP_CONTRACT處于關(guān)閉狀態(tài),否則表達式(x * y)+ z可能會編譯為已融合的多重加法。
#include <stdio.h>#include <math.h>#include <float.h>#include <fenv.h>#pragma STDC FENV_ACCESS ON int main(void){ // demo the difference between fma and built-in operators double in = 0.1; printf("0.1 double is %.23f (%a)\n", in, in); printf("0.1*10 is 1.0000000000000000555112 (0x8.0000000000002p-3)," " or 1.0 if rounded to double\n"); double expr_result = 0.1 * 10 - 1; printf("0.1 * 10 - 1 = %g : 1 subtracted after " "intermediate rounding to 1.0\n", expr_result); double fma_result = fma(0.1, 10, -1); printf("fma(0.1, 10, -1) = %g (%a)\n", fma_result, fma_result); // fma use in double-double arithmetic printf("\nin double-double arithmetic, 0.1 * 10 is representable as "); double high = 0.1 * 10; double low = fma(0.1, 10, -high); printf("%g + %g\n\n", high, low); //error handling feclearexcept(FE_ALL_EXCEPT); printf("fma(+Inf, 10, -Inf) = %f\n", fma(INFINITY, 10, -INFINITY)); if(fetestexcept(FE_INVALID)) puts(" FE_INVALID raised");}
可能的輸出:
0.1 double is 0.10000000000000000555112 (0x1.999999999999ap-4)0.1*10 is 1.0000000000000000555112 (0x8.0000000000002p-3), or 1.0 if rounded to double0.1 * 10 - 1 = 0 : 1 subtracted after intermediate rounding to 1.0fma(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
C11標準(ISO / IEC 9899:2011):
7.12.13.1 fma函數(shù)(p:258)
7.25類型通用數(shù)學<tgmath.h>(p:373-375)
F.10.10.1 fma函數(shù)(p:530)
C99標準(ISO / IEC 9899:1999):
7.12.13.1 fma函數(shù)(p:239)
7.22類型通用數(shù)學<tgmath.h>(p:335-337)
F.9.10.1 fma函數(shù)(p:466)
remainderremainderfremainderl (C99)(C99)(C99) | 計算浮點除法運算的有符號余數(shù)(函數(shù)) |
---|---|
remquoremquofremquol(C99)(C99)(C99) | 計算帶符號的余數(shù)以及除法操作(函數(shù))的最后三位 |
| fma的C ++文檔 |