Audacity  3.0.3
float_cast.h
Go to the documentation of this file.
1 /*
2 ** Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
3 **
4 ** Permission to use, copy, modify, distribute, and sell this file for any
5 ** purpose is hereby granted without fee, provided that the above copyright
6 ** and this permission notice appear in all copies. No representations are
7 ** made about the suitability of this software for any purpose. It is
8 ** provided "as is" without express or implied warranty.
9 */
10 
11 /* Version 1.1 */
12 
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 /* The presence of the required functions are detected during the configure
39 ** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
40 ** the config.h file.
41 */
42 #if (defined (WIN32) || defined (_WIN32)) && defined(_MSC_VER) && defined(_M_IX86)
43  // As of Visual Studio 2019 16.9, these functions have been made intrinsic and the build
44  // will fail. Unfortunately, the intrinsic versions run a LOT slower than the ones
45  // below, so force the compiler to use ours instead.
46  #pragma function( lrint, lrintf )
47 
48  // Including math.h allows us to use the inline assembler versions without
49  // producing errors in newer Visual Studio versions.
50  // Without the include, we get different linkage error messages.
51  // Without the inline assembler versions, these functions are VERY slow.
52  // I also see that the include was part of the original source for this file:
53  // http://www.mega-nerd.com/FPcast/
54 
55  #include <math.h>
56 
57  /* Win32 doesn't seem to have these functions.
58  ** Therefore implement inline versions of these functions here.
59  */
60  __inline long int
61  lrint (double flt)
62  { int intgr;
63 
64  _asm
65  { fld flt
66  fistp intgr
67  } ;
68 
69  return intgr ;
70  }
71 
72  __inline long int
73  lrintf (float flt)
74  { int intgr;
75 
76  _asm
77  { fld flt
78  fistp intgr
79  } ;
80 
81  return intgr ;
82  }
83 
84  __inline long long int
85  llrint (double flt)
86  { long long int intgr;
87 
88  _asm
89  { fld flt
90  fistp intgr
91  } ;
92 
93  return intgr ;
94  }
95 
96  __inline long long int
97  llrintf (float flt)
98  { long long int intgr;
99 
100  _asm
101  { fld flt
102  fistp intgr
103  } ;
104 
105  return intgr ;
106  }
107 #elif (defined (WIN32) || defined (_WIN32)) && defined(_M_X64)
108 
109  #include <math.h>
110  #include <immintrin.h>
111  #include <emmintrin.h>
112 
113  #ifdef _MSC_VER
114  #pragma function(lrint, lrintf)
115  #endif
116 
117  __inline
118  long int lrint(double flt)
119  {
120  return _mm_cvtsd_si32(_mm_set_sd(flt));
121  }
122 
123  __inline
124  long int lrintf (float flt)
125  {
126  return _mm_cvtss_si32(_mm_set_ss(flt));
127  }
128 
129  __inline
130  long long int llrint(double flt)
131  {
132  return _mm_cvtsd_si64(_mm_set_sd(flt));
133  }
134 
135  __inline
136  long long int llrintf(float flt)
137  {
138  return _mm_cvtss_si64(_mm_set_ss(flt));
139  }
140 
141 #elif (HAVE_LRINT && HAVE_LRINTF)
142 
143  /* These defines enable functionality introduced with the 1999 ISO C
144  ** standard. They must be defined before the inclusion of math.h to
145  ** engage them. If optimisation is enabled, these functions will be
146  ** inlined. With optimisation switched off, you have to link in the
147  ** maths library using -lm.
148  */
149 
150  #define _ISOC9X_SOURCE 1
151  #define _ISOC99_SOURCE 1
152 
153  #define __USE_ISOC9X 1
154  #define __USE_ISOC99 1
155 
156  #include <math.h>
157 #else
158 
159  /* dmazzoni: modified these to do a proper rounding, even though
160  * it's slower. Correctness and consistency is more important
161  * than speed, especially since lrint/lrintf are certainly not
162  * available everywhere.
163  *
164  * MM: Now uses internal math.h rint() function
165  */
166 
167  #include <math.h>
168 
169  #define lrint(dbl) ((int)rint(dbl))
170  #define lrintf(flt) ((int)rint(flt))
171 
172 #endif
lrintf
#define lrintf(flt)
Definition: float_cast.h:170
lrint
#define lrint(dbl)
Definition: float_cast.h:169