[Python-checkins] r70785 - in python/branches/py3k-short-float-repr: Objects/complexobject.c Python/pystrtod.c

eric.smith python-checkins at python.org
Tue Mar 31 02:01:17 CEST 2009


Author: eric.smith
Date: Tue Mar 31 02:01:17 2009
New Revision: 70785

Log:
Checkpoint. Memory management still needs work.

Modified:
   python/branches/py3k-short-float-repr/Objects/complexobject.c
   python/branches/py3k-short-float-repr/Python/pystrtod.c

Modified: python/branches/py3k-short-float-repr/Objects/complexobject.c
==============================================================================
--- python/branches/py3k-short-float-repr/Objects/complexobject.c	(original)
+++ python/branches/py3k-short-float-repr/Objects/complexobject.c	Tue Mar 31 02:01:17 2009
@@ -345,62 +345,107 @@
 }
 
 
-static void
-complex_to_buf(char *buf, int bufsz, PyComplexObject *v, int precision)
+static int
+complex_to_buf(char *buf, int bufsz, PyComplexObject *v, int mode,
+               int precision)
 {
-	char format[32];
-	if (v->cval.real == 0.) {
-		if (!Py_IS_FINITE(v->cval.imag)) {
-			if (Py_IS_NAN(v->cval.imag))
-				strncpy(buf, "nan*j", 6);
-			else if (copysign(1, v->cval.imag) == 1)
-				strncpy(buf, "inf*j", 6);
-			else
-				strncpy(buf, "-inf*j", 7);
-		}
-		else {
-			PyOS_snprintf(format, sizeof(format), "%%.%ig", precision);
-			PyOS_ascii_formatd(buf, bufsz - 1, format, v->cval.imag);
-			strncat(buf, "j", 1);
-		}
-	} else {
-		char re[64], im[64];
-		/* Format imaginary part with sign, real part without */
-		if (!Py_IS_FINITE(v->cval.real)) {
-			if (Py_IS_NAN(v->cval.real))
-				strncpy(re, "nan", 4);
-			/* else if (copysign(1, v->cval.real) == 1) */
-			else if (v->cval.real > 0)
-				strncpy(re, "inf", 4);
-			else
-				strncpy(re, "-inf", 5);
-		}
-		else {
-			PyOS_snprintf(format, sizeof(format), "%%.%ig", precision);
-			PyOS_ascii_formatd(re, sizeof(re), format, v->cval.real);
-		}
-		if (!Py_IS_FINITE(v->cval.imag)) {
-			if (Py_IS_NAN(v->cval.imag))
-				strncpy(im, "+nan*", 6);
-			/* else if (copysign(1, v->cval.imag) == 1) */
-			else if (v->cval.imag > 0)
-				strncpy(im, "+inf*", 6);
-			else
-				strncpy(im, "-inf*", 6);
-		}
-		else {
-			PyOS_snprintf(format, sizeof(format), "%%+.%ig", precision);
-			PyOS_ascii_formatd(im, sizeof(im), format, v->cval.imag);
-		}
-		PyOS_snprintf(buf, bufsz, "(%s%sj)", re, im);
-	}
+    int result = -1;
+    char* p;
+
+    /* If these are non-NULL, they'll need to be freed. */
+    char* pre = NULL;
+    char* pim = NULL;
+
+    /* These do not need to be freed. They're either aliases for pim
+       and pre, or pointers to constants. */
+    char* re = NULL;
+    char* im = NULL;
+    char* lead = "";
+    char* tail = "";
+
+    Py_ssize_t len;
+
+    if (v->cval.real == 0.) {
+        re = "";
+        if (!Py_IS_FINITE(v->cval.imag)) {
+            if (Py_IS_NAN(v->cval.imag))
+                im = "nan*";
+            else if (copysign(1, v->cval.imag) == 1)
+                im = "inf*";
+            else
+                im = "-inf*";
+        }
+        else {
+            pim = PyOS_double_to_string(v->cval.imag, mode, 'g', precision, 0, 0);
+            if (!pim) {
+                PyErr_NoMemory();
+                goto done;
+            }
+            im = pim;
+        }
+    } else {
+        /* Format imaginary part with sign, real part without */
+        if (!Py_IS_FINITE(v->cval.real)) {
+            if (Py_IS_NAN(v->cval.real))
+                re = "nan";
+            /* else if (copysign(1, v->cval.real) == 1) */
+            else if (v->cval.real > 0)
+                re = "inf";
+            else
+                re = "-inf";
+        }
+        else {
+            pre = PyOS_double_to_string(v->cval.real, mode, 'g', precision, 0, 0);
+            if (!pre) {
+                PyErr_NoMemory();
+                goto done;
+            }
+            re = pre;
+        }
+
+        if (!Py_IS_FINITE(v->cval.imag)) {
+            if (Py_IS_NAN(v->cval.imag))
+                im = "+nan*";
+            /* else if (copysign(1, v->cval.imag) == 1) */
+            else if (v->cval.imag > 0)
+                im = "+inf*";
+            else
+                im = "-inf*";
+        }
+        else {
+            pim = PyOS_double_to_string(v->cval.imag, mode, 'g', precision, 1, 0);
+            if (!pim) {
+                PyErr_NoMemory();
+                goto done;
+            }
+            im = pim;
+        }
+        lead = "(";
+        tail = ")";
+    }
+    /* Alloc the final buffer. Add one for the "j" in the format string. */
+    len = strlen(lead) + strlen(re) + strlen(im) + strlen(tail) + 2;
+    p = PyMem_Malloc(len);
+    if (!p) {
+        PyErr_NoMemory();
+        goto done;
+    }
+    PyOS_snprintf(p, len, "%s%s%sj%s", lead, re, im, tail);
+    strcpy(buf, p);
+    result = 0;
+done:
+    PyMem_Free(pim);
+    PyMem_Free(pre);
+
+    return result;
 }
 
 static PyObject *
 complex_repr(PyComplexObject *v)
 {
 	char buf[100];
-	complex_to_buf(buf, sizeof(buf), v, PREC_REPR);
+	if (complex_to_buf(buf, sizeof(buf), v, 0, 0) < 0)
+            return PyErr_NoMemory();
 	return PyUnicode_FromString(buf);
 }
 
@@ -408,7 +453,8 @@
 complex_str(PyComplexObject *v)
 {
 	char buf[100];
-	complex_to_buf(buf, sizeof(buf), v, PREC_STR);
+	if (complex_to_buf(buf, sizeof(buf), v, 2, PREC_STR) < 0)
+            return PyErr_NoMemory();
 	return PyUnicode_FromString(buf);
 }
 

Modified: python/branches/py3k-short-float-repr/Python/pystrtod.c
==============================================================================
--- python/branches/py3k-short-float-repr/Python/pystrtod.c	(original)
+++ python/branches/py3k-short-float-repr/Python/pystrtod.c	Tue Mar 31 02:01:17 2009
@@ -495,7 +495,7 @@
    number of significant digits. */
 
 static void
-format_float_short(char *buf, size_t buflen, double d, int mode, int precision)
+format_float_short(char *buf, size_t buflen, double d, int mode, int precision, int always_add_sign, int add_dot_0_if_integer)
 {
 	char *digits, *digits_end;
 	int decpt, sign, exp_len;
@@ -515,6 +515,9 @@
 			if (sign == 1) {
 				*buf++ = '-';
 			}
+			else if (always_add_sign) {
+				*buf++ = '+';
+			}
 			strncpy(buf, "inf", 3);
 			buf += 3;
 		} else {
@@ -526,6 +529,8 @@
 	else if (-4 < decpt && decpt <= 17) {
 		if (sign == 1) {
 			*buf++ = '-';
+		} else if (always_add_sign) {
+			*buf++ = '+';
 		}
 		/* use fixed-point notation if 1e-4 <= value < 1e17 */
 		if (decpt <= 0) {
@@ -551,8 +556,10 @@
 			buf += digits_len;
 			for (i=0; i < decpt-digits_len; i++)
 				*buf++ = '0';
-			*buf++ = '.';
-			*buf++ = '0';
+			if (add_dot_0_if_integer) {
+				*buf++ = '.';
+				*buf++ = '0';
+			}
 		}
 	}
 	else {
@@ -560,6 +567,8 @@
 		   at least 2 digits in exponent */
 		if (sign == 1) {
 			*buf++ = '-';
+		} else if (always_add_sign) {
+			*buf++ = '+';
 		}
 		*buf++ = digits[0];
 		if (digits_len > 1) {
@@ -578,7 +587,7 @@
                                          int mode,
                                          char format_code,
                                          int precision,
-                                         int sign,
+                                         int always_add_sign,
                                          int add_dot_0_if_integer)
 {
 	char fmt[32];
@@ -590,26 +599,7 @@
 
 	/* XXX validate format_code */
 
-	format_float_short(buf, 512, val, mode, precision);
-
-	if (add_dot_0_if_integer) {
-		/* If the result was just an integer, without a decimal, then
-		   add ".0" to the end of the string. */
-		char *cp = buf;
-		if (*cp == '-')
-			cp++;
-		for (; *cp != '\0'; cp++) {
-			/* Any non-digit means it's not an integer;
-			   this takes care of NAN and INF as well. */
-			if (!isdigit(Py_CHARMASK(*cp)))
-				break;
-		}
-		if (*cp == '\0') {
-			*cp++ = '.';
-			*cp++ = '0';
-			*cp++ = '\0';
-		}
-	}
+	format_float_short(buf, 512, val, mode, precision, always_add_sign, add_dot_0_if_integer);
 
 	return buf;
 }


More information about the Python-checkins mailing list