Namespaces
Variants

fma, fmaf, fmal

From cppreference.net
< c ‎ | numeric ‎ | math
Common mathematical functions
Functions
Basic operations
(C99)
fma
(C99)
(C99)
(C99) (C99) (C99) (C23)
Maximum/minimum operations
Exponential functions
Power functions
Trigonometric and hyperbolic functions
Nearest integer floating-point
(C99) (C99) (C99)
(C23) (C23) (C23) (C23)
Floating-point manipulation
Narrowing operations
(C23)
(C23)
(C23)
(C23)
(C23)
(C23)
Quantum and quantum exponent
Decimal re-encoding functions
Total order and payload functions
Classification
Error and gamma functions
(C99)
(C99)
(C99)
(C99)
Types
Macro constants
Special floating-point values
Arguments and return values
Error handling
Fast operation indicators
Definido en el encabezado <math.h>
float fmaf ( float x, float y, float z ) ;
(1) (desde C99)
double fma ( double x, double y, double z ) ;
(2) (desde C99)
long double fmal ( long double x, long double y, long double z ) ;
(3) (desde C99)
#define FP_FAST_FMA  /* implementation-defined */
(4) (desde C99)
#define FP_FAST_FMAF /* implementation-defined */
(5) (desde C99)
#define FP_FAST_FMAL /* implementation-defined */
(6) (desde C99)
Definido en el encabezado <tgmath.h>
#define fma( x, y, z )
(7) (desde C99)
1-3) Calcula ( x * y ) + z como si fuera con precisión infinita y redondeado solo una vez para ajustarse al tipo de resultado.
4-6) Si las constantes de macro FP_FAST_FMA , FP_FAST_FMAF , o FP_FAST_FMAL están definidas, la función correspondiente fma , fmaf , o fmal se evalúa más rápidamente (además de ser más precisa) que la expresión x * y + z para argumentos double , float , y long double , respectivamente. Si están definidas, estas macros se evalúan al entero 1 .
7) Macro genérico de tipos: Si algún argumento tiene tipo long double , fmal es llamado. De lo contrario, si algún argumento tiene tipo entero o tiene tipo double , fma es llamado. De lo contrario, fmaf es llamado.

Contenidos

Parámetros

x, y, z - valores de punto flotante

Valor de retorno

Si tiene éxito, devuelve el valor de ( x * y ) + z como si se calculara con precisión infinita y se redondeara una vez para ajustarse al tipo de resultado (o, alternativamente, calculado como una única operación ternaria de punto flotante).

Si ocurre un error de rango debido a desbordamiento, ±HUGE_VAL , ±HUGE_VALF , o ±HUGE_VALL es devuelto.

Si ocurre un error de rango debido a desbordamiento inferior, se devuelve el valor correcto (después del redondeo).

Manejo de errores

Los errores se reportan como se especifica en math_errhandling .

Si la implementación soporta aritmética de punto flotante IEEE (IEC 60559),

  • Si x es cero y y es infinito o si x es infinito y y es cero, y
    • si z no es un NaN, entonces se retorna NaN y se genera FE_INVALID ,
    • si z es un NaN, entonces se retorna NaN y puede generarse FE_INVALID .
  • Si x * y es un infinito exacto y z es un infinito con el signo opuesto, se retorna NaN y se genera FE_INVALID .
  • Si x o y son NaN, se retorna NaN.
  • Si z es NaN, y x * y no es 0 * Inf o Inf * 0 , entonces se retorna NaN (sin FE_INVALID ).

Notas

Esta operación comúnmente se implementa en hardware como la instrucción de CPU fused multiply-add . Si es compatible con el hardware, se espera que las macros apropiadas FP_FAST_FMA * estén definidas, pero muchas implementaciones utilizan la instrucción de CPU incluso cuando las macros no están definidas.

POSIX especifica que la situación donde el valor x * y es inválido y z es un NaN es un error de dominio.

Debido a su precisión intermedia infinita, fma es un componente común de otras operaciones matemáticas correctamente redondeadas, como sqrt o incluso la división (cuando no está proporcionada por la CPU, por ejemplo Itanium ).

Como con todas las expresiones de punto flotante, la expresión ( x * y ) + z puede ser compilada como una operación fused multiply-add a menos que el #pragma STDC FP_CONTRACT esté desactivado.

Ejemplo

#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");
}

Salida posible:

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

Referencias

  • Estándar C23 (ISO/IEC 9899:2024):
  • 7.12.13.1 Las funciones fma (p: TBD)
  • 7.25 Matemáticas genéricas de tipos <tgmath.h> (p: TBD)
  • F.10.10.1 Las funciones fma (p: TBD)
  • Estándar C17 (ISO/IEC 9899:2018):
  • 7.12.13.1 Las funciones fma (p: 188-189)
  • 7.25 Matemáticas genéricas de tipos <tgmath.h> (p: 272-273)
  • F.10.10.1 Las funciones fma (p: 386)
  • Estándar C11 (ISO/IEC 9899:2011):
  • 7.12.13.1 Las funciones fma (p: 258)
  • 7.25 Matemáticas genéricas de tipos <tgmath.h> (p: 373-375)
  • F.10.10.1 Las funciones fma (p: 530)
  • Estándar C99 (ISO/IEC 9899:1999):
  • 7.12.13.1 Las funciones fma (p: 239)
  • 7.22 Matemáticas genéricas de tipo <tgmath.h> (p: 335-337)
  • F.9.10.1 Las funciones fma (p: 466)

Véase también

calcula el resto con signo de la operación de división de punto flotante
(función)
(C99) (C99) (C99)
calcula el resto con signo así como los tres últimos bits de la operación de división
(función)