1 /* lround adapted to be llround for Newlib, 2009 by Craig Howland.  */
2 /*
3  * ====================================================
4  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5  *
6  * Developed at SunPro, a Sun Microsystems, Inc. business.
7  * Permission to use, copy, modify, and distribute this
8  * software is freely granted, provided that this notice
9  * is preserved.
10  * ====================================================
11  */
12 
13 #include "fdlibm.h"
14 #include <limits.h>
15 
16 #ifdef _NEED_FLOAT64
17 
18 long long int
llround64(__float64 x)19 llround64(__float64 x)
20 {
21   __int32_t sign, exponent_less_1023;
22   /* Most significant word, least significant word. */
23   __uint32_t msw, lsw;
24   long long int result;
25 
26   EXTRACT_WORDS(msw, lsw, x);
27 
28   /* Extract sign. */
29   sign = ((msw & 0x80000000) ? -1 : 1);
30   /* Extract exponent field. */
31   exponent_less_1023 = ((msw & 0x7ff00000) >> 20) - 1023;
32   msw &= 0x000fffff;
33   msw |= 0x00100000;
34 
35   /* exponent_less_1023 in [-1023,1024] */
36   if (exponent_less_1023 < 20)
37     {
38       /* exponent_less_1023 in [-1023,19] */
39       if (exponent_less_1023 < 0)
40         {
41           if (exponent_less_1023 < -1)
42             return 0;
43           else
44             return sign;
45         }
46       else
47         {
48           /* exponent_less_1023 in [0,19] */
49 	  /* shift amt in [0,19] */
50           msw += 0x80000 >> exponent_less_1023;
51 	  /* shift amt in [20,1] */
52           result = msw >> (20 - exponent_less_1023);
53         }
54     }
55   else if (exponent_less_1023 < (__int32_t) ((8 * sizeof (long long int)) - 1))
56     {
57       /* 64bit longlong: exponent_less_1023 in [20,62] */
58       if (exponent_less_1023 >= 52)
59 	/* 64bit longlong: exponent_less_1023 in [52,62] */
60 	/* 64bit longlong: shift amt in [32,42] */
61         result = ((long long int) msw << (exponent_less_1023 - 20))
62 		    /* 64bit longlong: shift amt in [0,10] */
63                     | ((long long int) lsw << (exponent_less_1023 - 52));
64       else
65         {
66 	  /* 64bit longlong: exponent_less_1023 in [20,51] */
67           unsigned int tmp = lsw
68 		    /* 64bit longlong: shift amt in [0,31] */
69                     + (0x80000000 >> (exponent_less_1023 - 20));
70           if (tmp < lsw)
71             ++msw;
72 	  /* 64bit longlong: shift amt in [0,31] */
73           result = ((long long int) msw << (exponent_less_1023 - 20))
74 		    /* ***64bit longlong: shift amt in [32,1] */
75                     | SAFE_RIGHT_SHIFT (tmp, (52 - exponent_less_1023));
76         }
77     }
78   else
79     {
80       /* Result is too large to be represented by a long long int. */
81       if (sign == 1 ||
82           !((sizeof(long long) == 4 && x > LLONG_MIN - 0.5) ||
83             (sizeof(long long) > 4 && x >= LLONG_MIN)))
84         {
85           __math_set_invalid();
86           return sign == 1 ? LLONG_MAX : LLONG_MIN;
87         }
88       return (long long)x;
89     }
90 
91   return sign * result;
92 }
93 
94 _MATH_ALIAS_k_d(llround)
95 
96 #endif /* _NEED_FLOAT64 */
97