Audacity 3.2.0
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
#define lrint(dbl)
Definition: float_cast.h:169
#define lrintf(flt)
Definition: float_cast.h:170