Index: gcc/mpfr/pow_z.c |
diff --git a/gcc/mpfr/pow_z.c b/gcc/mpfr/pow_z.c |
deleted file mode 100644 |
index 3e88a9bf2533a76dcce33020ef94c1443f5e2c9b..0000000000000000000000000000000000000000 |
--- a/gcc/mpfr/pow_z.c |
+++ /dev/null |
@@ -1,365 +0,0 @@ |
-/* mpfr_pow_z -- power function x^z with z a MPZ |
- |
-Copyright 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. |
-Contributed by the Arenaire and Cacao projects, INRIA. |
- |
-This file is part of the GNU MPFR Library. |
- |
-The GNU MPFR Library is free software; you can redistribute it and/or modify |
-it under the terms of the GNU Lesser General Public License as published by |
-the Free Software Foundation; either version 2.1 of the License, or (at your |
-option) any later version. |
- |
-The GNU MPFR Library is distributed in the hope that it will be useful, but |
-WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
-or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
-License for more details. |
- |
-You should have received a copy of the GNU Lesser General Public License |
-along with the GNU MPFR Library; see the file COPYING.LIB. If not, write to |
-the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, |
-MA 02110-1301, USA. */ |
- |
-#define MPFR_NEED_LONGLONG_H |
-#include "mpfr-impl.h" |
- |
-/* y <- x^|z| with z != 0 |
- if cr=1: ensures correct rounding of y |
- if cr=0: does not ensure correct rounding, but avoid spurious overflow |
- or underflow, and uses the precision of y as working precision (warning, |
- y and x might be the same variable). */ |
-static int |
-mpfr_pow_pos_z (mpfr_ptr y, mpfr_srcptr x, mpz_srcptr z, mp_rnd_t rnd, int cr) |
-{ |
- mpfr_t res; |
- mp_prec_t prec, err; |
- int inexact; |
- mp_rnd_t rnd1, rnd2; |
- mpz_t absz; |
- mp_size_t size_z; |
- MPFR_ZIV_DECL (loop); |
- MPFR_BLOCK_DECL (flags); |
- |
- MPFR_LOG_FUNC (("x[%#R]=%R z=? rnd=%d cr=%d", x, x, rnd, cr), |
- ("y[%#R]=%R inexact=%d", y, y, inexact)); |
- |
- MPFR_ASSERTD (mpz_sgn (z) != 0); |
- |
- if (MPFR_UNLIKELY (mpz_cmpabs_ui (z, 1) == 0)) |
- return mpfr_set (y, x, rnd); |
- |
- absz[0] = z[0]; |
- SIZ (absz) = ABS(SIZ(absz)); /* Hack to get abs(z) */ |
- MPFR_MPZ_SIZEINBASE2 (size_z, z); |
- |
- /* round towards 1 (or -1) to avoid spurious overflow or underflow, |
- i.e. if an overflow or underflow occurs, it is a real exception |
- and is not just due to the rounding error. */ |
- rnd1 = (MPFR_EXP(x) >= 1) ? GMP_RNDZ |
- : (MPFR_IS_POS(x) ? GMP_RNDU : GMP_RNDD); |
- rnd2 = (MPFR_EXP(x) >= 1) ? GMP_RNDD : GMP_RNDU; |
- |
- if (cr != 0) |
- prec = MPFR_PREC (y) + 3 + size_z + MPFR_INT_CEIL_LOG2 (MPFR_PREC (y)); |
- else |
- prec = MPFR_PREC (y); |
- mpfr_init2 (res, prec); |
- |
- MPFR_ZIV_INIT (loop, prec); |
- for (;;) |
- { |
- unsigned int inexmul; /* will be non-zero if res may be inexact */ |
- mp_size_t i = size_z; |
- |
- /* now 2^(i-1) <= z < 2^i */ |
- /* see below (case z < 0) for the error analysis, which is identical, |
- except if z=n, the maximal relative error is here 2(n-1)2^(-prec) |
- instead of 2(2n-1)2^(-prec) for z<0. */ |
- MPFR_ASSERTD (prec > (mpfr_prec_t) i); |
- err = prec - 1 - (mpfr_prec_t) i; |
- |
- MPFR_BLOCK (flags, |
- inexmul = mpfr_mul (res, x, x, rnd2); |
- MPFR_ASSERTD (i >= 2); |
- if (mpz_tstbit (absz, i - 2)) |
- inexmul |= mpfr_mul (res, res, x, rnd1); |
- for (i -= 3; i >= 0 && !MPFR_BLOCK_EXCEP; i--) |
- { |
- inexmul |= mpfr_mul (res, res, res, rnd2); |
- if (mpz_tstbit (absz, i)) |
- inexmul |= mpfr_mul (res, res, x, rnd1); |
- }); |
- if (MPFR_LIKELY (inexmul == 0 || cr == 0 |
- || MPFR_OVERFLOW (flags) || MPFR_UNDERFLOW (flags) |
- || MPFR_CAN_ROUND (res, err, MPFR_PREC (y), rnd))) |
- break; |
- /* Can't decide correct rounding, increase the precision */ |
- MPFR_ZIV_NEXT (loop, prec); |
- mpfr_set_prec (res, prec); |
- } |
- MPFR_ZIV_FREE (loop); |
- |
- /* Check Overflow */ |
- if (MPFR_OVERFLOW (flags)) |
- { |
- MPFR_LOG_MSG (("overflow\n", 0)); |
- inexact = mpfr_overflow (y, rnd, mpz_odd_p (absz) ? |
- MPFR_SIGN (x) : MPFR_SIGN_POS); |
- } |
- /* Check Underflow */ |
- else if (MPFR_UNDERFLOW (flags)) |
- { |
- MPFR_LOG_MSG (("underflow\n", 0)); |
- if (rnd == GMP_RNDN) |
- { |
- mpfr_t y2, zz; |
- |
- /* We cannot decide now whether the result should be rounded |
- toward zero or +Inf. So, let's use the general case of |
- mpfr_pow, which can do that. But the problem is that the |
- result can be exact! However, it is sufficient to try to |
- round on 2 bits (the precision does not matter in case of |
- underflow, since MPFR does not have subnormals), in which |
- case, the result cannot be exact due to previous filtering |
- of trivial cases. */ |
- MPFR_ASSERTD (mpfr_cmp_si_2exp (x, MPFR_SIGN (x), |
- MPFR_EXP (x) - 1) != 0); |
- mpfr_init2 (y2, 2); |
- mpfr_init2 (zz, ABS (SIZ (z)) * BITS_PER_MP_LIMB); |
- inexact = mpfr_set_z (zz, z, GMP_RNDN); |
- MPFR_ASSERTN (inexact == 0); |
- inexact = mpfr_pow_general (y2, x, zz, rnd, 1, |
- (mpfr_save_expo_t *) NULL); |
- mpfr_clear (zz); |
- mpfr_set (y, y2, GMP_RNDN); |
- mpfr_clear (y2); |
- __gmpfr_flags = MPFR_FLAGS_INEXACT | MPFR_FLAGS_UNDERFLOW; |
- } |
- else |
- { |
- inexact = mpfr_underflow (y, rnd, mpz_odd_p (absz) ? |
- MPFR_SIGN (x) : MPFR_SIGN_POS); |
- } |
- } |
- else |
- inexact = mpfr_set (y, res, rnd); |
- |
- mpfr_clear (res); |
- return inexact; |
-} |
- |
-/* The computation of y = pow(x,z) is done by |
- * y = set_ui(1) if z = 0 |
- * y = pow_ui(x,z) if z > 0 |
- * y = pow_ui(1/x,-z) if z < 0 |
- * |
- * Note: in case z < 0, we could also compute 1/pow_ui(x,-z). However, in |
- * case MAX < 1/MIN, where MAX is the largest positive value, i.e., |
- * MAX = nextbelow(+Inf), and MIN is the smallest positive value, i.e., |
- * MIN = nextabove(+0), then x^(-z) might produce an overflow, whereas |
- * x^z is representable. |
- */ |
- |
-int |
-mpfr_pow_z (mpfr_ptr y, mpfr_srcptr x, mpz_srcptr z, mp_rnd_t rnd) |
-{ |
- int inexact; |
- mpz_t tmp; |
- MPFR_SAVE_EXPO_DECL (expo); |
- |
- MPFR_LOG_FUNC (("x[%#R]=%R z=? rnd=%d", x, x, rnd), |
- ("y[%#R]=%R inexact=%d", y, y, inexact)); |
- |
- /* x^0 = 1 for any x, even a NaN */ |
- if (MPFR_UNLIKELY (mpz_sgn (z) == 0)) |
- return mpfr_set_ui (y, 1, rnd); |
- |
- if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x))) |
- { |
- if (MPFR_IS_NAN (x)) |
- { |
- MPFR_SET_NAN (y); |
- MPFR_RET_NAN; |
- } |
- else if (MPFR_IS_INF (x)) |
- { |
- /* Inf^n = Inf, (-Inf)^n = Inf for n even, -Inf for n odd */ |
- /* Inf ^(-n) = 0, sign = + if x>0 or z even */ |
- if (mpz_sgn (z) > 0) |
- MPFR_SET_INF (y); |
- else |
- MPFR_SET_ZERO (y); |
- if (MPFR_UNLIKELY (MPFR_IS_NEG (x) && mpz_odd_p (z))) |
- MPFR_SET_NEG (y); |
- else |
- MPFR_SET_POS (y); |
- MPFR_RET (0); |
- } |
- else /* x is zero */ |
- { |
- MPFR_ASSERTD (MPFR_IS_ZERO(x)); |
- if (mpz_sgn (z) > 0) |
- /* 0^n = +/-0 for any n */ |
- MPFR_SET_ZERO (y); |
- else |
- /* 0^(-n) if +/- INF */ |
- MPFR_SET_INF (y); |
- if (MPFR_LIKELY (MPFR_IS_POS (x) || mpz_even_p (z))) |
- MPFR_SET_POS (y); |
- else |
- MPFR_SET_NEG (y); |
- MPFR_RET(0); |
- } |
- } |
- |
- /* detect exact powers: x^-n is exact iff x is a power of 2 |
- Do it if n > 0 too as this is faster and this filtering is |
- needed in case of underflow. */ |
- if (MPFR_UNLIKELY (mpfr_cmp_si_2exp (x, MPFR_SIGN (x), |
- MPFR_EXP (x) - 1) == 0)) |
- { |
- mp_exp_t expx = MPFR_EXP (x); /* warning: x and y may be the same |
- variable */ |
- |
- MPFR_LOG_MSG (("x^n with x power of two\n", 0)); |
- mpfr_set_si (y, mpz_odd_p (z) ? MPFR_INT_SIGN(x) : 1, rnd); |
- MPFR_ASSERTD (MPFR_IS_FP (y)); |
- mpz_init (tmp); |
- mpz_mul_si (tmp, z, expx - 1); |
- MPFR_ASSERTD (MPFR_GET_EXP (y) == 1); |
- mpz_add_ui (tmp, tmp, 1); |
- inexact = 0; |
- if (MPFR_UNLIKELY (mpz_cmp_si (tmp, __gmpfr_emin) < 0)) |
- { |
- MPFR_LOG_MSG (("underflow\n", 0)); |
- /* |y| is a power of two, thus |y| <= 2^(emin-2), and in |
- rounding to nearest, the value must be rounded to 0. */ |
- if (rnd == GMP_RNDN) |
- rnd = GMP_RNDZ; |
- inexact = mpfr_underflow (y, rnd, MPFR_SIGN (y)); |
- } |
- else if (MPFR_UNLIKELY (mpz_cmp_si (tmp, __gmpfr_emax) > 0)) |
- { |
- MPFR_LOG_MSG (("overflow\n", 0)); |
- inexact = mpfr_overflow (y, rnd, MPFR_SIGN (y)); |
- } |
- else |
- MPFR_SET_EXP (y, mpz_get_si (tmp)); |
- mpz_clear (tmp); |
- MPFR_RET (inexact); |
- } |
- |
- MPFR_SAVE_EXPO_MARK (expo); |
- |
- if (mpz_sgn (z) > 0) |
- { |
- inexact = mpfr_pow_pos_z (y, x, z, rnd, 1); |
- MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); |
- } |
- else |
- { |
- /* Declaration of the intermediary variable */ |
- mpfr_t t; |
- mp_prec_t Nt; /* Precision of the intermediary variable */ |
- mp_rnd_t rnd1; |
- mp_size_t size_z; |
- MPFR_ZIV_DECL (loop); |
- |
- MPFR_MPZ_SIZEINBASE2 (size_z, z); |
- |
- /* initial working precision */ |
- Nt = MPFR_PREC (y); |
- Nt = Nt + size_z + 3 + MPFR_INT_CEIL_LOG2 (Nt); |
- /* ensures Nt >= bits(z)+2 */ |
- |
- /* initialise of intermediary variable */ |
- mpfr_init2 (t, Nt); |
- |
- /* We will compute rnd(rnd1(1/x) ^ (-z)), where rnd1 is the rounding |
- toward sign(x), to avoid spurious overflow or underflow. */ |
- rnd1 = MPFR_EXP (x) < 1 ? GMP_RNDZ : |
- (MPFR_SIGN (x) > 0 ? GMP_RNDU : GMP_RNDD); |
- |
- MPFR_ZIV_INIT (loop, Nt); |
- for (;;) |
- { |
- MPFR_BLOCK_DECL (flags); |
- |
- /* compute (1/x)^(-z), -z>0 */ |
- /* As emin = -emax, an underflow cannot occur in the division. |
- And if an overflow occurs, then this means that x^z overflows |
- too (since we have rounded toward 1 or -1). */ |
- MPFR_BLOCK (flags, mpfr_ui_div (t, 1, x, rnd1)); |
- MPFR_ASSERTD (! MPFR_UNDERFLOW (flags)); |
- /* t = (1/x)*(1+theta) where |theta| <= 2^(-Nt) */ |
- if (MPFR_UNLIKELY (MPFR_OVERFLOW (flags))) |
- goto overflow; |
- MPFR_BLOCK (flags, mpfr_pow_pos_z (t, t, z, rnd, 0)); |
- /* Now if z=-n, t = x^z*(1+theta)^(2n-1) where |theta| <= 2^(-Nt), |
- with theta maybe different from above. If (2n-1)*2^(-Nt) <= 1/2, |
- which is satisfied as soon as Nt >= bits(z)+2, then we can use |
- Lemma \ref{lemma_graillat} from algorithms.tex, which yields |
- t = x^z*(1+theta) with |theta| <= 2(2n-1)*2^(-Nt), thus the |
- error is bounded by 2(2n-1) ulps <= 2^(bits(z)+2) ulps. */ |
- if (MPFR_UNLIKELY (MPFR_OVERFLOW (flags))) |
- { |
- overflow: |
- MPFR_ZIV_FREE (loop); |
- mpfr_clear (t); |
- MPFR_SAVE_EXPO_FREE (expo); |
- MPFR_LOG_MSG (("overflow\n", 0)); |
- return mpfr_overflow (y, rnd, |
- mpz_odd_p (z) ? MPFR_SIGN (x) : |
- MPFR_SIGN_POS); |
- } |
- if (MPFR_UNLIKELY (MPFR_UNDERFLOW (flags))) |
- { |
- MPFR_ZIV_FREE (loop); |
- mpfr_clear (t); |
- MPFR_LOG_MSG (("underflow\n", 0)); |
- if (rnd == GMP_RNDN) |
- { |
- mpfr_t y2, zz; |
- |
- /* We cannot decide now whether the result should be |
- rounded toward zero or away from zero. So, like |
- in mpfr_pow_pos_z, let's use the general case of |
- mpfr_pow in precision 2. */ |
- MPFR_ASSERTD (mpfr_cmp_si_2exp (x, MPFR_SIGN (x), |
- MPFR_EXP (x) - 1) != 0); |
- mpfr_init2 (y2, 2); |
- mpfr_init2 (zz, ABS (SIZ (z)) * BITS_PER_MP_LIMB); |
- inexact = mpfr_set_z (zz, z, GMP_RNDN); |
- MPFR_ASSERTN (inexact == 0); |
- inexact = mpfr_pow_general (y2, x, zz, rnd, 1, |
- (mpfr_save_expo_t *) NULL); |
- mpfr_clear (zz); |
- mpfr_set (y, y2, GMP_RNDN); |
- mpfr_clear (y2); |
- MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, MPFR_FLAGS_UNDERFLOW); |
- goto end; |
- } |
- else |
- { |
- MPFR_SAVE_EXPO_FREE (expo); |
- return mpfr_underflow (y, rnd, mpz_odd_p (z) ? |
- MPFR_SIGN (x) : MPFR_SIGN_POS); |
- } |
- } |
- if (MPFR_LIKELY (MPFR_CAN_ROUND (t, Nt - size_z - 2, MPFR_PREC (y), |
- rnd))) |
- break; |
- /* actualisation of the precision */ |
- MPFR_ZIV_NEXT (loop, Nt); |
- mpfr_set_prec (t, Nt); |
- } |
- MPFR_ZIV_FREE (loop); |
- |
- inexact = mpfr_set (y, t, rnd); |
- mpfr_clear (t); |
- } |
- |
- end: |
- MPFR_SAVE_EXPO_FREE (expo); |
- return mpfr_check_range (y, inexact, rnd); |
-} |