Max delta: +/- 16384
[opus.git] / libcelt / float_cast.h
1 /*
2 ** Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
3 **
4 ** Permission to use, copy, modify, distribute, and sell this file for any 
5 ** purpose is hereby granted without fee, provided that the above copyright 
6 ** and this permission notice appear in all copies.  No representations are
7 ** made about the suitability of this software for any purpose.  It is 
8 ** provided "as is" without express or implied warranty.
9 */
10
11 /* Version 1.1 */
12
13 #ifndef FLOAT_CAST_H
14 #define FLOAT_CAST_H
15
16 /*============================================================================ 
17 **      On Intel Pentium processors (especially PIII and probably P4), converting
18 **      from float to int is very slow. To meet the C specs, the code produced by 
19 **      most C compilers targeting Pentium needs to change the FPU rounding mode 
20 **      before the float to int conversion is performed. 
21 **
22 **      Changing the FPU rounding mode causes the FPU pipeline to be flushed. It 
23 **      is this flushing of the pipeline which is so slow.
24 **
25 **      Fortunately the ISO C99 specifications define the functions lrint, lrintf,
26 **      llrint and llrintf which fix this problem as a side effect. 
27 **
28 **      On Unix-like systems, the configure process should have detected the 
29 **      presence of these functions. If they weren't found we have to replace them 
30 **      here with a standard C cast.
31 */
32
33 /*      
34 **      The C99 prototypes for lrint and lrintf are as follows:
35 **      
36 **              long int lrintf (float x) ;
37 **              long int lrint  (double x) ;
38 */
39
40 /*      The presence of the required functions are detected during the configure
41 **      process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
42 **      the config.h file.
43 */
44
45 #if (HAVE_LRINTF)
46 /*#if 0*/
47
48         /*      These defines enable functionality introduced with the 1999 ISO C
49         **      standard. They must be defined before the inclusion of math.h to
50         **      engage them. If optimisation is enabled, these functions will be 
51         **      inlined. With optimisation switched off, you have to link in the
52         **      maths library using -lm.
53         */
54
55         #define _ISOC9X_SOURCE  1
56         #define _ISOC99_SOURCE  1
57
58         #define __USE_ISOC9X    1
59         #define __USE_ISOC99    1
60
61         #include        <math.h>
62         #define float2int(x) lrintf(x)
63
64 #elif (defined(HAVE_LRINT))
65
66 #define _ISOC9X_SOURCE  1
67 #define _ISOC99_SOURCE  1
68
69 #define __USE_ISOC9X    1
70 #define __USE_ISOC99    1
71
72 #include        <math.h>
73 #define float2int(x) lrint(x)
74
75 #elif (defined (WIN64) || defined (_WIN64))
76         #include <xmmintrin.h>
77
78         __inline long int float2int(float value)
79         {
80                 return _mm_cvtss_si32(_mm_load_ss(&value));
81         }
82 #elif (defined (WIN32) || defined (_WIN32))
83
84         #include        <math.h>
85
86         /*      Win32 doesn't seem to have these functions. 
87         **      Therefore implement inline versions of these functions here.
88         */
89         
90         __inline long int 
91         float2int (float flt)
92         {       int intgr;
93
94                 _asm
95                 {       fld flt
96                         fistp intgr
97                         } ;
98                         
99                 return intgr ;
100         }
101
102 #else
103
104 #ifdef __GNUC__ /* supported by gcc, but not by all other compilers*/
105         #warning "Don't have the functions lrint() and lrintf ()."
106         #warning "Replacing these functions with a standard C cast."
107 #endif /* __GNUC__ */
108
109         #include        <math.h>
110
111         #define float2int(flt)          ((int)(floor(.5+flt)))
112
113 #endif
114
115
116 #endif /* FLOAT_CAST_H */