Mercurial > hg > CbC > CbC_gcc
diff gcc/real.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/real.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/real.c Thu Oct 25 07:37:49 2018 +0900 @@ -1,5 +1,5 @@ /* real.c - software floating point emulation. - Copyright (C) 1993-2017 Free Software Foundation, Inc. + Copyright (C) 1993-2018 Free Software Foundation, Inc. Contributed by Stephen L. Moshier (moshier@world.std.com). Re-written by Richard Henderson <rth@redhat.com> @@ -5048,6 +5048,102 @@ return false; } +/* Calculate nextafter (X, Y) or nexttoward (X, Y). Return true if + underflow or overflow needs to be raised. */ + +bool +real_nextafter (REAL_VALUE_TYPE *r, format_helper fmt, + const REAL_VALUE_TYPE *x, const REAL_VALUE_TYPE *y) +{ + int cmp = do_compare (x, y, 2); + /* If either operand is NaN, return qNaN. */ + if (cmp == 2) + { + get_canonical_qnan (r, 0); + return false; + } + /* If x == y, return y cast to target type. */ + if (cmp == 0) + { + real_convert (r, fmt, y); + return false; + } + + if (x->cl == rvc_zero) + { + get_zero (r, y->sign); + r->cl = rvc_normal; + SET_REAL_EXP (r, fmt->emin - fmt->p + 1); + r->sig[SIGSZ - 1] = SIG_MSB; + return false; + } + + int np2 = SIGNIFICAND_BITS - fmt->p; + /* For denormals adjust np2 correspondingly. */ + if (x->cl == rvc_normal && REAL_EXP (x) < fmt->emin) + np2 += fmt->emin - REAL_EXP (x); + + REAL_VALUE_TYPE u; + get_zero (r, x->sign); + get_zero (&u, 0); + set_significand_bit (&u, np2); + r->cl = rvc_normal; + SET_REAL_EXP (r, REAL_EXP (x)); + + if (x->cl == rvc_inf) + { + bool borrow = sub_significands (r, r, &u, 0); + gcc_assert (borrow); + SET_REAL_EXP (r, fmt->emax); + } + else if (cmp == (x->sign ? 1 : -1)) + { + if (add_significands (r, x, &u)) + { + /* Overflow. Means the significand had been all ones, and + is now all zeros. Need to increase the exponent, and + possibly re-normalize it. */ + SET_REAL_EXP (r, REAL_EXP (r) + 1); + if (REAL_EXP (r) > fmt->emax) + { + get_inf (r, x->sign); + return true; + } + r->sig[SIGSZ - 1] = SIG_MSB; + } + } + else + { + if (REAL_EXP (x) > fmt->emin && x->sig[SIGSZ - 1] == SIG_MSB) + { + int i; + for (i = SIGSZ - 2; i >= 0; i--) + if (x->sig[i]) + break; + if (i < 0) + { + /* When mantissa is 1.0, we need to subtract only + half of u: nextafter (1.0, 0.0) is 1.0 - __DBL_EPSILON__ / 2 + rather than 1.0 - __DBL_EPSILON__. */ + clear_significand_bit (&u, np2); + np2--; + set_significand_bit (&u, np2); + } + } + sub_significands (r, x, &u, 0); + } + + /* Clear out trailing garbage. */ + clear_significand_below (r, np2); + normalize (r); + if (REAL_EXP (r) <= fmt->emin - fmt->p) + { + get_zero (r, x->sign); + return true; + } + return r->cl == rvc_zero || REAL_EXP (r) < fmt->emin; +} + /* Write into BUF the maximum representable finite floating-point number, (1 - b**-p) * b**emax for a given FP format FMT as a hex float string. LEN is the size of BUF, and the buffer must be large @@ -5080,6 +5176,19 @@ gcc_assert (strlen (buf) < len); } +/* True if all values of integral type can be represented + by this floating-point type exactly. */ + +bool format_helper::can_represent_integral_type_p (tree type) const +{ + gcc_assert (! decimal_p () && INTEGRAL_TYPE_P (type)); + + /* INT?_MIN is power-of-two so it takes + only one mantissa bit. */ + bool signed_p = TYPE_SIGN (type) == SIGNED; + return TYPE_PRECISION (type) - signed_p <= significand_size (*this); +} + /* True if mode M has a NaN representation and the treatment of NaN operands is important. */ @@ -5183,3 +5292,29 @@ { return HONOR_SIGN_DEPENDENT_ROUNDING (GET_MODE (x)); } + +/* Fills r with the largest value such that 1 + r*r won't overflow. + This is used in both sin (atan (x)) and cos (atan(x)) optimizations. */ + +void +build_sinatan_real (REAL_VALUE_TYPE * r, tree type) +{ + REAL_VALUE_TYPE maxval; + mpfr_t mpfr_const1, mpfr_c, mpfr_maxval; + machine_mode mode = TYPE_MODE (type); + const struct real_format * fmt = REAL_MODE_FORMAT (mode); + + real_maxval (&maxval, 0, mode); + + mpfr_inits (mpfr_const1, mpfr_c, mpfr_maxval, NULL); + + mpfr_from_real (mpfr_const1, &dconst1, GMP_RNDN); + mpfr_from_real (mpfr_maxval, &maxval, GMP_RNDN); + + mpfr_sub (mpfr_c, mpfr_maxval, mpfr_const1, GMP_RNDN); + mpfr_sqrt (mpfr_c, mpfr_c, GMP_RNDZ); + + real_from_mpfr (r, mpfr_c, fmt, GMP_RNDZ); + + mpfr_clears (mpfr_const1, mpfr_c, mpfr_maxval, NULL); +}