• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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