Home | History | Annotate | Download | only in bits
      1 /* Inline math functions for x86-64.
      2    Copyright (C) 2002-2004, 2007, 2009, 2011 Free Software Foundation, Inc.
      3    This file is part of the GNU C Library.
      4 
      5    The GNU C Library is free software; you can redistribute it and/or
      6    modify it under the terms of the GNU Lesser General Public
      7    License as published by the Free Software Foundation; either
      8    version 2.1 of the License, or (at your option) any later version.
      9 
     10    The GNU C Library is distributed in the hope that it will be useful,
     11    but WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13    Lesser General Public License for more details.
     14 
     15    You should have received a copy of the GNU Lesser General Public
     16    License along with the GNU C Library; if not, write to the Free
     17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     18    02111-1307 USA.  */
     19 
     20 #ifndef _MATH_H
     21 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
     22 #endif
     23 
     24 #include <bits/wordsize.h>
     25 
     26 #ifndef __extern_always_inline
     27 # define __MATH_INLINE __inline
     28 #else
     29 # define __MATH_INLINE __extern_always_inline
     30 #endif
     31 
     32 
     33 /* The gcc, version 2.7 or below, has problems with all this inlining
     34    code.  So disable it for this version of the compiler.  */
     35 #if __GNUC_PREREQ (2, 8) && defined __USE_ISOC99
     36 __BEGIN_NAMESPACE_C99
     37 
     38 /* Test for negative number.  Used in the signbit() macro.  */
     39 __MATH_INLINE int
     40 __NTH (__signbitf (float __x))
     41 {
     42 # if __WORDSIZE == 32
     43   __extension__ union { float __f; int __i; } __u = { __f: __x };
     44   return __u.__i < 0;
     45 # else
     46   int __m;
     47   __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x));
     48   return __m & 0x8;
     49 # endif
     50 }
     51 __MATH_INLINE int
     52 __NTH (__signbit (double __x))
     53 {
     54 # if __WORDSIZE == 32
     55   __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
     56   return __u.__i[1] < 0;
     57 # else
     58   int __m;
     59   __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x));
     60   return __m & 0x80;
     61 # endif
     62 }
     63 __MATH_INLINE int
     64 __NTH (__signbitl (long double __x))
     65 {
     66   __extension__ union { long double __l; int __i[3]; } __u = { __l: __x };
     67   return (__u.__i[2] & 0x8000) != 0;
     68 }
     69 
     70 __END_NAMESPACE_C99
     71 #endif
     72 
     73 
     74 #if (__GNUC_PREREQ (2, 8) && !defined __NO_MATH_INLINES \
     75      && defined __OPTIMIZE__)
     76 
     77 # ifdef __USE_ISOC99
     78 __BEGIN_NAMESPACE_C99
     79 
     80 /* Round to nearest integer.  */
     81 #  if __WORDSIZE == 64 || defined __SSE_MATH__
     82 __MATH_INLINE long int
     83 __NTH (lrintf (float __x))
     84 {
     85   long int __res;
     86   __asm ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x));
     87   return __res;
     88 }
     89 #  endif
     90 #  if __WORDSIZE == 64 || defined __SSE2_MATH__
     91 __MATH_INLINE long int
     92 __NTH (lrint (double __x))
     93 {
     94   long int __res;
     95   __asm ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x));
     96   return __res;
     97 }
     98 #  endif
     99 #  if __WORDSIZE == 64
    100 __MATH_INLINE long long int
    101 __NTH (llrintf (float __x))
    102 {
    103   long long int __res;
    104   __asm ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x));
    105   return __res;
    106 }
    107 __MATH_INLINE long long int
    108 __NTH (llrint (double __x))
    109 {
    110   long long int __res;
    111   __asm ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x));
    112   return __res;
    113 }
    114 #  endif
    115 
    116 #  if defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ > 0 \
    117       && (__WORDSIZE == 64 || defined __SSE2_MATH__)
    118 /* Determine maximum of two values.  */
    119 __MATH_INLINE float
    120 __NTH (fmaxf (float __x, float __y))
    121 {
    122   __asm ("maxss %1, %0" : "+x" (__x) : "xm" (__y));
    123   return __x;
    124 }
    125 __MATH_INLINE double
    126 __NTH (fmax (double __x, double __y))
    127 {
    128   __asm ("maxsd %1, %0" : "+x" (__x) : "xm" (__y));
    129   return __x;
    130 }
    131 
    132 /* Determine minimum of two values.  */
    133 __MATH_INLINE float
    134 __NTH (fminf (float __x, float __y))
    135 {
    136   __asm ("minss %1, %0" : "+x" (__x) : "xm" (__y));
    137   return __x;
    138 }
    139 __MATH_INLINE double
    140 __NTH (fmin (double __x, double __y))
    141 {
    142   __asm ("minsd %1, %0" : "+x" (__x) : "xm" (__y));
    143   return __x;
    144 }
    145 #  endif
    146 
    147 __END_NAMESPACE_C99
    148 # endif
    149 
    150 # if defined __SSE4_1__ && (__WORDSIZE == 64 || defined __SSE2_MATH__)
    151 #  if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
    152 __BEGIN_NAMESPACE_C99
    153 
    154 /* Round to nearest integer.  */
    155 __MATH_INLINE double
    156 __NTH (rint (double __x))
    157 {
    158   double __res;
    159   __asm ("roundsd $4, %1, %0" : "=x" (__res) : "xm" (__x));
    160   return __res;
    161 }
    162 __MATH_INLINE float
    163 __NTH (rintf (float __x))
    164 {
    165   float __res;
    166   __asm ("roundss $4, %1, %0" : "=x" (__res) : "xm" (__x));
    167   return __res;
    168 }
    169 
    170 #   ifdef __USE_ISOC99
    171 /* Round to nearest integer without raising inexact exception.  */
    172 __MATH_INLINE double
    173 __NTH (nearbyint (double __x))
    174 {
    175   double __res;
    176   __asm ("roundsd $0xc, %1, %0" : "=x" (__res) : "xm" (__x));
    177   return __res;
    178 }
    179 __MATH_INLINE float
    180 __NTH (nearbyintf (float __x))
    181 {
    182   float __res;
    183   __asm ("roundss $0xc, %1, %0" : "=x" (__res) : "xm" (__x));
    184   return __res;
    185 }
    186 #   endif
    187 
    188 __END_NAMESPACE_C99
    189 #  endif
    190 
    191 __BEGIN_NAMESPACE_STD
    192 /* Smallest integral value not less than X.  */
    193 __MATH_INLINE double
    194 __NTH (ceil (double __x))
    195 {
    196   double __res;
    197   __asm ("roundsd $2, %1, %0" : "=x" (__res) : "xm" (__x));
    198   return __res;
    199 }
    200 __END_NAMESPACE_STD
    201 
    202 __BEGIN_NAMESPACE_C99
    203 __MATH_INLINE float
    204 __NTH (ceilf (float __x))
    205 {
    206   float __res;
    207   __asm ("roundss $2, %1, %0" : "=x" (__res) : "xm" (__x));
    208   return __res;
    209 }
    210 __END_NAMESPACE_C99
    211 
    212 __BEGIN_NAMESPACE_STD
    213 /* Largest integer not greater than X.  */
    214 __MATH_INLINE double
    215 __NTH (floor (double __x))
    216 {
    217   double __res;
    218   __asm ("roundsd $1, %1, %0" : "=x" (__res) : "xm" (__x));
    219   return __res;
    220 }
    221 __END_NAMESPACE_STD
    222 
    223 __BEGIN_NAMESPACE_C99
    224 __MATH_INLINE float
    225 __NTH (floorf (float __x))
    226 {
    227   float __res;
    228   __asm ("roundss $1, %1, %0" : "=x" (__res) : "xm" (__x));
    229   return __res;
    230 }
    231 __END_NAMESPACE_C99
    232 # endif
    233 
    234 #endif
    235