Line data Source code
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 : /* With GCC, when SSE is available, the fastest conversion is cvtss2si. */
65 : #if defined(__GNUC__) && defined(__SSE__)
66 :
67 : #include <xmmintrin.h>
68 0 : static OPUS_INLINE opus_int32 float2int(float x) {return _mm_cvt_ss2si(_mm_set_ss(x));}
69 :
70 : #elif defined(HAVE_LRINTF)
71 :
72 : /* These defines enable functionality introduced with the 1999 ISO C
73 : ** standard. They must be defined before the inclusion of math.h to
74 : ** engage them. If optimisation is enabled, these functions will be
75 : ** inlined. With optimisation switched off, you have to link in the
76 : ** maths library using -lm.
77 : */
78 :
79 : #define _ISOC9X_SOURCE 1
80 : #define _ISOC99_SOURCE 1
81 :
82 : #define __USE_ISOC9X 1
83 : #define __USE_ISOC99 1
84 :
85 : #include <math.h>
86 : #define float2int(x) lrintf(x)
87 :
88 : #elif (defined(HAVE_LRINT))
89 :
90 : #define _ISOC9X_SOURCE 1
91 : #define _ISOC99_SOURCE 1
92 :
93 : #define __USE_ISOC9X 1
94 : #define __USE_ISOC99 1
95 :
96 : #include <math.h>
97 : #define float2int(x) lrint(x)
98 :
99 : #elif (defined(_MSC_VER) && _MSC_VER >= 1400) && defined (_M_X64)
100 : #include <xmmintrin.h>
101 :
102 : __inline long int float2int(float value)
103 : {
104 : return _mm_cvtss_si32(_mm_load_ss(&value));
105 : }
106 : #elif (defined(_MSC_VER) && _MSC_VER >= 1400) && defined (_M_IX86)
107 : #include <math.h>
108 :
109 : /* Win32 doesn't seem to have these functions.
110 : ** Therefore implement OPUS_INLINE versions of these functions here.
111 : */
112 :
113 : __inline long int
114 : float2int (float flt)
115 : { int intgr;
116 :
117 : _asm
118 : { fld flt
119 : fistp intgr
120 : } ;
121 :
122 : return intgr ;
123 : }
124 :
125 : #else
126 :
127 : #if (defined(__GNUC__) && defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L)
128 : /* supported by gcc in C99 mode, but not by all other compilers */
129 : #warning "Don't have the functions lrint() and lrintf ()."
130 : #warning "Replacing these functions with a standard C cast."
131 : #endif /* __STDC_VERSION__ >= 199901L */
132 : #include <math.h>
133 : #define float2int(flt) ((int)(floor(.5+flt)))
134 : #endif
135 :
136 : #ifndef DISABLE_FLOAT_API
137 0 : static OPUS_INLINE opus_int16 FLOAT2INT16(float x)
138 : {
139 0 : x = x*CELT_SIG_SCALE;
140 0 : x = MAX32(x, -32768);
141 0 : x = MIN32(x, 32767);
142 0 : return (opus_int16)float2int(x);
143 : }
144 : #endif /* DISABLE_FLOAT_API */
145 :
146 : #endif /* FLOAT_CAST_H */
|