diff options
author | dgp <dgp@users.sourceforge.net> | 2005-10-04 21:02:29 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2005-10-04 21:02:29 (GMT) |
commit | bd1c0852fbc39078e6743648cdc05956ce34d147 (patch) | |
tree | 64722567b544529dad7426557daff38817783126 | |
parent | ae2a1eff464032022ba6854efb3bde8f236c7b56 (diff) | |
download | tcl-bd1c0852fbc39078e6743648cdc05956ce34d147.zip tcl-bd1c0852fbc39078e6743648cdc05956ce34d147.tar.gz tcl-bd1c0852fbc39078e6743648cdc05956ce34d147.tar.bz2 |
[kennykb-numerics-branch]
* generic/tclExecute.c: Updated TclIncrObj() to more efficiently
add native long integers. Also updated IllegalExprOperandType
and the INST_UMINUS, INST_UPLUS, INST_BITNOT, and
INST_TRY_CVT_TO_NUMERIC sections for performance.
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | generic/tclExecute.c | 198 |
2 files changed, 53 insertions, 148 deletions
@@ -4,7 +4,8 @@ * generic/tclExecute.c: Updated TclIncrObj() to more efficiently add native long integers. Also updated IllegalExprOperandType - and the INST_UMINUS and INST_BITNOT sections for performance. + and the INST_UMINUS, INST_UPLUS, INST_BITNOT, and + INST_TRY_CVT_TO_NUMERIC sections for performance. * generic/tclBasic.c: Updated more callers to make use of TclGetNumberFromObj. Removed some dead code. diff --git a/generic/tclExecute.c b/generic/tclExecute.c index bc025f2..e463c8d 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.44 2005/10/04 18:33:54 dgp Exp $ + * RCS: @(#) $Id: tclExecute.c,v 1.167.2.45 2005/10/04 21:02:30 dgp Exp $ */ #include "tclInt.h" @@ -5300,166 +5300,70 @@ TclExecuteByteCode(interp, codePtr) * operands if at all possible as numbers first, then strings. */ - double d; - Tcl_Obj *valuePtr; -#if 0 - char *s; - Tcl_ObjType *tPtr; - int converted, needNew, length; - long i; - Tcl_WideInt w; - - valuePtr = *tosPtr; - tPtr = valuePtr->typePtr; - converted = 0; - if (IS_INTEGER_TYPE(tPtr) - || ((tPtr == &tclDoubleType) && (valuePtr->bytes == NULL))) { - /* - * We already have a numeric internal rep, either some kind of - * integer, or a "pure" double. (Need "pure" so that we know the - * string rep of the double would not prefer to be interpreted as - * an integer.) - */ - } else { - /* - * Otherwise, we need to generate a numeric internal rep. from - * the string rep. - */ - s = Tcl_GetStringFromObj(valuePtr, &length); - if (TclLooksLikeInt(s, length)) { - GET_WIDE_OR_INT(result, valuePtr, i, w); - } else { - result = Tcl_GetDoubleFromObj(NULL, valuePtr, &d); - } - if (result == TCL_OK) { - converted = 1; - } - result = TCL_OK; /* reset the result variable */ - tPtr = valuePtr->typePtr; - } - - /* - * Ensure that the topmost stack object, if numeric, has a string rep - * the same as the formatted version of its internal rep. This is - * used, e.g., to make sure that "expr {0001}" yields "1", not - * "0001". We implement this by _discarding_ the string rep since we - * know it will be regenerated, if needed later, by formatting the - * internal rep's value. Also check if there has been an IEEE floating - * point error. - */ + ClientData ptr; + int type; + Tcl_Obj *valuePtr = *tosPtr; - objResultPtr = valuePtr; - needNew = 0; - if (IS_NUMERIC_TYPE(tPtr)) { - if (Tcl_IsShared(valuePtr)) { - if (valuePtr->bytes != NULL) { - /* - * We only need to make a copy of the object when it - * already had a string rep - */ - needNew = 1; - if (tPtr == &tclIntType) { - i = valuePtr->internalRep.longValue; - TclNewLongObj(objResultPtr, i); - } else if (tPtr == &tclWideIntType) { - TclGetWide(w,valuePtr); - TclNewWideIntObj(objResultPtr, w); - } else if (tPtr == &tclBignumType) { - mp_int big; - Tcl_GetBignumFromObj(NULL, valuePtr, &big); - objResultPtr = Tcl_NewBignumObj(&big); - } else { - d = valuePtr->internalRep.doubleValue; - TclNewDoubleObj(objResultPtr, d); - } - tPtr = objResultPtr->typePtr; - } + if (TclGetNumberFromObj(NULL, valuePtr, &ptr, &type) != TCL_OK) { + if (*pc == INST_UPLUS) { + /* ... +$NonNumeric => raise an error */ + result = TCL_ERROR; + TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr), + (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); + IllegalExprOperandType(interp, pc, valuePtr); + goto checkForCatch; } else { - Tcl_InvalidateStringRep(valuePtr); - } - - if (tPtr == &tclDoubleType) { - d = objResultPtr->internalRep.doubleValue; - if (IS_NAN(d)) { - TRACE(("\"%.20s\" => IEEE FLOATING PT ERROR\n", - O2S(objResultPtr))); - TclExprFloatError(interp, d); - result = TCL_ERROR; - goto checkForCatch; - } + /* ... TryConvertToNumeric($NonNumeric) is acceptable */ + TRACE(("\"%.20s\" => not numeric\n", O2S(valuePtr))); + NEXT_INST_F(1, 0, 0); } - converted = converted; /* lint, converted not used. */ - TRACE(("\"%.20s\" => numeric, %s, %s\n", O2S(valuePtr), - (converted? "converted" : "not converted"), - (needNew? "new Tcl_Obj" : "same Tcl_Obj"))); - } else { - TRACE(("\"%.20s\" => not numeric\n", O2S(valuePtr))); - } - if (needNew) { - NEXT_INST_F(1, 1, 1); - } else { - NEXT_INST_F(1, 0, 0); } -#else - valuePtr = *tosPtr; - result = Tcl_GetDoubleFromObj(NULL, valuePtr, &d); - if ((result == TCL_OK) || valuePtr->typePtr == &tclDoubleType) { - /* Value is now numeric (including NaN) */ #ifndef ACCEPT_NAN - if ((*pc == INST_TRY_CVT_TO_NUMERIC) && (result != TCL_OK)) { + if (type == TCL_NUMBER_NAN) { + result = TCL_ERROR; + if (*pc == INST_UPLUS) { + /* ... +$NonNumeric => raise an error */ + TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr), + (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); + IllegalExprOperandType(interp, pc, valuePtr); + } else { /* Numeric conversion of NaN -> error */ TRACE(("\"%.20s\" => IEEE FLOATING PT ERROR\n", O2S(objResultPtr))); - TclExprFloatError(interp, valuePtr->internalRep.doubleValue); - goto checkForCatch; + TclExprFloatError(interp, *((CONST double *)ptr)); } -#else - result = TCL_OK; + goto checkForCatch; + } #endif - /* - * Ensure that the numeric value has a string rep the same as - * the formatted version of its internal rep. This is used, e.g., - * to make sure that "expr {0001}" yields "1", not "0001". - * We implement this by _discarding_ the string rep since we - * know it will be regenerated, if needed later, by formatting - * the internal rep's value. - */ - if (valuePtr->bytes == NULL) { - TRACE(("\"%.20s\" => numeric, same Tcl_Obj\n", O2S(valuePtr))); - NEXT_INST_F(1, 0, 0); - } - if (Tcl_IsShared(valuePtr)) { - /* - * Here we do some surgery within the Tcl_Obj internals. - * We want to copy the intrep, but not the string, so we - * temporarily hide the string so we do not copy it. - */ - char *savedString = valuePtr->bytes; - valuePtr->bytes = NULL; - objResultPtr = Tcl_DuplicateObj(valuePtr); - valuePtr->bytes = savedString; - TRACE(("\"%.20s\" => numeric, new Tcl_Obj\n", O2S(valuePtr))); - NEXT_INST_F(1, 1, 1); - } - TclInvalidateStringRep(valuePtr); - result = TCL_OK; + + /* + * Ensure that the numeric value has a string rep the same as + * the formatted version of its internal rep. This is used, e.g., + * to make sure that "expr {0001}" yields "1", not "0001". + * We implement this by _discarding_ the string rep since we + * know it will be regenerated, if needed later, by formatting + * the internal rep's value. + */ + if (valuePtr->bytes == NULL) { TRACE(("\"%.20s\" => numeric, same Tcl_Obj\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } - /* Non-numeric argument... */ - if (*pc == INST_UPLUS) { - /* ... +$NonNumeric => raise an error */ - TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr), - (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); - IllegalExprOperandType(interp, pc, valuePtr); - goto checkForCatch; - } else { - /* ... TryConvertToNumeric($NonNumeric) is acceptable */ - TRACE(("\"%.20s\" => not numeric\n", O2S(valuePtr))); - result = TCL_OK; - NEXT_INST_F(1, 0, 0); + if (Tcl_IsShared(valuePtr)) { + /* + * Here we do some surgery within the Tcl_Obj internals. + * We want to copy the intrep, but not the string, so we + * temporarily hide the string so we do not copy it. + */ + char *savedString = valuePtr->bytes; + valuePtr->bytes = NULL; + objResultPtr = Tcl_DuplicateObj(valuePtr); + valuePtr->bytes = savedString; + TRACE(("\"%.20s\" => numeric, new Tcl_Obj\n", O2S(valuePtr))); + NEXT_INST_F(1, 1, 1); } -#endif + TclInvalidateStringRep(valuePtr); + TRACE(("\"%.20s\" => numeric, same Tcl_Obj\n", O2S(valuePtr))); + NEXT_INST_F(1, 0, 0); } case INST_BREAK: |