Namespaces
Variants

fma, fmaf, fmal

From cppreference.net
< c ‎ | numeric ‎ | math
Common mathematical functions
Functions
Basic operations
(C99)
fma
(C99)
(C99)
(C99) (C99) (C99) (C23)
Maximum/minimum operations
Exponential functions
Power functions
Trigonometric and hyperbolic functions
Nearest integer floating-point
(C99) (C99) (C99)
(C23) (C23) (C23) (C23)
Floating-point manipulation
Narrowing operations
(C23)
(C23)
(C23)
(C23)
(C23)
(C23)
Quantum and quantum exponent
Decimal re-encoding functions
Total order and payload functions
Classification
Error and gamma functions
(C99)
(C99)
(C99)
(C99)
Types
Macro constants
Special floating-point values
Arguments and return values
Error handling
Fast operation indicators
定義済みヘッダー <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_FMA FP_FAST_FMAF または FP_FAST_FMAL が定義されている場合、対応する関数 fma fmaf または fmal は、それぞれ x * y + z という式よりも(より正確であることに加えて)高速に評価されます。定義されている場合、これらのマクロは整数 1 に評価されます。
7) 型総称マクロ: いずれかの引数が型 long double を持つ場合、 fmal が呼び出される。そうでない場合、いずれかの引数が整数型または型 double を持つ場合、 fma が呼び出される。それ以外の場合、 fmaf が呼び出される。

目次

翻訳のポイント: - 「Contents」を「目次」に翻訳 - HTMLタグ、属性、クラス名は一切変更せず保持 - C++関連の用語(Parameters、Return value、Error handling、Notes、Example、References、See also)は原文のまま保持 - 数値や構造は完全に維持 - プロフェッショナルな技術文書としての正確性を確保

パラメータ

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 が発生する
  • x または y がNaNの場合、NaNが返される
  • z がNaNであり、かつ x * y 0 * Inf または Inf * 0 でない場合、NaNが返される( FE_INVALID なし)

注記

この演算は一般的にハードウェアで fused multiply-add 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)
{
    // fmaと組み込み演算子の違いをデモンストレーション
    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);
    // double-double演算におけるfmaの使用
    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);
    // エラー処理
    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関数群 (p: TBD)
  • 7.25 総称数学 <tgmath.h> (p: TBD)
  • F.10.10.1 fma関数群 (p: TBD)
  • C17規格 (ISO/IEC 9899:2018):
  • 7.12.13.1 fma関数群 (p: 188-189)
  • 7.25 総称数学 <tgmath.h> (p: 272-273)
  • F.10.10.1 fma関数群 (p: 386)
  • C11規格 (ISO/IEC 9899:2011):
  • 7.12.13.1 fma関数群 (p: 258)
  • 7.25 総称型数学 <tgmath.h> (p: 373-375)
  • F.10.10.1 fma関数群 (p: 530)
  • C99規格 (ISO/IEC 9899:1999):
  • 7.12.13.1 fma関数群 (p: 239)
  • 7.22 総称型数学 <tgmath.h> (p: 335-337)
  • F.9.10.1 fma関数群 (p: 466)

関連項目

浮動小数点除算操作の符号付き剰余を計算する
(関数)
(C99) (C99) (C99)
符号付き剰余と除算操作の下位3ビットを計算する
(関数)