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