diff options
author | dgp <dgp@users.sourceforge.net> | 2012-12-10 04:32:13 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2012-12-10 04:32:13 (GMT) |
commit | 6569c1296649af791d6392751df2e1a15e5c5f24 (patch) | |
tree | 75dd49031467d624d8c3ad2f9f8725b367933f3a | |
parent | c69e1e2500a8de36ee29f0220170bddaf320b3f1 (diff) | |
download | tcl-novem_numbers_eias.zip tcl-novem_numbers_eias.tar.gz tcl-novem_numbers_eias.tar.bz2 |
WIP getting rid of the ::tcl_precision variablenovem_numbers_eias
-rw-r--r-- | doc/PrintDbl.3 | 9 | ||||
-rw-r--r-- | doc/tclvars.n | 57 | ||||
-rw-r--r-- | generic/tcl.h | 6 | ||||
-rw-r--r-- | generic/tclBasic.c | 3 | ||||
-rw-r--r-- | generic/tclCompExpr.c | 2 | ||||
-rw-r--r-- | generic/tclInt.decls | 8 | ||||
-rw-r--r-- | generic/tclIntDecls.h | 10 | ||||
-rw-r--r-- | generic/tclObj.c | 5 | ||||
-rwxr-xr-x | generic/tclStrToD.c | 4 | ||||
-rw-r--r-- | generic/tclStubInit.c | 2 | ||||
-rw-r--r-- | generic/tclUtil.c | 158 | ||||
-rw-r--r-- | tests/basic.test | 1 | ||||
-rw-r--r-- | tests/util.test | 8 |
13 files changed, 34 insertions, 239 deletions
diff --git a/doc/PrintDbl.3 b/doc/PrintDbl.3 index 99b0113..baa415c 100644 --- a/doc/PrintDbl.3 +++ b/doc/PrintDbl.3 @@ -18,10 +18,7 @@ Tcl_PrintDouble \- Convert floating value to string .SH ARGUMENTS .AS Tcl_Interp *interp out .AP Tcl_Interp *interp in -Before Tcl 8.0, the \fBtcl_precision\fR variable in this interpreter -controlled the conversion. As of Tcl 8.0, this argument is ignored and -the conversion is controlled by the \fBtcl_precision\fR variable -that is now shared by all interpreters. +This argument is ignored. .AP double value in Floating-point value to be converted. .AP char *dst out @@ -41,9 +38,7 @@ so that it does not look like an integer. Where \fB%g\fR would generate an integer with no decimal point, \fBTcl_PrintDouble\fR adds .QW .0 . .PP -If the \fBtcl_precision\fR value is non-zero, the result will have -precisely that many digits of significance. If the value is zero -(the default), the result will have the fewest digits needed to +The string generated has the fewest digits needed to represent the number in such a way that \fBTcl_NewDoubleObj\fR will generate the same number when presented with the given string. IEEE semantics of rounding to even apply to the conversion. diff --git a/doc/tclvars.n b/doc/tclvars.n index 44a8e11..2ea08c9 100644 --- a/doc/tclvars.n +++ b/doc/tclvars.n @@ -10,7 +10,7 @@ .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME -argc, argv, argv0, auto_path, env, errorCode, errorInfo, tcl_interactive, tcl_library, tcl_nonwordchars, tcl_patchLevel, tcl_pkgPath, tcl_platform, tcl_precision, tcl_rcFileName, tcl_traceCompile, tcl_traceEval, tcl_wordchars, tcl_version \- Variables used by Tcl +argc, argv, argv0, auto_path, env, errorCode, errorInfo, tcl_interactive, tcl_library, tcl_nonwordchars, tcl_patchLevel, tcl_pkgPath, tcl_platform, tcl_rcFileName, tcl_traceCompile, tcl_traceEval, tcl_wordchars, tcl_version \- Variables used by Tcl .BE .SH DESCRIPTION .PP @@ -356,61 +356,6 @@ This gives the size of the native-machine word in bytes (strictly, it is same as the result of evaluating \fIsizeof(long)\fR in C.) .RE .TP -\fBtcl_precision\fR -. -This variable controls the number of digits to generate -when converting floating-point values to strings. It defaults -to 0. \fIApplications should not change this value;\fR it is -provided for compatibility with legacy code. -.PP -.RS -The default value of 0 is special, meaning that Tcl should -convert numbers using as few digits as possible while still -distinguishing any floating point number from its nearest -neighbours. It differs from using an arbitrarily high value -for \fItcl_precision\fR in that an inexact number like \fI1.4\fR -will convert as \fI1.4\fR rather than \fI1.3999999999999999\fR -even though the latter is nearer to the exact value of the -binary number. -.RE -.PP -.RS -If \fBtcl_precision\fR is not zero, then when Tcl converts a floating -point number, it creates a decimal representation of at most -\fBtcl_precision\fR significant digits; the result may be shorter if -the shorter result represents the original number exactly. If no -result of at most \fBtcl_precision\fR digits is an exact representation -of the original number, the one that is closest to the original -number is chosen. -If the original number lies precisely between two equally accurate -decimal representations, then the one with an even value for the least -significant digit is chosen; for instance, if \fBtcl_precision\fR is 3, then -0.3125 will convert to 0.312, not 0.313, while 0.6875 will convert to -0.688, not 0.687. Any string of trailing zeroes that remains is trimmed. -.RE -.PP -.RS -a \fBtcl_precision\fR value of 17 digits is -.QW perfect -for IEEE floating-point in that it allows -double-precision values to be converted to strings and back to -binary with no loss of information. For this reason, you will often -see it as a value in legacy code that must run on Tcl versions before -8.5. It is no longer recommended; as noted above, a zero value is the -preferred method. -.RE -.PP -.RS -All interpreters in a thread share a single \fBtcl_precision\fR value: -changing it in one interpreter will affect all other interpreters as -well. Safe interpreters are not allowed to modify the -variable. -.RE -.PP -.RS -Valid values for \fBtcl_precision\fR range from 0 to 17. -.RE -.TP \fBtcl_rcFileName\fR . This variable is used during initialization to indicate the name of a diff --git a/generic/tcl.h b/generic/tcl.h index 162983b..bfcc750 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -827,9 +827,9 @@ typedef struct Tcl_DString { #define Tcl_DStringValue(dsPtr) ((dsPtr)->string) /* - * Definitions for the maximum number of digits of precision that may be - * specified in the "tcl_precision" variable, and the number of bytes of - * buffer space required by Tcl_PrintDouble. + * Definitions for the maximum number of decimal digits of precision that may + * stored in a double, and the number of bytes of buffer space required by + * Tcl_PrintDouble. */ #define TCL_MAX_PREC 17 diff --git a/generic/tclBasic.c b/generic/tclBasic.c index 7202184..0b75fc8 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -897,9 +897,6 @@ Tcl_CreateInterp(void) Tcl_SetVar(interp, "tcl_patchLevel", TCL_PATCH_LEVEL, TCL_GLOBAL_ONLY); Tcl_SetVar(interp, "tcl_version", TCL_VERSION, TCL_GLOBAL_ONLY); - Tcl_TraceVar2(interp, "tcl_precision", NULL, - TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, - TclPrecTraceProc, NULL); TclpSetVariables(interp); #ifdef TCL_THREADS diff --git a/generic/tclCompExpr.c b/generic/tclCompExpr.c index 890d518..960ce9f 100644 --- a/generic/tclCompExpr.c +++ b/generic/tclCompExpr.c @@ -2339,10 +2339,12 @@ CompileExprTree( switch (nodePtr->lexeme) { case START: case QUESTION: +#if 1 if (convert && (nodePtr == rootPtr)) { TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr); } break; +#endif case OPEN_PAREN: /* do nothing */ diff --git a/generic/tclInt.decls b/generic/tclInt.decls index 8c46e55..3d9b1d9 100644 --- a/generic/tclInt.decls +++ b/generic/tclInt.decls @@ -359,10 +359,10 @@ declare 81 { # declare 87 { # void TclPlatformInit(Tcl_Interp *interp) # } -declare 88 { - char *TclPrecTraceProc(ClientData clientData, Tcl_Interp *interp, - const char *name1, const char *name2, int flags) -} +#declare 88 { +# char *TclPrecTraceProc(ClientData clientData, Tcl_Interp *interp, +# const char *name1, const char *name2, int flags) +#} declare 89 { int TclPreventAliasLoop(Tcl_Interp *interp, Tcl_Interp *cmdInterp, Tcl_Command cmd) diff --git a/generic/tclIntDecls.h b/generic/tclIntDecls.h index 65b1888..2b1f5c3 100644 --- a/generic/tclIntDecls.h +++ b/generic/tclIntDecls.h @@ -210,10 +210,7 @@ TCLAPI char * TclpRealloc(char *ptr, unsigned int size); /* Slot 85 is reserved */ /* Slot 86 is reserved */ /* Slot 87 is reserved */ -/* 88 */ -TCLAPI char * TclPrecTraceProc(ClientData clientData, - Tcl_Interp *interp, const char *name1, - const char *name2, int flags); +/* Slot 88 is reserved */ /* 89 */ TCLAPI int TclPreventAliasLoop(Tcl_Interp *interp, Tcl_Interp *cmdInterp, Tcl_Command cmd); @@ -673,7 +670,7 @@ typedef struct TclIntStubs { void (*reserved85)(void); void (*reserved86)(void); void (*reserved87)(void); - char * (*tclPrecTraceProc) (ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags); /* 88 */ + void (*reserved88)(void); int (*tclPreventAliasLoop) (Tcl_Interp *interp, Tcl_Interp *cmdInterp, Tcl_Command cmd); /* 89 */ void (*reserved90)(void); void (*tclProcCleanupProc) (Proc *procPtr); /* 91 */ @@ -983,8 +980,7 @@ extern const TclIntStubs *tclIntStubsPtr; /* Slot 85 is reserved */ /* Slot 86 is reserved */ /* Slot 87 is reserved */ -#define TclPrecTraceProc \ - (tclIntStubsPtr->tclPrecTraceProc) /* 88 */ +/* Slot 88 is reserved */ #define TclPreventAliasLoop \ (tclIntStubsPtr->tclPreventAliasLoop) /* 89 */ /* Slot 90 is reserved */ diff --git a/generic/tclObj.c b/generic/tclObj.c index 74cb29e..3a36375 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -2329,10 +2329,7 @@ SetDoubleFromAny( * UpdateStringOfDouble -- * * Update the string representation for a double-precision floating point - * object. This must obey the current tcl_precision value for - * double-to-string conversions. Note: This function does not free an - * existing old string rep so storage will be lost if this has not - * already been done. + * object. * * Results: * None. diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c index 2287a16..3edff7a 100755 --- a/generic/tclStrToD.c +++ b/generic/tclStrToD.c @@ -3934,8 +3934,8 @@ StrictBignumConversion( * This function is a service routine that produces the string of digits for * floating-point-to-decimal conversion. It can do a number of things * according to the 'flags' argument. Valid values for 'flags' include: - * TCL_DD_SHORTEST - This is the default for floating point conversion if - * ::tcl_precision is 0. It constructs the shortest string of + * TCL_DD_SHORTEST - This is the default for floating point conversion + * It constructs the shortest string of * digits that will reconvert to the given number when scanned. * For floating point numbers that are exactly between two * decimal numbers, it resolves using the 'round to even' rule. diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index c836f45..daae7f5 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -262,7 +262,7 @@ static const TclIntStubs tclIntStubs = { 0, /* 85 */ 0, /* 86 */ 0, /* 87 */ - TclPrecTraceProc, /* 88 */ + 0, /* 88 */ TclPreventAliasLoop, /* 89 */ 0, /* 90 */ TclProcCleanupProc, /* 91 */ diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 4b69628..2131cfe 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -93,13 +93,6 @@ static ProcessGlobalValue executableName = { #define CONVERT_ANY 16 /* - * The following key is used by Tcl_PrintDouble and TclPrecTraceProc to - * access the precision to be used for double formatting. - */ - -static Tcl_ThreadDataKey precisionKey; - -/* * Prototypes for functions defined later in this file. */ @@ -2920,10 +2913,9 @@ Tcl_DStringEndSublist( * string using. * * Results: - * The ASCII equivalent of "value" is written at "dst". It is written - * using the current precision, and it is guaranteed to contain a decimal - * point or exponent, so that it looks like a floating-point value and - * not an integer. + * The ASCII equivalent of "value" is written at "dst". It is guaranteed + * to contain a decimal point or exponent, so that it looks like a + * floating-point value and not an integer. * * Side effects: * None. @@ -2933,9 +2925,7 @@ Tcl_DStringEndSublist( void Tcl_PrintDouble( - Tcl_Interp *interp, /* Interpreter whose tcl_precision variable - * used to be used to control printing. It's - * ignored now. */ + Tcl_Interp *interp, /* Ignored. */ double value, /* Value to print as string. */ char *dst) /* Where to store converted value; must have * at least TCL_DOUBLE_SPACE characters. */ @@ -2945,7 +2935,6 @@ Tcl_PrintDouble( int signum; char *digits; char *end; - int *precisionPtr = Tcl_GetThreadData(&precisionKey, (int) sizeof(int)); /* * Handle NaN. @@ -2977,53 +2966,8 @@ Tcl_PrintDouble( * Ordinary (normal and denormal) values. */ - if (*precisionPtr == 0) { - digits = TclDoubleDigits(value, -1, TCL_DD_SHORTEST, - &exponent, &signum, &end); - } else { - /* - * There are at least two possible interpretations for tcl_precision. - * - * The first is, "choose the decimal representation having - * $tcl_precision digits of significance that is nearest to the given - * number, breaking ties by rounding to even, and then trimming - * trailing zeros." This gives the greatest possible precision in the - * decimal string, but offers the anomaly that [expr 0.1] will be - * "0.10000000000000001". - * - * The second is "choose the decimal representation having at most - * $tcl_precision digits of significance that is nearest to the given - * number. If no such representation converts exactly to the given - * number, choose the one that is closest, breaking ties by rounding - * to even. If more than one such representation converts exactly to - * the given number, choose the shortest, breaking ties in favour of - * the nearest, breaking remaining ties in favour of the one ending in - * an even digit." - * - * Tcl 8.4 implements the first of these, which gives rise to - * anomalies in formatting: - * - * % expr 0.1 - * 0.10000000000000001 - * % expr 0.01 - * 0.01 - * % expr 1e-7 - * 9.9999999999999995e-08 - * - * For human readability, it appears better to choose the second rule, - * and let [expr 0.1] return 0.1. But for 8.4 compatibility, we prefer - * the first (the recommended zero value for tcl_precision avoids the - * problem entirely). - * - * Uncomment TCL_DD_SHORTEN_FLAG in the next call to prefer the method - * that allows floating point values to be shortened if it can be done - * without loss of precision. - */ - - digits = TclDoubleDigits(value, *precisionPtr, - TCL_DD_E_FORMAT /* | TCL_DD_SHORTEN_FLAG */, - &exponent, &signum, &end); - } + digits = TclDoubleDigits(value, -1, TCL_DD_SHORTEST, &exponent, + &signum, &end); if (signum) { *dst++ = '-'; } @@ -3042,17 +2986,7 @@ Tcl_PrintDouble( c = *++p; } } - - /* - * Tcl 8.4 appears to format with at least a two-digit exponent; - * preserve that behaviour when tcl_precision != 0 - */ - - if (*precisionPtr == 0) { - sprintf(dst, "e%+d", exponent); - } else { - sprintf(dst, "e%+03d", exponent); - } + sprintf(dst, "e%+d", exponent); } else { /* * F format for others. @@ -3090,84 +3024,6 @@ Tcl_PrintDouble( /* *---------------------------------------------------------------------- * - * TclPrecTraceProc -- - * - * This function is invoked whenever the variable "tcl_precision" is - * written. - * - * Results: - * Returns NULL if all went well, or an error message if the new value - * for the variable doesn't make sense. - * - * Side effects: - * If the new value doesn't make sense then this function undoes the - * effect of the variable modification. Otherwise it modifies the format - * string that's used by Tcl_PrintDouble. - * - *---------------------------------------------------------------------- - */ - - /* ARGSUSED */ -char * -TclPrecTraceProc( - ClientData clientData, /* Not used. */ - Tcl_Interp *interp, /* Interpreter containing variable. */ - const char *name1, /* Name of variable. */ - const char *name2, /* Second part of variable name. */ - int flags) /* Information about what happened. */ -{ - Tcl_Obj *value; - int prec; - int *precisionPtr = Tcl_GetThreadData(&precisionKey, (int) sizeof(int)); - - /* - * If the variable is unset, then recreate the trace. - */ - - if (flags & TCL_TRACE_UNSETS) { - if ((flags & TCL_TRACE_DESTROYED) && !Tcl_InterpDeleted(interp)) { - Tcl_TraceVar2(interp, name1, name2, - TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES - |TCL_TRACE_UNSETS, TclPrecTraceProc, clientData); - } - return NULL; - } - - /* - * When the variable is read, reset its value from our shared value. This - * is needed in case the variable was modified in some other interpreter - * so that this interpreter's value is out of date. - */ - - - if (flags & TCL_TRACE_READS) { - Tcl_SetVar2Ex(interp, name1, name2, Tcl_NewIntObj(*precisionPtr), - flags & TCL_GLOBAL_ONLY); - return NULL; - } - - /* - * The variable is being written. Check the new value and disallow it if - * it isn't reasonable or if this is a safe interpreter (we don't want - * safe interpreters messing up the precision of other interpreters). - */ - - if (Tcl_IsSafe(interp)) { - return (char *) "can't modify precision from a safe interpreter"; - } - value = Tcl_GetVar2Ex(interp, name1, name2, flags & TCL_GLOBAL_ONLY); - if (value == NULL - || Tcl_GetIntFromObj(NULL, value, &prec) != TCL_OK - || prec < 0 || prec > TCL_MAX_PREC) { - return (char *) "improper value for precision"; - } - *precisionPtr = prec; - return NULL; -} - -/* - *---------------------------------------------------------------------- - * * TclNeedSpace -- * * This function checks to see whether it is appropriate to add a space diff --git a/tests/basic.test b/tests/basic.test index 7435571..8db950c 100644 --- a/tests/basic.test +++ b/tests/basic.test @@ -868,6 +868,7 @@ test basic-48.16.$noComp {expansion: testing for leaks} -setup { rename stress {} } -result 0 +set ::tcl_precision 0 test basic-48.17.$noComp {expansion: object safety} -setup { set old_precision $::tcl_precision set ::tcl_precision 4 diff --git a/tests/util.test b/tests/util.test index 0e50483..f428ee9 100644 --- a/tests/util.test +++ b/tests/util.test @@ -383,6 +383,7 @@ test util-5.51 {Tcl_StringMatch} { Wrapper_Tcl_StringMatch "" "" } 1 +if 0 { test util-6.1 {Tcl_PrintDouble - using tcl_precision} -setup { set old_precision $::tcl_precision set ::tcl_precision 12 @@ -415,6 +416,7 @@ test util-6.4 {Tcl_PrintDouble - using tcl_precision} -setup { } -cleanup { set tcl_precision $old_precision } -result {x1.1234} +} test util-6.5 {Tcl_PrintDouble - make sure there's a decimal point} { concat x[expr 2.0] } {x2.0} @@ -422,6 +424,7 @@ test util-6.6 {Tcl_PrintDouble - make sure there's a decimal point} { concat x[expr 3.0e98] } {x3e+98} +if 0 { test util-7.1 {TclPrecTraceProc - unset callbacks} -setup { set old_precision $::tcl_precision } -body { @@ -465,6 +468,7 @@ test util-7.4 {TclPrecTraceProc - write traces, bogus values} -setup { } -cleanup { set ::tcl_precision $old_precision } -result {1 {can't set "tcl_precision": improper value for precision} 12} +} # This test always succeeded in the C locale anyway... test util-8.1 {TclNeedSpace - correct UTF8 handling} { @@ -2118,6 +2122,7 @@ test util-15.8 {smallest normal} {*}{ } } +if 0 { set saved_precision $::tcl_precision foreach ::tcl_precision {0 12} { for {set e -312} {$e < -9} {incr e} { @@ -3986,6 +3991,8 @@ test util-16.1.17.306 {8.4 compatible formatting of doubles} \ test util-16.1.17.307 {8.4 compatible formatting of doubles} \ {expr 1e307} \ 9.9999999999999999e+306 +set ::tcl_precision $saved_precision +} test util-17.1 {bankers' rounding [Bug 3349507]} {ieeeFloatingPoint} { set r {} @@ -4016,7 +4023,6 @@ test util-17.1 {bankers' rounding [Bug 3349507]} {ieeeFloatingPoint} { 0x4400000000000000 0xc400000000000000 }] -set ::tcl_precision $saved_precision # cleanup ::tcltest::cleanupTests |