名稱空間
變體
操作

fma、fmaf、fmal

來自 cppreference.com
< c‎ | 數值‎ | 數學
 
 
 
常用數學函式
函式
基本操作
(C99)
fma
(C99)
(C99)
(C99)(C99)(C99)(C23)
最大值/最小值操作
(C99)
(C99)
指數函式
(C23)
(C99)
(C99)
(C23)
(C23)

(C99)
(C99)(C23)
(C23)
(C23)
冪函式
(C99)
(C23)
(C23)

(C99)
(C23)
(C23)
三角函式和雙曲函式
(C23)
(C23)
(C23)
(C23)
(C99)
(C99)
(C99)
最近整數浮點數
(C99)(C99)(C99)
(C99)

(C99)(C99)(C99)
(C23)(C23)(C23)(C23)
浮點數操作
(C99)(C99)
(C99)(C23)
(C99)
窄化操作
(C23)
(C23)
(C23)
(C23)
(C23)
(C23)
量子與量子指數
十進位制重新編碼函式
總序和載荷函式
分類
(C99)
(C99)
(C99)
(C23)
誤差函式和伽馬函式
(C99)
(C99)
(C99)
(C99)
型別
宏常量
特殊浮點值
(C99)(C23)
引數和返回值
錯誤處理
快速操作指示符
 
定義於標頭檔案 <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 起)
定義於標頭檔案 <tgmath.h>
#define fma( x, y, z )
(7) (C99 起)
1-3) 計算 (x * y) + z,如同以無限精度計算並僅舍入一次以適應結果型別。
4-6) 如果宏常量 FP_FAST_FMAFP_FAST_FMAFFP_FAST_FMAL 已定義,則對應的函式 fmafmaffmal 對於 doublefloatlong double 引數(分別為)的求值速度比表示式 x * y + z 更快(且更精確)。如果已定義,這些宏將求值為整數 1
7) 型別通用宏:如果任何引數具有 long double 型別,則呼叫 fmal。否則,如果任何引數具有整數型別或 double 型別,則呼叫 fma。否則,呼叫 fmaf

目錄

[編輯] 引數

x、y、z - 浮點值

[編輯] 返回值

如果成功,返回 (x * y) + z 的值,如同以無限精度計算並舍入一次以適應結果型別(或者,作為單個三元浮點運算計算)。

若發生因溢位導致的範圍錯誤,則返回 ±HUGE_VAL±HUGE_VALF±HUGE_VALL

如果發生下溢導致的範圍錯誤,返回正確的值(舍入後)。

[編輯] 錯誤處理

錯誤按 math_errhandling 中指定的方式報告。

如果實現支援 IEEE 浮點運算 (IEC 60559),

  • 如果 x 為零且 y 為無窮大,或者 x 為無窮大且 y 為零,並且
    • 如果 z 不是 NaN,則返回 NaN 並引發 FE_INVALID
    • 如果 z 是 NaN,則返回 NaN 並可能引發 FE_INVALID
  • 如果 x * y 是精確的無窮大且 z 是符號相反的無窮大,則返回 NaN 並引發 FE_INVALID
  • 如果 xy 是 NaN,則返回 NaN。
  • 如果 z 是 NaN,且 x * y 不是 0 * InfInf * 0,則返回 NaN(不引發 FE_INVALID)。

[編輯] 注意

此操作通常在硬體中實現為 融合乘加 CPU 指令。如果硬體支援,則預計會定義相應的 FP_FAST_FMA* 宏,但即使未定義宏,許多實現也使用 CPU 指令。

POSIX 規定,當值 x * y 無效且 z 是 NaN 的情況為域錯誤。

由於其無限中間精度,fma 是其他正確舍入的數學運算(如 sqrt 甚至除法(如果 CPU 不提供,例如 Itanium))的常見構建塊。

與所有浮點表示式一樣,表示式 (x * y) + z 可能會被編譯為融合乘加,除非 #pragma STDC FP_CONTRACT 已關閉。

[編輯] 示例

#include <fenv.h>
#include <float.h>
#include <math.h>
#include <stdio.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 double
0.1 * 10 - 1 = 0 : 1 subtracted after intermediate rounding to 1.0
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

[編輯] 參考

  • C23 標準 (ISO/IEC 9899:2024)
  • 7.12.13.1 fma 函式(頁碼:待定)
  • 7.25 型別通用數學 <tgmath.h> (p: TBD)
  • F.10.10.1 fma 函式(頁碼:待定)
  • C17 標準 (ISO/IEC 9899:2018)
  • 7.12.13.1 fma 函式(頁碼:188-189)
  • 7.25 型別通用數學 <tgmath.h> (p: 272-273)
  • F.10.10.1 fma 函式(頁碼:386)
  • C11 標準 (ISO/IEC 9899:2011)
  • 7.12.13.1 fma 函式(頁碼:258)
  • 7.25 型別通用數學 <tgmath.h> (p: 373-375)
  • F.10.10.1 fma 函式(頁碼:530)
  • C99 標準 (ISO/IEC 9899:1999)
  • 7.12.13.1 fma 函式(頁碼:239)
  • 7.22 型別通用數學 <tgmath.h> (p: 335-337)
  • F.9.10.1 fma 函式(頁碼:466)

[編輯] 另請參閱

計算浮點除法運算的帶符號餘數
(函式) [編輯]
(C99)(C99)(C99)
計算帶符號餘數以及除法運算的最後三位
(函式) [編輯]
C++ 文件 適用於 fma