1 /* Round to integer type. Common helper functions.
2 Copyright (C) 2016-2018 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
23 #include <math-barriers.h>
24 #include <math_private.h>
28 /* The including file should have defined UNSIGNED to 0 (signed return
29 type) or 1 (unsigned return type), INEXACT to 0 (no inexact
30 exceptions) or 1 (raise inexact exceptions) and RET_TYPE to the
31 return type (intmax_t or uintmax_t). */
33 /* Return the maximum unbiased exponent for an argument (negative if
34 NEGATIVE is set) that might be in range for a call to a fromfp
35 function with width WIDTH (greater than 0, and not exceeding that
36 of intmax_t). The truncated argument may still be out of range in
37 the case of negative arguments, and if not out of range it may
38 become out of range as a result of rounding. */
41 fromfp_max_exponent (bool negative
, int width
)
44 return negative
? -1 : width
- 1;
46 return negative
? width
- 1 : width
- 2;
49 /* Return the result of rounding an integer value X (passed as the
50 absolute value; NEGATIVE is true if the value is negative), where
51 HALF_BIT is true if the bit with value 0.5 is set and MORE_BITS is
52 true if any lower bits are set, in the rounding direction
56 fromfp_round (bool negative
, uintmax_t x
, bool half_bit
, bool more_bits
,
62 return x
+ (!negative
&& (half_bit
|| more_bits
));
65 return x
+ (negative
&& (half_bit
|| more_bits
));
67 case FP_INT_TOWARDZERO
:
69 /* Unknown rounding directions are defined to mean unspecified
70 rounding; treat this as truncation. */
73 case FP_INT_TONEARESTFROMZERO
:
76 case FP_INT_TONEAREST
:
77 return x
+ (half_bit
&& ((x
& 1) || more_bits
));
81 /* Integer rounding, of a value whose exponent EXPONENT did not exceed
82 the maximum exponent MAX_EXPONENT and so did not necessarily
83 overflow, has produced X (possibly wrapping to 0); the sign is
84 negative if NEGATIVE is true. Return whether this overflowed the
88 fromfp_overflowed (bool negative
, uintmax_t x
, int exponent
, int max_exponent
)
94 else if (max_exponent
== INTMAX_WIDTH
- 1)
95 return exponent
== INTMAX_WIDTH
- 1 && x
== 0;
97 return x
== (1ULL << (max_exponent
+ 1));
102 return exponent
== max_exponent
&& x
!= (1ULL << max_exponent
);
104 return x
== (1ULL << (max_exponent
+ 1));
108 /* Handle a domain error for a call to a fromfp function with an
109 argument which is negative if NEGATIVE is set, and specified width
110 (not exceeding that of intmax_t) WIDTH. The return value is
111 unspecified (with it being unclear if the result needs to fit
112 within WIDTH bits in this case); we choose to saturate to the given
113 number of bits (treating NaNs like any other value). */
116 fromfp_domain_error (bool negative
, unsigned int width
)
118 feraiseexcept (FE_INVALID
);
120 /* The return value is unspecified; we choose to saturate to the
121 given number of bits (treating NaNs like any other value). */
126 else if (width
== INTMAX_WIDTH
)
129 return (1ULL << width
) - 1;
136 return -(1ULL << (width
- 1));
138 return (1ULL << (width
- 1)) - 1;
142 /* Given X, the absolute value of a floating-point number (negative if
143 NEGATIVE is set) truncated towards zero, where HALF_BIT is true if
144 the bit with value 0.5 is set and MORE_BITS is true if any lower
145 bits are set, round it in the rounding direction ROUND, handle
146 errors and exceptions and return the appropriate return value for a
147 fromfp function. X originally had floating-point exponent
148 EXPONENT, which does not exceed MAX_EXPONENT, the return value from
149 fromfp_max_exponent with width WIDTH. */
152 fromfp_round_and_return (bool negative
, uintmax_t x
, bool half_bit
,
153 bool more_bits
, int round
, int exponent
,
154 int max_exponent
, unsigned int width
)
156 uintmax_t uret
= fromfp_round (negative
, x
, half_bit
, more_bits
, round
);
157 if (fromfp_overflowed (negative
, uret
, exponent
, max_exponent
))
158 return fromfp_domain_error (negative
, width
);
160 if (INEXACT
&& (half_bit
|| more_bits
))
162 /* There is no need for this to use the specific floating-point
163 type for which this header is included, and there is no need
164 for this header to know that type at all, so just use float
166 float force_inexact
= 1.0f
+ FLT_MIN
;
167 math_force_eval (force_inexact
);
170 /* A negative argument not rounding to zero will already have
171 produced a domain error. */
174 return negative
? -uret
: uret
;