std:: fma, std:: fmaf, std:: fmal
|
ヘッダーで定義
<cmath>
|
||
| (1) | ||
|
float
fma
(
float
x,
float
y,
float
z
)
;
double
fma
(
double
x,
double
y,
double
z
)
;
|
(C++11以降)
(C++23まで) |
|
|
constexpr
/* floating-point-type */
fma
(
/* floating-point-type */
x,
|
(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 */
|
(A) |
(C++11以降)
(C++23以降constexpr) |
std::fma
のオーバーロードを、パラメータ
x
、
y
および
z
の型としてすべてのcv修飾されない浮動小数点型に対して提供する。
(C++23以降)
std::fma
は、それぞれ
double
、
float
、
long
double
引数に対して、式
x
*
y
+
z
よりも(より正確であることに加えて)高速に評価されます。定義されている場合、これらのマクロは整数
1
に評価されます。
目次 |
パラメータ
| 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 に対して以下を保証するのに十分なものであれば良いのです:
|
(C++23まで) |
|
num1
、
num2
および
num3
が算術型を持つ場合、
std
::
fma
(
num1, num2, num3
)
は
std
::
fma
(
static_cast
<
/*common-floating-point-type*/
>
(
num1
)
,
最も高いランクとサブランクを持つ浮動小数点型が存在しない場合、 オーバーロード解決 は提供されたオーバーロードから使用可能な候補を生成しません。 |
(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ビット
(関数) |
|
Cドキュメント
for
fma
|
|