1 | /* |
---|
2 | * ==================================================== |
---|
3 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
---|
4 | * |
---|
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 | * ==================================================== |
---|
10 | */ |
---|
11 | /* |
---|
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 |
---|
22 | |
---|
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]>); |
---|
29 | |
---|
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. |
---|
37 | |
---|
38 | RETURNS |
---|
39 | <[x]> rounded to an integral value as an integer. |
---|
40 | |
---|
41 | SEEALSO |
---|
42 | See the <<round>> functions for the return being the same floating-point type |
---|
43 | as the argument. <<lrint>>, <<llrint>>. |
---|
44 | |
---|
45 | PORTABILITY |
---|
46 | ANSI C, POSIX |
---|
47 | |
---|
48 | */ |
---|
49 | |
---|
50 | #include "fdlibm.h" |
---|
51 | |
---|
52 | #ifndef _DOUBLE_IS_32BITS |
---|
53 | |
---|
54 | #ifdef __STDC__ |
---|
55 | long int lround(double x) |
---|
56 | #else |
---|
57 | long int lround(x) |
---|
58 | double x; |
---|
59 | #endif |
---|
60 | { |
---|
61 | __int32_t sign, exponent_less_1023; |
---|
62 | /* Most significant word, least significant word. */ |
---|
63 | __uint32_t msw, lsw; |
---|
64 | long int result; |
---|
65 | |
---|
66 | EXTRACT_WORDS(msw, lsw, x); |
---|
67 | |
---|
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) |
---|
76 | { |
---|
77 | /* exponent_less_1023 in [-1023,19] */ |
---|
78 | if (exponent_less_1023 < 0) |
---|
79 | { |
---|
80 | if (exponent_less_1023 < -1) |
---|
81 | return 0; |
---|
82 | else |
---|
83 | return sign; |
---|
84 | } |
---|
85 | else |
---|
86 | { |
---|
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); |
---|
92 | } |
---|
93 | } |
---|
94 | else if (exponent_less_1023 < (8 * sizeof (long int)) - 1) |
---|
95 | { |
---|
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 |
---|
105 | { |
---|
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)); |
---|
120 | } |
---|
121 | } |
---|
122 | else |
---|
123 | /* Result is too large to be represented by a long int. */ |
---|
124 | return (long int)x; |
---|
125 | |
---|
126 | return sign * result; |
---|
127 | } |
---|
128 | |
---|
129 | #endif /* _DOUBLE_IS_32BITS */ |
---|