// tgmath.h — type-generic math macros.
//
// Selects between the `f`-suffixed (float) and unsuffixed (double)
// math functions based on argument type via C11 _Generic.  Our
// `long double` is aliased to double, so the `l`-suffixed variants
// aren't separately provided.
//
// Usage: `sqrt(x)` picks `sqrtf(x)` if x is float, `sqrt(x)` if double.

#ifndef _TGMATH_H
#define _TGMATH_H

#include <math.h>

#define __tg1(fn, x) \
    _Generic((x), float: fn##f, default: fn)(x)

#define __tg2(fn, x, y) \
    _Generic((x), float: fn##f, default: fn) \
        ((x), (y))

#undef  sin
#define sin(x)        __tg1(sin, x)
#undef  cos
#define cos(x)        __tg1(cos, x)
#undef  tan
#define tan(x)        __tg1(tan, x)
#undef  asin
#define asin(x)       __tg1(asin, x)
#undef  acos
#define acos(x)       __tg1(acos, x)
#undef  atan
#define atan(x)       __tg1(atan, x)
#undef  atan2
#define atan2(y, x)   __tg2(atan2, y, x)
#undef  sinh
#define sinh(x)       __tg1(sinh, x)
#undef  cosh
#define cosh(x)       __tg1(cosh, x)
#undef  tanh
#define tanh(x)       __tg1(tanh, x)
#undef  exp
#define exp(x)        __tg1(exp, x)
#undef  log
#define log(x)        __tg1(log, x)
#undef  log10
#define log10(x)      __tg1(log10, x)
#undef  pow
#define pow(x, y)     __tg2(pow, x, y)
#undef  sqrt
#define sqrt(x)       __tg1(sqrt, x)
#undef  ceil
#define ceil(x)       __tg1(ceil, x)
#undef  floor
#define floor(x)      __tg1(floor, x)
#undef  fabs
#define fabs(x)       __tg1(fabs, x)
#undef  fmod
#define fmod(x, y)    __tg2(fmod, x, y)
#undef  copysign
#define copysign(x,y) __tg2(copysign, x, y)
#undef  log2
#define log2(x)       __tg1(log2, x)
#undef  exp2
#define exp2(x)       __tg1(exp2, x)
#undef  log1p
#define log1p(x)      __tg1(log1p, x)
#undef  expm1
#define expm1(x)      __tg1(expm1, x)
#undef  hypot
#define hypot(x, y)   __tg2(hypot, x, y)
#undef  cbrt
#define cbrt(x)       __tg1(cbrt, x)
#undef  trunc
#define trunc(x)      __tg1(trunc, x)
#undef  round
#define round(x)      __tg1(round, x)
#undef  fmax
#define fmax(x, y)    __tg2(fmax, x, y)
#undef  fmin
#define fmin(x, y)    __tg2(fmin, x, y)
#undef  fdim
#define fdim(x, y)    __tg2(fdim, x, y)
#undef  asinh
#define asinh(x)      __tg1(asinh, x)
#undef  acosh
#define acosh(x)      __tg1(acosh, x)
#undef  atanh
#define atanh(x)      __tg1(atanh, x)
#undef  remainder
#define remainder(x,y) __tg2(remainder, x, y)
#undef  rint
#define rint(x)       __tg1(rint, x)
#undef  nearbyint
#define nearbyint(x)  __tg1(nearbyint, x)

#endif
