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