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 FUNCTION
15 <<lrint>>, <<lrintf>>, <<llrint>>, <<llrintf>>---round to integer
16 INDEX
17 	lrint
18 INDEX
19 	lrintf
20 INDEX
21 	llrint
22 INDEX
23 	llrintf
24 
25 SYNOPSIS
26 	#include <math.h>
27 	long int lrint(double <[x]>);
28 	long int lrintf(float <[x]>);
29 	long long int llrint(double <[x]>);
30 	long long int llrintf(float <[x]>);
31 
32 DESCRIPTION
33 The <<lrint>> and <<llrint>> functions round their argument to the nearest
34 integer value, using the current rounding direction.  If the rounded value is
35 outside the range of the return type, the numeric result is unspecified.  A
36 range error may occur if the magnitude of <[x]> is too large.
37 The "inexact" floating-point exception is raised in implementations that
38 support it when the result differs in value from the argument (i.e., when
39 a fraction actually has been truncated).
40 
41 RETURNS
42 <[x]> rounded to an integral value, using the current rounding direction.
43 
44 SEEALSO
45 <<lround>>
46 
47 PORTABILITY
48 ANSI C, POSIX
49 
50 */
51 
52 /*
53  * lrint(x)
54  * Return x rounded to integral value according to the prevailing
55  * rounding mode.
56  * Method:
57  *	Using floating addition.
58  * Exception:
59  *	Inexact flag raised if x not equal to lrint(x).
60  */
61 
62 #include "fdlibm.h"
63 #include <limits.h>
64 
65 #ifdef _NEED_FLOAT64
66 
67 static const __float64
68 
69 /* Adding a double, x, to 2^52 will cause the result to be rounded based on
70    the fractional part of x, according to the implementation's current rounding
71    mode.  2^52 is the smallest double that can be represented using all 52 significant
72    digits. */
73 TWO52[2]={
74   _F_64(4.50359962737049600000e+15), /* 0x43300000, 0x00000000 */
75  _F_64(-4.50359962737049600000e+15), /* 0xC3300000, 0x00000000 */
76 };
77 
78 long int
lrint64(__float64 x)79 lrint64(__float64 x)
80 {
81   __int32_t i0,j0,sx;
82   __uint32_t i1;
83   __float64 t;
84   volatile __float64 w;
85   long int result;
86 
87   EXTRACT_WORDS(i0,i1,x);
88 
89   /* Extract sign bit. */
90   sx = (i0>>31)&1;
91 
92   /* Extract exponent field. */
93   j0 = ((i0 & 0x7ff00000) >> 20) - 1023;
94   /* j0 in [-1023,1024] */
95 
96   if(j0 < 20)
97     {
98       /* j0 in [-1023,19] */
99       /* shift amt in [0,19] */
100       w = TWO52[sx] + x;
101       t = w - TWO52[sx];
102       GET_HIGH_WORD(i0, t);
103       /* After round:  j0 in [0,20] */
104       j0 = ((i0 & 0x7ff00000) >> 20) - 1023;
105       i0 &= 0x000fffff;
106       i0 |= 0x00100000;
107       /* shift amt in [20,0] */
108       if (j0 < 0)
109         result = 0;
110       else
111         result = i0 >> (20 - j0);
112     }
113   else if (j0 < (int)(8 * sizeof (long int)) - 1)
114     {
115       /* 32bit return: j0 in [20,30] */
116       /* 64bit return: j0 in [20,62] */
117       if (j0 >= 52)
118 	/* 64bit return: j0 in [52,62] */
119 	/* 64bit return: left shift amt in [32,42] */
120         result = ((long int) ((i0 & 0x000fffff) | 0x00100000) << (j0 - 20)) |
121 		/* 64bit return: right shift amt in [0,10] */
122                    ((long int) i1 << (j0 - 52));
123       else
124         {
125           if (sizeof (long) == 4 && x > LONG_MAX) {
126             t = nearbyint(x);
127             if (t == LONG_MAX)
128               __math_set_inexact();
129             else
130               __math_set_invalid();
131           } else {
132             /* 32bit return: j0 in [20,30] */
133             /* 64bit return: j0 in [20,51] */
134             w = TWO52[sx] + x;
135             t = w - TWO52[sx];
136           }
137           EXTRACT_WORDS (i0, i1, t);
138           j0 = ((i0 & 0x7ff00000) >> 20) - 1023;
139           i0 &= 0x000fffff;
140           i0 |= 0x00100000;
141           /* After round:
142 	   * 32bit return: j0 in [20,31];
143 	   * 64bit return: j0 in [20,52] */
144 	  /* 32bit return: left shift amt in [0,11] */
145 	  /* 64bit return: left shift amt in [0,32] */
146           /* ***32bit return: right shift amt in [32,21] */
147           /* ***64bit return: right shift amt in [32,0] */
148           result = ((long int) i0 << (j0 - 20))
149 			| SAFE_RIGHT_SHIFT (i1, (52 - j0));
150         }
151     }
152   else
153     {
154       if (sizeof (long) == 4 && (__float64) LONG_MIN - _F_64(1.0) < x && x < (__float64) LONG_MIN) {
155         if (nearbyint(x) == LONG_MIN)
156           __math_set_inexact();
157         else
158           __math_set_invalid();
159         return LONG_MIN;
160       }
161       else if (x != LONG_MIN)
162       {
163         __math_set_invalid();
164         return sx ? LONG_MIN : LONG_MAX;
165       }
166       return (long int) x;
167     }
168 
169   return sx ? -result : result;
170 }
171 
172 _MATH_ALIAS_j_d(lrint)
173 
174 #endif /* _NEED_FLOAT64 */
175