summaryrefslogtreecommitdiff
path: root/sysdeps/x86_64/fpu/bits/mathinline.h
blob: 780f8786ddaa40d1da5a44a51f043ebe7774bae5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* Inline math functions for x86-64.
   Copyright (C) 2002-2004, 2007, 2009, 2011 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */

#ifndef _MATH_H
# error "Never use <bits/mathinline.h> directly; include <math.h> instead."
#endif

#include <bits/wordsize.h>

#ifndef __extern_always_inline
# define __MATH_INLINE __inline
#else
# define __MATH_INLINE __extern_always_inline
#endif


#if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2

/* Test for negative number.  Used in the signbit() macro.  */
__MATH_INLINE int
__NTH (__signbitf (float __x))
{
# if __WORDSIZE == 32
  __extension__ union { float __f; int __i; } __u = { __f: __x };
  return __u.__i < 0;
# else
  int __m;
  __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x));
  return __m & 0x8;
# endif
}
__MATH_INLINE int
__NTH (__signbit (double __x))
{
# if __WORDSIZE == 32
  __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
  return __u.__i[1] < 0;
# else
  int __m;
  __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x));
  return __m & 0x80;
# endif
}
__MATH_INLINE int
__NTH (__signbitl (long double __x))
{
  __extension__ union { long double __l; int __i[3]; } __u = { __l: __x };
  return (__u.__i[2] & 0x8000) != 0;
}

#ifdef __USE_ISOC99
__BEGIN_NAMESPACE_C99

/* Round to nearest integer.  */
#  if __WORDSIZE == 64 || defined __SSE_MATH__
__MATH_INLINE long int
__NTH (lrintf (float __x))
{
  long int __res;
  __asm ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x));
  return __res;
}
#  endif
#  if __WORDSIZE == 64 || defined __SSE2_MATH__
__MATH_INLINE long int
__NTH (lrint (double __x))
{
  long int __res;
  __asm ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x));
  return __res;
}
#  endif
#  if __WORDSIZE == 64
__MATH_INLINE long long int
__NTH (llrintf (float __x))
{
  long long int __res;
  __asm ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x));
  return __res;
}
__MATH_INLINE long long int
__NTH (llrint (double __x))
{
  long long int __res;
  __asm ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x));
  return __res;
}
#  endif

#  if __FINITE_MATH_ONLY__ == 1 && (__WORDSIZE == 64 || defined __SSE2_MATH__)
/* Determine maximum of two values.  */
__MATH_INLINE float
__NTH (fmaxf (float __x, float __y))
{
  __asm ("maxss %1, %0" : "+x" (__x) : "xm" (__y));
  return __x;
}
__MATH_INLINE double
__NTH (fmax (double __x, double __y))
{
  __asm ("maxsd %1, %0" : "+x" (__x) : "xm" (__y));
  return __x;
}

/* Determine minimum of two values.  */
__MATH_INLINE float
__NTH (fminf (float __x, float __y))
{
  __asm ("minss %1, %0" : "+x" (__x) : "xm" (__y));
  return __x;
}
__MATH_INLINE double
__NTH (fmin (double __x, double __y))
{
  __asm ("minsd %1, %0" : "+x" (__x) : "xm" (__y));
  return __x;
}
#  endif

__END_NAMESPACE_C99
# endif

#endif