1 /*
2  * ====================================================
3  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
4  *
5  * Developed at SunPro, a Sun Microsystems, Inc. business.
6  * Permission to use, copy, modify, and distribute this
7  * software is freely granted, provided that this notice
8  * is preserved.
9  * ====================================================
10  */
11 /*
12 FUNCTION
13 <<lround>>, <<lroundf>>, <<llround>>, <<llroundf>>---round to integer, to nearest
14 INDEX
15 	lround
16 INDEX
17 	lroundf
18 INDEX
19 	llround
20 INDEX
21 	llroundf
22 
23 SYNOPSIS
24 	#include <math.h>
25 	long int lround(double <[x]>);
26 	long int lroundf(float <[x]>);
27 	long long int llround(double <[x]>);
28 	long long int llroundf(float <[x]>);
29 
30 DESCRIPTION
31 	The <<lround>> and <<llround>> functions round their argument to the
32 	nearest integer value, rounding halfway cases away from zero, regardless
33 	of the current rounding direction.  If the rounded value is outside the
34 	range of the return type, the numeric result is unspecified (depending
35 	upon the floating-point implementation, not the library).  A range
36 	error may occur if the magnitude of x is too large.
37 
38 RETURNS
39 <[x]> rounded to an integral value as an integer.
40 
41 SEEALSO
42 See the <<round>> functions for the return being the same floating-point type
43 as the argument.  <<lrint>>, <<llrint>>.
44 
45 PORTABILITY
46 ANSI C, POSIX
47 
48 */
49 
50 #include "fdlibm.h"
51 #include <limits.h>
52 
53 #ifdef _NEED_FLOAT64
54 
55 long int
lround64(__float64 x)56 lround64(__float64 x)
57 {
58   __int32_t sign, exponent_less_1023;
59   /* Most significant word, least significant word. */
60   __uint32_t msw, lsw;
61   long int result;
62 
63   EXTRACT_WORDS(msw, lsw, x);
64 
65   /* Extract sign. */
66   sign = ((msw & 0x80000000) ? -1 : 1);
67   /* Extract exponent field. */
68   exponent_less_1023 = ((msw & 0x7ff00000) >> 20) - 1023;
69   msw &= 0x000fffff;
70   msw |= 0x00100000;
71   /* exponent_less_1023 in [-1023,1024] */
72   if (exponent_less_1023 < 20)
73     {
74       /* exponent_less_1023 in [-1023,19] */
75       if (exponent_less_1023 < 0)
76         {
77           if (exponent_less_1023 < -1)
78             return 0;
79           else
80             return sign;
81         }
82       else
83         {
84           /* exponent_less_1023 in [0,19] */
85 	  /* shift amt in [0,19] */
86           msw += 0x80000 >> exponent_less_1023;
87 	  /* shift amt in [20,1] */
88           result = msw >> (20 - exponent_less_1023);
89         }
90     }
91   else if (exponent_less_1023 < (__int32_t) ((8 * sizeof (long int)) - 1))
92     {
93       /* 32bit long: exponent_less_1023 in [20,30] */
94       /* 64bit long: exponent_less_1023 in [20,62] */
95       if (exponent_less_1023 >= 52)
96 	/* 64bit long: exponent_less_1023 in [52,62] */
97 	/* 64bit long: shift amt in [32,42] */
98         result = ((long int) msw << (exponent_less_1023 - 20))
99 		/* 64bit long: shift amt in [0,10] */
100             | ((long int) lsw << (exponent_less_1023 - 52));
101       else
102         {
103 	  /* 32bit long: exponent_less_1023 in [20,30] */
104 	  /* 64bit long: exponent_less_1023 in [20,51] */
105           __uint32_t tmp = lsw
106 		    /* 32bit long: shift amt in [0,10] */
107 		    /* 64bit long: shift amt in [0,31] */
108                     + (0x80000000 >> (exponent_less_1023 - 20));
109           if (tmp < lsw)
110             ++msw;
111 	  /* 32bit long: shift amt in [0,10] */
112 	  /* 64bit long: shift amt in [0,31] */
113           result = ((long int) msw << (exponent_less_1023 - 20))
114 		    /* ***32bit long: shift amt in [32,22] */
115 		    /* ***64bit long: shift amt in [32,1] */
116                     | SAFE_RIGHT_SHIFT (tmp, (52 - exponent_less_1023));
117         }
118     }
119   else
120   {
121     /* Result is too large to be represented by a long int. */
122     if (sign == 1 ||
123         !((sizeof(long) == 4 && x > LONG_MIN - _F_64(0.5)) ||
124           (sizeof(long) > 4 && x >= LONG_MIN)))
125     {
126       __math_set_invalid();
127       return sign == 1 ? LONG_MAX : LONG_MIN;
128     }
129     return (long int)x;
130   }
131 
132   if (sizeof (long) == 4 && sign == 1 && result == LONG_MIN)
133     __math_set_invalid();
134 
135   return sign * result;
136 }
137 
138 _MATH_ALIAS_j_d(lround)
139 
140 #endif /* _NEED_FLOAT64 */
141