Namespaces
Variants

std:: fma, std:: fmaf, std:: fmal

From cppreference.net
Common mathematical functions
Nearest integer floating point operations
(C++11)
(C++11)
(C++11) (C++11) (C++11)
Floating point manipulation functions
(C++11) (C++11)
(C++11)
(C++11)
Classification and comparison
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
Types
(C++11)
(C++11)
(C++11)
Macro constants
ヘッダーで定義 <cmath>
(1)
float fma ( float x, float y, float z ) ;

double fma ( double x, double y, double z ) ;

long double fma ( long double x, long double y, long double z ) ;
(C++11以降)
(C++23まで)
constexpr /* floating-point-type */

fma ( /* floating-point-type */ x,
/* floating-point-type */ y,

/* floating-point-type */ z ) ;
(C++23以降)
float fmaf ( float x, float y, float z ) ;
(2) (C++11以降)
(C++23以降constexpr)
long double fmal ( long double x, long double y, long double z ) ;
(3) (C++11以降)
(C++23以降constexpr)
#define FP_FAST_FMA  /* implementation-defined */
(4) (C++11以降)
#define FP_FAST_FMAF /* implementation-defined */
(5) (C++11以降)
#define FP_FAST_FMAL /* implementation-defined */
(6) (C++11以降)
ヘッダーで定義 <cmath>
template < class Arithmetic1, class Arithmetic2, class Arithmetic3 >

/* common-floating-point-type */

fma ( Arithmetic1 x, Arithmetic2 y, Arithmetic3 z ) ;
(A) (C++11以降)
(C++23以降constexpr)
1-3) 無限精度で計算したかのように x * y + z を計算し、結果型に合うように一度だけ丸める。 ライブラリは、 std::fma のオーバーロードを、パラメータ x y および z の型としてすべてのcv修飾されない浮動小数点型に対して提供する。 (C++23以降)
4-6) マクロ定数 FP_FAST_FMA FP_FAST_FMAF または FP_FAST_FMAL が定義されている場合、関数 std::fma は、それぞれ double float long double 引数に対して、式 x * y + z よりも(より正確であることに加えて)高速に評価されます。定義されている場合、これらのマクロは整数 1 に評価されます。
A) その他の算術型のすべての組み合わせに対して、追加のオーバーロードが提供されています。

目次

パラメータ

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 なし)

注記

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

POSIX ( fma , fmaf , fmal ) はさらに、 FE_INVALID を返すと規定されている状況が定義域エラーであることを追加で規定しています。

無限の中間精度を持つため、 std::fma は他の正しく丸められた数学演算、例えば std::sqrt や除算(CPUによって提供されない場合、例: Itanium )の共通の構成要素です。

すべての浮動小数点式と同様に、式 x * y + z は、 #pragma STDC FP_CONTRACT がオフでない限り、融合積和演算としてコンパイルされる可能性があります。

追加のオーバーロードは (A) と完全に同一である必要はありません。それらは、第一引数 num1 、第二引数 num2 および第三引数 num3 に対して以下を保証するのに十分なものであれば良いのです:

  • num1 num2 または num3 の型が long double の場合、 std :: fma ( num1, num2, num3 ) std :: fma ( static_cast < long double > ( num1 ) ,
    static_cast < long double > ( num2 ) ,
    static_cast < long double > ( num3 ) )
    と同じ効果を持つ。
  • それ以外の場合、 num1 num2 および/または num3 の型が double または整数型の場合、 std :: fma ( num1, num2, num3 ) std :: fma ( static_cast < double > ( num1 ) ,
    static_cast < double > ( num2 ) ,
    static_cast < double > ( num3 ) )
    と同じ効果を持つ。
  • それ以外の場合、 num1 num2 または num3 の型が float の場合、 std :: fma ( num1, num2, num3 ) std :: fma ( static_cast < float > ( num1 ) ,
    static_cast < float > ( num2 ) ,
    static_cast < float > ( num3 ) )
    と同じ効果を持つ。
(C++23まで)

num1 num2 および num3 が算術型を持つ場合、 std :: fma ( num1, num2, num3 ) std :: fma ( static_cast < /*common-floating-point-type*/ > ( num1 ) ,
static_cast < /*common-floating-point-type*/ > ( num2 ) ,
static_cast < /*common-floating-point-type*/ > ( num3 ) )
と同じ効果を持ちます。ここで /*common-floating-point-type*/ は、 num1 num2 および num3 の型の中で最も高い 浮動小数点変換ランク と最も高い 浮動小数点変換サブランク を持つ浮動小数点型です。整数型の引数は double と同じ浮動小数点変換ランクを持つものと見なされます。

最も高いランクとサブランクを持つ浮動小数点型が存在しない場合、 オーバーロード解決 は提供されたオーバーロードから使用可能な候補を生成しません。

(C++23以降)

#include <cfenv>
#include <cmath>
#include <iomanip>
#include <iostream>
#ifndef __GNUC__
#pragma STDC FENV_ACCESS ON
#endif
int main()
{
    // fmaと組み込み演算子の違いをデモンストレーション
    const 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";
    const double expr_result = 0.1 * 10 - 1;
    const double fma_result = std::fma(0.1, 10, -1);
    std::cout << "0.1 * 10 - 1 = " << expr_result
              << " : 中間丸め後に1を減算\n"
              << "fma(0.1, 10, -1) = " << std::setprecision(6) << fma_result << " ("
              << std::hexfloat << fma_result << std::defaultfloat << ")\n\n";
    // fmaは倍々精度演算で使用される
    const double high = 0.1 * 10;
    const double low = std::fma(0.1, 10, -high);
    std::cout << "倍々精度演算では、0.1 * 10 は "
              << high << " + " << low << " として表現可能\n\n";
    // エラー処理
    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 が発生\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を減算
fma(0.1, 10, -1) = 5.55112e-17 (0x1p-54)
倍々精度演算では、0.1 * 10 は 1 + 5.55112e-17 として表現可能
fma(+Inf, 10, -Inf) = -nan
    FE_INVALID が発生

関連項目

(C++11) (C++11) (C++11)
除算演算の符号付き剰余
(関数)
(C++11) (C++11) (C++11)
符号付き剰余および除算演算の下位3ビット
(関数)