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