Update to LGPL v2.1.
[jlayton/glibc.git] / sysdeps / alpha / fpu / bits / mathinline.h
1 /* Inline math functions for Alpha.
2    Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by David Mosberger-Tang.
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 #ifdef __cplusplus
26 # define __MATH_INLINE __inline
27 #else
28 # define __MATH_INLINE extern __inline
29 #endif
30
31 #ifdef __USE_ISOC99
32 # define isunordered(x, y)                              \
33   (__extension__                                        \
34    ({ double __r;                                       \
35       __asm ("cmptun/su %1,%2,%0\n\ttrapb"              \
36              : "=&f" (__r) : "f" (x), "f"(y));          \
37       __r != 0; }))
38
39 # define isgreater(x, y)                                \
40   (__extension__                                        \
41    ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \
42       !isunordered(__x, __y) && __x > __y; }))
43 # define isgreaterequal(x, y)                           \
44   (__extension__                                        \
45    ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \
46       !isunordered(__x, __y) && __x >= __y; }))
47 # define isless(x, y)                                   \
48   (__extension__                                        \
49    ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \
50       !isunordered(__x, __y) && __x < __y; }))
51 # define islessequal(x, y)                              \
52   (__extension__                                        \
53    ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \
54       !isunordered(__x, __y) && __x <= __y; }))
55 # define islessgreater(x, y)                            \
56   (__extension__                                        \
57    ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \
58       !isunordered(__x, __y) && __x != __y; }))
59 #endif /* ISO C99 */
60
61 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
62
63 #define __inline_copysign(NAME, TYPE)                                   \
64 __MATH_INLINE TYPE                                                      \
65 NAME (TYPE __x, TYPE __y) __THROW                                       \
66 {                                                                       \
67   TYPE __z;                                                             \
68   __asm ("cpys %1, %2, %0" : "=f" (__z) : "f" (__y), "f" (__x));        \
69   return __z;                                                           \
70 }
71
72 __inline_copysign(__copysignf, float)
73 __inline_copysign(copysignf, float)
74 __inline_copysign(__copysign, double)
75 __inline_copysign(copysign, double)
76
77 #undef __MATH_INLINE_copysign
78
79
80 #if __GNUC_PREREQ (2, 8)
81 __MATH_INLINE float __fabsf (float __x) __THROW { return __builtin_fabsf (__x); }
82 __MATH_INLINE float fabsf (float __x) __THROW { return __builtin_fabsf (__x); }
83 __MATH_INLINE double __fabs (double __x) __THROW { return __builtin_fabs (__x); }
84 __MATH_INLINE double fabs (double __x) __THROW { return __builtin_fabs (__x); }
85 #else
86 #define __inline_fabs(NAME, TYPE)                       \
87 __MATH_INLINE TYPE                                      \
88 NAME (TYPE __x) __THROW                                 \
89 {                                                       \
90   TYPE __z;                                             \
91   __asm ("cpys $f31, %1, %0" : "=f" (__z) : "f" (__x)); \
92   return __z;                                           \
93 }
94
95 __inline_fabs(__fabsf, float)
96 __inline_fabs(fabsf, float)
97 __inline_fabs(__fabs, double)
98 __inline_fabs(fabs, double)
99
100 #undef __inline_fabs
101 #endif
102
103
104 /* Use the -inf rounding mode conversion instructions to implement
105    floor.  We note when the exponent is large enough that the value
106    must be integral, as this avoids unpleasant integer overflows.  */
107
108 __MATH_INLINE float
109 __floorf (float __x) __THROW
110 {
111   /* Check not zero since floor(-0) == -0.  */
112   if (__x != 0 && fabsf (__x) < 16777216.0f)  /* 1 << FLT_MANT_DIG */
113     {
114       /* Note that Alpha S_Floating is stored in registers in a
115          restricted T_Floating format, so we don't even need to
116          convert back to S_Floating in the end.  The initial
117          conversion to T_Floating is needed to handle denormals.  */
118
119       float __tmp1, __tmp2;
120
121       __asm ("cvtst/s %3,%2\n\t"
122 #ifdef _IEEE_FP_INEXACT
123              "cvttq/svim %2,%1\n\t"
124 #else
125              "cvttq/svm %2,%1\n\t"
126 #endif
127              "cvtqt/m %1,%0\n\t"
128              : "=f"(__x), "=&f"(__tmp1), "=&f"(__tmp2)
129              : "f"(__x));
130     }
131   return __x;
132 }
133
134 __MATH_INLINE double
135 __floor (double __x) __THROW
136 {
137   if (__x != 0 && fabs (__x) < 9007199254740992.0)  /* 1 << DBL_MANT_DIG */
138     {
139       double __tmp1;
140       __asm (
141 #ifdef _IEEE_FP_INEXACT
142              "cvttq/svim %2,%1\n\t"
143 #else
144              "cvttq/svm %2,%1\n\t"
145 #endif
146              "cvtqt/m %1,%0\n\t"
147              : "=f"(__x), "=&f"(__tmp1)
148              : "f"(__x));
149     }
150   return __x;
151 }
152
153 __MATH_INLINE float floorf (float __x) __THROW { return __floorf(__x); }
154 __MATH_INLINE double floor (double __x) __THROW { return __floor(__x); }
155
156
157 #ifdef __USE_ISOC99
158
159 __MATH_INLINE float __fdimf (float __x, float __y) __THROW
160 {
161   return __x < __y ? 0.0f : __x - __y;
162 }
163
164 __MATH_INLINE float fdimf (float __x, float __y) __THROW
165 {
166   return __x < __y ? 0.0f : __x - __y;
167 }
168
169 __MATH_INLINE double __fdim (double __x, double __y) __THROW
170 {
171   return __x < __y ? 0.0 : __x - __y;
172 }
173
174 __MATH_INLINE double fdim (double __x, double __y) __THROW
175 {
176   return __x < __y ? 0.0 : __x - __y;
177 }
178
179 #endif /* C99 */
180
181 #endif /* __NO_MATH_INLINES */