Espacios de nombres
Variantes
Acciones

std::fma, std::fmaf, std::fmal

De cppreference.com
< cpp‎ | numeric‎ | math
 
 
 
Funciones matemáticas comunes
Funciones
Operaciones básicas
(C++11)
(C++11)
fma
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)(C++11)(C++11)
Funciones exponenciales
(C++11)
(C++11)
(C++11)
(C++11)
Funciones de potencias
(C++11)
(C++11)
Funciones trigonométricas e hiperbólicas
(C++11)
(C++11)
(C++11)
Funciones de error y gamma
(C++11)
(C++11)
(C++11)
(C++11)
Operaciones de punto flotante del entero más cercano
(C++11)(C++11)(C++11)
(C++11)
(C++11)
(C++11)(C++11)(C++11)
Funciones de manipulación de punto flotante
(C++11)(C++11)
(C++11)
(C++11)
(C++11)(C++11)
(C++11)
Clasificación/comparación
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
Constantes de macro
(C++11)(C++11)(C++11)(C++11)(C++11)
 
Definido en el archivo de encabezado <cmath>
float       fma ( float x, float y, float z );
(1) (desde C++11)
(constexpr since C++23)
float       fmaf( float x, float y, float z );
(2) (desde C++11)
(constexpr since C++23)
double      fma ( double x, double y, double z );
(3) (desde C++11)
(constexpr since C++23)
long double fma ( long double x, long double y, long double z );
(4) (desde C++11)
(constexpr since C++23)
long double fmal( long double x, long double y, long double z );
(5) (desde C++11)
(constexpr since C++23)
Promovido    fma ( Aritmético1 x, Aritmético2 y, Arithmetic3 z );
(6) (desde C++11)
(constexpr since C++23)
#define FP_FAST_FMA  /* definido por la implementación */
(7) (desde C++11)
#define FP_FAST_FMAF /* definido por la implementación */
(8) (desde C++11)
#define FP_FAST_FMAL /* definido por la implementación */
(9) (desde C++11)
1-5) Calcula (x*y) + z como si tuviera una precisión infinita y lo redondea solo una vez para ajustarse al tipo de resultado.
6) Un conjunto de sobrecargas o una plantilla de función para todas las combinaciones de los argumentos de tipo aritmético no cubiertas por (1-5). Si algún argumento tiene tipo entero, se convierte a double. Si cualquier otro argumento es long double, entonces el tipo de retorno es long double, de lo contrario es double.
7-9) Si están definidas las constantes de macro FP_FAST_FMA, FP_FAST_FMAF, o FP_FAST_FMAL, la función std::fma se evalúa más rápidamente (además de ser más precisa) que la expresión x*y+z para argumentos float, double, y long double, respectivamente. Si estám definidas, estas macros se evalúan al entero 1.

Contenido

[editar] Parámetros

x, y, z - Valores de tipos de punto flotante o tipos enteros.

[editar] Valor de retorno

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

Si se produce un error de rango debido a desbordamiento, se devuelve ±HUGE_VAL, ±HUGE_VALF, o ±HUGE_VALL.

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

[editar] Manejo de errores

Los errores se informan como se especifica en math_errhandling.

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

  • Si x es cero e y es infinita o si x es infinita e y es cero, y z no es NaN, entonces se devuelve NaN y se genera FE_INVALID.
  • Si x es cero e y es infinita o si x es infinita e y es cero, y z es NaN, entonces se devuelve NaN y puede generarse FE_INVALID.
  • Si x*y es una infinidad exacta y z es una infinidad con el signo opuesto, se devuelve NaN y se genera FE_INVALID
  • Si x o y son NaN, se devuelve NaN.
  • Si z es NaN, y x*y no son 0*Inf o Inf*0, entonces se devuelve NaN (sin que se genere FE_INVALID).

[editar] Notas

Esta operación se implementa comúnmente en hardware como instrucción de CPU suma y multiplicación fusionada Si es compatible con el hardware, se espera que se definan las macros FP_FAST_FMA? apropiadas, pero muchas implementaciones generan el uso de la instrucción de la CPU incluso cuando las macros no están definidas.

POSIX además especifica que las situaciones especificadas para devolver FE_INVALID sean errores de dominio.

Debido a su infinita precisión intermedia, std::fma es un bloque de construcción común de otras operaciones matemáticas redondeadas correctamente, como std::sqrto incluso la división (donde no se proporciona por la CPU, por ejemplo, Itanium).

Al igual que con todas las expresiones de punto flotante, la expresión (x*y) + z se puede compilar como una suma y multiplicación fusionada a menos que #pragma STDC FP_CONTRACT esté deshabilitado.

[editar] Ejemplo

#include <iostream>
#include <iomanip>
#include <cmath>
#include <cfenv>
#ifndef __GNUC__
#pragma STDC FENV_ACCESS ON
#endif
int main()
{
    // demo de la diferencia entre fma y operadores integrados
    const double in = 0.1;
    std::cout << "0.1 double es " << std::setprecision(23) << in
              << " (" << std::hexfloat << in << std::defaultfloat << ")\n"
              << "0.1*10 es 1.0000000000000000555112 (0x8.0000000000002p-3), "
              << "o 1.0 si redondeado a 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 restado después del redondeo intermedio\n"
              << "fma(0.1, 10, -1) = " << std::setprecision(6) << fma_result << " ("
              << std::hexfloat << fma_result << std::defaultfloat << ")\n\n";
 
    // fma se usa en aritmética double-double
    const double high = 0.1 * 10;
    const double low = std::fma(0.1, 10, -high);
    std::cout << "en aritmética double-double, 0.1 * 10 es representable como "
              << high << " + " << low << "\n\n";
 
    // manejo de errores 
    std::feclearexcept(FE_ALL_EXCEPT);
    std::cout << "fma(+Inf, 10, -Inf) = " << std::fma(INFINITY, 10, -INFINITY) << '\n';
    if(std::fetestexcept(FE_INVALID))
        std::cout << "    Se generó FE_INVALID\n";
}

Posible salida:

0.1 double es 0.10000000000000000555112 (0x1.999999999999ap-4)
0.1*10 es 1.0000000000000000555112 (0x8.0000000000002p-3), o 1.0 si redondeado a double
0.1 * 10 - 1 = 0 : 1 restado después del redondeo intermedio
fma(0.1, 10, -1) = 5.55112e-17 (0x1p-54)
 
en aritmética double-double, 0.1 * 10 es representable como 1 + 5.55112e-17
 
fma(+Inf, 10, -Inf) = -nan
    Se generó FE_INVALID

[editar] Véase también

(C++11)(C++11)(C++11)
Resto con signo de la operación de división
(función) [editar]
(C++11)(C++11)(C++11)
Resto con signo, así como los tres últimos bits de la operación de división
(función) [editar]