1/* Round to nearest integer value, rounding halfway cases to even.
2 ldbl-96 version.
3 Copyright (C) 2016-2018 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
19
20#include <math.h>
21#include <math_private.h>
22#include <libm-alias-ldouble.h>
23#include <stdint.h>
24
25#define BIAS 0x3fff
26#define MANT_DIG 64
27#define MAX_EXP (2 * BIAS + 1)
28
29long double
30__roundevenl (long double x)
31{
32 uint16_t se;
33 uint32_t hx, lx;
34 GET_LDOUBLE_WORDS (se, hx, lx, x);
35 int exponent = se & 0x7fff;
36 if (exponent >= BIAS + MANT_DIG - 1)
37 {
38 /* Integer, infinity or NaN. */
39 if (exponent == MAX_EXP)
40 /* Infinity or NaN; quiet signaling NaNs. */
41 return x + x;
42 else
43 return x;
44 }
45 else if (exponent >= BIAS + MANT_DIG - 32)
46 {
47 /* Not necessarily an integer; integer bit is in low word.
48 Locate the bits with exponents 0 and -1. */
49 int int_pos = (BIAS + MANT_DIG - 1) - exponent;
50 int half_pos = int_pos - 1;
51 uint32_t half_bit = 1U << half_pos;
52 uint32_t int_bit = 1U << int_pos;
53 if ((lx & (int_bit | (half_bit - 1))) != 0)
54 {
55 /* No need to test whether HALF_BIT is set. */
56 lx += half_bit;
57 if (lx < half_bit)
58 {
59 hx++;
60 if (hx == 0)
61 {
62 hx = 0x80000000;
63 se++;
64 }
65 }
66 }
67 lx &= ~(int_bit - 1);
68 }
69 else if (exponent == BIAS + MANT_DIG - 33)
70 {
71 /* Not necessarily an integer; integer bit is bottom of high
72 word, half bit is top of low word. */
73 if (((hx & 1) | (lx & 0x7fffffff)) != 0)
74 {
75 lx += 0x80000000;
76 if (lx < 0x80000000)
77 {
78 hx++;
79 if (hx == 0)
80 {
81 hx = 0x80000000;
82 se++;
83 }
84 }
85 }
86 lx = 0;
87 }
88 else if (exponent >= BIAS)
89 {
90 /* At least 1; not necessarily an integer, integer bit and half
91 bit are in the high word. Locate the bits with exponents 0
92 and -1. */
93 int int_pos = (BIAS + MANT_DIG - 33) - exponent;
94 int half_pos = int_pos - 1;
95 uint32_t half_bit = 1U << half_pos;
96 uint32_t int_bit = 1U << int_pos;
97 if (((hx & (int_bit | (half_bit - 1))) | lx) != 0)
98 {
99 hx += half_bit;
100 if (hx < half_bit)
101 {
102 hx = 0x80000000;
103 se++;
104 }
105 }
106 hx &= ~(int_bit - 1);
107 lx = 0;
108 }
109 else if (exponent == BIAS - 1 && (hx > 0x80000000 || lx != 0))
110 {
111 /* Interval (0.5, 1). */
112 se = (se & 0x8000) | 0x3fff;
113 hx = 0x80000000;
114 lx = 0;
115 }
116 else
117 {
118 /* Rounds to 0. */
119 se &= 0x8000;
120 hx = 0;
121 lx = 0;
122 }
123 SET_LDOUBLE_WORDS (x, se, hx, lx);
124 return x;
125}
126libm_alias_ldouble (__roundeven, roundeven)
127