Namespaces
Variants

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

From cppreference.net
Common mathematical functions
Nearest integer floating point operations
(C++11)
(C++11)
(C++11) (C++11) (C++11)
Floating point manipulation functions
(C++11) (C++11)
(C++11)
(C++11)
Classification and comparison
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
Types
(C++11)
(C++11)
(C++11)
Macro constants
헤더 파일에 정의됨 <cmath>
(1)
float fma ( float x, float y, float z ) ;

double fma ( double x, double y, double z ) ;

long double fma ( long double x, long double y, long double z ) ;
(C++11부터)
(C++23까지)
constexpr /* floating-point-type */

fma ( /* floating-point-type */ x,
/* floating-point-type */ y,

/* floating-point-type */ z ) ;
(C++23부터)
float fmaf ( float x, float y, float z ) ;
(2) (C++11부터)
(C++23부터 constexpr)
long double fmal ( long double x, long double y, long double z ) ;
(3) (C++11부터)
(C++23부터 constexpr)
#define FP_FAST_FMA  /* implementation-defined */
(4) (C++11부터)
#define FP_FAST_FMAF /* implementation-defined */
(5) (C++11부터)
#define FP_FAST_FMAL /* implementation-defined */
(6) (C++11부터)
헤더 파일에 정의됨 <cmath>
template < class Arithmetic1, class Arithmetic2, class Arithmetic3 >

/* common-floating-point-type */

fma ( Arithmetic1 x, Arithmetic2 y, Arithmetic3 z ) ;
(A) (C++11부터)
(C++23부터 constexpr)
1-3) 무한 정밀도로 계산된 x * y + z 를 결과 타입에 맞추어 한 번만 반올림하는 방식으로 연산을 수행합니다. 라이브러리는 모든 cv-unqualified 부동소수점 타입에 대해 매개변수 x , y , z 의 타입으로 std::fma 의 오버로드를 제공합니다. (C++23부터)
4-6) 매크로 상수 FP_FAST_FMA , FP_FAST_FMAF , 또는 FP_FAST_FMAL 이 정의된 경우, 함수 std::fma 는 각각 double , float , 및 long double 인수에 대해 표현식 x * y + z 보다 (더 정밀할 뿐만 아니라) 더 빠르게 평가됩니다. 정의된 경우, 이러한 매크로는 정수 1 로 평가됩니다.
A) 추가적인 오버로드들이 다른 모든 산술 타입 조합에 대해 제공됩니다.

목차

매개변수

x, y, z - 부동 소수점 또는 정수 값

반환값

성공 시, 무한 정밀도로 계산된 후 결과 타입에 맞게 한 번 반올림된 x * y + z 의 값을 반환합니다 (또는 대안적으로 단일 삼항 부동 소수점 연산으로 계산된 값).

오버플로로 인한 범위 오류가 발생하는 경우, ±HUGE_VAL , ±HUGE_VALF , 또는 ±HUGE_VALL 가 반환됩니다.

언더플로우로 인한 범위 오류가 발생하면, 올바른 값(반올림 후)이 반환됩니다.

오류 처리

오류는 math_errhandling 에 명시된 대로 보고됩니다.

구현이 IEEE 부동 소수점 연산(IEC 60559)을 지원하는 경우,

  • 만약 x 가 0이고 y 가 무한대이거나, 또는 x 가 무한대이고 y 가 0인 경우:
    • 만약 z 가 NaN이 아니면, NaN이 반환되고 FE_INVALID 가 발생합니다,
    • 만약 z 가 NaN이면, NaN이 반환되고 FE_INVALID 가 발생할 수 있습니다.
  • 만약 x * y 가 정확한 무한대이고 z 가 반대 부호의 무한대인 경우, NaN이 반환되고 FE_INVALID 가 발생합니다.
  • 만약 x 또는 y 가 NaN이면, NaN이 반환됩니다.
  • 만약 z 가 NaN이고, x * y 0 * Inf 또는 Inf * 0 가 아닌 경우, NaN이 반환됩니다 ( FE_INVALID 없이).

참고 사항

이 연산은 일반적으로 하드웨어에서 fused multiply-add CPU 명령어로 구현됩니다. 하드웨어에서 지원되는 경우, 해당 FP_FAST_FMA ? 매크로가 정의될 것으로 예상되지만, 많은 구현에서는 매크로가 정의되지 않은 경우에도 CPU 명령어를 사용합니다.

POSIX ( fma , fmaf , fmal ) 는 추가적으로 FE_INVALID 을 반환하도록 명시된 상황들이 도메인 오류임을 지정합니다.

무한한 중간 정밀도 덕분에, std::fma 는 올바르게 반올림된 다른 수학 연산들, 예를 들어 std::sqrt 또는 심지어 (CPU에서 제공되지 않는 경우, 예를 들어 Itanium 에서처럼) 나눗셈과 같은 연산들의 공통 구성 요소입니다.

모든 부동 소수점 표현식과 마찬가지로, x * y + z 표현식은 #pragma STDC FP_CONTRACT 가 off 상태가 아닌 한 fused multiply-add로 컴파일될 수 있습니다.

추가 오버로드는 반드시 (A) 와 동일하게 제공될 필요가 없습니다. 첫 번째 인수 num1 , 두 번째 인수 num2 , 그리고 세 번째 인수 num3 에 대해 다음을 보장하기에 충분하기만 하면 됩니다:

  • 만약 num1 , num2 또는 num3 long double 타입을 가지면, std :: fma ( num1, num2, num3 ) 는 다음 코드와 동일한 효과를 가집니다: std :: fma ( static_cast < long double > ( num1 ) ,
    static_cast < long double > ( num2 ) ,
    static_cast < long double > ( num3 ) )
    .
  • 그렇지 않고 만약 num1 , num2 및/또는 num3 double 또는 정수 타입을 가지면, std :: fma ( num1, num2, num3 ) 는 다음 코드와 동일한 효과를 가집니다: std :: fma ( static_cast < double > ( num1 ) ,
    static_cast < double > ( num2 ) ,
    static_cast < double > ( num3 ) )
    .
  • 그렇지 않고 만약 num1 , num2 또는 num3 float 타입을 가지면, std :: fma ( num1, num2, num3 ) 는 다음 코드와 동일한 효과를 가집니다: std :: fma ( static_cast < float > ( num1 ) ,
    static_cast < float > ( num2 ) ,
    static_cast < float > ( num3 ) )
    .
(C++23 이전)

num1 , num2 , num3 가 산술 타입을 가지는 경우, std :: fma ( num1, num2, num3 ) 는 다음 코드와 동일한 효과를 가집니다: std :: fma ( static_cast < /*common-floating-point-type*/ > ( num1 ) ,
static_cast < /*common-floating-point-type*/ > ( num2 ) ,
static_cast < /*common-floating-point-type*/ > ( num3 ) )
, 여기서 /*common-floating-point-type*/ num1 , num2 , num3 의 타입들 중에서 가장 높은 부동소수점 변환 등급 과 가장 높은 부동소수점 변환 하위 등급 을 가지는 부동소수점 타입입니다. 정수 타입의 인수들은 double 과 동일한 부동소수점 변환 등급을 가진 것으로 간주됩니다.

가장 높은 등급과 하위 등급을 가지는 부동소수점 타입이 존재하지 않는 경우, 오버로드 해결 은 제공된 오버로드들 중에서 사용 가능한 후보를 결과로 내지 않습니다.

(C++23부터)

예제

#include <cfenv>
#include <cmath>
#include <iomanip>
#include <iostream>
#ifndef __GNUC__
#pragma STDC FENV_ACCESS ON
#endif
int main()
{
    // fma와 기본 연산자의 차이점을 보여줌
    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는 double-double 연산에서 사용됨
    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";
    // 오류 처리
    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";
}

가능한 출력:

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

참고 항목

(C++11) (C++11) (C++11)
나눗셈 연산의 부호 있는 나머지
(함수)
(C++11) (C++11) (C++11)
부호 있는 나머지 및 나눗셈 연산의 마지막 세 비트
(함수)