Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfloat_cast.h
Go to the documentation of this file.
00001 /* 00002 ** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com> 00003 ** 00004 ** This program is free software; you can redistribute it and/or modify 00005 ** it under the terms of the GNU Lesser General Public License as published by 00006 ** the Free Software Foundation; either version 2.1 of the License, or 00007 ** (at your option) any later version. 00008 ** 00009 ** This program is distributed in the hope that it will be useful, 00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 ** GNU Lesser General Public License for more details. 00013 ** 00014 ** You should have received a copy of the GNU Lesser General Public License 00015 ** along with this program; if not, write to the Free Software 00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 */ 00018 00019 /* Version 1.5 */ 00020 00021 #ifndef FLOAT_CAST_HEADER 00022 #define FLOAT_CAST_HEADER 00023 00024 /*============================================================================ 00025 ** On Intel Pentium processors (especially PIII and probably P4), converting 00026 ** from float to int is very slow. To meet the C specs, the code produced by 00027 ** most C compilers targeting Pentium needs to change the FPU rounding mode 00028 ** before the float to int conversion is performed. 00029 ** 00030 ** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It 00031 ** is this flushing of the pipeline which is so slow. 00032 ** 00033 ** Fortunately the ISO C99 specifications define the functions lrint, lrintf, 00034 ** llrint and llrintf which fix this problem as a side effect. 00035 ** 00036 ** On Unix-like systems, the configure process should have detected the 00037 ** presence of these functions. If they weren't found we have to replace them 00038 ** here with a standard C cast. 00039 */ 00040 00041 /* 00042 ** The C99 prototypes for lrint and lrintf are as follows: 00043 ** 00044 ** long int lrintf (float x) ; 00045 ** long int lrint (double x) ; 00046 */ 00047 00048 #include "config.h" 00049 00050 /* 00051 ** The presence of the required functions are detected during the configure 00052 ** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in 00053 ** the config.h file. 00054 */ 00055 00056 #define HAVE_LRINT_REPLACEMENT 0 00057 00058 #if (HAVE_LRINT && HAVE_LRINTF) 00059 00060 /* 00061 ** These defines enable functionality introduced with the 1999 ISO C 00062 ** standard. They must be defined before the inclusion of math.h to 00063 ** engage them. If optimisation is enabled, these functions will be 00064 ** inlined. With optimisation switched off, you have to link in the 00065 ** maths library using -lm. 00066 */ 00067 00068 #define _ISOC9X_SOURCE 1 00069 #define _ISOC99_SOURCE 1 00070 00071 #define __USE_ISOC9X 1 00072 #define __USE_ISOC99 1 00073 00074 #include <math.h> 00075 00076 #elif (defined (__CYGWIN__)) 00077 00078 #include <math.h> 00079 00080 #undef HAVE_LRINT_REPLACEMENT 00081 #define HAVE_LRINT_REPLACEMENT 1 00082 00083 #undef lrint 00084 #undef lrintf 00085 00086 #define lrint double2int 00087 #define lrintf float2int 00088 00089 /* 00090 ** The native CYGWIN lrint and lrintf functions are buggy: 00091 ** http://sourceware.org/ml/cygwin/2005-06/msg00153.html 00092 ** http://sourceware.org/ml/cygwin/2005-09/msg00047.html 00093 ** and slow. 00094 ** These functions (pulled from the Public Domain MinGW math.h header) 00095 ** replace the native versions. 00096 */ 00097 00098 static inline long double2int (double in) 00099 { long retval ; 00100 00101 __asm__ __volatile__ 00102 ( "fistpl %0" 00103 : "=m" (retval) 00104 : "t" (in) 00105 : "st" 00106 ) ; 00107 00108 return retval ; 00109 } /* double2int */ 00110 00111 static inline long float2int (float in) 00112 { long retval ; 00113 00114 __asm__ __volatile__ 00115 ( "fistpl %0" 00116 : "=m" (retval) 00117 : "t" (in) 00118 : "st" 00119 ) ; 00120 00121 return retval ; 00122 } /* float2int */ 00123 00124 #elif (defined (WIN64) || defined(_WIN64)) 00125 00126 /* Win64 section should be places before Win32 one, because 00127 ** most likely both WIN32 and WIN64 will be defined in 64-bit case. 00128 */ 00129 00130 #include <math.h> 00131 00132 /* Win64 doesn't seem to have these functions, nor inline assembly. 00133 ** Therefore implement inline versions of these functions here. 00134 */ 00135 #include <emmintrin.h> 00136 #include <mmintrin.h> 00137 00138 __inline long int 00139 lrint(double flt) 00140 { 00141 return _mm_cvtsd_si32(_mm_load_sd(&flt)); 00142 } 00143 00144 __inline long int 00145 lrintf(float flt) 00146 { 00147 return _mm_cvtss_si32(_mm_load_ss(&flt)); 00148 } 00149 00150 #elif (defined (WIN32) || defined (_WIN32)) 00151 00152 #undef HAVE_LRINT_REPLACEMENT 00153 #define HAVE_LRINT_REPLACEMENT 1 00154 00155 #include <math.h> 00156 00157 /* 00158 ** Win32 doesn't seem to have these functions. 00159 ** Therefore implement inline versions of these functions here. 00160 */ 00161 00162 #ifdef _MSC_VER 00163 __inline long int 00164 lrint (double flt) 00165 { int intgr ; 00166 00167 _asm 00168 { fld flt 00169 fistp intgr 00170 } ; 00171 00172 return intgr ; 00173 } 00174 00175 __inline long int 00176 lrintf (float flt) 00177 { int intgr ; 00178 00179 _asm 00180 { fld flt 00181 fistp intgr 00182 } ; 00183 00184 return intgr ; 00185 } 00186 #else 00187 static __inline long int 00188 lrint (double flt) 00189 { 00190 int intgr ; 00191 __asm__ __volatile__ ("fldl %1; fistpl %0;" : "=m" (intgr) : "m" (flt)); 00192 return intgr ; 00193 } 00194 00195 static __inline long int 00196 lrintf (float flt) 00197 { 00198 int intgr ; 00199 00200 __asm__ __volatile__ ("flds %1; fistpl %0;" : "=m" (intgr) : "m" (flt)); 00201 return intgr ; 00202 } 00203 #endif 00204 00205 #elif (defined (__MWERKS__) && defined (macintosh)) 00206 00207 /* This MacOS 9 solution was provided by Stephane Letz */ 00208 00209 #undef HAVE_LRINT_REPLACEMENT 00210 #define HAVE_LRINT_REPLACEMENT 1 00211 #include <math.h> 00212 00213 #undef lrint 00214 #undef lrintf 00215 00216 #define lrint double2int 00217 #define lrintf float2int 00218 00219 inline int 00220 float2int (register float in) 00221 { long res [2] ; 00222 00223 asm 00224 { fctiw in, in 00225 stfd in, res 00226 } 00227 return res [1] ; 00228 } /* float2int */ 00229 00230 inline int 00231 double2int (register double in) 00232 { long res [2] ; 00233 00234 asm 00235 { fctiw in, in 00236 stfd in, res 00237 } 00238 return res [1] ; 00239 } /* double2int */ 00240 00241 #elif (defined (__MACH__) && defined (__APPLE__)) 00242 00243 /* For Apple MacOSX. */ 00244 00245 #undef HAVE_LRINT_REPLACEMENT 00246 #define HAVE_LRINT_REPLACEMENT 1 00247 #include <math.h> 00248 00249 #undef lrint 00250 #undef lrintf 00251 00252 #define lrint double2int 00253 #define lrintf float2int 00254 00255 inline static long 00256 float2int (register float in) 00257 { int res [2] ; 00258 00259 __asm__ __volatile__ 00260 ( "fctiw %1, %1\n\t" 00261 "stfd %1, %0" 00262 : "=m" (res) /* Output */ 00263 : "f" (in) /* Input */ 00264 : "memory" 00265 ) ; 00266 00267 return res [1] ; 00268 } /* lrintf */ 00269 00270 inline static long 00271 double2int (register double in) 00272 { int res [2] ; 00273 00274 __asm__ __volatile__ 00275 ( "fctiw %1, %1\n\t" 00276 "stfd %1, %0" 00277 : "=m" (res) /* Output */ 00278 : "f" (in) /* Input */ 00279 : "memory" 00280 ) ; 00281 00282 return res [1] ; 00283 } /* lrint */ 00284 00285 #else 00286 #ifndef __sgi 00287 #warning "Don't have the functions lrint() and lrintf()." 00288 #warning "Replacing these functions with a standard C cast." 00289 #endif 00290 00291 #include <math.h> 00292 00293 #define lrint(dbl) ((long) (dbl)) 00294 #define lrintf(flt) ((long) (flt)) 00295 00296 #endif 00297 00298 00299 #endif /* FLOAT_CAST_HEADER */ 00300 Generated on Sun May 27 2012 04:34:11 for ReactOS by
1.7.6.1
|