]> iEval git - audio-libsamplerate.git/blob - libsamplerate/src/float_cast.h
0318427e5fa93543b709d22972f063beb719f93b
[audio-libsamplerate.git] / libsamplerate / src / float_cast.h
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 __inline long int
153 lrint (double flt)
154 { int intgr ;
155
156 _asm
157 { fld flt
158 fistp intgr
159 } ;
160
161 return intgr ;
162 }
163
164 __inline long int
165 lrintf (float flt)
166 { int intgr ;
167
168 _asm
169 { fld flt
170 fistp intgr
171 } ;
172
173 return intgr ;
174 }
175
176 #elif (defined (__MWERKS__) && defined (macintosh))
177
178 /* This MacOS 9 solution was provided by Stephane Letz */
179
180 #undef HAVE_LRINT_REPLACEMENT
181 #define HAVE_LRINT_REPLACEMENT 1
182 #include <math.h>
183
184 #undef lrint
185 #undef lrintf
186
187 #define lrint double2int
188 #define lrintf float2int
189
190 inline int
191 float2int (register float in)
192 { long res [2] ;
193
194 asm
195 { fctiw in, in
196 stfd in, res
197 }
198 return res [1] ;
199 } /* float2int */
200
201 inline int
202 double2int (register double in)
203 { long res [2] ;
204
205 asm
206 { fctiw in, in
207 stfd in, res
208 }
209 return res [1] ;
210 } /* double2int */
211
212 #elif (defined (__MACH__) && defined (__APPLE__))
213
214 /* For Apple MacOSX. */
215
216 #undef HAVE_LRINT_REPLACEMENT
217 #define HAVE_LRINT_REPLACEMENT 1
218 #include <math.h>
219
220 #undef lrint
221 #undef lrintf
222
223 #define lrint double2int
224 #define lrintf float2int
225
226 inline static long
227 float2int (register float in)
228 { int res [2] ;
229
230 __asm__ __volatile__
231 ( "fctiw %1, %1\n\t"
232 "stfd %1, %0"
233 : "=m" (res) /* Output */
234 : "f" (in) /* Input */
235 : "memory"
236 ) ;
237
238 return res [1] ;
239 } /* lrintf */
240
241 inline static long
242 double2int (register double in)
243 { int res [2] ;
244
245 __asm__ __volatile__
246 ( "fctiw %1, %1\n\t"
247 "stfd %1, %0"
248 : "=m" (res) /* Output */
249 : "f" (in) /* Input */
250 : "memory"
251 ) ;
252
253 return res [1] ;
254 } /* lrint */
255
256 #else
257 #ifndef __sgi
258 #warning "Don't have the functions lrint() and lrintf()."
259 #warning "Replacing these functions with a standard C cast."
260 #endif
261
262 #include <math.h>
263
264 #define lrint(dbl) ((long) (dbl))
265 #define lrintf(flt) ((long) (flt))
266
267 #endif
268
269
270 #endif /* FLOAT_CAST_HEADER */
271
This page took 0.0643049999999999 seconds and 5 git commands to generate.