|
|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Defined in header <math.h> | ||
float fmaf(float x,float y,float z); | (1) | (since C99) |
double fma(double x,double y,double z); | (2) | (since C99) |
longdouble fmal(longdouble x,longdouble y,longdouble z); | (3) | (since C99) |
#define FP_FAST_FMA /* implementation-defined */ | (4) | (since C99) |
#define FP_FAST_FMAF /* implementation-defined */ | (5) | (since C99) |
#define FP_FAST_FMAL /* implementation-defined */ | (6) | (since C99) |
Defined in header <tgmath.h> | ||
#define fma( x, y, z ) | (7) | (since C99) |
FP_FAST_FMA,FP_FAST_FMAF, orFP_FAST_FMAL are defined, the corresponding functionfma,fmaf, orfmal evaluates faster (in addition to being more precise) than the expressionx* y+ z fordouble,float, andlongdouble arguments, respectively. If defined, these macros evaluate to integer1.fmal is called. Otherwise, if any argument has integer type or has typedouble,fma is called. Otherwise,fmaf is called.Contents |
| x, y, z | - | floating-point values |
If successful, returns the value of(x* y)+ z as if calculated to infinite precision and rounded once to fit the result type (or, alternatively, calculated as a single ternary floating-point operation).
If a range error due to overflow occurs,±HUGE_VAL,±HUGE_VALF, or±HUGE_VALL is returned.
If a range error due to underflow occurs, the correct value (after rounding) is returned.
Errors are reported as specified inmath_errhandling.
If the implementation supports IEEE floating-point arithmetic (IEC 60559),
This operation is commonly implemented in hardware asfused multiply-add CPU instruction. If supported by hardware, the appropriateFP_FAST_FMA* macros are expected to be defined, but many implementations make use of the CPU instruction even when the macros are not defined.
POSIX specifies that the situation where the valuex* y is invalid andz is a NaN is a domain error.
Due to its infinite intermediate precision,fma is a common building block of other correctly-rounded mathematical operations, such assqrt or even the division (where not provided by the CPU, e.g.Itanium).
As with all floating-point expressions, the expression(x* y)+ z may be compiled as a fused mutiply-add unless the#pragmaSTDC FP_CONTRACT is off.
#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 operatorsdouble 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 arithmeticprintf("\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 handlingfeclearexcept(FE_ALL_EXCEPT);printf("fma(+Inf, 10, -Inf) = %f\n", fma(INFINITY,10,-INFINITY));if(fetestexcept(FE_INVALID))puts(" FE_INVALID raised");}
Possible output:
0.1 double is 0.10000000000000000555112 (0x1.999999999999ap-4)0.1*10 is 1.0000000000000000555112 (0x8.0000000000002p-3), or 1.0 if rounded to double0.1 * 10 - 1 = 0 : 1 subtracted after intermediate rounding to 1.0fma(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
(C99)(C99)(C99) | computes signed remainder of the floating-point division operation (function)[edit] |
(C99)(C99)(C99) | computes signed remainder as well as the three last bits of the division operation (function)[edit] |
C++ documentation forfma | |