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
Défini dans l'en-tête <math.h>
float fmaf ( float x, float y, float z ) ;
(1) (depuis C99)
double fma ( double x, double y, double z ) ;
(2) (depuis C99)
long double fmal ( long double x, long double y, long double z ) ;
(3) (depuis C99)
#define FP_FAST_FMA  /* implementation-defined */
(4) (depuis C99)
#define FP_FAST_FMAF /* implementation-defined */
(5) (depuis C99)
#define FP_FAST_FMAL /* implementation-defined */
(6) (depuis C99)
Défini dans l'en-tête <tgmath.h>
#define fma( x, y, z )
(7) (depuis C99)
1-3) Calcule ( x * y ) + z comme si avec une précision infinie et arrondi une seule fois pour correspondre au type de résultat.
4-6) Si les constantes de macro FP_FAST_FMA , FP_FAST_FMAF , ou FP_FAST_FMAL sont définies, la fonction correspondante fma , fmaf , ou fmal s'évalue plus rapidement (en plus d'être plus précise) que l'expression x * y + z pour les arguments de type double , float , et long double , respectivement. Si définies, ces macros s'évaluent à l'entier 1 .
7) Macro générique de type : Si un argument a le type long double , fmal est appelé. Sinon, si un argument a un type entier ou a le type double , fma est appelé. Sinon, fmaf est appelé.

Table des matières

Paramètres

x, y, z - valeurs en virgule flottante

Valeur de retour

En cas de succès, retourne la valeur de ( x * y ) + z comme si elle était calculée avec une précision infinie puis arrondie une fois pour correspondre au type de résultat (ou, alternativement, calculée comme une seule opération ternaire en virgule flottante).

Si une erreur de plage due à un dépassement de capacité se produit, ±HUGE_VAL , ±HUGE_VALF , ou ±HUGE_VALL est renvoyé.

Si une erreur de plage due à un dépassement inférieur se produit, la valeur correcte (après arrondi) est retournée.

Gestion des erreurs

Les erreurs sont signalées comme spécifié dans math_errhandling .

Si l'implémentation prend en charge l'arithmétique à virgule flottante IEEE (IEC 60559),

  • Si x est nul et y est infini ou si x est infini et y est nul, et
    • si z n'est pas un NaN, alors NaN est retourné et FE_INVALID est déclenché,
    • si z est un NaN, alors NaN est retourné et FE_INVALID peut être déclenché.
  • Si x * y est un infini exact et z est un infini de signe opposé, NaN est retourné et FE_INVALID est déclenché.
  • Si x ou y sont NaN, NaN est retourné.
  • Si z est NaN, et x * y n'est pas 0 * Inf ou Inf * 0 , alors NaN est retourné (sans FE_INVALID ).

Notes

Cette opération est couramment implémentée en matériel sous forme d'instruction CPU de fused multiply-add . Si elle est supportée par le matériel, les macros appropriées FP_FAST_FMA * sont censées être définies, mais de nombreuses implémentations utilisent l'instruction CPU même lorsque les macros ne sont pas définies.

POSIX spécifie que la situation où la valeur x * y est invalide et z est un NaN constitue une erreur de domaine.

En raison de sa précision intermédiaire infinie, fma est un composant commun d'autres opérations mathématiques correctement arrondies, telles que sqrt ou même la division (lorsque non fournie par le CPU, par exemple Itanium ).

Comme pour toutes les expressions en virgule flottante, l'expression ( x * y ) + z peut être compilée comme une opération fusionnée multiply-add, sauf si le #pragma STDC FP_CONTRACT est désactivé.

Exemple

#include <fenv.h>
#include <float.h>
#include <math.h>
#include <stdio.h>
// #pragma STDC FENV_ACCESS ON
int main(void)
{
    // démontre la différence entre fma et les opérateurs intégrés
    double in = 0.1;
    printf("0.1 en double vaut %.23f (%a)\n", in, in);
    printf("0.1*10 vaut 1.0000000000000000555112 (0x8.0000000000002p-3),"
           " ou 1.0 si arrondi en double\n");
    double expr_result = 0.1 * 10 - 1;
    printf("0.1 * 10 - 1 = %g : 1 soustrait après "
           "arrondi intermédiaire à 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);
    // utilisation de fma en arithmétique double-double
    printf("\nen arithmétique double-double, 0.1 * 10 est représentable comme ");
    double high = 0.1 * 10;
    double low = fma(0.1, 10, -high);
    printf("%g + %g\n\n", high, low);
    // gestion des erreurs
    feclearexcept(FE_ALL_EXCEPT);
    printf("fma(+Inf, 10, -Inf) = %f\n", fma(INFINITY, 10, -INFINITY));
    if (fetestexcept(FE_INVALID))
        puts("    FE_INVALID levée");
}

Sortie possible :

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

Références

  • Norme C23 (ISO/IEC 9899:2024):
  • 7.12.13.1 Les fonctions fma (p: TBD)
  • 7.25 Mathématiques génériques de type <tgmath.h> (p: TBD)
  • F.10.10.1 Les fonctions fma (p: TBD)
  • Norme C17 (ISO/CEI 9899:2018) :
  • 7.12.13.1 Les fonctions fma (p: 188-189)
  • 7.25 Mathématiques génériques <tgmath.h> (p: 272-273)
  • F.10.10.1 Les fonctions fma (p: 386)
  • Norme C11 (ISO/IEC 9899:2011) :
  • 7.12.13.1 Les fonctions fma (p: 258)
  • 7.25 Mathématiques génériques <tgmath.h> (p: 373-375)
  • F.10.10.1 Les fonctions fma (p: 530)
  • Norme C99 (ISO/CEI 9899:1999) :
  • 7.12.13.1 Les fonctions fma (p: 239)
  • 7.22 Mathématiques génériques de type <tgmath.h> (p: 335-337)
  • F.9.10.1 Les fonctions fma (p: 466)

Voir aussi

calcule le reste signé de l'opération de division en virgule flottante
(fonction)
(C99) (C99) (C99)
calcule le reste signé ainsi que les trois derniers bits de l'opération de division
(fonction)