diff options
author | dgp <dgp@users.sourceforge.net> | 2005-08-25 21:21:33 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2005-08-25 21:21:33 (GMT) |
commit | de9e7888717097309aee50bf5fcd90453ee3dff8 (patch) | |
tree | 96d4a374f1736bc1cf74430bab58a46f4926c3f8 | |
parent | 7937b78b247368beaf75e2f37177f5134e7a31f2 (diff) | |
download | tcl-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-- | ChangeLog | 5 | ||||
-rw-r--r-- | generic/tclExecute.c | 16 |
2 files changed, 19 insertions, 2 deletions
@@ -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))); |