ReactOS  0.4.13-dev-39-g8b6696f
float_cast.h
Go to the documentation of this file.
1 /*
2 ** Copyright (c) 2001-2016, Erik de Castro Lopo <erikd@mega-nerd.com>
3 ** All rights reserved.
4 **
5 ** This code is released under 2-clause BSD license. Please see the
6 ** file at : https://github.com/erikd/libsamplerate/blob/master/COPYING
7 */
8 
9 /* Version 1.5 */
10 
11 #ifndef FLOAT_CAST_HEADER
12 #define FLOAT_CAST_HEADER
13 
14 /*============================================================================
15 ** On Intel Pentium processors (especially PIII and probably P4), converting
16 ** from float to int is very slow. To meet the C specs, the code produced by
17 ** most C compilers targeting Pentium needs to change the FPU rounding mode
18 ** before the float to int conversion is performed.
19 **
20 ** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
21 ** is this flushing of the pipeline which is so slow.
22 **
23 ** Fortunately the ISO C99 specifications define the functions lrint, lrintf,
24 ** llrint and llrintf which fix this problem as a side effect.
25 **
26 ** On Unix-like systems, the configure process should have detected the
27 ** presence of these functions. If they weren't found we have to replace them
28 ** here with a standard C cast.
29 */
30 
31 /*
32 ** The C99 prototypes for lrint and lrintf are as follows:
33 **
34 ** long int lrintf (float x) ;
35 ** long int lrint (double x) ;
36 */
37 
38 #include "config.h"
39 
40 /*
41 ** The presence of the required functions are detected during the configure
42 ** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
43 ** the config.h file.
44 */
45 
46 #define HAVE_LRINT_REPLACEMENT 0
47 
48 #if (HAVE_LRINT && HAVE_LRINTF)
49 
50  /*
51  ** These defines enable functionality introduced with the 1999 ISO C
52  ** standard. They must be defined before the inclusion of math.h to
53  ** engage them. If optimisation is enabled, these functions will be
54  ** inlined. With optimisation switched off, you have to link in the
55  ** maths library using -lm.
56  */
57 
58  #define _ISOC9X_SOURCE 1
59  #define _ISOC99_SOURCE 1
60 
61  #define __USE_ISOC9X 1
62  #define __USE_ISOC99 1
63 
64  #include <math.h>
65 
66 #elif (defined (__CYGWIN__))
67 
68  #include <math.h>
69 
70  #undef HAVE_LRINT_REPLACEMENT
71  #define HAVE_LRINT_REPLACEMENT 1
72 
73  #undef lrint
74  #undef lrintf
75 
76  #define lrint double2int
77  #define lrintf float2int
78 
79  /*
80  ** The native CYGWIN lrint and lrintf functions are buggy:
81  ** http://sourceware.org/ml/cygwin/2005-06/msg00153.html
82  ** http://sourceware.org/ml/cygwin/2005-09/msg00047.html
83  ** and slow.
84  ** These functions (pulled from the Public Domain MinGW math.h header)
85  ** replace the native versions.
86  */
87 
88  static inline long double2int (double in)
89  { long retval ;
90 
91  __asm__ __volatile__
92  ( "fistpl %0"
93  : "=m" (retval)
94  : "t" (in)
95  : "st"
96  ) ;
97 
98  return retval ;
99  } /* double2int */
100 
101  static inline long float2int (float in)
102  { long retval ;
103 
104  __asm__ __volatile__
105  ( "fistpl %0"
106  : "=m" (retval)
107  : "t" (in)
108  : "st"
109  ) ;
110 
111  return retval ;
112  } /* float2int */
113 
114 #elif (defined (WIN64) || defined(_WIN64))
115 
116  /* Win64 section should be places before Win32 one, because
117  ** most likely both WIN32 and WIN64 will be defined in 64-bit case.
118  */
119 
120  #include <math.h>
121 
122  /* Win64 doesn't seem to have these functions, nor inline assembly.
123  ** Therefore implement inline versions of these functions here.
124  */
125  #include <emmintrin.h>
126  #include <mmintrin.h>
127 
128  __inline long int
129  lrint(double flt)
130  {
131  return _mm_cvtsd_si32(_mm_load_sd(&flt));
132  }
133 
134  __inline long int
135  lrintf(float flt)
136  {
137  return _mm_cvtss_si32(_mm_load_ss(&flt));
138  }
139 
140 #elif (defined (WIN32) || defined (_WIN32))
141 
142  #undef HAVE_LRINT_REPLACEMENT
143  #define HAVE_LRINT_REPLACEMENT 1
144 
145  #include <math.h>
146 
147  /*
148  ** Win32 doesn't seem to have these functions.
149  ** Therefore implement inline versions of these functions here.
150  */
151 
152 #ifdef _MSC_VER
153  __inline long int
154  lrint (double flt)
155  { int intgr ;
156 
157  _asm
158  { fld flt
159  fistp intgr
160  } ;
161 
162  return intgr ;
163  }
164 
165  __inline long int
166  lrintf (float flt)
167  { int intgr ;
168 
169  _asm
170  { fld flt
171  fistp intgr
172  } ;
173 
174  return intgr ;
175  }
176 #endif
177 
178 #elif (defined (__MWERKS__) && defined (macintosh))
179 
180  /* This MacOS 9 solution was provided by Stephane Letz */
181 
182  #undef HAVE_LRINT_REPLACEMENT
183  #define HAVE_LRINT_REPLACEMENT 1
184  #include <math.h>
185 
186  #undef lrint
187  #undef lrintf
188 
189  #define lrint double2int
190  #define lrintf float2int
191 
192  inline int
193  float2int (register float in)
194  { long res [2] ;
195 
196  asm
197  { fctiw in, in
198  stfd in, res
199  }
200  return res [1] ;
201  } /* float2int */
202 
203  inline int
204  double2int (register double in)
205  { long res [2] ;
206 
207  asm
208  { fctiw in, in
209  stfd in, res
210  }
211  return res [1] ;
212  } /* double2int */
213 
214 #elif (defined (__MACH__) && defined (__APPLE__))
215 
216  /* For Apple MacOSX. */
217 
218  #undef HAVE_LRINT_REPLACEMENT
219  #define HAVE_LRINT_REPLACEMENT 1
220  #include <math.h>
221 
222  #undef lrint
223  #undef lrintf
224 
225  #define lrint double2int
226  #define lrintf float2int
227 
228  inline static long
229  float2int (register float in)
230  { int res [2] ;
231 
232  __asm__ __volatile__
233  ( "fctiw %1, %1\n\t"
234  "stfd %1, %0"
235  : "=m" (res) /* Output */
236  : "f" (in) /* Input */
237  : "memory"
238  ) ;
239 
240  return res [1] ;
241  } /* lrintf */
242 
243  inline static long
244  double2int (register double in)
245  { int res [2] ;
246 
247  __asm__ __volatile__
248  ( "fctiw %1, %1\n\t"
249  "stfd %1, %0"
250  : "=m" (res) /* Output */
251  : "f" (in) /* Input */
252  : "memory"
253  ) ;
254 
255  return res [1] ;
256  } /* lrint */
257 
258 #else
259  #ifndef __sgi
260  #warning "Don't have the functions lrint() and lrintf()."
261  #warning "Replacing these functions with a standard C cast."
262  #endif
263 
264  #include <math.h>
265 
266  #define lrint(dbl) ((long) (dbl))
267  #define lrintf(flt) ((long) (flt))
268 
269 #endif
270 
271 
272 #endif /* FLOAT_CAST_HEADER */
273 
#define _mm_cvtss_si32
Definition: xmmintrin.h:69
_Check_return_ __CRT_INLINE long lrint(_In_ double x)
Definition: math.h:267
__m128d _mm_load_sd(double const *)
__asm__("\t.globl GetPhys\n" "GetPhys:\t\n" "mflr 0\n\t" "stwu 0,-16(1)\n\t" "mfmsr 5\n\t" "andi. 6,5,0xffef\n\t" "mtmsr 6\n\t" "isync\n\t" "sync\n\t" "lwz 3,0(3)\n\t" "mtmsr 5\n\t" "isync\n\t" "sync\n\t" "lwz 0,0(1)\n\t" "addi 1,1,16\n\t" "mtlr 0\n\t" "blr")
_Check_return_ __CRT_INLINE long lrintf(_In_ float x)
Definition: math.h:268
__m128 _mm_load_ss(float const *)
GLuint in
Definition: glext.h:9616
GLuint res
Definition: glext.h:9613
int _mm_cvtsd_si32(__m128d)