From f8cf12e3304f75d9b47518935fcbeb8dc38a7c82 Mon Sep 17 00:00:00 2001 From: Kevin B Kenny Date: Tue, 11 Sep 2007 02:39:34 +0000 Subject: * generic/tclExecute.c: Corrected an off-by-one error in the setting of MaxBaseWide for certain powers. [Bug 1767293 - problem reported in comments when bug was reopened]. --- ChangeLog | 6 ++++++ generic/tclExecute.c | 28 +++++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5276c37..a2d8c5e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2007-09-11 Kevin B. Kenny + + * generic/tclExecute.c: Corrected an off-by-one error in the + setting of MaxBaseWide for certain powers. [Bug 1767293 - + problem reported in comments when bug was reopened]. + 2007-09-10 Jeff Hobbs * generic/tclLink.c (Tcl_UpdateLinkedVar): guard against var being diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 606d2d1..1d48e9c 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.333 2007/09/10 21:47:21 msofer Exp $ + * RCS: @(#) $Id: tclExecute.c,v 1.334 2007/09/11 02:39:35 kennykb Exp $ */ #include "tclInt.h" @@ -621,7 +621,8 @@ InitByteCodeExecution( * instruction tracing. */ { #if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) - int i; + int i, j; + Tcl_WideInt w, x; #endif #ifdef TCL_COMPILE_DEBUG if (Tcl_LinkVar(interp, "tcl_traceExec", (char *) &tclTraceExec, @@ -634,8 +635,29 @@ InitByteCodeExecution( (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); #endif /* TCL_COMPILE_STATS */ #if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) + + /* + * Fill in a table of what base can be raised to powers 2, 3, ... 16 + * without overflowing a Tcl_WideInt + */ for (i = 2; i <= 16; ++i) { - MaxBaseWide[i-2] = (Tcl_WideInt) pow((double) LLONG_MAX, 1.0 / i); + + /* Compute an initial guess in floating point */ + + w = (Tcl_WideInt) pow((double) LLONG_MAX, 1.0 / i) + 1; + + /* Correct the guess if it's too high */ + + for (;;) { + x = LLONG_MAX; + for (j = 0; j < i; ++j) { + x /= w; + } + if (x == 1) break; + --w; + } + + MaxBaseWide[i-2] = w; } #endif } -- cgit v0.12