diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-09-17 01:28:50 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-09-17 01:28:50 +0000 |
commit | b0db7939a3a9dbe5cdc3f21b65c7727a0a723fe0 (patch) | |
tree | 13b37fe93a02d7ab652503bcdc4b3b55cdb5e3d6 /gcc/real.c | |
parent | 7c4f0b1d149a7f54e531cc148616dd6838816eb2 (diff) | |
download | gcc-b0db7939a3a9dbe5cdc3f21b65c7727a0a723fe0.tar.gz |
gcc/
* builtin-types.def (BT_FN_FLOAT_CONST_STRING): New.
(BT_FN_DOUBLE_CONST_STRING, BT_FN_LONG_DOUBLE_CONST_STRING): New.
* builtins.def (__builtin_nan, __builtin_nanf, __builtin_nanl): New.
(__builtin_nans, __builtin_nansf, __builtin_nansl): New.
* builtins.c (fold_builtin_nan): New.
(fold_builtin): Call it.
* real.c (real_nan): Parse a non-empty string.
(round_for_format): Fix NaN significand truncation.
* real.h (real_nan): Return bool.
* doc/extend.texi: Document new builtins.
libstdc++/
* include/std/std_limits.h (__glibcpp_f32_QNaN_bytes,
__glibcpp_f32_has_QNaN, __glibcpp_f32_SNaN_bytes,
__glibcpp_f32_has_SNaN, __glibcpp_f64_QNaN_bytes,
__glibcpp_f64_has_QNaN, __glibcpp_f64_SNaN_bytes,
__glibcpp_f64_has_SNaN, __glibcpp_f80_QNaN_bytes,
__glibcpp_f80_has_QNaN, __glibcpp_f80_SNaN_bytes,
__glibcpp_f80_has_SNaN, __glibcpp_f96_QNaN_bytes,
__glibcpp_f96_has_QNaN, __glibcpp_f96_SNaN_bytes,
__glibcpp_f96_has_SNaN, __glibcpp_f128_QNaN_bytes,
__glibcpp_f128_has_QNaN, __glibcpp_f128_SNaN_bytes,
__glibcpp_f128_has_SNaN, __glibcpp_float_QNaN_bytes,
__glibcpp_float_has_QNaN, __glibcpp_float_SNaN_bytes,
__glibcpp_float_has_SNaN, __glibcpp_double_QNaN_bytes,
__glibcpp_double_has_QNaN, __glibcpp_double_SNaN_bytes,
__glibcpp_double_has_SNaN, __glibcpp_long_double_QNaN_bytes,
__glibcpp_long_double_has_QNaN, __glibcpp_long_double_SNaN_bytes,
__glibcpp_long_double_has_SNaN): Remove.
(__glibcpp_f128_is_iec559): True if IEEE.
(__glibcpp_float_QNaN, __glibcpp_float_SNaN): Remove.
(__glibcpp_double_QNaN, __glibcpp_double_SNaN): Remove.
(__glibcpp_long_double_QNaN, __glibcpp_long_double_SNaN): Remove.
(std::numeric_limits<float>::has_quiet_NaN): Use __builtin_nanf.
(std::numeric_limits<float>::has_signaling_NaN): Mirror has_quiet_NaN.
(std::numeric_limits<float>::quiet_NaN): Use __builtin_nanf.
(std::numeric_limits<float>::signaling_NaN): Use __builtin_nansf.
(std::numeric_limits<double>): Similarly.
(std::numeric_limits<long double>): Similarly.
* src/limits.cc (__glibcpp_float_QNaN, __glibcpp_float_SNaN): Remove.
(__glibcpp_double_QNaN, __glibcpp_double_SNaN): Remove.
(__glibcpp_long_double_QNaN, __glibcpp_long_double_SNaN): Remove.
* testsuite/18_support/numeric_limits.cc (test_infinity): New.
(test_denorm_min, test_qnan, test_is_iec559): New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@57221 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/real.c')
-rw-r--r-- | gcc/real.c | 101 |
1 files changed, 94 insertions, 7 deletions
diff --git a/gcc/real.c b/gcc/real.c index 61ab02ce6a9..5859f0ff878 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -1946,16 +1946,22 @@ real_inf (tr) /* Fills R with a NaN whose significand is described by STR. If QUIET, we force a QNaN, else we force an SNaN. The string, if not empty, - is parsed as a number and placed in the significand. */ + is parsed as a number and placed in the significand. Return true + if the string was successfully parsed. */ -void +bool real_nan (tr, str, quiet, mode) REAL_VALUE_TYPE *tr; const char *str; int quiet; - enum machine_mode mode ATTRIBUTE_UNUSED; + enum machine_mode mode; { struct real_value *r = (struct real_value *) tr; + const struct real_format *fmt; + + fmt = fmt_for_mode[mode - QFmode]; + if (fmt == NULL) + abort (); if (*str == 0) { @@ -1965,8 +1971,89 @@ real_nan (tr, str, quiet, mode) get_canonical_snan (r, 0); } else - /* FIXME */ - abort (); + { + int base = 10, d; + bool neg = false; + + memset (r, 0, sizeof (*r)); + r->class = rvc_nan; + + /* Parse akin to strtol into the significand of R. */ + + while (ISSPACE (*str)) + str++; + if (*str == '-') + str++, neg = true; + else if (*str == '+') + str++; + if (*str == '0') + { + if (*++str == 'x') + str++, base = 16; + else + base = 8; + } + + while ((d = hex_value (*str)) < base) + { + struct real_value u; + + switch (base) + { + case 8: + lshift_significand (r, r, 3); + break; + case 16: + lshift_significand (r, r, 4); + break; + case 10: + lshift_significand_1 (&u, r); + lshift_significand (r, r, 3); + add_significands (r, r, &u); + break; + default: + abort (); + } + + get_zero (&u, 0); + u.sig[0] = d; + add_significands (r, r, &u); + + str++; + } + + /* Must have consumed the entire string for success. */ + if (*str != 0) + return false; + + /* Shift the significand into place such that the bits + are in the most significant bits for the format. */ + lshift_significand (r, r, SIGNIFICAND_BITS - fmt->p); + + /* Our MSB is always unset for NaNs. */ + r->sig[SIGSZ-1] &= ~SIG_MSB; + + /* Force quiet or signalling NaN. */ + if (quiet) + r->sig[SIGSZ-1] |= SIG_MSB >> 1; + else + r->sig[SIGSZ-1] &= ~(SIG_MSB >> 1); + + /* Force at least one bit of the significand set. */ + for (d = 0; d < SIGSZ; ++d) + if (r->sig[d]) + break; + if (d == SIGSZ) + r->sig[SIGSZ-1] |= SIG_MSB >> 2; + + /* Our intermediate format forces QNaNs to have MSB-1 set. + If the target format has QNaNs with the top bit unset, + mirror the output routines and invert the top two bits. */ + if (!fmt->qnan_msb_set) + r->sig[SIGSZ-1] ^= (SIG_MSB >> 1) | (SIG_MSB >> 2); + } + + return true; } /* Fills R with 2**N. */ @@ -2023,7 +2110,7 @@ round_for_format (fmt, r) return; case rvc_nan: - clear_significand_below (r, np2 + 1); + clear_significand_below (r, np2); /* If we've cleared the entire significand, we need one bit set for this to continue to be a NaN. */ @@ -2031,7 +2118,7 @@ round_for_format (fmt, r) if (r->sig[i]) break; if (i == SIGSZ) - r->sig[SIGSZ-1] = SIG_MSB >> 1; + r->sig[SIGSZ-1] = SIG_MSB >> 2; return; case rvc_normal: |