0dcceb3f5303ef6760c7122103ce0b11d46ccf7e
2 ** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
4 ** This program is free software; you can redistribute it and/or modify
5 ** it under the terms of the GNU Lesser General Public License as published by
6 ** the Free Software Foundation; either version 2.1 of the License, or
7 ** (at your option) any later version.
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ** GNU Lesser General Public License for more details.
14 ** You should have received a copy of the GNU Lesser General Public License
15 ** along with this program; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #ifndef FLOAT_CAST_HEADER
22 #define FLOAT_CAST_HEADER
24 /*============================================================================
25 ** On Intel Pentium processors (especially PIII and probably P4), converting
26 ** from float to int is very slow. To meet the C specs, the code produced by
27 ** most C compilers targeting Pentium needs to change the FPU rounding mode
28 ** before the float to int conversion is performed.
30 ** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
31 ** is this flushing of the pipeline which is so slow.
33 ** Fortunately the ISO C99 specifications define the functions lrint, lrintf,
34 ** llrint and llrintf which fix this problem as a side effect.
36 ** On Unix-like systems, the configure process should have detected the
37 ** presence of these functions. If they weren't found we have to replace them
38 ** here with a standard C cast.
42 ** The C99 prototypes for lrint and lrintf are as follows:
44 ** long int lrintf (float x) ;
45 ** long int lrint (double x) ;
51 ** The presence of the required functions are detected during the configure
52 ** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
56 #define HAVE_LRINT_REPLACEMENT 0
58 #if (HAVE_LRINT && HAVE_LRINTF)
61 ** These defines enable functionality introduced with the 1999 ISO C
62 ** standard. They must be defined before the inclusion of math.h to
63 ** engage them. If optimisation is enabled, these functions will be
64 ** inlined. With optimisation switched off, you have to link in the
65 ** maths library using -lm.
68 #define _ISOC9X_SOURCE 1
69 #define _ISOC99_SOURCE 1
71 #define __USE_ISOC9X 1
72 #define __USE_ISOC99 1
76 #elif (defined (__CYGWIN__))
80 #undef HAVE_LRINT_REPLACEMENT
81 #define HAVE_LRINT_REPLACEMENT 1
86 #define lrint double2int
87 #define lrintf float2int
90 ** The native CYGWIN lrint and lrintf functions are buggy:
91 ** http://sourceware.org/ml/cygwin/2005-06/msg00153.html
92 ** http://sourceware.org/ml/cygwin/2005-09/msg00047.html
94 ** These functions (pulled from the Public Domain MinGW math.h header)
95 ** replace the native versions.
98 static inline long double2int (double in
)
111 static inline long float2int (float in
)
124 #elif (defined (WIN64) || defined(_WIN64))
126 /* Win64 section should be places before Win32 one, because
127 ** most likely both WIN32 and WIN64 will be defined in 64-bit case.
132 /* Win64 doesn't seem to have these functions, nor inline assembly.
133 ** Therefore implement inline versions of these functions here.
135 #include <emmintrin.h>
136 #include <mmintrin.h>
141 return _mm_cvtsd_si32(_mm_load_sd(&flt
));
147 return _mm_cvtss_si32(_mm_load_ss(&flt
));
150 #elif (defined (WIN32) || defined (_WIN32))
152 #undef HAVE_LRINT_REPLACEMENT
153 #define HAVE_LRINT_REPLACEMENT 1
158 ** Win32 doesn't seem to have these functions.
159 ** Therefore implement inline versions of these functions here.
187 extern __inline
long int
191 __asm__
__volatile__ ("fldl %1; fistpl %0;" : "=m" (intgr
) : "m" (flt
));
195 extern __inline
long int
200 __asm__
__volatile__ ("flds %1; fistpl %0;" : "=m" (intgr
) : "m" (flt
));
205 #elif (defined (__MWERKS__) && defined (macintosh))
207 /* This MacOS 9 solution was provided by Stephane Letz */
209 #undef HAVE_LRINT_REPLACEMENT
210 #define HAVE_LRINT_REPLACEMENT 1
216 #define lrint double2int
217 #define lrintf float2int
220 float2int (register float in
)
231 double2int (register double in
)
241 #elif (defined (__MACH__) && defined (__APPLE__))
243 /* For Apple MacOSX. */
245 #undef HAVE_LRINT_REPLACEMENT
246 #define HAVE_LRINT_REPLACEMENT 1
252 #define lrint double2int
253 #define lrintf float2int
256 float2int (register float in
)
262 : "=m" (res
) /* Output */
263 : "f" (in
) /* Input */
271 double2int (register double in
)
277 : "=m" (res
) /* Output */
278 : "f" (in
) /* Input */
287 #warning "Don't have the functions lrint() and lrintf()."
288 #warning "Replacing these functions with a standard C cast."
293 #define lrint(dbl) ((long) (dbl))
294 #define lrintf(flt) ((long) (flt))
299 #endif /* FLOAT_CAST_HEADER */