1 //
2 // tgmath.h
3 //
4 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //
6 // The type-generic math library.
7 //
8 #pragma once
9 #ifndef _TGMATH
10 #define _TGMATH
11
12 #include <corecrt.h>
13
14 #if (_CRT_HAS_CXX17 == 1) && !defined(_CRT_USE_C_TGMATH_H)
15
16 #include <ctgmath>
17
18 #else // ^^^^ /std:c++17 ^^^^ // vvvv _CRT_USE_C_TGMATH_H vvvv
19
20 #include <math.h>
21 #include <complex.h>
22
23 #if _CRT_HAS_C11 == 0
24
25 #ifndef _CRT_SILENCE_NONCONFORMING_TGMATH_H
26
27 #pragma message(_CRT_WARNING_MESSAGE("UCRT4000", \
28 "This header does not conform to the C99 standard. " \
29 "C99 functionality is available when compiling in C11 mode or higher (/std:c11). " \
30 "Functionality equivalent to the type-generic functions provided by tgmath.h is available " \
31 "in <ctgmath> when compiling as C++. " \
32 "If compiling in C++17 mode or higher (/std:c++17), this header will automatically include <ctgmath> instead. " \
33 "You can define _CRT_SILENCE_NONCONFORMING_TGMATH_H to acknowledge that you have received this warning."))
34
35 #endif // _CRT_SILENCE_NONCONFORMING_TGMATH_H
36
37 #else // ^^^^ Default C Support ^^^^ // vvvv C11 Support vvvv
38
39 #pragma warning(push)
40 #pragma warning(disable: _UCRT_DISABLED_WARNINGS)
41 _UCRT_DISABLE_CLANG_WARNINGS
42 _CRT_BEGIN_C_HEADER
43
44 #define __tgmath_resolve_real_binary_op(X, Y) _Generic((X), \
45 long double: 0.0l, \
46 \
47 default: _Generic((Y), \
48 long double: 0.0l, \
49 default: 0.0 \
50 ), \
51 \
52 float: _Generic((Y), \
53 long double: 0.0l, \
54 default: 0.0, \
55 float: 0.0f \
56 ) \
57 )
58
59 #define fabs(X) _Generic((X), \
60 _Lcomplex: cabsl, \
61 _Fcomplex: cabsf, \
62 _Dcomplex: cabs, \
63 long double: fabsl, \
64 float: fabsf, \
65 default: fabs \
66 )(X)
67
68 #define exp(X) _Generic((X), \
69 _Lcomplex: cexpl, \
70 _Fcomplex: cexpf, \
71 _Dcomplex: cexp, \
72 long double: expl, \
73 float: expf, \
74 default: exp \
75 )(X)
76
77 #define log(X) _Generic((X), \
78 _Lcomplex: clogl, \
79 _Fcomplex: clogf, \
80 _Dcomplex: clog, \
81 long double: logl, \
82 float: logf, \
83 default: log \
84 )(X)
85
86 // C99 Complex types currently not supported. Complex types do not cast/promote implicitly - need inline helper functions.
87
__cpowl_lc_dc(_Lcomplex const __lc,_Dcomplex const __dc)88 inline _Lcomplex __cpowl_lc_dc(_Lcomplex const __lc, _Dcomplex const __dc)
89 {
90 return cpowl(__lc, _LCbuild(__dc._Val[0], __dc._Val[1]));
91 }
92
__cpowl_dc_lc(_Dcomplex const __dc,_Lcomplex const __lc)93 inline _Lcomplex __cpowl_dc_lc(_Dcomplex const __dc, _Lcomplex const __lc)
94 {
95 return cpowl(_LCbuild(__dc._Val[0], __dc._Val[1]), __lc);
96 }
97
__cpowl_lc_fc(_Lcomplex const __lc,_Fcomplex const __fc)98 inline _Lcomplex __cpowl_lc_fc(_Lcomplex const __lc, _Fcomplex const __fc)
99 {
100 return cpowl(__lc, _LCbuild(__fc._Val[0], __fc._Val[1]));
101 }
102
__cpowl_fc_lc(_Fcomplex const __fc,_Lcomplex const __lc)103 inline _Lcomplex __cpowl_fc_lc(_Fcomplex const __fc, _Lcomplex const __lc)
104 {
105 return cpowl(_LCbuild(__fc._Val[0], __fc._Val[1]), __lc);
106 }
107
__cpowl_lc_l(_Lcomplex const __lc,long double const __l)108 inline _Lcomplex __cpowl_lc_l(_Lcomplex const __lc, long double const __l)
109 {
110 return cpowl(__lc, _LCbuild(__l, 0.0));
111 }
112
__cpowl_l_lc(long double const __l,_Lcomplex const __lc)113 inline _Lcomplex __cpowl_l_lc(long double const __l, _Lcomplex const __lc)
114 {
115 return cpowl(_LCbuild(__l, 0.0), __lc);
116 }
117
__cpowl_lc_d(_Lcomplex const __lc,double const __d)118 inline _Lcomplex __cpowl_lc_d(_Lcomplex const __lc, double const __d)
119 {
120 return cpowl(__lc, _LCbuild(__d, 0.0));
121 }
122
__cpowl_d_lc(double const __d,_Lcomplex const __lc)123 inline _Lcomplex __cpowl_d_lc(double const __d, _Lcomplex const __lc)
124 {
125 return cpowl(_LCbuild(__d, 0.0), __lc);
126 }
127
__cpowl_lc_f(_Lcomplex const __lc,float const __f)128 inline _Lcomplex __cpowl_lc_f(_Lcomplex const __lc, float const __f)
129 {
130 return cpowl(__lc, _LCbuild(__f, 0.0));
131 }
132
__cpowl_f_lc(float const __f,_Lcomplex const __lc)133 inline _Lcomplex __cpowl_f_lc(float const __f, _Lcomplex const __lc)
134 {
135 return cpowl(_LCbuild(__f, 0.0), __lc);
136 }
137
__cpowl_dc_l(_Dcomplex const __dc,long double const __l)138 inline _Lcomplex __cpowl_dc_l(_Dcomplex const __dc, long double const __l)
139 {
140 return cpowl(_LCbuild(__dc._Val[0], __dc._Val[1]), _LCbuild(__l, 0.0));
141 }
142
__cpowl_l_dc(long double const __l,_Dcomplex const __dc)143 inline _Lcomplex __cpowl_l_dc(long double const __l, _Dcomplex const __dc)
144 {
145 return cpowl(_LCbuild(__l, 0.0), _LCbuild(__dc._Val[0], __dc._Val[1]));
146 }
147
__cpowl_fc_l(_Fcomplex const __fc,long double const __l)148 inline _Lcomplex __cpowl_fc_l(_Fcomplex const __fc, long double const __l)
149 {
150 return cpowl(_LCbuild(__fc._Val[0], __fc._Val[1]), _LCbuild(__l, 0.0));
151 }
152
__cpowl_l_fc(long double const __l,_Fcomplex const __fc)153 inline _Lcomplex __cpowl_l_fc(long double const __l, _Fcomplex const __fc)
154 {
155 return cpowl(_LCbuild(__l, 0.0), _LCbuild(__fc._Val[0], __fc._Val[1]));
156 }
157
__cpow_dc_fc(_Dcomplex const __dc,_Fcomplex const __fc)158 inline _Dcomplex __cpow_dc_fc(_Dcomplex const __dc, _Fcomplex const __fc)
159 {
160 return cpow(__dc, _Cbuild(__fc._Val[0], __fc._Val[1]));
161 }
162
__cpow_fc_dc(_Fcomplex const __fc,_Dcomplex const __dc)163 inline _Dcomplex __cpow_fc_dc(_Fcomplex const __fc, _Dcomplex const __dc)
164 {
165 return cpow(_Cbuild(__fc._Val[0], __fc._Val[1]), __dc);
166 }
167
__cpow_dc_d(_Dcomplex const __dc,double const __d)168 inline _Dcomplex __cpow_dc_d(_Dcomplex const __dc, double const __d)
169 {
170 return cpow(__dc, _Cbuild(__d, 0.0));
171 }
172
__cpow_d_dc(double const __d,_Dcomplex const __dc)173 inline _Dcomplex __cpow_d_dc(double const __d, _Dcomplex const __dc)
174 {
175 return cpow(_Cbuild(__d, 0.0), __dc);
176 }
177
__cpow_dc_f(_Dcomplex const __dc,float const __f)178 inline _Dcomplex __cpow_dc_f(_Dcomplex const __dc, float const __f)
179 {
180 return cpow(__dc, _Cbuild(__f, 0.0));
181 }
182
__cpow_f_dc(float const __f,_Dcomplex const __dc)183 inline _Dcomplex __cpow_f_dc(float const __f, _Dcomplex const __dc)
184 {
185 return cpow(_Cbuild(__f, 0.0), __dc);
186 }
187
__cpow_fc_d(_Fcomplex const __fc,double const __d)188 inline _Dcomplex __cpow_fc_d(_Fcomplex const __fc, double const __d)
189 {
190 return cpow(_Cbuild(__fc._Val[0], __fc._Val[1]), _Cbuild(__d, 0.0));
191 }
192
__cpow_d_fc(double const __d,_Fcomplex const __fc)193 inline _Dcomplex __cpow_d_fc(double const __d, _Fcomplex const __fc)
194 {
195 return cpow(_Cbuild(__d, 0.0), _Cbuild(__fc._Val[0], __fc._Val[1]));
196 }
197
__cpowf_fc_f(_Fcomplex const __fc,float const __f)198 inline _Fcomplex __cpowf_fc_f(_Fcomplex const __fc, float const __f)
199 {
200 return cpowf(__fc, _FCbuild(__f, 0.0f));
201 }
202
__cpowf_f_fc(float const __f,_Fcomplex const __fc)203 inline _Fcomplex __cpowf_f_fc(float const __f, _Fcomplex const __fc)
204 {
205 return cpowf(_FCbuild(__f, 0.0f), __fc);
206 }
207
208 #define pow(X, Y) _Generic((X), \
209 _Lcomplex: _Generic((Y), \
210 _Lcomplex: cpowl, \
211 _Fcomplex: __cpowl_lc_fc, \
212 _Dcomplex: __cpowl_lc_dc, \
213 long double: __cpowl_lc_l, \
214 default: __cpowl_lc_d, \
215 float: __cpowl_lc_f \
216 ), \
217 \
218 _Fcomplex: _Generic((Y), \
219 _Lcomplex: __cpowl_fc_lc, \
220 _Fcomplex: cpowf, \
221 _Dcomplex: __cpow_fc_dc, \
222 long double: __cpowl_fc_l, \
223 default: __cpow_fc_d, \
224 float: __cpowf_fc_f \
225 ), \
226 \
227 _Dcomplex: _Generic((Y), \
228 _Lcomplex: __cpowl_dc_lc, \
229 _Fcomplex: __cpow_dc_fc, \
230 _Dcomplex: cpow, \
231 long double: __cpowl_dc_l, \
232 default: __cpow_dc_d, \
233 float: __cpow_dc_f \
234 ), \
235 \
236 long double: _Generic((Y), \
237 _Lcomplex: __cpowl_l_lc, \
238 _Fcomplex: __cpowl_l_fc, \
239 _Dcomplex: __cpowl_l_dc, \
240 default: powl \
241 ), \
242 \
243 float: _Generic((Y), \
244 _Lcomplex: __cpowl_f_lc, \
245 _Fcomplex: __cpowf_f_fc, \
246 _Dcomplex: __cpow_f_dc, \
247 long double: powl, \
248 default: pow, \
249 float: powf \
250 ), \
251 \
252 default: _Generic((Y), \
253 _Lcomplex: __cpowl_d_lc, \
254 _Fcomplex: __cpow_d_fc, \
255 _Dcomplex: __cpow_d_dc, \
256 long double: powl, \
257 default: pow \
258 ) \
259 )(X, Y)
260
261 #define sqrt(X) _Generic((X), \
262 _Lcomplex: csqrtl, \
263 _Fcomplex: csqrtf, \
264 _Dcomplex: csqrt, \
265 long double: sqrtl, \
266 float: sqrtf, \
267 default: sqrt \
268 )(X)
269
270 #define sin(X) _Generic((X), \
271 _Lcomplex: csinl, \
272 _Fcomplex: csinf, \
273 _Dcomplex: csin, \
274 long double: sinl, \
275 float: sinf, \
276 default: sin \
277 )(X)
278
279 #define cos(X) _Generic((X), \
280 _Lcomplex: ccosl, \
281 _Fcomplex: ccosf, \
282 _Dcomplex: ccos, \
283 long double: cosl, \
284 float: cosf, \
285 default: cos \
286 )(X)
287
288 #define tan(X) _Generic((X), \
289 _Lcomplex: ctanl, \
290 _Fcomplex: ctanf, \
291 _Dcomplex: ctan, \
292 long double: tanl, \
293 float: tanf, \
294 default: tan \
295 )(X)
296
297 #define asin(X) _Generic((X), \
298 _Lcomplex: casinl, \
299 _Fcomplex: casinf, \
300 _Dcomplex: casin, \
301 long double: asinl, \
302 float: asinf, \
303 default: asin \
304 )(X)
305
306 #define acos(X) _Generic((X), \
307 _Lcomplex: cacosl, \
308 _Fcomplex: cacosf, \
309 _Dcomplex: cacos, \
310 long double: acosl, \
311 float: acosf, \
312 default: acos \
313 )(X)
314
315 #define atan(X) _Generic((X), \
316 _Lcomplex: catanl, \
317 _Fcomplex: catanf, \
318 _Dcomplex: catan, \
319 long double: atanl, \
320 float: atanf, \
321 default: atan \
322 )(X)
323
324 #define asinh(X) _Generic((X), \
325 _Lcomplex: casinhl, \
326 _Fcomplex: casinhf, \
327 _Dcomplex: casinh, \
328 long double: asinhl, \
329 float: asinhf, \
330 default: asinh \
331 )(X)
332
333 #define acosh(X) _Generic((X), \
334 _Lcomplex: cacoshl, \
335 _Fcomplex: cacoshf, \
336 _Dcomplex: cacosh, \
337 long double: acoshl, \
338 float: acoshf, \
339 default: acosh \
340 )(X)
341
342 #define atanh(X) _Generic((X), \
343 _Lcomplex: catanhl, \
344 _Fcomplex: catanhf, \
345 _Dcomplex: catanh, \
346 long double: atanhl, \
347 float: atanhf, \
348 default: atanh \
349 )(X)
350
351 #define atan2(X, Y) _Generic(__tgmath_resolve_real_binary_op((X), (Y)), \
352 long double: atan2l, \
353 float: atan2f, \
354 default: atan2 \
355 )(X, Y)
356
357 #define cbrt(X) _Generic((X), \
358 long double: cbrtl, \
359 float: cbrtf, \
360 default: cbrt \
361 )(X)
362
363 #define ceil(X) _Generic((X), \
364 long double: ceill, \
365 float: ceilf, \
366 default: ceil \
367 )(X)
368
369 #define copysign(X, Y) _Generic(__tgmath_resolve_real_binary_op((X), (Y)), \
370 long double: copysignl, \
371 float: copysignf, \
372 default: copysign \
373 )(X, Y)
374
375 #define erf(X) _Generic((X), \
376 long double: erfl, \
377 float: erff, \
378 default: erf \
379 )(X)
380
381 #define erfc(X) _Generic((X), \
382 long double: erfcl, \
383 float: erfcf, \
384 default: erfc \
385 )(X)
386
387 #define exp2(X) _Generic((X), \
388 long double: exp2l, \
389 float: exp2f, \
390 default: exp2 \
391 )(X)
392
393 #define expm1(X) _Generic((X), \
394 long double: expm1l, \
395 float: expm1f, \
396 default: expm1 \
397 )(X)
398
399 #define fdim(X, Y) _Generic(__tgmath_resolve_real_binary_op((X), (Y)), \
400 long double: fdiml, \
401 float: fdimf, \
402 default: fdim \
403 )(X, Y)
404
405 #define floor(X) _Generic((X), \
406 long double: floorl, \
407 float: floorf, \
408 default: floor \
409 )(X)
410
411 #define fma(X, Y, Z) _Generic(__tgmath_resolve_real_binary_op((X), __tgmath_resolve_real_binary_op((Y), (Z))), \
412 long double: fmal, \
413 float: fmaf, \
414 default: fma \
415 )(X, Y, Z)
416
417 #define fmax(X, Y) _Generic(__tgmath_resolve_real_binary_op((X), (Y)), \
418 long double: fmaxl, \
419 float: fmaxf, \
420 default: fmax \
421 )(X, Y)
422
423 #define fmin(X, Y) _Generic(__tgmath_resolve_real_binary_op((X), (Y)), \
424 long double: fminl, \
425 float: fminf, \
426 default: fmin \
427 )(X, Y)
428
429 #define fmod(X, Y) _Generic(__tgmath_resolve_real_binary_op((X), (Y)), \
430 long double: fmodl, \
431 float: fmodf, \
432 default: fmod \
433 )(X, Y)
434
435 #define frexp(X, INT_PTR) _Generic((X), \
436 long double: frexpl, \
437 float: frexpf, \
438 default: frexp \
439 )(X, INT_PTR)
440
441 #define hypot(X, Y) _Generic(__tgmath_resolve_real_binary_op((X), (Y)), \
442 long double: hypotl, \
443 float: hypotf, \
444 default: hypot \
445 )(X, Y)
446
447 #define ilogb(X) _Generic((X), \
448 long double: ilogbl, \
449 float: ilogbf, \
450 default: ilogb \
451 )(X)
452
453 #define ldexp(X, INT) _Generic((X), \
454 long double: ldexpl, \
455 float: ldexpf, \
456 default: ldexp \
457 )(X, INT)
458
459 #define lgamma(X) _Generic((X), \
460 long double: lgammal, \
461 float: lgammaf, \
462 default: lgamma \
463 )(X)
464
465 #define llrint(X) _Generic((X), \
466 long double: llrintl, \
467 float: llrintf, \
468 default: llrint \
469 )(X)
470
471 #define llround(X) _Generic((X), \
472 long double: llroundl, \
473 float: llroundf, \
474 default: llround \
475 )(X)
476
477 #define log10(X) _Generic((X), \
478 long double: log10l, \
479 float: log10f, \
480 default: log10 \
481 )(X)
482
483 #define log1p(X) _Generic((X), \
484 long double: log1pl, \
485 float: log1pf, \
486 default: log1p \
487 )(X)
488
489 #define log2(X) _Generic((X), \
490 long double: log2l, \
491 float: log2f, \
492 default: log2 \
493 )(X)
494
495 #define logb(X) _Generic((X), \
496 long double: logbl, \
497 float: logbf, \
498 default: logb \
499 )(X)
500
501 #define lrint(X) _Generic((X), \
502 long double: lrintl, \
503 float: lrintf, \
504 default: lrint \
505 )(X)
506
507 #define lround(X) _Generic((X), \
508 long double: lroundl, \
509 float: lroundf, \
510 default: lround \
511 )(X)
512
513 #define nearbyint(X) _Generic((X), \
514 long double: nearbyintl, \
515 float: nearbyintf, \
516 default: nearbyint \
517 )(X)
518
519 #define nextafter(X, Y) _Generic(__tgmath_resolve_real_binary_op((X), (Y)), \
520 long double: nextafterl, \
521 float: nextafterf, \
522 default: nextafter \
523 )(X, Y)
524
525 #define nexttoward(X, LONG_DOUBLE) _Generic((X), \
526 long double: nexttowardl, \
527 float: nexttowardf, \
528 default: nexttoward \
529 )(X, LONG_DOUBLE)
530
531 #define remainder(X, Y) _Generic(__tgmath_resolve_real_binary_op((X), (Y)), \
532 long double: remainderl, \
533 float: remainderf, \
534 default: remainder \
535 )(X, Y)
536
537 #define remquo(X, Y, INT_PTR) _Generic(__tgmath_resolve_real_binary_op((X), (Y)), \
538 long double: remquol, \
539 float: remquof, \
540 default: remquo \
541 )(X, Y, INT_PTR)
542
543 #define rint(X) _Generic((X), \
544 long double: rintl, \
545 float: rintf, \
546 default: rint \
547 )(X)
548
549 #define round(X) _Generic((X), \
550 long double: roundl, \
551 float: roundf, \
552 default: round \
553 )(X)
554
555 #define scalbln(X, LONG) _Generic((X), \
556 long double: scalblnl, \
557 float: scalblnf, \
558 default: scalbln \
559 )(X, LONG)
560
561 #define scalbn(X, INT) _Generic((X), \
562 long double: scalbnl, \
563 float: scalbnf, \
564 default: scalbn \
565 )(X, INT)
566
567 #define tgamma(X) _Generic((X), \
568 long double: tgammal, \
569 float: tgammaf, \
570 default: tgamma \
571 )(X)
572
573 #define trunc(X) _Generic((X), \
574 long double: truncl, \
575 float: truncf, \
576 default: trunc \
577 )(X)
578
__carg_d(double const __d)579 inline double __carg_d(double const __d)
580 {
581 return carg(_Cbuild(__d, 0.0));
582 }
583
584 #define carg(X) _Generic((X), \
585 _Lcomplex: cargl, \
586 _Fcomplex: cargf, \
587 _Dcomplex: carg, \
588 default: __carg_d \
589 )(X)
590
__conj_d(double const __d)591 inline _Dcomplex __conj_d(double const __d)
592 {
593 return conj(_Cbuild(__d, 0.0));
594 }
595
596 #define conj(X) _Generic((X), \
597 _Lcomplex: conjl, \
598 _Fcomplex: conjf, \
599 _Dcomplex: conj, \
600 default: __conj_d \
601 )(X)
602
__creal_d(double const __d)603 inline double __creal_d(double const __d)
604 {
605 // The real part of a double casted to a double complex is just the double value.
606 return __d;
607 }
608
609 #define creal(X) _Generic((X), \
610 _Lcomplex: creall, \
611 _Fcomplex: crealf, \
612 _Dcomplex: creal, \
613 default: __creal_d \
614 )(X)
615
__cimag_d(double const __d)616 inline double __cimag_d(double const __d)
617 {
618 // The imaginary part of a double casted to a double complex is 0.
619 (void) __d;
620 return 0.0;
621 }
622
623 #define cimag(X) _Generic((X), \
624 _Lcomplex: cimagl, \
625 _Fcomplex: cimagf, \
626 _Dcomplex: cimag, \
627 default: __cimag_d \
628 )(X)
629
__cproj_d(double const __d)630 inline _Dcomplex __cproj_d(double const __d)
631 {
632 return cproj(_Cbuild(__d, 0.0));
633 }
634
635 #define cproj(X) _Generic((X), \
636 _Lcomplex: cprojl, \
637 _Fcomplex: cprojf, \
638 _Dcomplex: cproj, \
639 default: __cproj_d \
640 )(X)
641
642 _CRT_END_C_HEADER
643 _UCRT_RESTORE_CLANG_WARNINGS
644 #pragma warning(pop) // _UCRT_DISABLED_WARNINGS
645
646 #endif // _CRT_HAS_C11 == 0
647
648 #endif // (_CRT_HAS_CXX17 == 1) && !defined(_CRT_USE_C_TGMATH_H)
649
650 #endif // _TGMATH
651