Add missing libgcc_s.h header.
[uclibc-ng.git] / libm / ldouble_wrappers.c
blob7d5af90b6e45a9be92f7db2abf991cfa757932f5
1 /* vi: set sw=4 ts=4: */
2 /*
3 * Wrapper functions implementing all the long double math functions
4 * defined by SuSv3 by actually calling the double version of
5 * each function and then casting the result back to a long double
6 * to return to the user.
8 * Copyright (C) 2005 by Erik Andersen <andersen@uclibc.org>
10 * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
13 #include <features.h>
14 /* Prevent math.h from defining colliding inlines */
15 #undef __USE_EXTERN_INLINES
16 #include "math.h"
17 #include <complex.h>
19 #define WRAPPER1(func) \
20 long double func##l(long double x) \
21 { \
22 return (long double) func((double) x); \
24 #define int_WRAPPER1(func) \
25 int func##l(long double x) \
26 { \
27 return func((double) x); \
29 #define long_WRAPPER1(func) \
30 long func##l(long double x) \
31 { \
32 return func((double) x); \
34 #define long_long_WRAPPER1(func) \
35 long long func##l(long double x) \
36 { \
37 return func((double) x); \
40 #if defined __i386__ && defined __OPTIMIZE__
41 # undef WRAPPER1
42 # undef int_WRAPPER1
43 # undef long_WRAPPER1
44 # undef long_long_WRAPPER1
45 /* gcc 4.3.1 generates really ugly code with redundant pair of store/load:
46 * sub $0x10,%esp
47 * fldt 0x14(%esp)
48 * fstpl 0x8(%esp)
49 * fldl 0x8(%esp) <-- ??
50 * fstpl (%esp) <-- ??
51 * call function
52 * add $0x10,%esp
53 * ret
54 * I can hope newer gcc will eliminate that. However, I don't think
55 * it will be smart enough to reuse argument stack space and use
56 * jump instead of call. Let's do it by hand.
57 * The asm below loads long double x into st(0), then stores it back
58 * to the same location, but as a double. At this point, stack looks
59 * exactly as "double func(double)" expects it to be.
60 * The return value is returned in st(0) per ABI in both cases (returning
61 * a long double or returning a double). So we can simply jump to func.
62 * Using __GI_func in jump to make optimized intra-library jump.
63 * gcc will still generate a useless "ret" after asm. Oh well...
65 # define WRAPPER1(func) \
66 long double func##l(long double x) \
67 { \
68 long double st_top; \
69 __asm ( \
70 " fldt %1\n" \
71 " fstpl %1\n" \
72 " jmp " __stringify(__GI_##func) "\n" \
73 : "=t" (st_top) \
74 : "m" (x) \
75 ); \
76 return st_top; \
78 # define int_WRAPPER1(func) \
79 int func##l(long double x) \
80 { \
81 int ret; \
82 __asm ( \
83 " fldt %1\n" \
84 " fstpl %1\n" \
85 " jmp " __stringify(__GI_##func) "\n" \
86 : "=a" (ret) \
87 : "m" (x) \
88 ); \
89 return ret; \
91 # define long_WRAPPER1(func) \
92 long func##l(long double x) \
93 { \
94 long ret; \
95 __asm ( \
96 " fldt %1\n" \
97 " fstpl %1\n" \
98 " jmp " __stringify(__GI_##func) "\n" \
99 : "=a" (ret) \
100 : "m" (x) \
101 ); \
102 return ret; \
104 # define long_long_WRAPPER1(func) \
105 long long func##l(long double x) \
107 long long ret; \
108 __asm ( \
109 " fldt %1\n" \
110 " fstpl %1\n" \
111 " jmp " __stringify(__GI_##func) "\n" \
112 : "=A" (ret) \
113 : "m" (x) \
114 ); \
115 return ret; \
117 #endif /* __i386__ && __OPTIMIZE__ */
119 #if defined __NO_LONG_DOUBLE_MATH
120 # define int_WRAPPER_C99(func) /* not needed */
121 # else
122 # define int_WRAPPER_C99(func) \
123 int func##l(long double x) \
125 return func((double) x); \
127 libm_hidden_def(func##l)
128 #endif
130 /* Implement the following, as defined by SuSv3 */
131 #if 0
132 long double acoshl(long double);
133 long double acosl(long double);
134 long double asinhl(long double);
135 long double asinl(long double);
136 long double atan2l(long double, long double);
137 long double atanhl(long double);
138 long double atanl(long double);
139 long double cargl(long double complex);
140 long double cbrtl(long double);
141 long double ceill(long double);
142 long double copysignl(long double, long double);
143 long double coshl(long double);
144 long double cosl(long double);
145 long double erfcl(long double);
146 long double erfl(long double);
147 long double exp2l(long double);
148 long double expl(long double);
149 long double expm1l(long double);
150 long double fabsl(long double);
151 long double fdiml(long double, long double);
152 long double floorl(long double);
153 long double fmal(long double, long double, long double);
154 long double fmaxl(long double, long double);
155 long double fminl(long double, long double);
156 long double fmodl(long double, long double);
157 long double frexpl(long double value, int *);
158 long double hypotl(long double, long double);
159 int ilogbl(long double);
160 long double ldexpl(long double, int);
161 long double lgammal(long double);
162 long long llrintl(long double);
163 long long llroundl(long double);
164 long double log10l(long double);
165 long double log1pl(long double);
166 long double log2l(long double);
167 long double logbl(long double);
168 long double logl(long double);
169 long lrintl(long double);
170 long lroundl(long double);
171 long double modfl(long double, long double *);
172 long double nearbyintl(long double);
173 long double nextafterl(long double, long double);
174 long double nexttowardl(long double, long double);
175 long double powl(long double, long double);
176 long double remainderl(long double, long double);
177 long double remquol(long double, long double, int *);
178 long double rintl(long double);
179 long double roundl(long double);
180 long double scalblnl(long double, long);
181 long double scalbnl(long double, int);
182 long double sinhl(long double);
183 long double sinl(long double);
184 long double sqrtl(long double);
185 long double tanhl(long double);
186 long double tanl(long double);
187 long double tgammal(long double);
188 long double truncl(long double);
189 #endif
191 #ifdef L_acoshl
192 WRAPPER1(acosh)
193 #endif
195 #ifdef L_acosl
196 WRAPPER1(acos)
197 #endif
199 #ifdef L_asinhl
200 WRAPPER1(asinh)
201 #endif
203 #ifdef L_asinl
204 WRAPPER1(asin)
205 #endif
207 #ifdef L_atan2l
208 long double atan2l (long double x, long double y)
210 return (long double) atan2( (double)x, (double)y );
212 #endif
214 #ifdef L_atanhl
215 WRAPPER1(atanh)
216 #endif
218 #ifdef L_atanl
219 WRAPPER1(atan)
220 #endif
222 #ifdef L_cargl
223 long double cargl (long double complex x)
225 return (long double) carg( (double complex)x );
227 #endif
229 #ifdef L_cbrtl
230 WRAPPER1(cbrt)
231 #endif
233 #ifdef L_ceill
234 WRAPPER1(ceil)
235 #endif
237 #ifdef L_copysignl
238 long double copysignl (long double x, long double y)
240 return (long double) copysign( (double)x, (double)y );
242 #endif
244 #ifdef L_coshl
245 WRAPPER1(cosh)
246 #endif
248 #ifdef L_cosl
249 WRAPPER1(cos)
250 #endif
252 #ifdef L_erfcl
253 WRAPPER1(erfc)
254 #endif
256 #ifdef L_erfl
257 WRAPPER1(erf)
258 #endif
260 #ifdef L_exp2l
261 WRAPPER1(exp2)
262 #endif
264 #ifdef L_expl
265 WRAPPER1(exp)
266 #endif
268 #ifdef L_expm1l
269 WRAPPER1(expm1)
270 #endif
272 #ifdef L_fabsl
273 WRAPPER1(fabs)
274 #endif
276 #ifdef L_fdiml
277 long double fdiml (long double x, long double y)
279 return (long double) fdim( (double)x, (double)y );
281 #endif
283 #ifdef L_floorl
284 WRAPPER1(floor)
285 #endif
287 #ifdef L_fmal
288 long double fmal (long double x, long double y, long double z)
290 return (long double) fma( (double)x, (double)y, (double)z );
292 #endif
294 #ifdef L_fmaxl
295 long double fmaxl (long double x, long double y)
297 return (long double) fmax( (double)x, (double)y );
299 #endif
301 #ifdef L_fminl
302 long double fminl (long double x, long double y)
304 return (long double) fmin( (double)x, (double)y );
306 #endif
308 #ifdef L_fmodl
309 long double fmodl (long double x, long double y)
311 return (long double) fmod( (double)x, (double)y );
313 #endif
315 #ifdef L_frexpl
316 long double frexpl (long double x, int *ex)
318 return (long double) frexp( (double)x, ex );
320 #endif
322 #ifdef L_gammal
323 /* WRAPPER1(gamma) won't work, tries to call __GI_xxx,
324 * and gamma() hasn't got one. */
325 long double gammal(long double x)
327 return (long double) gamma((double) x);
329 #endif
331 #ifdef L_hypotl
332 long double hypotl (long double x, long double y)
334 return (long double) hypot( (double)x, (double)y );
336 #endif
338 #ifdef L_ilogbl
339 int_WRAPPER1(ilogb)
340 #endif
342 #ifdef L_ldexpl
343 long double ldexpl (long double x, int ex)
345 return (long double) ldexp( (double)x, ex );
347 #endif
349 #ifdef L_lgammal
350 WRAPPER1(lgamma)
351 #endif
353 #ifdef L_llrintl
354 long_long_WRAPPER1(llrint)
355 #endif
357 #ifdef L_llroundl
358 long_long_WRAPPER1(llround)
359 #endif
361 #ifdef L_log10l
362 WRAPPER1(log10)
363 #endif
365 #ifdef L_log1pl
366 WRAPPER1(log1p)
367 #endif
369 #ifdef L_log2l
370 /* WRAPPER1(log2) won't work */
371 long double log2l(long double x)
373 return (long double) log2((double)x);
375 #endif
377 #ifdef L_logbl
378 WRAPPER1(logb)
379 #endif
381 #ifdef L_logl
382 WRAPPER1(log)
383 #endif
385 #ifdef L_lrintl
386 long_WRAPPER1(lrint)
387 #endif
389 #ifdef L_lroundl
390 long_WRAPPER1(lround)
391 #endif
393 #ifdef L_modfl
394 long double modfl (long double x, long double *iptr)
396 double y, result;
397 result = modf ( x, &y );
398 *iptr = (long double)y;
399 return (long double) result;
401 #endif
403 #ifdef L_nearbyintl
404 WRAPPER1(nearbyint)
405 #endif
407 #ifdef L_nextafterl
408 long double nextafterl (long double x, long double y)
410 return (long double) nextafter( (double)x, (double)y );
412 #endif
414 /* Disabled in Makefile.in */
415 #if 0 /* def L_nexttowardl */
416 long double nexttowardl (long double x, long double y)
418 return (long double) nexttoward( (double)x, (double)y );
420 libm_hidden_def(nexttowardl)
421 #endif
423 #ifdef L_powl
424 long double powl (long double x, long double y)
426 return (long double) pow( (double)x, (double)y );
428 #endif
430 #ifdef L_remainderl
431 long double remainderl (long double x, long double y)
433 return (long double) remainder( (double)x, (double)y );
435 #endif
437 #ifdef L_remquol
438 long double remquol (long double x, long double y, int *quo)
440 return (long double) remquo( (double)x, (double)y, quo );
442 #endif
444 #ifdef L_rintl
445 WRAPPER1(rint)
446 #endif
448 #ifdef L_roundl
449 WRAPPER1(round)
450 #endif
452 #ifdef L_scalblnl
453 long double scalblnl (long double x, long ex)
455 return (long double) scalbln( (double)x, ex );
457 #endif
459 #ifdef L_scalbnl
460 long double scalbnl (long double x, int ex)
462 return (long double) scalbn( (double)x, ex );
464 #endif
466 /* scalb is an obsolete function */
468 #ifdef L_sinhl
469 WRAPPER1(sinh)
470 #endif
472 #ifdef L_sinl
473 WRAPPER1(sin)
474 #endif
476 #ifdef L_sqrtl
477 WRAPPER1(sqrt)
478 #endif
480 #ifdef L_tanhl
481 WRAPPER1(tanh)
482 #endif
484 #ifdef L_tanl
485 WRAPPER1(tan)
486 #endif
488 #ifdef L_tgammal
489 WRAPPER1(tgamma)
490 #endif
492 #ifdef L_truncl
493 WRAPPER1(trunc)
494 #endif
496 #ifdef L_significandl
497 /* WRAPPER1(significand) won't work, tries to call __GI_xxx,
498 * and significand() hasn't got one. */
499 long double significandl(long double x)
501 return (long double) significand((double) x);
503 #endif
505 #ifdef __DO_C99_MATH__
507 #ifdef L___fpclassifyl
508 int_WRAPPER_C99(__fpclassify)
509 #endif
511 #ifdef L___finitel
512 int_WRAPPER_C99(__finite)
513 #endif
515 #ifdef L___signbitl
516 int_WRAPPER_C99(__signbit)
517 #endif
519 #ifdef L___isnanl
520 int_WRAPPER_C99(__isnan)
521 #endif
523 #ifdef L___isinfl
524 int_WRAPPER_C99(__isinf)
525 #endif
527 #endif