Alexandre Lision | 744f742 | 2013-09-25 11:39:37 -0400 | [diff] [blame] | 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. |
Alexandre Lision | 8538238 | 2014-01-27 15:54:16 -0500 | [diff] [blame] | 104 | ** Therefore implement OPUS_INLINE versions of these functions here. |
Alexandre Lision | 744f742 | 2013-09-25 11:39:37 -0400 | [diff] [blame] | 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 |
Alexandre Lision | 8538238 | 2014-01-27 15:54:16 -0500 | [diff] [blame] | 131 | static OPUS_INLINE opus_int16 FLOAT2INT16(float x) |
Alexandre Lision | 744f742 | 2013-09-25 11:39:37 -0400 | [diff] [blame] | 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 */ |