Cygwin: mmap: allow remapping part of an existing anonymous mapping
[newlib-cygwin.git] / newlib / libm / common / s_llround.c
blob0bc35ac6e57314814d80e2a842806cc7d0cefd56
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.
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 * ====================================================
13 #include "fdlibm.h"
15 #ifndef _DOUBLE_IS_32BITS
17 long long int
18 llround(double x)
20 __int32_t sign, exponent_less_1023;
21 /* Most significant word, least significant word. */
22 __uint32_t msw, lsw;
23 long long int result;
25 EXTRACT_WORDS(msw, lsw, x);
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;
34 /* exponent_less_1023 in [-1023,1024] */
35 if (exponent_less_1023 < 20)
37 /* exponent_less_1023 in [-1023,19] */
38 if (exponent_less_1023 < 0)
40 if (exponent_less_1023 < -1)
41 return 0;
42 else
43 return sign;
45 else
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);
54 else if (exponent_less_1023 < (8 * sizeof (long long int)) - 1)
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
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));
77 else
78 /* Result is too large to be represented by a long long int. */
79 return (long long int)x;
81 return sign * result;
84 #endif /* _DOUBLE_IS_32BITS */