fma, fmaf, fmal
|
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Definiert im Header
<math.h>
|
||
|
float
fmaf
(
float
x,
float
y,
float
z
)
;
|
(1) | (seit C99) |
|
double
fma
(
double
x,
double
y,
double
z
)
;
|
(2) | (seit C99) |
|
long
double
fmal
(
long
double
x,
long
double
y,
long
double
z
)
;
|
(3) | (seit C99) |
|
#define FP_FAST_FMA /* implementation-defined */
|
(4) | (seit C99) |
|
#define FP_FAST_FMAF /* implementation-defined */
|
(5) | (seit C99) |
|
#define FP_FAST_FMAL /* implementation-defined */
|
(6) | (seit C99) |
|
Definiert im Header
<tgmath.h>
|
||
|
#define fma( x, y, z )
|
(7) | (seit C99) |
FP_FAST_FMA
,
FP_FAST_FMAF
oder
FP_FAST_FMAL
definiert sind, wertet die entsprechende Funktion
fma
,
fmaf
oder
fmal
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 Integerwert
1
.
fmal
aufgerufen. Andernfalls, wenn ein Argument Ganzzahltyp oder den Typ
double
hat, wird
fma
aufgerufen. Andernfalls wird
fmaf
aufgerufen.
Inhaltsverzeichnis |
Parameter
| x, y, z | - | Gleitkommawerte |
Rückgabewert
Bei Erfolg wird der Wert von ( x * y ) + z zurückgegeben, als ob mit unendlicher Präzision berechnet und einmal gerundet, um in den Ergebnistyp zu passen (oder alternativ als einzelne ternäre Gleitkommaoperation berechnet).
Wenn ein Bereichsfehler aufgrund von Überlauf 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
festgelegt.
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, wird NaN zurückgegeben und FE_INVALID ausgelöst,
- wenn z ein NaN ist, 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, 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, wird erwartet, dass die entsprechenden FP_FAST_FMA * Makros definiert sind, jedoch nutzen viele Implementierungen den CPU-Befehl selbst dann, wenn die Makros nicht definiert sind.
POSIX legt fest , dass der Fall, in dem der Wert x * y ungültig ist und z ein NaN ist, ein Domänenfehler ist.
Aufgrund seiner unendlich genauen Zwischenpräzision ist
fma
ein häufig verwendeter Baustein für andere korrekt gerundete mathematische Operationen, wie
sqrt
oder sogar die Division (sofern nicht vom Prozessor bereitgestellt, z.B.
Itanium
).
Wie bei allen Gleitkomma-Ausdrücken kann der Ausdruck ( x * y ) + z als kombinierte Multiplikations-Addition kompiliert werden, es sei denn, #pragma STDC FP_CONTRACT ist deaktiviert.
Beispiel
#include <fenv.h> #include <float.h> #include <math.h> #include <stdio.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"); }
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 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
Referenzen
- C23-Standard (ISO/IEC 9899:2024):
-
- 7.12.13.1 Die fma-Funktionen (S.: TBD)
-
- 7.25 Typgenerische Mathematik <tgmath.h> (S.: TBD)
-
- F.10.10.1 Die fma-Funktionen (S.: TBD)
- C17-Standard (ISO/IEC 9899:2018):
-
- 7.12.13.1 The fma functions (S. 188-189)
-
- 7.25 Type-generic math <tgmath.h> (S. 272-273)
-
- F.10.10.1 The fma functions (S. 386)
- C11-Standard (ISO/IEC 9899:2011):
-
- 7.12.13.1 Die fma-Funktionen (S. 258)
-
- 7.25 Typgenerische Mathematik <tgmath.h> (S. 373-375)
-
- F.10.10.1 Die fma-Funktionen (S. 530)
- C99-Standard (ISO/IEC 9899:1999):
-
- 7.12.13.1 The fma functions (S. 239)
-
- 7.22 Type-generic math <tgmath.h> (S. 335-337)
-
- F.9.10.1 The fma functions (S. 466)
Siehe auch
|
(C99)
(C99)
(C99)
|
Berechnet den vorzeichenbehafteten Rest der Gleitkomma-Divisionsoperation
(Funktion) |
|
(C99)
(C99)
(C99)
|
Berechnet den vorzeichenbehafteten Rest sowie die letzten drei Bits der Divisionsoperation
(Funktion) |
|
C++-Dokumentation
für
fma
|
|