summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2005-08-25 21:21:33 (GMT)
committerdgp <dgp@users.sourceforge.net>2005-08-25 21:21:33 (GMT)
commitde9e7888717097309aee50bf5fcd90453ee3dff8 (patch)
tree96d4a374f1736bc1cf74430bab58a46f4926c3f8
parent7937b78b247368beaf75e2f37177f5134e7a31f2 (diff)
downloadtcl-de9e7888717097309aee50bf5fcd90453ee3dff8.zip
tcl-de9e7888717097309aee50bf5fcd90453ee3dff8.tar.gz
tcl-de9e7888717097309aee50bf5fcd90453ee3dff8.tar.bz2
[kennykb-numerics-branch]
* generic/tclExecute.c: Bug fix. INST_RSHIFT: shift of negative values produced incorrect results.
-rw-r--r--ChangeLog5
-rw-r--r--generic/tclExecute.c16
2 files changed, 19 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index d1a7f4b..c4598e7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -8,7 +8,10 @@
[kennykb-numerics-branch] Merge updates from HEAD
- * generic/tclExecute.c: Bug fix. INST_*SHIFT* opcodes stack
+ * generic/tclExecute.c: Bug fix. INST_RSHIFT: shift of negative
+ values produced incorrect results.
+
+ * generic/tclExecute.c: Bug fix. INST_*SHIFT opcodes stack
management. [expr 0<<6] should be 0, not 6.
* generic/tclBasic.c: Extended the domain of round(.) to all
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index a22e3af..f37bc2c 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.c
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclExecute.c,v 1.167.2.37 2005/08/25 15:46:30 dgp Exp $
+ * RCS: @(#) $Id: tclExecute.c,v 1.167.2.38 2005/08/25 21:21:33 dgp Exp $
*/
#include "tclInt.h"
@@ -3854,6 +3854,7 @@ TclExecuteByteCode(interp, codePtr)
if (*pc == INST_LSHIFT) {
mp_mul_2d(&big1, shift, &bigResult);
} else {
+#if 0
mp_div_2d(&big1, shift, &bigResult, NULL);
if (mp_iszero(&bigResult) && big1.sign == MP_NEG) {
/* When right shifting a negative value, keep the sign bit */
@@ -3862,6 +3863,19 @@ TclExecuteByteCode(interp, codePtr)
Tcl_GetBignumFromObj(NULL, eePtr->constants[1], &bigOne);
mp_sub(&bigResult, &bigOne, &bigResult);
}
+#else
+ mp_int bigRemainder;
+ mp_init(&bigRemainder);
+ mp_div_2d(&big1, shift, &bigResult, &bigRemainder);
+ if (!mp_iszero(&bigRemainder) && (bigRemainder.sign == MP_NEG)) {
+ /* Convert to Tcl's integer division rules */
+ mp_int bigOne;
+ Tcl_GetBignumFromObj(NULL, eePtr->constants[1], &bigOne);
+ mp_sub(&bigResult, &bigOne, &bigResult);
+ mp_clear(&bigOne);
+ }
+ mp_clear(&bigRemainder);
+#endif
}
mp_clear(&big1);
TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));