ReactOS 0.4.15-dev-8236-g99f0937
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
int _mm_cvtsd_si32(__m128d a)
Definition: emmintrin.h:874
__m128d _mm_load_sd(double const *dp)
Definition: emmintrin.h:991
GLuint res
Definition: glext.h:9613
GLuint in
Definition: glext.h:9616
_Check_return_ __CRT_INLINE long lrint(_In_ double x)
Definition: math.h:292
_Check_return_ __CRT_INLINE long lrintf(_In_ float x)
Definition: math.h:293
__asm__(".p2align 4, 0x90\n" ".seh_proc __seh2_global_filter_func\n" "__seh2_global_filter_func:\n" "\tsub %rbp, %rax\n" "\tpush %rbp\n" "\t.seh_pushreg %rbp\n" "\tsub $32, %rsp\n" "\t.seh_stackalloc 32\n" "\t.seh_endprologue\n" "\tsub %rax, %rdx\n" "\tmov %rdx, %rbp\n" "\tjmp *%r8\n" "__seh2_global_filter_func_exit:\n" "\t.p2align 4\n" "\tadd $32, %rsp\n" "\tpop %rbp\n" "\tret\n" "\t.seh_endproc")
#define _mm_cvtss_si32
Definition: xmmintrin.h:245
__m128 _mm_load_ss(float const *p)
Definition: xmmintrin.h:956