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
헤더 파일에 정의됨 <math.h>
float fmaf ( float x, float y, float z ) ;
(1) (C99부터)
double fma ( double x, double y, double z ) ;
(2) (C99부터)
long double fmal ( long double x, long double y, long double z ) ;
(3) (C99부터)
#define FP_FAST_FMA  /* implementation-defined */
(4) (C99부터)
#define FP_FAST_FMAF /* implementation-defined */
(5) (C99부터)
#define FP_FAST_FMAL /* implementation-defined */
(6) (C99부터)
헤더 파일에 정의됨 <tgmath.h>
#define fma( x, y, z )
(7) (C99부터)
1-3) 무한 정밀도로 계산된 것처럼 ( x * y ) + z 를 계산하고 결과 타입에 맞추기 위해 한 번만 반올림합니다.
4-6) 매크로 상수 FP_FAST_FMA , FP_FAST_FMAF , 또는 FP_FAST_FMAL 가 정의된 경우, 해당 함수 fma , fmaf , 또는 fmal 은 각각 x * y + z 표현식보다 (더 정밀할 뿐만 아니라) 더 빠르게 평가됩니다. 정의된 경우 이러한 매크로는 정수 1 로 평가됩니다.
7) 타입-제네릭 매크로: 인자 중 하나라도 long double 타입을 가지면 fmal 이 호출됩니다. 그렇지 않고 인자 중 하나라도 정수 타입이거나 double 타입을 가지면 fma 가 호출됩니다. 그 외의 경우에는 fmaf 가 호출됩니다.

목차

매개변수

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는 x * y 값이 유효하지 않고 z 가 NaN인 상황을 도메인 오류로 명시합니다.

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

모든 부동 소수점 표현식과 마찬가지로, ( x * y ) + z 표현식은 #pragma STDC FP_CONTRACT 가 꺼져 있지 않는 한 fused multiply-add로 컴파일될 수 있습니다.

예제

#include <fenv.h>
#include <float.h>
#include <math.h>
#include <stdio.h>
// #pragma STDC FENV_ACCESS ON
int main(void)
{
    // fma와 기본 연산자의 차이점을 보여줌
    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);
    // double-double 연산에서의 fma 사용
    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);
    // 오류 처리
    feclearexcept(FE_ALL_EXCEPT);
    printf("fma(+Inf, 10, -Inf) = %f\n", fma(INFINITY, 10, -INFINITY));
    if (fetestexcept(FE_INVALID))
        puts("    FE_INVALID raised");
}

가능한 출력:

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

참고문헌

  • C23 표준 (ISO/IEC 9899:2024):
  • 7.12.13.1 The fma functions (p: TBD)
  • 7.25 Type-generic math <tgmath.h> (p: TBD)
  • F.10.10.1 The fma functions (p: TBD)
  • C17 표준 (ISO/IEC 9899:2018):
  • 7.12.13.1 fma 함수들 (p: 188-189)
  • 7.25 타입-제네릭 수학 <tgmath.h> (p: 272-273)
  • F.10.10.1 fma 함수들 (p: 386)
  • C11 표준 (ISO/IEC 9899:2011):
  • 7.12.13.1 The fma functions (p: 258)
  • 7.25 Type-generic math <tgmath.h> (p: 373-375)
  • F.10.10.1 The fma functions (p: 530)
  • C99 표준 (ISO/IEC 9899:1999):
  • 7.12.13.1 fma 함수들 (p: 239)
  • 7.22 타입-제네릭 수학 <tgmath.h> (p: 335-337)
  • F.9.10.1 fma 함수들 (p: 466)

참고 항목

부동 소수점 나눗셈 연산의 부호 있는 나머지를 계산합니다
(함수)
(C99) (C99) (C99)
부호 있는 나머지와 나눗셈 연산의 마지막 세 비트를 계산합니다
(함수)