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