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