名前空間
変種
操作

fma, fmaf, fmal

提供: cppreference.com
< c‎ | numeric‎ | math
 
 
 
一般的な数学関数
関数
基本操作
(C99)
fma
(C99)
(C99)
(C99)
(C99)
(C99)(C99)(C99)
指数関数
(C99)
(C99)
(C99)
(C99)
冪関数
(C99)
(C99)
三角関数と双曲線関数
(C99)
(C99)
(C99)
誤差関数とガンマ関数
(C99)
(C99)
(C99)
(C99)
最も近い整数
(C99)(C99)(C99)
(C99)
(C99)(C99)(C99)
浮動小数点操作関数
(C99)(C99)
(C99)
(C99)
分類
(C99)
(C99)
(C99)
(C99)(C99)
マクロ定数
FP_FAST_FMAFFP_FAST_FMAFP_FAST_FMAL
(C99)(C99)(C99)
 
ヘッダ <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_FMAF, FP_FAST_FMA または FP_FAST_FMAL が定義されている場合、対応する関数 fmaf, fma または fmal は、それぞれ float, double, long 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 が発生します。
  • x がゼロで y が無限大、または x が無限大で y がゼロで、かつ 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 は発生しません)。

[編集] ノート

この演算は一般的に融合積和演算 CPU 命令としてハードウェアで実装されています。 ハードウェアでサポートされている場合、適切な FP_FAST_FMA* マクロが定義されていることが期待されますが、多くの処理系では、マクロが定義されていなくても CPU 命令を使用します。

POSIX は FE_INVALID を返すと規定されている状況は定義域エラーであると規定しています

その無限の中間精度のため、 fma は sqrt や除算 (Itanium など CPU によって提供されない場合) のような、正確に丸める他の数学演算の共通のビルディングブロックになります。

すべての浮動小数点演算と同様に、 #pragma STDC FP_CONTRACT が OFF でなければ、式 (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 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

[編集] 参考文献

  • C11 standard (ISO/IEC 9899:2011):
  • 7.12.13.1 The fma functions (p: 258)
  • 7.25 Type-generic math <tgmath.h> (p: 373-375)
  • F.10.10.1 The fma functions (p: 530)
  • C99 standard (ISO/IEC 9899:1999):
  • 7.12.13.1 The fma functions (p: 239)
  • 7.22 Type-generic math <tgmath.h> (p: 335-337)
  • F.9.10.1 The fma functions (p: 466)

[編集] 関連項目

浮動小数点除算の符号付きの余りを計算します
(関数) [edit]
(C99)(C99)(C99)
除算の下位3ビットと符号付きの余りを計算します
(関数) [edit]