dma: rework config parsing
[dragonfly.git] / contrib / mpfr / exceptions.c
blob7d441cf61fdc86e5eb2f699c97007e30f3f49b09
1 /* Exception flags and utilities.
3 Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
4 Contributed by the Arenaire and Cacao projects, INRIA.
6 This file is part of the GNU MPFR Library.
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or (at your
11 option) any later version.
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21 MA 02110-1301, USA. */
23 #include "mpfr-impl.h"
25 unsigned int MPFR_THREAD_ATTR __gmpfr_flags = 0;
27 mp_exp_t MPFR_THREAD_ATTR __gmpfr_emin = MPFR_EMIN_DEFAULT;
28 mp_exp_t MPFR_THREAD_ATTR __gmpfr_emax = MPFR_EMAX_DEFAULT;
30 #undef mpfr_get_emin
32 mp_exp_t
33 mpfr_get_emin (void)
35 return __gmpfr_emin;
38 #undef mpfr_set_emin
40 int
41 mpfr_set_emin (mp_exp_t exponent)
43 if (exponent >= MPFR_EMIN_MIN && exponent <= MPFR_EMIN_MAX)
45 __gmpfr_emin = exponent;
46 return 0;
48 else
50 return 1;
54 mp_exp_t
55 mpfr_get_emin_min (void)
57 return MPFR_EMIN_MIN;
60 mp_exp_t
61 mpfr_get_emin_max (void)
63 return MPFR_EMIN_MAX;
66 #undef mpfr_get_emax
68 mp_exp_t
69 mpfr_get_emax (void)
71 return __gmpfr_emax;
74 #undef mpfr_set_emax
76 int
77 mpfr_set_emax (mp_exp_t exponent)
79 if (exponent >= MPFR_EMAX_MIN && exponent <= MPFR_EMAX_MAX)
81 __gmpfr_emax = exponent;
82 return 0;
84 else
86 return 1;
90 mp_exp_t
91 mpfr_get_emax_min (void)
93 return MPFR_EMAX_MIN;
95 mp_exp_t
96 mpfr_get_emax_max (void)
98 return MPFR_EMAX_MAX;
102 #undef mpfr_clear_flags
104 void
105 mpfr_clear_flags (void)
107 __gmpfr_flags = 0;
110 #undef mpfr_clear_underflow
112 void
113 mpfr_clear_underflow (void)
115 __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_UNDERFLOW;
118 #undef mpfr_clear_overflow
120 void
121 mpfr_clear_overflow (void)
123 __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_OVERFLOW;
126 #undef mpfr_clear_nanflag
128 void
129 mpfr_clear_nanflag (void)
131 __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_NAN;
134 #undef mpfr_clear_inexflag
136 void
137 mpfr_clear_inexflag (void)
139 __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_INEXACT;
142 #undef mpfr_clear_erangeflag
144 void
145 mpfr_clear_erangeflag (void)
147 __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE;
150 #undef mpfr_clear_underflow
152 void
153 mpfr_set_underflow (void)
155 __gmpfr_flags |= MPFR_FLAGS_UNDERFLOW;
158 #undef mpfr_clear_overflow
160 void
161 mpfr_set_overflow (void)
163 __gmpfr_flags |= MPFR_FLAGS_OVERFLOW;
166 #undef mpfr_clear_nanflag
168 void
169 mpfr_set_nanflag (void)
171 __gmpfr_flags |= MPFR_FLAGS_NAN;
174 #undef mpfr_clear_inexflag
176 void
177 mpfr_set_inexflag (void)
179 __gmpfr_flags |= MPFR_FLAGS_INEXACT;
182 #undef mpfr_clear_erangeflag
184 void
185 mpfr_set_erangeflag (void)
187 __gmpfr_flags |= MPFR_FLAGS_ERANGE;
191 #undef mpfr_check_range
194 mpfr_check_range (mpfr_ptr x, int t, mp_rnd_t rnd_mode)
196 if (MPFR_LIKELY( MPFR_IS_PURE_FP(x)) )
197 { /* x is a non-zero FP */
198 mp_exp_t exp = MPFR_EXP (x); /* Do not use MPFR_GET_EXP */
199 if (MPFR_UNLIKELY( exp < __gmpfr_emin) )
201 /* The following test is necessary because in the rounding to the
202 * nearest mode, mpfr_underflow always rounds away from 0. In
203 * this rounding mode, we need to round to 0 if:
204 * _ |x| < 2^(emin-2), or
205 * _ |x| = 2^(emin-2) and the absolute value of the exact
206 * result is <= 2^(emin-2).
208 if (rnd_mode == GMP_RNDN &&
209 (exp + 1 < __gmpfr_emin ||
210 (mpfr_powerof2_raw(x) &&
211 (MPFR_IS_NEG(x) ? t <= 0 : t >= 0))))
212 rnd_mode = GMP_RNDZ;
213 return mpfr_underflow(x, rnd_mode, MPFR_SIGN(x));
215 if (MPFR_UNLIKELY( exp > __gmpfr_emax) )
216 return mpfr_overflow(x, rnd_mode, MPFR_SIGN(x));
218 else if (MPFR_UNLIKELY (t != 0 && MPFR_IS_INF (x)))
220 /* We need to do the following because most MPFR functions are
221 * implemented in the following way:
222 * Ziv's loop:
223 * | Compute an approximation to the result and an error bound.
224 * | Possible underflow/overflow detection -> return.
225 * | If can_round, break (exit the loop).
226 * | Otherwise, increase the working precision and loop.
227 * Round the approximation in the target precision.
228 * Restore the flags (that could have been set due to underflows
229 * or overflows during the internal computations).
230 * Execute: return mpfr_check_range (...).
231 * The problem is that an overflow could be generated when rounding the
232 * approximation (in general, such an overflow could not be detected
233 * earlier), and the overflow flag is lost when the flags are restored.
234 * So, the simplest solution is to detect this overflow case here in
235 * mpfr_check_range, which is easy to do since the rounded result is
236 * necessarily an inexact infinity.
238 __gmpfr_flags |= MPFR_FLAGS_OVERFLOW;
240 MPFR_RET (t); /* propagate inexact ternary value, unlike most functions */
243 #undef mpfr_underflow_p
246 mpfr_underflow_p (void)
248 return __gmpfr_flags & MPFR_FLAGS_UNDERFLOW;
251 #undef mpfr_overflow_p
254 mpfr_overflow_p (void)
256 return __gmpfr_flags & MPFR_FLAGS_OVERFLOW;
259 #undef mpfr_nanflag_p
262 mpfr_nanflag_p (void)
264 return __gmpfr_flags & MPFR_FLAGS_NAN;
267 #undef mpfr_inexflag_p
270 mpfr_inexflag_p (void)
272 return __gmpfr_flags & MPFR_FLAGS_INEXACT;
275 #undef mpfr_erangeflag_p
278 mpfr_erangeflag_p (void)
280 return __gmpfr_flags & MPFR_FLAGS_ERANGE;
283 /* #undef mpfr_underflow */
285 /* Note: In the rounding to the nearest mode, mpfr_underflow
286 always rounds away from 0. In this rounding mode, you must call
287 mpfr_underflow with rnd_mode = GMP_RNDZ if the exact result
288 is <= 2^(emin-2) in absolute value. */
291 mpfr_underflow (mpfr_ptr x, mp_rnd_t rnd_mode, int sign)
293 int inex;
295 MPFR_ASSERT_SIGN (sign);
297 if (rnd_mode == GMP_RNDN
298 || MPFR_IS_RNDUTEST_OR_RNDDNOTTEST(rnd_mode, MPFR_IS_POS_SIGN (sign)))
300 mpfr_setmin (x, __gmpfr_emin);
301 inex = 1;
303 else
305 MPFR_SET_ZERO(x);
306 inex = -1;
308 MPFR_SET_SIGN(x, sign);
309 __gmpfr_flags |= MPFR_FLAGS_INEXACT | MPFR_FLAGS_UNDERFLOW;
310 return sign > 0 ? inex : -inex;
313 /* #undef mpfr_overflow */
316 mpfr_overflow (mpfr_ptr x, mp_rnd_t rnd_mode, int sign)
318 int inex;
320 MPFR_ASSERT_SIGN(sign);
321 MPFR_CLEAR_FLAGS(x);
322 if (rnd_mode == GMP_RNDN
323 || MPFR_IS_RNDUTEST_OR_RNDDNOTTEST(rnd_mode, sign > 0))
325 MPFR_SET_INF(x);
326 inex = 1;
328 else
330 mpfr_setmax (x, __gmpfr_emax);
331 inex = -1;
333 MPFR_SET_SIGN(x,sign);
334 __gmpfr_flags |= MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW;
335 return sign > 0 ? inex : -inex;