Cygwin: mmap: allow remapping part of an existing anonymous mapping
[newlib-cygwin.git] / newlib / libm / common / s_lround.c
blobc0a4ebc4084df32c6dbab39e389996157f16da21
1 /*
2 * ====================================================
3 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 * Developed at SunPro, a Sun Microsystems, Inc. business.
6 * Permission to use, copy, modify, and distribute this
7 * software is freely granted, provided that this notice
8 * is preserved.
9 * ====================================================
12 FUNCTION
13 <<lround>>, <<lroundf>>, <<llround>>, <<llroundf>>---round to integer, to nearest
14 INDEX
15 lround
16 INDEX
17 lroundf
18 INDEX
19 llround
20 INDEX
21 llroundf
23 SYNOPSIS
24 #include <math.h>
25 long int lround(double <[x]>);
26 long int lroundf(float <[x]>);
27 long long int llround(double <[x]>);
28 long long int llroundf(float <[x]>);
30 DESCRIPTION
31 The <<lround>> and <<llround>> functions round their argument to the
32 nearest integer value, rounding halfway cases away from zero, regardless
33 of the current rounding direction. If the rounded value is outside the
34 range of the return type, the numeric result is unspecified (depending
35 upon the floating-point implementation, not the library). A range
36 error may occur if the magnitude of x is too large.
38 RETURNS
39 <[x]> rounded to an integral value as an integer.
41 SEEALSO
42 See the <<round>> functions for the return being the same floating-point type
43 as the argument. <<lrint>>, <<llrint>>.
45 PORTABILITY
46 ANSI C, POSIX
50 #include "fdlibm.h"
52 #ifndef _DOUBLE_IS_32BITS
54 #ifdef __STDC__
55 long int lround(double x)
56 #else
57 long int lround(x)
58 double x;
59 #endif
61 __int32_t sign, exponent_less_1023;
62 /* Most significant word, least significant word. */
63 __uint32_t msw, lsw;
64 long int result;
66 EXTRACT_WORDS(msw, lsw, x);
68 /* Extract sign. */
69 sign = ((msw & 0x80000000) ? -1 : 1);
70 /* Extract exponent field. */
71 exponent_less_1023 = ((msw & 0x7ff00000) >> 20) - 1023;
72 msw &= 0x000fffff;
73 msw |= 0x00100000;
74 /* exponent_less_1023 in [-1023,1024] */
75 if (exponent_less_1023 < 20)
77 /* exponent_less_1023 in [-1023,19] */
78 if (exponent_less_1023 < 0)
80 if (exponent_less_1023 < -1)
81 return 0;
82 else
83 return sign;
85 else
87 /* exponent_less_1023 in [0,19] */
88 /* shift amt in [0,19] */
89 msw += 0x80000 >> exponent_less_1023;
90 /* shift amt in [20,1] */
91 result = msw >> (20 - exponent_less_1023);
94 else if (exponent_less_1023 < (8 * sizeof (long int)) - 1)
96 /* 32bit long: exponent_less_1023 in [20,30] */
97 /* 64bit long: exponent_less_1023 in [20,62] */
98 if (exponent_less_1023 >= 52)
99 /* 64bit long: exponent_less_1023 in [52,62] */
100 /* 64bit long: shift amt in [32,42] */
101 result = ((long int) msw << (exponent_less_1023 - 20))
102 /* 64bit long: shift amt in [0,10] */
103 | (lsw << (exponent_less_1023 - 52));
104 else
106 /* 32bit long: exponent_less_1023 in [20,30] */
107 /* 64bit long: exponent_less_1023 in [20,51] */
108 unsigned int tmp = lsw
109 /* 32bit long: shift amt in [0,10] */
110 /* 64bit long: shift amt in [0,31] */
111 + (0x80000000 >> (exponent_less_1023 - 20));
112 if (tmp < lsw)
113 ++msw;
114 /* 32bit long: shift amt in [0,10] */
115 /* 64bit long: shift amt in [0,31] */
116 result = ((long int) msw << (exponent_less_1023 - 20))
117 /* ***32bit long: shift amt in [32,22] */
118 /* ***64bit long: shift amt in [32,1] */
119 | SAFE_RIGHT_SHIFT (tmp, (52 - exponent_less_1023));
122 else
123 /* Result is too large to be represented by a long int. */
124 return (long int)x;
126 return sign * result;
129 #endif /* _DOUBLE_IS_32BITS */