diff options
| author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2022-07-17 13:13:24 (GMT) |
|---|---|---|
| committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2022-07-17 13:13:24 (GMT) |
| commit | c2350850a9f065f4c85fa3a8f78b3a2329bb5e7d (patch) | |
| tree | ec8b854cddf1ec6e25bd92a58d0bcb9bb05c576c | |
| parent | 7c405a789e8e6b94cd18659c9994db418d92ad73 (diff) | |
| parent | 86196ac2048f44c7bc4fc2c057558b8e7ebdca11 (diff) | |
| download | tcl-c2350850a9f065f4c85fa3a8f78b3a2329bb5e7d.zip tcl-c2350850a9f065f4c85fa3a8f78b3a2329bb5e7d.tar.gz tcl-c2350850a9f065f4c85fa3a8f78b3a2329bb5e7d.tar.bz2 | |
Merge 8.7
| -rw-r--r-- | generic/tclStrToD.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c index 9cd3811..a97ec04 100644 --- a/generic/tclStrToD.c +++ b/generic/tclStrToD.c @@ -1679,7 +1679,6 @@ MakeLowPrecisionDouble( int numSigDigs, /* Number of digits in the significand */ long exponent) /* Power of ten */ { - double retval; /* Value of the number. */ mp_int significandBig; /* Significand expressed as a bignum. */ /* @@ -1687,18 +1686,25 @@ MakeLowPrecisionDouble( * This causes the result of double-precision calculations to be rounded * twice: once to the precision of double-extended and then again to the * precision of double. Double-rounding introduces gratuitous errors of 1 - * ulp, so we need to change rounding mode to 53-bits. + * ulp, so we need to change rounding mode to 53-bits. We also make + * 'retval' volatile, so that it doesn't get promoted to a register. */ - - TCL_IEEE_DOUBLE_ROUNDING; + volatile double retval; /* Value of the number. */ /* - * Test for the easy cases. + * Test for zero significand, which requires explicit construction + * of -0.0. (Unary minus returns a positive zero.) */ - if (significand == 0) { return copysign(0.0, -signum); } + + /* + * Set the FP control word for 53 bits, WARNING: It must be reset + * before returning. + */ + TCL_IEEE_DOUBLE_ROUNDING; + if (numSigDigs <= QUICK_MAX) { if (exponent >= 0) { if (exponent <= mmaxpow) { @@ -1798,7 +1804,6 @@ MakeHighPrecisionDouble( int numSigDigs, /* Number of significant digits */ long exponent) /* Power of 10 by which to multiply */ { - double retval; int machexp = 0; /* Machine exponent of a power of 10. */ /* @@ -1806,19 +1811,30 @@ MakeHighPrecisionDouble( * This causes the result of double-precision calculations to be rounded * twice: once to the precision of double-extended and then again to the * precision of double. Double-rounding introduces gratuitous errors of 1 - * ulp, so we need to change rounding mode to 53-bits. + * ulp, so we need to change rounding mode to 53-bits. We also make + * 'retval' volatile to make sure that it doesn't get promoted to a + * register. */ - - TCL_IEEE_DOUBLE_ROUNDING; + volatile double retval; /* - * Quick checks for zero, and over/underflow. Be careful to avoid - * integer overflow when calculating with 'exponent'. + * A zero significand requires explicit construction of -0.0. + * (Unary minus returns positive zero.) */ - if (mp_iszero(significand)) { return copysign(0.0, -signum); } + + /* + * Set the 53-bit rounding mode. WARNING: It must be reset before + * returning. + */ + TCL_IEEE_DOUBLE_ROUNDING; + + /* + * Make quick checks for over/underflow. Be careful to avoid + * integer overflow when calculating with 'exponent'. + */ if (exponent >= 0 && exponent-1 > maxDigits-numSigDigs) { retval = HUGE_VAL; goto returnValue; |
