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
14 /*============================================================================
15 ** On Intel Pentium processors (especially PIII and probably P4), converting
16 ** from float to int is very slow. To meet the C specs, the code produced by
17 ** most C compilers targeting Pentium needs to change the FPU rounding mode
18 ** before the float to int conversion is performed.
19 **
20 ** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
21 ** is this flushing of the pipeline which is so slow.
22 **
23 ** Fortunately the ISO C99 specifications define the functions lrint, lrintf,
24 ** llrint and llrintf which fix this problem as a side effect.
25 **
26 ** On Unix-like systems, the configure process should have detected the
27 ** presence of these functions. If they weren't found we have to replace them
28 ** here with a standard C cast.
29 */
30
31 /*
32 ** The C99 prototypes for lrint and lrintf are as follows:
33 **
34 ** long int lrintf (float x) ;
35 ** long int lrint (double x) ;
36 */
37
38 #ifndef float_cast_h
39 #define float_cast_h
40
41 #include "config.h"
42
43 /* The presence of the required functions are detected during the configure
44 ** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
45 ** the config.h file.
46 */
47
48 #if (HAVE_LRINT && HAVE_LRINTF)
49
50 /* These defines enable functionality introduced with the 1999 ISO C
51 ** standard. They must be defined before the inclusion of math.h to
52 ** engage them. If optimisation is enabled, these functions will be
53 ** inlined. With optimisation switched off, you have to link in the
54 ** maths library using -lm.
55 */
56
57 #define _ISOC9X_SOURCE 1
58 #define _ISOC99_SOURCE 1
59
60 #define __USE_ISOC9X 1
61 #define __USE_ISOC99 1
62
63 #include <math.h>
64
65 #elif (defined (WIN32) || defined (_WIN32))
66
67 #include <math.h>
68
69 /* Win32 doesn't seem to have these functions.
70 ** Therefore implement inline versions of these functions here.
71 */
72
73 __inline long int
74 lrint (double flt) ;
75 { int intgr;
76
77 _asm
78 { fld flt
79 fistp intgr
80 } ;
81
82 return intgr ;
83 }
84
85 __inline long int
lrintf(float flt)86 lrintf (float flt)
87 { int intgr;
88
89 _asm
90 { fld flt
91 fistp intgr
92 } ;
93
94 return intgr ;
95 }
96
97 #else
98
99 #warning "Don't have the functions lrint() and lrintf ()."
100 #warning "Replacing these functions with a standard C cast."
101
102 #include <math.h>
103
104 #define lrint(dbl) ((int)(dbl))
105
106 /*
107 * Round float to int
108 */
109 static inline int
lrintf(float f)110 lrintf (float f)
111 {
112 f += (3<<22);
113 return *((int*)&f) - 0x4b400000;
114 }
115
116 #endif
117
118 #endif /* float_cast_h */
119