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
15 #ifdef _NEED_FLOAT64
16
17 long long int
llround64(__float64 x)18 llround64(__float64 x)
19 {
20 __int32_t sign, exponent_less_1023;
21 /* Most significant word, least significant word. */
22 __uint32_t msw, lsw;
23 long long int result;
24
25 EXTRACT_WORDS(msw, lsw, x);
26
27 /* Extract sign. */
28 sign = ((msw & 0x80000000) ? -1 : 1);
29 /* Extract exponent field. */
30 exponent_less_1023 = ((msw & 0x7ff00000) >> 20) - 1023;
31 msw &= 0x000fffff;
32 msw |= 0x00100000;
33
34 /* exponent_less_1023 in [-1023,1024] */
35 if (exponent_less_1023 < 20)
36 {
37 /* exponent_less_1023 in [-1023,19] */
38 if (exponent_less_1023 < 0)
39 {
40 if (exponent_less_1023 < -1)
41 return 0;
42 else
43 return sign;
44 }
45 else
46 {
47 /* exponent_less_1023 in [0,19] */
48 /* shift amt in [0,19] */
49 msw += 0x80000 >> exponent_less_1023;
50 /* shift amt in [20,1] */
51 result = msw >> (20 - exponent_less_1023);
52 }
53 }
54 else if (exponent_less_1023 < (__int32_t) ((8 * sizeof (long long int)) - 1))
55 {
56 /* 64bit longlong: exponent_less_1023 in [20,62] */
57 if (exponent_less_1023 >= 52)
58 /* 64bit longlong: exponent_less_1023 in [52,62] */
59 /* 64bit longlong: shift amt in [32,42] */
60 result = ((long long int) msw << (exponent_less_1023 - 20))
61 /* 64bit longlong: shift amt in [0,10] */
62 | (lsw << (exponent_less_1023 - 52));
63 else
64 {
65 /* 64bit longlong: exponent_less_1023 in [20,51] */
66 unsigned int tmp = lsw
67 /* 64bit longlong: shift amt in [0,31] */
68 + (0x80000000 >> (exponent_less_1023 - 20));
69 if (tmp < lsw)
70 ++msw;
71 /* 64bit longlong: shift amt in [0,31] */
72 result = ((long long int) msw << (exponent_less_1023 - 20))
73 /* ***64bit longlong: shift amt in [32,1] */
74 | SAFE_RIGHT_SHIFT (tmp, (52 - exponent_less_1023));
75 }
76 }
77 else
78 /* Result is too large to be represented by a long long int. */
79 return (long long int)x;
80
81 return sign * result;
82 }
83
84 _MATH_ALIAS_k_d(llround)
85
86 #endif /* _NEED_FLOAT64 */
87