1 
2 /* @(#)s_lrint.c 5.1 93/09/24 */
3 /*
4  * ====================================================
5  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
6  *
7  * Developed at SunPro, a Sun Microsystems, Inc. business.
8  * Permission to use, copy, modify, and distribute this
9  * software is freely granted, provided that this notice
10  * is preserved.
11  * ====================================================
12  */
13 
14 /*
15  * lrint(x)
16  * Return x rounded to integral value according to the prevailing
17  * rounding mode.
18  * Method:
19  *	Using floating addition.
20  * Exception:
21  *	Inexact flag raised if x not equal to lrint(x).
22  */
23 
24 #include "fdlibm.h"
25 
26 #ifndef _DOUBLE_IS_32BITS
27 
28 #ifdef __STDC__
29 static const double
30 #else
31 static double
32 #endif
33 
34 /* Adding a double, x, to 2^52 will cause the result to be rounded based on
35    the fractional part of x, according to the implementation's current rounding
36    mode.  2^52 is the smallest double that can be represented using all 52 significant
37    digits. */
38 TWO52[2]={
39   4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
40  -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
41 };
42 
43 #ifdef __STDC__
lrint(double x)44 	long int lrint(double x)
45 #else
46 	long int lrint(x)
47 	double x;
48 #endif
49 {
50   __int32_t i0,j0,sx;
51   __uint32_t i1;
52   double t;
53   volatile double w;
54   long int result;
55 
56   EXTRACT_WORDS(i0,i1,x);
57   sx = (i0>>31)&1;
58   j0 = ((i0 & 0x7ff00000) >> 20) - 1023;
59 
60   if(j0 < 20)
61     {
62       if(j0 < -1)
63         return 0;
64       else
65         {
66           w = TWO52[sx] + x;
67           t = w - TWO52[sx];
68           GET_HIGH_WORD(i0, t);
69           j0 = ((i0 & 0x7ff00000) >> 20) - 1023;
70           i0 &= 0x000fffff;
71           i0 |= 0x00100000;
72           result = i0 >> (20 - j0);
73         }
74     }
75   else if (j0 < (8 * sizeof (long int)) - 1)
76     {
77       if (j0 >= 52)
78         result = ((long int) i0 << (j0 - 20)) | (i1 << (j0 - 52));
79       else
80         {
81           w = TWO52[sx] + x;
82           t = w - TWO52[sx];
83           EXTRACT_WORDS (i0, i1, t);
84           j0 = ((i0 & 0x7ff00000) >> 20) - 1023;
85           i0 &= 0x000fffff;
86           i0 |= 0x00100000;
87           result = ((long int) i0 << (j0 - 20)) | (i1 >> (52 - j0));
88         }
89     }
90   else
91     {
92       return (long int) x;
93     }
94 
95   return sx ? -result : result;
96 }
97 
98 #endif /* _DOUBLE_IS_32BITS */
99