1 #ifndef _TGMATH_H 2 #define _TGMATH_H 3 4 #ifdef __ICCARM__ /* for iar */ 5 #include_next <tgmath.h> 6 #else 7 8 /* 9 the return types are only correct with gcc (__GNUC__) 10 otherwise they are long double or long double complex 11 12 the long double version of a function is never chosen when 13 sizeof(double) == sizeof(long double) 14 (but the return type is set correctly with gcc) 15 */ 16 17 #include <math.h> 18 #include <complex.h> 19 20 #define __IS_FP(x) (sizeof((x)+1ULL) == sizeof((x)+1.0f)) 21 #define __IS_CX(x) (__IS_FP(x) && sizeof(x) == sizeof((x)+I)) 22 #define __IS_REAL(x) (__IS_FP(x) && 2*sizeof(x) == sizeof((x)+I)) 23 24 #define __FLT(x) (__IS_REAL(x) && sizeof(x) == sizeof(float)) 25 #define __LDBL(x) (__IS_REAL(x) && sizeof(x) == sizeof(long double) && sizeof(long double) != sizeof(double)) 26 27 #define __FLTCX(x) (__IS_CX(x) && sizeof(x) == sizeof(float complex)) 28 #define __DBLCX(x) (__IS_CX(x) && sizeof(x) == sizeof(double complex)) 29 #define __LDBLCX(x) (__IS_CX(x) && sizeof(x) == sizeof(long double complex) && sizeof(long double) != sizeof(double)) 30 31 /* return type */ 32 33 #ifdef __GNUC__ 34 /* 35 the result must be casted to the right type 36 (otherwise the result type is determined by the conversion 37 rules applied to all the function return types so it is long 38 double or long double complex except for integral functions) 39 40 this cannot be done in c99, so the typeof gcc extension is 41 used and that the type of ?: depends on wether an operand is 42 a null pointer constant or not 43 (in c11 _Generic can be used) 44 45 the c arguments below must be integer constant expressions 46 so they can be in null pointer constants 47 (__IS_FP above was carefully chosen this way) 48 */ 49 /* if c then t else void */ 50 #define __type1(c,t) __typeof__(*(0?(t*)0:(void*)!(c))) 51 /* if c then t1 else t2 */ 52 #define __type2(c,t1,t2) __typeof__(*(0?(__type1(c,t1)*)0:(__type1(!(c),t2)*)0)) 53 /* cast to double when x is integral, otherwise use typeof(x) */ 54 #define __RETCAST(x) ( \ 55 __type2(__IS_FP(x), __typeof__(x), double)) 56 /* 2 args case, should work for complex types (cpow) */ 57 #define __RETCAST_2(x, y) ( \ 58 __type2(__IS_FP(x) && __IS_FP(y), \ 59 __typeof__((x)+(y)), \ 60 __typeof__((x)+(y)+1.0))) 61 /* 3 args case (fma only) */ 62 #define __RETCAST_3(x, y, z) ( \ 63 __type2(__IS_FP(x) && __IS_FP(y) && __IS_FP(z), \ 64 __typeof__((x)+(y)+(z)), \ 65 __typeof__((x)+(y)+(z)+1.0))) 66 /* drop complex from the type of x */ 67 /* TODO: wrong when sizeof(long double)==sizeof(double) */ 68 #define __RETCAST_REAL(x) ( \ 69 __type2(__IS_FP(x) && sizeof((x)+I) == sizeof(float complex), float, \ 70 __type2(sizeof((x)+1.0+I) == sizeof(double complex), double, \ 71 long double))) 72 /* add complex to the type of x */ 73 #define __RETCAST_CX(x) (__typeof__(__RETCAST(x)0+I)) 74 #else 75 #define __RETCAST(x) 76 #define __RETCAST_2(x, y) 77 #define __RETCAST_3(x, y, z) 78 #define __RETCAST_REAL(x) 79 #define __RETCAST_CX(x) 80 #endif 81 82 /* function selection */ 83 84 #define __tg_real_nocast(fun, x) ( \ 85 __FLT(x) ? fun ## f (x) : \ 86 __LDBL(x) ? fun ## l (x) : \ 87 fun(x) ) 88 89 #define __tg_real(fun, x) (__RETCAST(x)__tg_real_nocast(fun, x)) 90 91 #define __tg_real_2_1(fun, x, y) (__RETCAST(x)( \ 92 __FLT(x) ? fun ## f (x, y) : \ 93 __LDBL(x) ? fun ## l (x, y) : \ 94 fun(x, y) )) 95 96 #define __tg_real_2(fun, x, y) (__RETCAST_2(x, y)( \ 97 __FLT(x) && __FLT(y) ? fun ## f (x, y) : \ 98 __LDBL((x)+(y)) ? fun ## l (x, y) : \ 99 fun(x, y) )) 100 101 #define __tg_complex(fun, x) (__RETCAST_CX(x)( \ 102 __FLTCX((x)+I) && __IS_FP(x) ? fun ## f (x) : \ 103 __LDBLCX((x)+I) ? fun ## l (x) : \ 104 fun(x) )) 105 106 #define __tg_complex_retreal(fun, x) (__RETCAST_REAL(x)( \ 107 __FLTCX((x)+I) && __IS_FP(x) ? fun ## f (x) : \ 108 __LDBLCX((x)+I) ? fun ## l (x) : \ 109 fun(x) )) 110 111 #define __tg_real_complex(fun, x) (__RETCAST(x)( \ 112 __FLTCX(x) ? c ## fun ## f (x) : \ 113 __DBLCX(x) ? c ## fun (x) : \ 114 __LDBLCX(x) ? c ## fun ## l (x) : \ 115 __FLT(x) ? fun ## f (x) : \ 116 __LDBL(x) ? fun ## l (x) : \ 117 fun(x) )) 118 119 /* special cases */ 120 121 #define __tg_real_remquo(x, y, z) (__RETCAST_2(x, y)( \ 122 __FLT(x) && __FLT(y) ? remquof(x, y, z) : \ 123 __LDBL((x)+(y)) ? remquol(x, y, z) : \ 124 remquo(x, y, z) )) 125 126 #define __tg_real_fma(x, y, z) (__RETCAST_3(x, y, z)( \ 127 __FLT(x) && __FLT(y) && __FLT(z) ? fmaf(x, y, z) : \ 128 __LDBL((x)+(y)+(z)) ? fmal(x, y, z) : \ 129 fma(x, y, z) )) 130 131 #define __tg_real_complex_pow(x, y) (__RETCAST_2(x, y)( \ 132 __FLTCX((x)+(y)) && __IS_FP(x) && __IS_FP(y) ? cpowf(x, y) : \ 133 __FLTCX((x)+(y)) ? cpow(x, y) : \ 134 __DBLCX((x)+(y)) ? cpow(x, y) : \ 135 __LDBLCX((x)+(y)) ? cpowl(x, y) : \ 136 __FLT(x) && __FLT(y) ? powf(x, y) : \ 137 __LDBL((x)+(y)) ? powl(x, y) : \ 138 pow(x, y) )) 139 140 #define __tg_real_complex_fabs(x) (__RETCAST_REAL(x)( \ 141 __FLTCX(x) ? cabsf(x) : \ 142 __DBLCX(x) ? cabs(x) : \ 143 __LDBLCX(x) ? cabsl(x) : \ 144 __FLT(x) ? fabsf(x) : \ 145 __LDBL(x) ? fabsl(x) : \ 146 fabs(x) )) 147 148 /* suppress any macros in math.h or complex.h */ 149 150 #undef acos 151 #undef acosh 152 #undef asin 153 #undef asinh 154 #undef atan 155 #undef atan2 156 #undef atanh 157 #undef carg 158 #undef cbrt 159 #undef ceil 160 #undef cimag 161 #undef conj 162 #undef copysign 163 #undef cos 164 #undef cosh 165 #undef cproj 166 #undef creal 167 #undef erf 168 #undef erfc 169 #undef exp 170 #undef exp2 171 #undef expm1 172 #undef fabs 173 #undef fdim 174 #undef floor 175 #undef fma 176 #undef fmax 177 #undef fmin 178 #undef fmod 179 #undef frexp 180 #undef hypot 181 #undef ilogb 182 #undef ldexp 183 #undef lgamma 184 #undef llrint 185 #undef llround 186 #undef log 187 #undef log10 188 #undef log1p 189 #undef log2 190 #undef logb 191 #undef lrint 192 #undef lround 193 #undef nearbyint 194 #undef nextafter 195 #undef nexttoward 196 #undef pow 197 #undef remainder 198 #undef remquo 199 #undef rint 200 #undef round 201 #undef scalbln 202 #undef scalbn 203 #undef sin 204 #undef sinh 205 #undef sqrt 206 #undef tan 207 #undef tanh 208 #undef tgamma 209 #undef trunc 210 211 /* tg functions */ 212 213 #define acos(x) __tg_real_complex(acos, (x)) 214 #define acosh(x) __tg_real_complex(acosh, (x)) 215 #define asin(x) __tg_real_complex(asin, (x)) 216 #define asinh(x) __tg_real_complex(asinh, (x)) 217 #define atan(x) __tg_real_complex(atan, (x)) 218 #define atan2(x,y) __tg_real_2(atan2, (x), (y)) 219 #define atanh(x) __tg_real_complex(atanh, (x)) 220 #define carg(x) __tg_complex_retreal(carg, (x)) 221 #define cbrt(x) __tg_real(cbrt, (x)) 222 #define ceil(x) __tg_real(ceil, (x)) 223 #define cimag(x) __tg_complex_retreal(cimag, (x)) 224 #define conj(x) __tg_complex(conj, (x)) 225 #define copysign(x,y) __tg_real_2(copysign, (x), (y)) 226 #define cos(x) __tg_real_complex(cos, (x)) 227 #define cosh(x) __tg_real_complex(cosh, (x)) 228 #define cproj(x) __tg_complex(cproj, (x)) 229 #define creal(x) __tg_complex_retreal(creal, (x)) 230 #define erf(x) __tg_real(erf, (x)) 231 #define erfc(x) __tg_real(erfc, (x)) 232 #define exp(x) __tg_real_complex(exp, (x)) 233 #define exp2(x) __tg_real(exp2, (x)) 234 #define expm1(x) __tg_real(expm1, (x)) 235 #define fabs(x) __tg_real_complex_fabs(x) 236 #define fdim(x,y) __tg_real_2(fdim, (x), (y)) 237 #define floor(x) __tg_real(floor, (x)) 238 #define fma(x,y,z) __tg_real_fma((x), (y), (z)) 239 #define fmax(x,y) __tg_real_2(fmax, (x), (y)) 240 #define fmin(x,y) __tg_real_2(fmin, (x), (y)) 241 #define fmod(x,y) __tg_real_2(fmod, (x), (y)) 242 #define frexp(x,y) __tg_real_2_1(frexp, (x), (y)) 243 #define hypot(x,y) __tg_real_2(hypot, (x), (y)) 244 #define ilogb(x) __tg_real_nocast(ilogb, (x)) 245 #define ldexp(x,y) __tg_real_2_1(ldexp, (x), (y)) 246 #define lgamma(x) __tg_real(lgamma, (x)) 247 #define llrint(x) __tg_real_nocast(llrint, (x)) 248 #define llround(x) __tg_real_nocast(llround, (x)) 249 #define log(x) __tg_real_complex(log, (x)) 250 #define log10(x) __tg_real(log10, (x)) 251 #define log1p(x) __tg_real(log1p, (x)) 252 #define log2(x) __tg_real(log2, (x)) 253 #define logb(x) __tg_real(logb, (x)) 254 #define lrint(x) __tg_real_nocast(lrint, (x)) 255 #define lround(x) __tg_real_nocast(lround, (x)) 256 #define nearbyint(x) __tg_real(nearbyint, (x)) 257 #define nextafter(x,y) __tg_real_2(nextafter, (x), (y)) 258 #define nexttoward(x,y) __tg_real_2(nexttoward, (x), (y)) 259 #define pow(x,y) __tg_real_complex_pow((x), (y)) 260 #define remainder(x,y) __tg_real_2(remainder, (x), (y)) 261 #define remquo(x,y,z) __tg_real_remquo((x), (y), (z)) 262 #define rint(x) __tg_real(rint, (x)) 263 #define round(x) __tg_real(round, (x)) 264 #define scalbln(x,y) __tg_real_2_1(scalbln, (x), (y)) 265 #define scalbn(x,y) __tg_real_2_1(scalbn, (x), (y)) 266 #define sin(x) __tg_real_complex(sin, (x)) 267 #define sinh(x) __tg_real_complex(sinh, (x)) 268 #define sqrt(x) __tg_real_complex(sqrt, (x)) 269 #define tan(x) __tg_real_complex(tan, (x)) 270 #define tanh(x) __tg_real_complex(tanh, (x)) 271 #define tgamma(x) __tg_real(tgamma, (x)) 272 #define trunc(x) __tg_real(trunc, (x)) 273 274 #endif /* __ICCARM__ */ 275 #endif 276