]>
Commit | Line | Data |
---|---|---|
7ce331c0 EA |
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 | |
c4e44e97 | 7 | * software is freely granted, provided that this notice |
7ce331c0 EA |
8 | * is preserved. |
9 | * ==================================================== | |
10 | */ | |
11 | ||
7ce331c0 EA |
12 | /* |
13 | * rint(x) | |
14 | * Return x rounded to integral value according to the prevailing | |
15 | * rounding mode. | |
16 | * Method: | |
17 | * Using floating addition. | |
18 | * Exception: | |
19 | * Inexact flag raised if x not equal to rint(x). | |
20 | */ | |
21 | ||
22 | #include "math.h" | |
23 | #include "math_private.h" | |
24 | ||
7ce331c0 | 25 | static const double |
7ce331c0 EA |
26 | TWO52[2]={ |
27 | 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ | |
28 | -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ | |
29 | }; | |
30 | ||
38b7304e | 31 | double rint(double x) |
7ce331c0 | 32 | { |
c61c6d98 | 33 | int32_t i0, _j0, sx; |
7ce331c0 | 34 | u_int32_t i,i1; |
4435b3ae DV |
35 | double t; |
36 | /* We use w = x + 2^52; t = w - 2^52; trick to round x to integer. | |
37 | * This trick requires that compiler does not optimize it | |
38 | * by keeping intermediate result w in a register wider than double. | |
39 | * Declaring w volatile assures that value gets truncated to double | |
40 | * (unfortunately, it also forces store+load): | |
41 | */ | |
42 | volatile double w; | |
43 | ||
7ce331c0 | 44 | EXTRACT_WORDS(i0,i1,x); |
4435b3ae | 45 | /* Unbiased exponent */ |
c61c6d98 | 46 | _j0 = ((((u_int32_t)i0) >> 20)&0x7ff)-0x3ff; |
4435b3ae | 47 | |
c61c6d98 | 48 | if (_j0 > 51) { |
4435b3ae | 49 | //Why bother? Just returning x works too |
c61c6d98 | 50 | //if (_j0 == 0x400) /* inf or NaN */ |
4435b3ae DV |
51 | // return x+x; |
52 | return x; /* x is integral */ | |
53 | } | |
54 | ||
55 | /* Sign */ | |
56 | sx = ((u_int32_t)i0) >> 31; | |
57 | ||
c61c6d98 PM |
58 | if (_j0<20) { |
59 | if (_j0<0) { /* |x| < 1 */ | |
4435b3ae | 60 | if (((i0&0x7fffffff)|i1)==0) return x; |
7ce331c0 EA |
61 | i1 |= (i0&0x0fffff); |
62 | i0 &= 0xfffe0000; | |
63 | i0 |= ((i1|-i1)>>12)&0x80000; | |
64 | SET_HIGH_WORD(x,i0); | |
4435b3ae DV |
65 | w = TWO52[sx]+x; |
66 | t = w-TWO52[sx]; | |
7ce331c0 EA |
67 | GET_HIGH_WORD(i0,t); |
68 | SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31)); | |
4435b3ae | 69 | return t; |
7ce331c0 | 70 | } else { |
c61c6d98 | 71 | i = (0x000fffff)>>_j0; |
4435b3ae | 72 | if (((i0&i)|i1)==0) return x; /* x is integral */ |
7ce331c0 | 73 | i>>=1; |
4435b3ae | 74 | if (((i0&i)|i1)!=0) { |
c61c6d98 PM |
75 | if (_j0==19) i1 = 0x40000000; |
76 | else i0 = (i0&(~i))|((0x20000)>>_j0); | |
7ce331c0 EA |
77 | } |
78 | } | |
7ce331c0 | 79 | } else { |
c61c6d98 | 80 | i = ((u_int32_t)(0xffffffff))>>(_j0-20); |
4435b3ae | 81 | if ((i1&i)==0) return x; /* x is integral */ |
7ce331c0 | 82 | i>>=1; |
c61c6d98 | 83 | if ((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(_j0-20)); |
7ce331c0 EA |
84 | } |
85 | INSERT_WORDS(x,i0,i1); | |
86 | w = TWO52[sx]+x; | |
87 | return w-TWO52[sx]; | |
88 | } | |
9cc29786 | 89 | libm_hidden_def(rint) |
30bd4a6c DV |
90 | |
91 | strong_alias(rint, nearbyint) | |
92 | libm_hidden_def(nearbyint) |