123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- /* Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com> */
- /*
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- /* Version 1.1 */
- #ifndef FLOAT_CAST_H
- #define FLOAT_CAST_H
- #include "arch.h"
- /*============================================================================
- ** On Intel Pentium processors (especially PIII and probably P4), converting
- ** from float to int is very slow. To meet the C specs, the code produced by
- ** most C compilers targeting Pentium needs to change the FPU rounding mode
- ** before the float to int conversion is performed.
- **
- ** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
- ** is this flushing of the pipeline which is so slow.
- **
- ** Fortunately the ISO C99 specifications define the functions lrint, lrintf,
- ** llrint and llrintf which fix this problem as a side effect.
- **
- ** On Unix-like systems, the configure process should have detected the
- ** presence of these functions. If they weren't found we have to replace them
- ** here with a standard C cast.
- */
- /*
- ** The C99 prototypes for lrint and lrintf are as follows:
- **
- ** long int lrintf (float x) ;
- ** long int lrint (double x) ;
- */
- /* The presence of the required functions are detected during the configure
- ** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
- ** the config.h file.
- */
- /* With GCC, when SSE is available, the fastest conversion is cvtss2si. */
- #if defined(__GNUC__) && defined(__SSE__)
- #include <xmmintrin.h>
- static OPUS_INLINE opus_int32 float2int(float x) {return _mm_cvt_ss2si(_mm_set_ss(x));}
- #elif defined(HAVE_LRINTF)
- /* These defines enable functionality introduced with the 1999 ISO C
- ** standard. They must be defined before the inclusion of math.h to
- ** engage them. If optimisation is enabled, these functions will be
- ** inlined. With optimisation switched off, you have to link in the
- ** maths library using -lm.
- */
- #define _ISOC9X_SOURCE 1
- #define _ISOC99_SOURCE 1
- #define __USE_ISOC9X 1
- #define __USE_ISOC99 1
- #include <math.h>
- #define float2int(x) lrintf(x)
- #elif (defined(HAVE_LRINT))
- #define _ISOC9X_SOURCE 1
- #define _ISOC99_SOURCE 1
- #define __USE_ISOC9X 1
- #define __USE_ISOC99 1
- #include <math.h>
- #define float2int(x) lrint(x)
- #elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1))
- #include <xmmintrin.h>
- static __inline long int float2int(float value)
- {
- return _mm_cvtss_si32(_mm_load_ss(&value));
- }
- #elif (defined(_MSC_VER) && _MSC_VER >= 1400) && defined (_M_IX86)
- #include <math.h>
- /* Win32 doesn't seem to have these functions.
- ** Therefore implement OPUS_INLINE versions of these functions here.
- */
- static __inline long int
- float2int (float flt)
- { int intgr;
- _asm
- { fld flt
- fistp intgr
- } ;
- return intgr ;
- }
- #else
- #if (defined(__GNUC__) && defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L)
- /* supported by gcc in C99 mode, but not by all other compilers */
- #warning "Don't have the functions lrint() and lrintf ()."
- #warning "Replacing these functions with a standard C cast."
- #endif /* __STDC_VERSION__ >= 199901L */
- #include <math.h>
- #define float2int(flt) ((int)(floor(.5+flt)))
- #endif
- #ifndef DISABLE_FLOAT_API
- static OPUS_INLINE opus_int16 FLOAT2INT16(float x)
- {
- x = x*CELT_SIG_SCALE;
- x = MAX32(x, -32768);
- x = MIN32(x, 32767);
- return (opus_int16)float2int(x);
- }
- #endif /* DISABLE_FLOAT_API */
- #endif /* FLOAT_CAST_H */
|