81c2539b6bffdaf788ee8fbc192bf7ba04ad1076
[kopensolaris-gnu/glibc.git] / sysdeps / sparc / fpu / bits / mathinline.h
1 /* Inline math functions for SPARC.
2    Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Jakub Jelinek <jakub@redhat.com>.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 #ifndef _MATH_H
22 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
23 #endif
24
25 #include <bits/wordsize.h>
26
27 #ifdef __GNUC__
28
29 #ifdef __USE_ISOC99
30
31 # if __WORDSIZE == 32
32
33 #  define __unordered_cmp(x, y) \
34   (__extension__                                                              \
35    ({ unsigned __r;                                                           \
36       if (sizeof(x) == 4 && sizeof(y) == 4)                                   \
37         {                                                                     \
38           float __x = (x); float __y = (y);                                   \
39           __asm__("fcmps %1,%2; st %%fsr, %0" : "=m" (__r) : "f" (__x),       \
40                   "f" (__y) : "cc");                                          \
41         }                                                                     \
42       else                                                                    \
43         {                                                                     \
44           double __x = (x); double __y = (y);                                 \
45           __asm__("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x),    \
46                   "f" (__y) : "cc");                                          \
47         }                                                                     \
48       __r; }))
49
50 #  define isgreater(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (2 << 10))
51 #  define isgreaterequal(x, y) ((__unordered_cmp (x, y) & (1 << 10)) == 0)
52 #  define isless(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (1 << 10))
53 #  define islessequal(x, y) ((__unordered_cmp (x, y) & (2 << 10)) == 0)
54 #  define islessgreater(x, y) (((__unordered_cmp (x, y) + (1 << 10)) & (2 << 10)) != 0)
55 #  define isunordered(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (3 << 10))
56
57 # else /* sparc64 */
58
59 #  define __unordered_v9cmp(x, y, op, qop) \
60   (__extension__                                                              \
61    ({ unsigned __r;                                                           \
62       if (sizeof(x) == 4 && sizeof(y) == 4)                                   \
63         {                                                                     \
64           float __x = (x); float __y = (y);                                   \
65           __asm__("fcmps\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0"             \
66                   : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc");       \
67         }                                                                     \
68       else if (sizeof(x) <= 8 && sizeof(y) <= 8)                              \
69         {                                                                     \
70           double __x = (x); double __y = (y);                                 \
71           __asm__("fcmpd\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0"             \
72                   : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc");       \
73         }                                                                     \
74       else                                                                    \
75         {                                                                     \
76           long double __x = (x); long double __y = (y);                       \
77           extern int _Qp_cmp(const long double *a, const long double *b);     \
78           __r = qop;                                                          \
79         }                                                                     \
80       __r; }))
81
82 #  define isgreater(x, y) __unordered_v9cmp(x, y, "g", _Qp_cmp (&__x, &__y) == 2)
83 #  define isgreaterequal(x, y) __unordered_v9cmp(x, y, "ge", (_Qp_cmp (&__x, &__y) & 1) == 0)
84 #  define isless(x, y) __unordered_v9cmp(x, y, "l", _Qp_cmp (&__x, &__y) == 1)
85 #  define islessequal(x, y) __unordered_v9cmp(x, y, "le", (_Qp_cmp (&__x, &__y) & 2) == 0)
86 #  define islessgreater(x, y) __unordered_v9cmp(x, y, "lg", ((_Qp_cmp (&__x, &__y) + 1) & 2) != 0)
87 #  define isunordered(x, y) __unordered_v9cmp(x, y, "u", _Qp_cmp (&__x, &__y) == 3)
88
89 # endif /* sparc64 */
90
91 #endif /* __USE_ISOC99 */
92
93 #if (!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) && defined __OPTIMIZE__
94
95 # ifdef __cplusplus
96 #  define __MATH_INLINE __inline
97 # else
98 #  define __MATH_INLINE extern __inline
99 # endif  /* __cplusplus */
100
101 /* The gcc, version 2.7 or below, has problems with all this inlining
102    code.  So disable it for this version of the compiler.  */
103 # if __GNUC_PREREQ (2, 8)
104
105 #  ifdef __USE_ISOC99
106
107 /* Test for negative number.  Used in the signbit() macro.  */
108 __MATH_INLINE int
109 __signbitf (float __x) __THROW
110 {
111   __extension__ union { float __f; int __i; } __u = { __f: __x };
112   return __u.__i < 0;
113 }
114
115 #   if __WORDSIZE == 32
116
117 __MATH_INLINE int
118 __signbit (double __x) __THROW
119 {
120   __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
121   return __u.__i[0] < 0;
122 }
123
124 __MATH_INLINE int
125 __signbitl (long double __x) __THROW
126 {
127   return __signbit ((double)__x);
128 }
129
130 #   else /* sparc64 */
131
132 __MATH_INLINE int
133 __signbit (double __x) __THROW
134 {
135   __extension__ union { double __d; long int __i; } __u = { __d: __x };
136   return __u.__i < 0;
137 }
138
139 __MATH_INLINE int
140 __signbitl (long double __x) __THROW
141 {
142   __extension__ union { long double __l; long int __i[2]; } __u = { __l: __x };
143   return __u.__i[0] < 0;
144 }
145
146 #   endif /* sparc64 */
147
148 #  endif /* __USE_ISOC99 */
149
150 #  ifndef __NO_MATH_INLINES
151
152 __MATH_INLINE double
153 sqrt (double __x) __THROW
154 {
155   register double __r;
156   __asm ("fsqrtd %1,%0" : "=f" (__r) : "f" (__x));
157   return __r;
158 }
159
160 __MATH_INLINE float
161 sqrtf (float __x) __THROW
162 {
163   register float __r;
164   __asm ("fsqrts %1,%0" : "=f" (__r) : "f" (__x));
165   return __r;
166 }
167
168 #   if __WORDSIZE == 64
169 __MATH_INLINE long double
170 sqrtl (long double __x) __THROW
171 {
172   long double __r;
173   extern void _Qp_sqrt (long double *, __const__ long double *);
174   _Qp_sqrt (&__r, &__x);
175   return __r;
176 }
177 #   endif /* sparc64 */
178
179 #  endif /* !__NO_MATH_INLINES */
180
181 /* This code is used internally in the GNU libc.  */
182 #  ifdef __LIBC_INTERNAL_MATH_INLINES
183 __MATH_INLINE double
184 __ieee754_sqrt (double __x)
185 {
186   register double __r;
187   __asm ("fsqrtd %1,%0" : "=f" (__r) : "f" (__x));
188   return __r;
189 }
190
191 __MATH_INLINE float
192 __ieee754_sqrtf (float __x)
193 {
194   register float __r;
195   __asm ("fsqrts %1,%0" : "=f" (__r) : "f" (__x));
196   return __r;
197 }
198
199 #   if __WORDSIZE == 64
200 __MATH_INLINE long double
201 __ieee754_sqrtl (long double __x)
202 {
203   long double __r;
204   extern void _Qp_sqrt (long double *, __const__ long double *);
205   _Qp_sqrt(&__r, &__x);
206   return __r;
207 }
208 #   endif /* sparc64 */
209 #  endif /* __LIBC_INTERNAL_MATH_INLINES */
210 # endif /* gcc 2.8+ */
211
212 # ifdef __USE_ISOC99
213
214 #  ifndef __NO_MATH_INLINES
215
216 __MATH_INLINE double fdim (double __x, double __y) __THROW;
217 __MATH_INLINE double
218 fdim (double __x, double __y) __THROW
219 {
220   return __x < __y ? 0 : __x - __y;
221 }
222
223 __MATH_INLINE float fdimf (float __x, float __y) __THROW;
224 __MATH_INLINE float
225 fdimf (float __x, float __y) __THROW
226 {
227   return __x < __y ? 0 : __x - __y;
228 }
229
230 #  endif /* !__NO_MATH_INLINES */
231 # endif /* __USE_ISOC99 */
232 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
233 #endif /* __GNUC__ */