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 | #ifndef _DOUBLE_IS_32BITS |
---|
16 | |
---|
17 | long long int |
---|
18 | llround(double 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 < (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 | #endif /* _DOUBLE_IS_32BITS */ |
---|