型別通用數學 (自 C99 起)
來自 cppreference.com
標頭檔案 <tgmath.h> 包含標頭檔案 <math.h> 和 <complex.h>,並定義了幾個型別通用宏,這些宏根據引數的型別確定要呼叫的實數函式或(如果適用)複數函式。
對於每個宏,在無後綴的 <math.h> 函式中,其對應實數型別為 double 的引數被稱為通用引數(例如,pow 的兩個引數都是通用引數,但 scalbn 的第一個引數才是通用引數)。
當使用 <tgmath.h> 的宏時,傳遞給通用引數的引數型別決定了宏選擇哪個函式,如下所述。如果引數的型別與所選函式的引數型別不相容,則行為未定義(例如,如果將複數引數傳遞給僅接受實數的 <tgmath.h> 宏:float complex fc; ceil(fc); 或 double complex dc; double d; fmax(dc, d); 都是未定義行為的例子)。
注意:型別通用宏在 C99 中以實現定義的方式實現,但 C11 關鍵字 _Generic 使得以可移植方式實現這些宏成為可能。
目錄 |
[編輯] 複數/實數型別通用宏
對於所有同時具有實數和複數對應項的函式,都存在一個型別通用宏 XXX
,它呼叫以下任一函式:
- 實數函式
- float 變體
XXXf
- double 變體
XXX
- long double 變體
XXXl
- float 變體
- 複數函式
- float 變體
cXXXf
- double 變體
cXXX
- long double 變體
cXXXl
- float 變體
上述規則的一個例外是 fabs
宏(參見下表)。
呼叫的函式確定如下:
- 如果通用引數的任何引數是虛數,則行為在每個函式參考頁面上單獨指定(特別是,
sin
、cos
、tag
、cosh
、sinh
、tanh
、asin
、atan
、asinh
和atanh
呼叫實數函式,sin
、tan
、sinh
、tanh
、asin
、atan
、asinh
和atanh
的返回型別是虛數,而cos
和cosh
的返回型別是實數)。 - 如果通用引數的任何引數是複數,則呼叫複數函式,否則呼叫實數函式。
- 如果通用引數的任何引數是 long double,則呼叫 long double 變體。否則,如果任何引數是 double 或整數,則呼叫 double 變體。否則,呼叫 float 變體。
型別通用宏如下:
型別通用 宏 |
實數函式 變體 |
複數函式 變體 | ||||
---|---|---|---|---|---|---|
float | double | long double | float | double | long double | |
fabs | fabsf | fabs | fabsl | cabsf | cabs | cabsl |
exp | expf | exp | expl | cexpf | cexp | cexpl |
log | logf | log | logl | clogf | clog | clogl |
pow | powf | pow | powl | cpowf | cpow | cpowl |
sqrt | sqrtf | sqrt | sqrtl | csqrtf | csqrt | csqrtl |
sin | sinf | sin | sinl | csinf | csin | csinl |
cos | cosf | cos | cosl | ccosf | ccos | ccosl |
tan | tanf | tan | tanl | ctanf | ctan | ctanl |
asin | asinf | asin | asinl | casinf | casin | casinl |
acos | acosf | acos | acosl | cacosf | cacos | cacosl |
atan | atanf | atan | atanl | catanf | catan | catanl |
sinh | sinhf | sinh | sinhl | csinhf | csinh | csinhl |
cosh | coshf | cosh | coshl | ccoshf | ccosh | ccoshl |
tanh | tanhf | tanh | tanhl | ctanhf | ctanh | ctanhl |
asinh | asinhf | asinh | asinhl | casinhf | casinh | casinhl |
acosh | acoshf | acosh | acoshl | cacoshf | cacosh | cacoshl |
atanh | atanhf | atanh | atanhl | catanhf | catanh | catanhl |
[編輯] 僅實數函式
對於所有沒有複數對應項的函式,除了 modf
,都存在一個型別通用宏 XXX
,它呼叫實數函式的變體之一
- float 變體
XXXf
- double 變體
XXX
- long double 變體
XXXl
呼叫的函式確定如下:
- 如果通用引數的任何引數是 long double,則呼叫 long double 變體。否則,如果通用引數的任何引數是 double,則呼叫 double 變體。否則,呼叫 float 變體。
[編輯] 僅複數函式
對於所有沒有實數對應項的複數函式,都存在一個型別通用宏 cXXX
,它呼叫複數函式的變體之一
呼叫的函式確定如下:
- 如果通用引數的任何引數是實數、複數或虛數,則呼叫相應的複數函式。
型別通用 宏 |
複數函式 變體 | ||
---|---|---|---|
float | double | long double | |
carg | cargf | carg | cargl |
conj | conjf | conj | conjl |
creal | crealf | creal | creall |
cimag | cimagf | cimag | cimagl |
cproj | cprojf | cproj | cprojl |
[編輯] 示例
執行此程式碼
#include <stdio.h> #include <tgmath.h> int main(void) { int i = 2; printf("sqrt(2) = %f\n", sqrt(i)); // argument type is int, calls sqrt float f = 0.5; printf("sin(0.5f) = %f\n", sin(f)); // argument type is float, calls sinf float complex dc = 1 + 0.5*I; float complex z = sqrt(dc); // argument type is float complex, calls csqrtf printf("sqrt(1 + 0.5i) = %f+%fi\n", creal(z), // argument type is float complex, calls crealf cimag(z)); // argument type is float complex, calls cimagf }
輸出
sqrt(2) = 1.414214 sin(0.5f) = 0.479426 sqrt(1 + 0.5i) = 1.029086+0.242934i
[編輯] 參考
- C23 標準 (ISO/IEC 9899:2024)
- 7.25 型別通用數學 <tgmath.h> (p: TBD)
- C17 標準 (ISO/IEC 9899:2018)
- 7.25 型別通用數學 <tgmath.h> (p: 272-273)
- C11 標準 (ISO/IEC 9899:2011)
- 7.25 型別通用數學 <tgmath.h> (p: 373-375)
- C99 標準 (ISO/IEC 9899:1999)
- 7.22 型別通用數學 <tgmath.h> (p: 335-337)