std::fma,st...f,std::fmal(3)
π NAME π
std::fma, std::fmaf, std::fmal β C++ Standard Library, bestie. That's the whole name section, she's lowkey self-titled π
β¨ Synopsis β¨
okay so this is all Defined in header <cmath> β keep that in ur notes π
float fma ( float x, float y, float z );
double fma ( double x, double y, double z ); (since C++11) (until C++23)
long double fma ( long double x, long double y, long double z );
constexpr /* floating-point-type */
fma ( /* floating-point-type */ x, (since C++23)
/* floating-point-type */ y,
/* floating-point-type */ z );
float fmaf( float x, float y, float z ); (2) (since C++11)
(1) (constexpr since C++23)
long double fmal( long double x, long double y, long double z ); (3) (since C++11)
(constexpr since C++23)
#define FP_FAST_FMA /* implementation-defined */ (4) (since C++11)
#define FP_FAST_FMAF /* implementation-defined */ (5) (since C++11)
#define FP_FAST_FMAL /* implementation-defined */ (6) (since C++11)
π¦ Additional overloads
also Defined in header <cmath> π«
template< class Arithmetic1, class Arithmetic2, class Arithmetic3 >
/* common-floating-point-type */ (A) (since C++11)
(constexpr since C++23)
fma( Arithmetic1 x, Arithmetic2 y, Arithmetic3 z );
- 1β3) Computes
x * y + zas if to infinite precision and rounded only once to fit the result type. β¨ The library provides overloads ofstd::fmafor all cv-unqualified floating-point types as the type of the parametersx,yandz. (since C++23) - 4β6) If the macro constants
FP_FAST_FMA,FP_FAST_FMAF, orFP_FAST_FMALare defined, the functionstd::fmaevaluates faster (in addition to being more precise) than the expressionx * y + zfordouble,float, andlong doublearguments, respectively. If defined, these macros evaluate to integer1. π₯ - A) Additional overloads are provided for all other combinations of arithmetic types. π«Ά
π Parameters π
x,y,zβ floating-point or integer values
π Return value π
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). no cap, that's the whole flex π
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. πΈ
π Error handling π
Errors are reported as specified in math_errhandling.
If the implementation supports IEEE floating-point arithmetic (IEC 60559):
- If
xis zero andyis infinite or ifxis infinite andyis zero, and- if
zis not a NaN, then NaN is returned andFE_INVALIDis raised, - if
zis a NaN, then NaN is returned andFE_INVALIDmay be raised.
- if
- If
x * yis an exact infinity andzis an infinity with the opposite sign, NaN is returned andFE_INVALIDis raised. - If
xoryare NaN, NaN is returned. - If
zis NaN, andx * yis not0 * InforInf * 0, then NaN is returned (withoutFE_INVALID).
π Notes π
This operation is commonly implemented in hardware as a fused multiply-add CPU instruction. If supported by hardware, the appropriate FP_FAST_FMA? macros are expected to be defined, but many implementations make use of the CPU instruction even when the macros are not defined. sneaky but iconic π§
POSIX (fma, fmaf, fmal) additionally specifies that the situations specified to return FE_INVALID are domain errors.
Due to its infinite intermediate precision, std::fma is a common building block of other correctly-rounded mathematical operations, such as std::sqrt or even the division (where not provided by the CPU, e.g. Itanium). she's the main character of floating-point math fr fr π
As with all floating-point expressions, the expression x * y + z may be compiled as a fused multiply-add unless the #pragma STDC FP_CONTRACT is off. β
ngl the overload rules below are a whole mood, but they matter, so read them bestie π
The additional overloads are not required to be provided exactly as (A). They only need to be sufficient to ensure that for their first argument num1, second argument num2 and third argument num3:
- If
num1,num2ornum3has typelong double, thenstd::fma(num1, num2, num3)has the same effect asstd::fma(static_cast<long double>(num1), static_cast<long double>(num2), static_cast<long double>(num3)). - (until C++23) Otherwise, if
num1,num2and/ornum3has typedoubleor an integer type, thenstd::fma(num1, num2, num3)has the same effect asstd::fma(static_cast<double>(num1), static_cast<double>(num2), static_cast<double>(num3)). - (until C++23) Otherwise, if
num1,num2ornum3has typefloat, thenstd::fma(num1, num2, num3)has the same effect asstd::fma(static_cast<float>(num1), static_cast<float>(num2), static_cast<float>(num3)). - (since C++23) If
num1,num2andnum3have arithmetic types, thenstd::fma(num1, num2, num3)has the same effect asstd::fma(static_cast</* common-floating-point-type */>(num1), static_cast</* common-floating-point-type */>(num2), static_cast</* common-floating-point-type */>(num3)), where/* common-floating-point-type */is the floating-point type with the greatest floating-point conversion rank and greatest floating-point conversion subrank among the types ofnum1,num2andnum3, arguments of integer type are considered to have the same floating-point conversion rank asdouble.
If no such floating-point type with the greatest rank and subrank exists, then overload resolution does not result in a usable candidate from the overloads provided. π (yes that's a real fail state, not a vibe check)
π Example π
// Run this code
#include <cfenv>
#include <cmath>
#include <iomanip>
#include <iostream>
#ifndef __GNUC__
#pragma STDC FENV_ACCESS ON
#endif
int main()
{
// demo the difference between fma and built-in operators
const double in = 0.1;
std::cout << "0.1 double is " << std::setprecision(23) << in
<< " (" << std::hexfloat << in << std::defaultfloat << ")\n"
<< "0.1*10 is 1.0000000000000000555112 (0x8.0000000000002p-3), "
<< "or 1.0 if rounded to 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 subtracted after intermediate rounding\n"
<< "fma(0.1, 10, -1) = " << std::setprecision(6) << fma_result << " ("
<< std::hexfloat << fma_result << std::defaultfloat << ")\n\n";
// fma is used in double-double arithmetic
const double high = 0.1 * 10;
const double low = std::fma(0.1, 10, -high);
std::cout << "in double-double arithmetic, 0.1 * 10 is representable as "
<< high << " + " << low << "\n\n";
// error handling
std::feclearexcept(FE_ALL_EXCEPT);
std::cout << "fma(+Inf, 10, -Inf) = " << std::fma(INFINITY, 10, -INFINITY) << '\n';
if (std::fetestexcept(FE_INVALID))
std::cout << " FE_INVALID raised\n";
}
πΈ 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 double
0.1 * 10 - 1 = 0 : 1 subtracted after intermediate rounding
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
π«Ά See also π«Ά
remainder,remainderf,remainderlβ signed remainder of the division operation (C++11) (function)remquo,remquof,remquolβ signed remainder as well as the three last bits of the division operation (C++11) (function)- C documentation for
fma
that's the whole page bestie, go forth and multiply-add fused-ly πβ¨ this one's from http://cppreference.com, dated 2024.06.10, page std::fma,st...f,std::fmal(3) β mwah, stan cppreference for the lore πππ
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms