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 #include <stdio.h>
79 long int
lrint64(__float64 x)80 lrint64(__float64 x)
81 {
82   __int32_t i0,j0,sx;
83   __uint32_t i1;
84   __float64 t;
85   volatile __float64 w;
86   long int result;
87 
88   EXTRACT_WORDS(i0,i1,x);
89 
90   /* Extract sign bit. */
91   sx = (i0>>31)&1;
92 
93   /* Extract exponent field. */
94   j0 = ((i0 & 0x7ff00000) >> 20) - 1023;
95   /* j0 in [-1023,1024] */
96 
97   if(j0 < 20)
98     {
99       /* j0 in [-1023,19] */
100       /* shift amt in [0,19] */
101       w = TWO52[sx] + x;
102       t = w - TWO52[sx];
103       GET_HIGH_WORD(i0, t);
104       /* After round:  j0 in [0,20] */
105       j0 = ((i0 & 0x7ff00000) >> 20) - 1023;
106       i0 &= 0x000fffff;
107       i0 |= 0x00100000;
108       /* shift amt in [20,0] */
109       if (j0 < 0)
110         result = 0;
111       else
112         result = i0 >> (20 - j0);
113     }
114   else if (j0 < (int)(8 * sizeof (long int)) - 1)
115     {
116       /* 32bit return: j0 in [20,30] */
117       /* 64bit return: j0 in [20,62] */
118       if (j0 >= 52)
119 	/* 64bit return: j0 in [52,62] */
120 	/* 64bit return: left shift amt in [32,42] */
121         result = ((long int) ((i0 & 0x000fffff) | 0x00100000) << (j0 - 20)) |
122 		/* 64bit return: right shift amt in [0,10] */
123                    ((long int) i1 << (j0 - 52));
124       else
125         {
126           if (sizeof (long) == 4 && x > LONG_MAX) {
127             t = nearbyint(x);
128             if (t == LONG_MAX)
129               __math_set_inexact64();
130             else
131               __math_set_invalid();
132           } else {
133             /* 32bit return: j0 in [20,30] */
134             /* 64bit return: j0 in [20,51] */
135             w = TWO52[sx] + x;
136             t = w - TWO52[sx];
137           }
138           EXTRACT_WORDS (i0, i1, t);
139           j0 = ((i0 & 0x7ff00000) >> 20) - 1023;
140           i0 &= 0x000fffff;
141           i0 |= 0x00100000;
142           /* After round:
143 	   * 32bit return: j0 in [20,31];
144 	   * 64bit return: j0 in [20,52] */
145 	  /* 32bit return: left shift amt in [0,11] */
146 	  /* 64bit return: left shift amt in [0,32] */
147           /* ***32bit return: right shift amt in [32,21] */
148           /* ***64bit return: right shift amt in [32,0] */
149           result = ((long int) i0 << (j0 - 20))
150 			| SAFE_RIGHT_SHIFT (i1, (52 - j0));
151         }
152     }
153   else
154     {
155       if (sizeof (long) == 4 && (__float64) LONG_MIN - _F_64(1.0) < x && x < (__float64) LONG_MIN) {
156         if (nearbyint(x) == LONG_MIN)
157           __math_set_inexact64();
158         else
159           __math_set_invalid();
160         return LONG_MIN;
161       }
162       else if (x != LONG_MIN)
163       {
164         __math_set_invalid();
165         return sx ? LONG_MIN : LONG_MAX;
166       }
167       return (long int) x;
168     }
169 
170   return sx ? -result : result;
171 }
172 
173 _MATH_ALIAS_j_d(lrint)
174 
175 #endif /* _NEED_FLOAT64 */
176