std:: fma, std:: fmaf, std:: fmal
|
Definiert im Header
<cmath>
|
||
| (1) | ||
|
float
fma
(
float
x,
float
y,
float
z
)
;
double
fma
(
double
x,
double
y,
double
z
)
;
|
(seit C++11)
(bis C++23) |
|
|
constexpr
/* floating-point-type */
fma
(
/* floating-point-type */
x,
|
(seit C++23) | |
|
float
fmaf
(
float
x,
float
y,
float
z
)
;
|
(2) |
(seit C++11)
(constexpr seit C++23) |
|
long
double
fmal
(
long
double
x,
long
double
y,
long
double
z
)
;
|
(3) |
(seit C++11)
(constexpr seit C++23) |
|
#define FP_FAST_FMA /* implementation-defined */
|
(4) | (seit C++11) |
|
#define FP_FAST_FMAF /* implementation-defined */
|
(5) | (seit C++11) |
|
#define FP_FAST_FMAL /* implementation-defined */
|
(6) | (seit C++11) |
|
Definiert im Header
<cmath>
|
||
|
template
<
class
Arithmetic1,
class
Arithmetic2,
class
Arithmetic3
>
/* common-floating-point-type */
|
(A) |
(seit C++11)
(constexpr seit C++23) |
std::fma
für alle nicht-cv-qualifizierten Gleitkommatypen als Typ der Parameter
x
,
y
und
z
bereit.
(seit C++23)
std::fma
schneller aus (zusätzlich zur höheren Genauigkeit) als der Ausdruck
x
*
y
+
z
für
double
-,
float
- bzw.
long
double
-Argumente. Falls definiert, evaluieren diese Makros zum ganzzahligen Wert
1
.
Inhaltsverzeichnis |
Parameter
| x, y, z | - | Gleitkomma- oder Ganzzahlwerte |
Rückgabewert
Bei Erfolg wird der Wert von x * y + z zurückgegeben, als ob er mit unendlicher Genauigkeit berechnet und einmal gerundet wurde, um in den Ergebnistyp zu passen (oder alternativ als einzelner ternärer Gleitkommaoperation berechnet).
Wenn ein Bereichsfehler aufgrund von Überlaufs auftritt,
±HUGE_VAL
,
±HUGE_VALF
, oder
±HUGE_VALL
wird zurückgegeben.
Wenn ein Bereichsfehler aufgrund von Unterlauf auftritt, wird der korrekte Wert (nach Rundung) zurückgegeben.
Fehlerbehandlung
Fehler werden gemeldet, wie in math_errhandling spezifiziert.
Wenn die Implementierung IEEE-Gleitkommaarithmetik (IEC 60559) unterstützt,
-
Wenn
x
null ist und
y
unendlich ist oder wenn
x
unendlich ist und
y
null ist, und
- wenn z kein NaN ist, dann wird NaN zurückgegeben und FE_INVALID ausgelöst,
- wenn z ein NaN ist, dann wird NaN zurückgegeben und FE_INVALID kann ausgelöst werden.
- Wenn x * y ein exaktes Unendlich ist und z ein Unendlich mit entgegengesetztem Vorzeichen ist, wird NaN zurückgegeben und FE_INVALID ausgelöst.
- Wenn x oder y NaN sind, wird NaN zurückgegeben.
- Wenn z NaN ist, und x * y nicht 0 * Inf oder Inf * 0 ist, dann wird NaN zurückgegeben (ohne FE_INVALID ).
Hinweise
Diese Operation wird in der Hardware üblicherweise als fused multiply-add CPU-Befehl implementiert. Falls hardwareunterstützt, sollten die entsprechenden FP_FAST_FMA ? Makros definiert sein, jedoch nutzen viele Implementierungen den CPU-Befehl selbst dann, wenn die Makros nicht definiert sind.
POSIX
(
fma
,
fmaf
,
fmal
)
spezifiziert zusätzlich, dass die Situationen, die zur Rückgabe von
FE_INVALID
führen, Domänenfehler sind.
Aufgrund seiner unendlich genauen Zwischenpräzision ist
std::fma
ein häufig verwendeter Baustein für andere korrekt gerundete mathematische Operationen, wie
std::sqrt
oder sogar die Division (sofern nicht vom Prozessor bereitgestellt, z.B.
Itanium
).
Wie bei allen Fließkomma-Ausdrücken kann der Ausdruck x * y + z als fused multiply-add kompiliert werden, es sei denn, das #pragma STDC FP_CONTRACT ist deaktiviert.
Die zusätzlichen Überladungen müssen nicht exakt wie (A) bereitgestellt werden. Sie müssen lediglich sicherstellen, dass für ihr erstes Argument num1 , zweites Argument num2 und drittes Argument num3 :
|
(bis C++23) |
|
Wenn
num1
,
num2
und
num3
arithmetische Typen haben, dann hat
std
::
fma
(
num1, num2, num3
)
denselben Effekt wie
std
::
fma
(
static_cast
<
/*common-floating-point-type*/
>
(
num1
)
,
Wenn kein solcher Gleitkommatyp mit dem höchsten Rang und Unterrang existiert, dann führt die Überlagerungsauflösung nicht zu einem verwendbaren Kandidaten aus den bereitgestellten Überlagerungen. |
(seit C++23) |
Beispiel
#include <cfenv> #include <cmath> #include <iomanip> #include <iostream> #ifndef __GNUC__ #pragma STDC FENV_ACCESS ON #endif int main() { // demo the difference between fma and built-in operators 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 subtracted after intermediate rounding\n" << "fma(0.1, 10, -1) = " << std::setprecision(6) << fma_result << " (" << std::hexfloat << fma_result << std::defaultfloat << ")\n\n"; // fma is used in double-double arithmetic const double high = 0.1 * 10; const double low = std::fma(0.1, 10, -high); std::cout << "in double-double arithmetic, 0.1 * 10 is representable as " << high << " + " << low << "\n\n"; // error handling 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 raised\n"; }
Mögliche Ausgabe:
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
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
Siehe auch
|
(C++11)
(C++11)
(C++11)
|
Signierter Rest der Divisionsoperation
(Funktion) |
|
(C++11)
(C++11)
(C++11)
|
Signierter Rest sowie die drei letzten Bits der Divisionsoperation
(Funktion) |
|
C-Dokumentation
für
fma
|
|