summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2022-07-17 13:13:24 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2022-07-17 13:13:24 (GMT)
commitc2350850a9f065f4c85fa3a8f78b3a2329bb5e7d (patch)
treeec8b854cddf1ec6e25bd92a58d0bcb9bb05c576c
parent7c405a789e8e6b94cd18659c9994db418d92ad73 (diff)
parent86196ac2048f44c7bc4fc2c057558b8e7ebdca11 (diff)
downloadtcl-c2350850a9f065f4c85fa3a8f78b3a2329bb5e7d.zip
tcl-c2350850a9f065f4c85fa3a8f78b3a2329bb5e7d.tar.gz
tcl-c2350850a9f065f4c85fa3a8f78b3a2329bb5e7d.tar.bz2
Merge 8.7
-rw-r--r--generic/tclStrToD.c42
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;