Tcl Source Code

Artifact [8fcc7778e5]
Login

Artifact 8fcc7778e5215c4d23d0dcd4666b16683e671e15:

Attachment "132.patch" to ticket [722737ffff] added by kennykb 2003-12-20 00:24:51.
? generic/kevin-dtoa.c
? generic/kevin_dtoa.c
? generic/y.output
? generic/y.tab.c
? generic/y.tab.h
Index: generic/tclDecls.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclDecls.h,v
retrieving revision 1.100
diff -b -u -r1.100 tclDecls.h
Index: generic/tclInt.decls
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.decls,v
retrieving revision 1.67
diff -b -u -r1.67 tclInt.decls
--- generic/tclInt.decls	15 Dec 2003 00:49:38 -0000	1.67
+++ generic/tclInt.decls	19 Dec 2003 17:10:47 -0000
@@ -734,6 +734,17 @@
     Tcl_Obj *TclDbNewListObjDirect(int objc, Tcl_Obj **objv,
 	    CONST char *file, int line)
 }
+
+# added for 8.5 floating point conversion
+
+declare 182 generic {
+    char* TclDToA( double d, int mode, int nDigits, \
+                   int* decPt, int* signum, char** endPtr )
+}
+declare 183 generic {
+    void TclFreeDToA( char* digits )
+}
+
 ##############################################################################
 
 # Define the platform specific internal Tcl interface. These functions are
Index: generic/tclIntDecls.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIntDecls.h,v
retrieving revision 1.55
diff -b -u -r1.55 tclIntDecls.h
--- generic/tclIntDecls.h	15 Dec 2003 00:49:38 -0000	1.55
+++ generic/tclIntDecls.h	19 Dec 2003 17:10:47 -0000
@@ -957,6 +957,17 @@
 EXTERN Tcl_Obj *	TclDbNewListObjDirect _ANSI_ARGS_((int objc, 
 				Tcl_Obj ** objv, CONST char * file, int line));
 #endif
+#ifndef TclDToA_TCL_DECLARED
+#define TclDToA_TCL_DECLARED
+/* 182 */
+EXTERN char*		TclDToA _ANSI_ARGS_((double d, int mode, int nDigits, 
+				int* decPt, int* signum, char** endPtr));
+#endif
+#ifndef TclFreeDToA_TCL_DECLARED
+#define TclFreeDToA_TCL_DECLARED
+/* 183 */
+EXTERN void		TclFreeDToA _ANSI_ARGS_((char* digits));
+#endif
 
 typedef struct TclIntStubs {
     int magic;
@@ -1168,6 +1179,8 @@
     Tcl_Obj * (*tcl_GetStartupScript) _ANSI_ARGS_((CONST char ** encodingNamePtr)); /* 179 */
     Tcl_Obj * (*tclNewListObjDirect) _ANSI_ARGS_((int objc, Tcl_Obj ** objv)); /* 180 */
     Tcl_Obj * (*tclDbNewListObjDirect) _ANSI_ARGS_((int objc, Tcl_Obj ** objv, CONST char * file, int line)); /* 181 */
+    char* (*tclDToA) _ANSI_ARGS_((double d, int mode, int nDigits, int* decPt, int* signum, char** endPtr)); /* 182 */
+    void (*tclFreeDToA) _ANSI_ARGS_((char* digits)); /* 183 */
 } TclIntStubs;
 
 #ifdef __cplusplus
@@ -1807,6 +1820,14 @@
 #define TclDbNewListObjDirect \
 	(tclIntStubsPtr->tclDbNewListObjDirect) /* 181 */
 #endif
+#ifndef TclDToA
+#define TclDToA \
+	(tclIntStubsPtr->tclDToA) /* 182 */
+#endif
+#ifndef TclFreeDToA
+#define TclFreeDToA \
+	(tclIntStubsPtr->tclFreeDToA) /* 183 */
+#endif
 
 #endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */
 
Index: generic/tclIntPlatDecls.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIntPlatDecls.h,v
retrieving revision 1.21
diff -b -u -r1.21 tclIntPlatDecls.h
Index: generic/tclPlatDecls.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclPlatDecls.h,v
retrieving revision 1.20
diff -b -u -r1.20 tclPlatDecls.h
Index: generic/tclStubInit.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclStubInit.c,v
retrieving revision 1.91
diff -b -u -r1.91 tclStubInit.c
--- generic/tclStubInit.c	15 Dec 2003 00:49:38 -0000	1.91
+++ generic/tclStubInit.c	19 Dec 2003 17:10:48 -0000
@@ -276,6 +276,8 @@
     Tcl_GetStartupScript, /* 179 */
     TclNewListObjDirect, /* 180 */
     TclDbNewListObjDirect, /* 181 */
+    TclDToA, /* 182 */
+    TclFreeDToA, /* 183 */
 };
 
 TclIntPlatStubs tclIntPlatStubs = {
Index: generic/tclUtil.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclUtil.c,v
retrieving revision 1.43
diff -b -u -r1.43 tclUtil.c
--- generic/tclUtil.c	4 Sep 2003 16:44:12 -0000	1.43
+++ generic/tclUtil.c	19 Dec 2003 17:10:48 -0000
@@ -61,12 +61,11 @@
  * TclPrecTraceProc.
  */
 
-static char precisionString[10] = "12";
+static char precisionString[10] = "17";
 				/* The string value of all the tcl_precision
 				 * variables. */
-static char precisionFormat[10] = "%.12g";
-				/* The format string actually used in calls
-				 * to sprintf. */
+static int prec = 17;		/* The corresponding integer value. */
+
 TCL_DECLARE_MUTEX(precisionMutex)
 
 /*
@@ -1881,34 +1880,125 @@
 					 * must have at least TCL_DOUBLE_SPACE
 					 * characters. */
 {
-    char *p, c;
-    Tcl_UniChar ch;
 
-    Tcl_MutexLock(&precisionMutex);
-    sprintf(dst, precisionFormat, value);
-    Tcl_MutexUnlock(&precisionMutex);
+    char* digits0;
+    char* digits;		/* String of significant digits
+				 * for the conversion of value */
 
-    /*
-     * If the ASCII result looks like an integer, add ".0" so that it
-     * doesn't look like an integer anymore.  This prevents floating-point
-     * values from being converted to integers unintentionally.
-     * Check for ASCII specifically to speed up the function.
+    char* endPtr;		/* Pointer to the end of the string of
+				 * significant digits */
+    int decPt;			/* Position of the decimal point relative
+				 * to 'digits' */
+    int signum;			/* Flag == 1 if the number is negative */
+    char* p;			/* Pointer used to accumulate the
+				 * result string. */
+
+    p = dst;
+
+    /* Convert the value to a string of digits. */
+
+    digits0 = digits = TclDToA( value, 4, prec, &decPt, &signum, &endPtr );
+
+    /* Put in a minus sign if necessary */
+
+    if ( signum ) {
+	*p++ = '-';
+    }
+
+    /* Handle Infinity and NaN */
+
+    if ( decPt == 9999 ) {
+	while ( *p++ = *digits++ ) {
+	    /* do nothing */
+	}
+    } else {
+
+	/* Test whether to render the number in E format. The test goes
+	 * as follows:
+	 * (1) If decPt <= -3, then the string will be shorter in E format.
+	 *     Use it.
+	 * (2) If the decimal point is more than 5 places past the end
+	 *     of the string of significant digits, then E format is shorter.
+	 * (3) Otherwise, F format is shorter.
      */
 
-    for (p = dst; *p != 0; ) {
-	if (UCHAR(*p) < 0x80) {
-	    c = *p++;
+	if ( decPt <= -3 || decPt > ( endPtr - digits ) + 5 ) {
+
+	    /* E format. Render the significand with one digit before
+	     * the decimal point. */
+
+	    *p++ = *digits++;
+	    if ( *digits ) {
+		*p++ = '.';
+		while ( *p = *digits++ ) {
+		    p++;
+		}
+	    }
+
+	    /* (decPt-1) is the exponent. Put in its signum. */
+
+	    *p++ = 'e';
+	    --decPt;
+	    if ( decPt < 0 ) {
+		*p++ = '-';
+		decPt = -decPt;
 	} else {
-	    p += Tcl_UtfToUniChar(p, &ch);
-	    c = UCHAR(ch);
+		*p++ = '+';
 	}
-	if ((c == '.') || isalpha(UCHAR(c))) {	/* INTL: ISO only. */
-	    return;
+	    
+	    /* Put in the exponent */
+
+	    if ( decPt >= 100 ) {
+		*p++ = '0' + ( decPt / 100 );
+		decPt = decPt % 100;
 	}
+	    *p++ = '0' + ( decPt / 10 );
+	    *p++ = '0' + ( decPt % 10 );
+	    *p++ = '\0';
+
+	} else {
+
+	    /* F format */
+
+	    if ( decPt <= 0 ) {
+
+		/* Leading decimal point */
+
+		*p++ = '0';
+		*p++ = '.';
+		while ( decPt++ < 0 ) {
+		    *p++ = '0';
     }
-    p[0] = '.';
-    p[1] = '0';
-    p[2] = 0;
+
+	    } else {
+
+		/* Digits before the decimal point */
+
+		while ( decPt-- > 0 ) {
+		    if ( *digits ) {
+			*p++ = *digits++;
+		    } else {
+			*p++ = '0';
+		    }
+		}
+		*p++ = '.';
+	    }	
+
+	    /* Collect digits after the decimal point */
+
+	    if ( *digits ) {
+		while ( *p++ = *digits++ ) {
+		    /* do nothing */
+		}
+	    } else {
+		*p++ = '0';
+		*p++ = '\0';
+	    }
+	}
+    }
+
+    TclFreeDToA( digits0 );
+
 }
 
 /*
@@ -1942,7 +2032,6 @@
 {
     CONST char *value;
     char *end;
-    int prec;
 
     /*
      * If the variable is unset, then recreate the trace.
@@ -1999,7 +2088,6 @@
 	return "improper value for precision";
     }
     TclFormatInt(precisionString, prec);
-    sprintf(precisionFormat, "%%.%dg", prec);
     Tcl_MutexUnlock(&precisionMutex);
     return (char *) NULL;
 }
Index: tests/expr-old.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/expr-old.test,v
retrieving revision 1.17
diff -b -u -r1.17 expr-old.test
--- tests/expr-old.test	27 Mar 2003 13:48:58 -0000	1.17
+++ tests/expr-old.test	19 Dec 2003 17:10:49 -0000
@@ -93,7 +93,7 @@
 # automatic conversion to integers where needed.
 
 test expr-old-2.1 {floating-point operators} {expr -4.2} -4.2
-test expr-old-2.2 {floating-point operators} {expr -(1.1+4.2)} -5.3
+test expr-old-2.2 {floating-point operators} {expr -(1.1+4.4)} -5.5
 test expr-old-2.3 {floating-point operators} {expr +5.7} 5.7
 test expr-old-2.4 {floating-point operators} {expr +--+-62.0} -62.0
 test expr-old-2.5 {floating-point operators} {expr !2.1} 0
@@ -430,7 +430,7 @@
 test expr-old-25.16 {type conversions} {expr 2+2.5} 4.5
 test expr-old-25.17 {type conversions} {expr 2+2.5} 4.5
 test expr-old-25.18 {type conversions} {expr 2.0e2} 200.0
-test expr-old-25.19 {type conversions} {eformat} {expr 2.0e15} 2e+15
+test expr-old-25.19 {type conversions} {expr 2.0e15} 2e+15
 test expr-old-25.20 {type conversions} {expr 10.0} 10.0
 
 # Various error conditions.
Index: tests/scan.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/scan.test,v
retrieving revision 1.14
diff -b -u -r1.14 scan.test
--- tests/scan.test	22 Jun 2002 04:19:47 -0000	1.14
+++ tests/scan.test	19 Dec 2003 17:10:49 -0000
@@ -427,7 +427,7 @@
 test scan-6.1 {floating-point scanning} {
     set a {}; set b {}; set c {}; set d {}
     list [scan "2.1 -3.0e8 .99962 a" "%f%g%e%f" a b c d] $a $b $c $d
-} {3 2.1 -300000000.0 0.99962 {}}
+} {3 2.1 -3e+08 0.99962 {}}
 test scan-6.2 {floating-point scanning} {
     set a {}; set b {}; set c {}; set d {}
     list [scan "-1.2345 +8.2 9" "%3e %3lf %f %f" a b c d] $a $b $c $d
@@ -448,7 +448,7 @@
     set a {}; set b {}; set c {}; set d {}
     list [scan "4.6 99999.7 876.43e-1 118" "%f %f %f %e" a b c d] $a $b $c $d
 } {4 4.6 99999.7 87.643 118.0}
-test scan-6.6 {floating-point scanning} {eformat} {
+test scan-6.6 {floating-point scanning} {
     set a {}; set b {}; set c {}; set d {}
     list [scan "1.2345 697.0e-3 124 .00005" "%f %e %f %e" a b c d] $a $b $c $d
 } {4 1.2345 0.697 124.0 5e-05}
Index: tests/util.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/util.test,v
retrieving revision 1.13
diff -b -u -r1.13 util.test
--- tests/util.test	27 Aug 2003 20:29:36 -0000	1.13
+++ tests/util.test	19 Dec 2003 17:10:49 -0000
@@ -287,17 +287,18 @@
     concat x[expr 1.39999999999]
 } {x1.39999999999}
 test util-6.3 {Tcl_PrintDouble - using tcl_precision} {
+    set tcl_precision 12
     concat x[expr 1.399999999999]
 } {x1.4}
 test util-6.4 {Tcl_PrintDouble - using tcl_precision} {
     set tcl_precision 5
     concat x[expr 1.123412341234]
 } {x1.1234}
-set tcl_precision 12
+set tcl_precision 17
 test util-6.5 {Tcl_PrintDouble - make sure there's a decimal point} {
     concat x[expr 2.0]
 } {x2.0}
-test util-6.6 {Tcl_PrintDouble - make sure there's a decimal point} {eformat} {
+test util-6.6 {Tcl_PrintDouble - make sure there's a decimal point} {
     concat x[expr 3.0e98]
 } {x3e+98}
 
@@ -329,7 +330,7 @@
     list [catch {set tcl_precision abc} msg] $msg $tcl_precision
 } {1 {can't set "tcl_precision": improper value for precision} 12}
 
-set tcl_precision 12
+set tcl_precision 17
 
 # This test always succeeded in the C locale anyway...
 test util-8.1 {TclNeedSpace - correct UTF8 handling} {
Index: unix/Makefile.in
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/Makefile.in,v
retrieving revision 1.133
diff -b -u -r1.133 Makefile.in
--- unix/Makefile.in	21 Oct 2003 00:23:34 -0000	1.133
+++ unix/Makefile.in	19 Dec 2003 17:10:49 -0000
@@ -304,7 +304,8 @@
 GENERIC_OBJS = regcomp.o regexec.o regfree.o regerror.o tclAlloc.o \
 	tclAsync.o tclBasic.o tclBinary.o tclCkalloc.o tclClock.o \
 	tclCmdAH.o tclCmdIL.o tclCmdMZ.o tclCompCmds.o tclCompExpr.o \
-	tclCompile.o tclConfig.o tclDate.o tclDictObj.o tclEncoding.o \
+	tclCompile.o tclConfig.o tclDate.o\
+	tclDictObj.o tclDToA.o tclEncoding.o \
 	tclEnv.o tclEvent.o tclExecute.o tclFCmd.o tclFileName.o tclGet.o \
 	tclHash.o tclHistory.o tclIndexObj.o tclInterp.o tclIO.o tclIOCmd.o \
 	tclIOGT.o tclIOSock.o tclIOUtil.o tclLink.o tclListObj.o \
@@ -355,6 +356,7 @@
 	$(GENERIC_DIR)/tclConfig.c \
 	$(GENERIC_DIR)/tclDate.c \
 	$(GENERIC_DIR)/tclDictObj.c \
+	$(GENERIC_DIR)/tclDToA.c \
 	$(GENERIC_DIR)/tclEncoding.c \
 	$(GENERIC_DIR)/tclEnv.c \
 	$(GENERIC_DIR)/tclEvent.c \
@@ -846,6 +848,9 @@
 
 tclDictObj.o: $(GENERIC_DIR)/tclDictObj.c
 	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclDictObj.c
+
+tclDToA.o: $(GENERIC_DIR)/tclDToA.c $(GENERIC_DIR)/dtoa.c
+	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclDToA.c
 
 tclEncoding.o: $(GENERIC_DIR)/tclEncoding.c
 	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclEncoding.c
Index: win/Makefile.in
===================================================================
RCS file: /cvsroot/tcl/tcl/win/Makefile.in,v
retrieving revision 1.75
diff -b -u -r1.75 Makefile.in
--- win/Makefile.in	10 Nov 2003 22:55:47 -0000	1.75
+++ win/Makefile.in	19 Dec 2003 17:10:49 -0000
@@ -221,6 +221,7 @@
 	tclConfig.$(OBJEXT) \
 	tclDate.$(OBJEXT) \
 	tclDictObj.$(OBJEXT) \
+	tclDToA.$(OBJECT) \
 	tclEncoding.$(OBJEXT) \
 	tclEnv.$(OBJEXT) \
 	tclEvent.$(OBJEXT) \
Index: win/makefile.bc
===================================================================
RCS file: /cvsroot/tcl/tcl/win/makefile.bc,v
retrieving revision 1.18
diff -b -u -r1.18 makefile.bc
--- win/makefile.bc	10 Nov 2003 22:55:48 -0000	1.18
+++ win/makefile.bc	19 Dec 2003 17:10:49 -0000
@@ -211,6 +211,7 @@
 	$(TMPDIR)\tclConfig.obj \
 	$(TMPDIR)\tclDate.obj \
 	$(TMPDIR)\tclDictObj.obj \
+	$(TMPDIR)\tclDToA.obj \
 	$(TMPDIR)\tclEncoding.obj \
 	$(TMPDIR)\tclEnv.obj \
 	$(TMPDIR)\tclEvent.obj \
Index: win/makefile.vc
===================================================================
RCS file: /cvsroot/tcl/tcl/win/makefile.vc,v
retrieving revision 1.113
diff -b -u -r1.113 makefile.vc
--- win/makefile.vc	10 Nov 2003 22:55:48 -0000	1.113
+++ win/makefile.vc	19 Dec 2003 17:10:49 -0000
@@ -242,6 +242,7 @@
 	$(TMP_DIR)\tclConfig.obj \
 	$(TMP_DIR)\tclDate.obj \
 	$(TMP_DIR)\tclDictObj.obj \
+	$(TMP_DIR)\tclDToA.obj \
 	$(TMP_DIR)\tclEncoding.obj \
 	$(TMP_DIR)\tclEnv.obj \
 	$(TMP_DIR)\tclEvent.obj \