|
1 /* Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com> */ |
|
2 /* |
|
3 Redistribution and use in source and binary forms, with or without |
|
4 modification, are permitted provided that the following conditions |
|
5 are met: |
|
6 |
|
7 - Redistributions of source code must retain the above copyright |
|
8 notice, this list of conditions and the following disclaimer. |
|
9 |
|
10 - Redistributions in binary form must reproduce the above copyright |
|
11 notice, this list of conditions and the following disclaimer in the |
|
12 documentation and/or other materials provided with the distribution. |
|
13 |
|
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
15 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
16 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
17 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER |
|
18 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
|
19 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
|
20 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
|
21 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
|
22 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
|
23 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
25 */ |
|
26 |
|
27 /* Version 1.1 */ |
|
28 |
|
29 #ifndef FLOAT_CAST_H |
|
30 #define FLOAT_CAST_H |
|
31 |
|
32 |
|
33 #include "arch.h" |
|
34 |
|
35 /*============================================================================ |
|
36 ** On Intel Pentium processors (especially PIII and probably P4), converting |
|
37 ** from float to int is very slow. To meet the C specs, the code produced by |
|
38 ** most C compilers targeting Pentium needs to change the FPU rounding mode |
|
39 ** before the float to int conversion is performed. |
|
40 ** |
|
41 ** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It |
|
42 ** is this flushing of the pipeline which is so slow. |
|
43 ** |
|
44 ** Fortunately the ISO C99 specifications define the functions lrint, lrintf, |
|
45 ** llrint and llrintf which fix this problem as a side effect. |
|
46 ** |
|
47 ** On Unix-like systems, the configure process should have detected the |
|
48 ** presence of these functions. If they weren't found we have to replace them |
|
49 ** here with a standard C cast. |
|
50 */ |
|
51 |
|
52 /* |
|
53 ** The C99 prototypes for lrint and lrintf are as follows: |
|
54 ** |
|
55 ** long int lrintf (float x) ; |
|
56 ** long int lrint (double x) ; |
|
57 */ |
|
58 |
|
59 /* The presence of the required functions are detected during the configure |
|
60 ** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in |
|
61 ** the config.h file. |
|
62 */ |
|
63 |
|
64 #if (HAVE_LRINTF) |
|
65 |
|
66 /* These defines enable functionality introduced with the 1999 ISO C |
|
67 ** standard. They must be defined before the inclusion of math.h to |
|
68 ** engage them. If optimisation is enabled, these functions will be |
|
69 ** inlined. With optimisation switched off, you have to link in the |
|
70 ** maths library using -lm. |
|
71 */ |
|
72 |
|
73 #define _ISOC9X_SOURCE 1 |
|
74 #define _ISOC99_SOURCE 1 |
|
75 |
|
76 #define __USE_ISOC9X 1 |
|
77 #define __USE_ISOC99 1 |
|
78 |
|
79 #include <math.h> |
|
80 #define float2int(x) lrintf(x) |
|
81 |
|
82 #elif (defined(HAVE_LRINT)) |
|
83 |
|
84 #define _ISOC9X_SOURCE 1 |
|
85 #define _ISOC99_SOURCE 1 |
|
86 |
|
87 #define __USE_ISOC9X 1 |
|
88 #define __USE_ISOC99 1 |
|
89 |
|
90 #include <math.h> |
|
91 #define float2int(x) lrint(x) |
|
92 |
|
93 #elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined (WIN64) || defined (_WIN64)) |
|
94 #include <xmmintrin.h> |
|
95 |
|
96 __inline long int float2int(float value) |
|
97 { |
|
98 return _mm_cvtss_si32(_mm_load_ss(&value)); |
|
99 } |
|
100 #elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined (WIN32) || defined (_WIN32)) |
|
101 #include <math.h> |
|
102 |
|
103 /* Win32 doesn't seem to have these functions. |
|
104 ** Therefore implement OPUS_INLINE versions of these functions here. |
|
105 */ |
|
106 |
|
107 __inline long int |
|
108 float2int (float flt) |
|
109 { int intgr; |
|
110 |
|
111 _asm |
|
112 { fld flt |
|
113 fistp intgr |
|
114 } ; |
|
115 |
|
116 return intgr ; |
|
117 } |
|
118 |
|
119 #else |
|
120 |
|
121 #if (defined(__GNUC__) && defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) |
|
122 /* supported by gcc in C99 mode, but not by all other compilers */ |
|
123 #warning "Don't have the functions lrint() and lrintf ()." |
|
124 #warning "Replacing these functions with a standard C cast." |
|
125 #endif /* __STDC_VERSION__ >= 199901L */ |
|
126 #include <math.h> |
|
127 #define float2int(flt) ((int)(floor(.5+flt))) |
|
128 #endif |
|
129 |
|
130 #ifndef DISABLE_FLOAT_API |
|
131 static OPUS_INLINE opus_int16 FLOAT2INT16(float x) |
|
132 { |
|
133 x = x*CELT_SIG_SCALE; |
|
134 x = MAX32(x, -32768); |
|
135 x = MIN32(x, 32767); |
|
136 return (opus_int16)float2int(x); |
|
137 } |
|
138 #endif /* DISABLE_FLOAT_API */ |
|
139 |
|
140 #endif /* FLOAT_CAST_H */ |