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 274