Back to index

glibc  2.9
mathinline.h
Go to the documentation of this file.
00001 /* Inline math functions for SPARC.
00002    Copyright (C) 1999, 2000, 2001, 2002, 2004, 2006, 2007
00003    Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005    Contributed by Jakub Jelinek <jakub@redhat.com>.
00006 
00007    The GNU C Library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    The GNU C Library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with the GNU C Library; if not, write to the Free
00019    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00020    02111-1307 USA.  */
00021 
00022 #ifndef _MATH_H
00023 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
00024 #endif
00025 
00026 #include <bits/wordsize.h>
00027 
00028 #ifdef __GNUC__
00029 
00030 #if defined __USE_ISOC99 && !__GNUC_PREREQ (3, 0)
00031 # undef isgreater
00032 # undef isgreaterequal
00033 # undef isless
00034 # undef islessequal
00035 # undef islessgreater
00036 # undef isunordered
00037 
00038 # if __WORDSIZE == 32
00039 
00040 #  ifndef __NO_LONG_DOUBLE_MATH
00041 
00042 #   define __unordered_cmp(x, y) \
00043   (__extension__                                                     \
00044    ({ unsigned __r;                                                  \
00045       if (sizeof (x) == 4 && sizeof (y) == 4)                               \
00046        {                                                             \
00047          float __x = (x); float __y = (y);                                  \
00048          __asm__ ("fcmps %1,%2; st %%fsr, %0" : "=m" (__r) : "f" (__x),      \
00049                  "f" (__y) : "cc");                                         \
00050        }                                                             \
00051       else if (sizeof (x) <= 8 && sizeof (y) <= 8)                          \
00052        {                                                             \
00053          double __x = (x); double __y = (y);                                \
00054          __asm__ ("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x),   \
00055                  "f" (__y) : "cc");                                         \
00056        }                                                             \
00057       else                                                           \
00058        {                                                             \
00059          long double __x = (x); long double __y = (y);                      \
00060          extern int _Q_cmp (const long double a, const long double b);             \
00061          __r = _Q_cmp (__x, __y) << 10;                              \
00062        }                                                             \
00063       __r; }))
00064 
00065 #  else
00066 
00067 #   define __unordered_cmp(x, y) \
00068   (__extension__                                                     \
00069    ({ unsigned __r;                                                  \
00070       if (sizeof (x) == 4 && sizeof (y) == 4)                               \
00071        {                                                             \
00072          float __x = (x); float __y = (y);                                  \
00073          __asm__ ("fcmps %1,%2; st %%fsr, %0" : "=m" (__r) : "f" (__x),      \
00074                  "f" (__y) : "cc");                                         \
00075        }                                                             \
00076       else                                                           \
00077        {                                                             \
00078          double __x = (x); double __y = (y);                                \
00079          __asm__ ("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x),   \
00080                  "f" (__y) : "cc");                                         \
00081        }                                                             \
00082       __r; }))
00083 
00084 #  endif
00085 
00086 #  define isgreater(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (2 << 10))
00087 #  define isgreaterequal(x, y) ((__unordered_cmp (x, y) & (1 << 10)) == 0)
00088 #  define isless(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (1 << 10))
00089 #  define islessequal(x, y) ((__unordered_cmp (x, y) & (2 << 10)) == 0)
00090 #  define islessgreater(x, y) (((__unordered_cmp (x, y) + (1 << 10)) & (2 << 10)) != 0)
00091 #  define isunordered(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (3 << 10))
00092 
00093 # else /* sparc64 */
00094 
00095 #  define __unordered_v9cmp(x, y, op, qop) \
00096   (__extension__                                                     \
00097    ({ unsigned __r;                                                  \
00098       if (sizeof (x) == 4 && sizeof (y) == 4)                               \
00099        {                                                             \
00100          float __x = (x); float __y = (y);                                  \
00101          __asm__ ("fcmps\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0"           \
00102                  : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc");      \
00103        }                                                             \
00104       else if (sizeof (x) <= 8 && sizeof (y) <= 8)                          \
00105        {                                                             \
00106          double __x = (x); double __y = (y);                                \
00107          __asm__ ("fcmpd\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0"           \
00108                  : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc");      \
00109        }                                                             \
00110       else                                                           \
00111        {                                                             \
00112          long double __x = (x); long double __y = (y);                      \
00113          extern int _Qp_cmp (const long double *a, const long double *b);    \
00114          __r = qop;                                                  \
00115        }                                                             \
00116       __r; }))
00117 
00118 #  define isgreater(x, y) __unordered_v9cmp(x, y, "g", _Qp_cmp (&__x, &__y) == 2)
00119 #  define isgreaterequal(x, y) __unordered_v9cmp(x, y, "ge", (_Qp_cmp (&__x, &__y) & 1) == 0)
00120 #  define isless(x, y) __unordered_v9cmp(x, y, "l", _Qp_cmp (&__x, &__y) == 1)
00121 #  define islessequal(x, y) __unordered_v9cmp(x, y, "le", (_Qp_cmp (&__x, &__y) & 2) == 0)
00122 #  define islessgreater(x, y) __unordered_v9cmp(x, y, "lg", ((_Qp_cmp (&__x, &__y) + 1) & 2) != 0)
00123 #  define isunordered(x, y) __unordered_v9cmp(x, y, "u", _Qp_cmp (&__x, &__y) == 3)
00124 
00125 # endif /* sparc64 */
00126 
00127 #endif /* __USE_ISOC99 */
00128 
00129 #if (!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) && defined __OPTIMIZE__
00130 
00131 # ifndef __extern_inline
00132 #  define __MATH_INLINE __inline
00133 # else
00134 #  define __MATH_INLINE __extern_inline
00135 # endif  /* __cplusplus */
00136 
00137 /* The gcc, version 2.7 or below, has problems with all this inlining
00138    code.  So disable it for this version of the compiler.  */
00139 # if __GNUC_PREREQ (2, 8)
00140 
00141 #  ifdef __USE_ISOC99
00142 
00143 /* Test for negative number.  Used in the signbit() macro.  */
00144 __MATH_INLINE int
00145 __NTH (__signbitf (float __x))
00146 {
00147   __extension__ union { float __f; int __i; } __u = { __f: __x };
00148   return __u.__i < 0;
00149 }
00150 
00151 #   if __WORDSIZE == 32
00152 
00153 __MATH_INLINE int
00154 __NTH (__signbit (double __x))
00155 {
00156   __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
00157   return __u.__i[0] < 0;
00158 }
00159 
00160 #    ifndef __NO_LONG_DOUBLE_MATH
00161 __MATH_INLINE int
00162 __NTH (__signbitl (long double __x))
00163 {
00164   __extension__ union { long double __l; int __i[4]; } __u = { __l: __x };
00165   return __u.__i[0] < 0;
00166 }
00167 #    else
00168 __MATH_INLINE int
00169 __NTH (__signbitl (long double __x))
00170 {
00171   return __signbit ((double)__x);
00172 }
00173 #    endif
00174 
00175 #   else /* sparc64 */
00176 
00177 __MATH_INLINE int
00178 __NTH (__signbit (double __x))
00179 {
00180   __extension__ union { double __d; long int __i; } __u = { __d: __x };
00181   return __u.__i < 0;
00182 }
00183 
00184 __MATH_INLINE int
00185 __NTH (__signbitl (long double __x))
00186 {
00187   __extension__ union { long double __l; long int __i[2]; } __u = { __l: __x };
00188   return __u.__i[0] < 0;
00189 }
00190 
00191 #   endif /* sparc64 */
00192 
00193 #  endif /* __USE_ISOC99 */
00194 
00195 #  if !defined __NO_MATH_INLINES && !__GNUC_PREREQ (3, 2)
00196 
00197 __MATH_INLINE double
00198 __NTH (sqrt (double __x))
00199 {
00200   register double __r;
00201   __asm ("fsqrtd %1,%0" : "=f" (__r) : "f" (__x));
00202   return __r;
00203 }
00204 
00205 __MATH_INLINE float
00206 __NTH (sqrtf (float __x))
00207 {
00208   register float __r;
00209   __asm ("fsqrts %1,%0" : "=f" (__r) : "f" (__x));
00210   return __r;
00211 }
00212 
00213 #   if __WORDSIZE == 64
00214 __MATH_INLINE long double
00215 __NTH (sqrtl (long double __x))
00216 {
00217   long double __r;
00218   extern void _Qp_sqrt (long double *, __const__ long double *);
00219   _Qp_sqrt (&__r, &__x);
00220   return __r;
00221 }
00222 #   elif !defined __NO_LONG_DOUBLE_MATH
00223 __MATH_INLINE long double
00224 sqrtl (long double __x) __THROW
00225 {
00226   extern long double _Q_sqrt (__const__ long double);
00227   return _Q_sqrt (__x);
00228 }
00229 #   endif /* sparc64 */
00230 
00231 #  endif /* !__NO_MATH_INLINES && !GCC 3.2+ */
00232 
00233 /* This code is used internally in the GNU libc.  */
00234 #  ifdef __LIBC_INTERNAL_MATH_INLINES
00235 __MATH_INLINE double
00236 __ieee754_sqrt (double __x)
00237 {
00238   register double __r;
00239   __asm ("fsqrtd %1,%0" : "=f" (__r) : "f" (__x));
00240   return __r;
00241 }
00242 
00243 __MATH_INLINE float
00244 __ieee754_sqrtf (float __x)
00245 {
00246   register float __r;
00247   __asm ("fsqrts %1,%0" : "=f" (__r) : "f" (__x));
00248   return __r;
00249 }
00250 
00251 #   if __WORDSIZE == 64
00252 __MATH_INLINE long double
00253 __ieee754_sqrtl (long double __x)
00254 {
00255   long double __r;
00256   extern void _Qp_sqrt (long double *, __const__ long double *);
00257   _Qp_sqrt(&__r, &__x);
00258   return __r;
00259 }
00260 #   elif !defined __NO_LONG_DOUBLE_MATH
00261 __MATH_INLINE long double
00262 __ieee754_sqrtl (long double __x)
00263 {
00264   extern long double _Q_sqrt (__const__ long double);
00265   return _Q_sqrt (__x);
00266 }
00267 #   endif /* sparc64 */
00268 #  endif /* __LIBC_INTERNAL_MATH_INLINES */
00269 # endif /* gcc 2.8+ */
00270 
00271 # ifdef __USE_ISOC99
00272 
00273 #  ifndef __NO_MATH_INLINES
00274 
00275 __MATH_INLINE double __NTH (fdim (double __x, double __y));
00276 __MATH_INLINE double
00277 __NTH (fdim (double __x, double __y))
00278 {
00279   return __x <= __y ? 0 : __x - __y;
00280 }
00281 
00282 __MATH_INLINE float __NTH (fdimf (float __x, float __y));
00283 __MATH_INLINE float
00284 __NTH (fdimf (float __x, float __y))
00285 {
00286   return __x <= __y ? 0 : __x - __y;
00287 }
00288 
00289 #  endif /* !__NO_MATH_INLINES */
00290 # endif /* __USE_ISOC99 */
00291 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
00292 #endif /* __GNUC__ */