[Python-checkins] r46780 - sandbox/trunk/decimal-c/_decimal.c

mateusz.rukowicz python-checkins at python.org
Fri Jun 9 18:41:30 CEST 2006


Author: mateusz.rukowicz
Date: Fri Jun  9 18:41:29 2006
New Revision: 46780

Modified:
   sandbox/trunk/decimal-c/_decimal.c
Log:
Rewrite _do_decimal_str which is a way easier to code and understand now, and actually works, some bug fixes also.


Modified: sandbox/trunk/decimal-c/_decimal.c
==============================================================================
--- sandbox/trunk/decimal-c/_decimal.c	(original)
+++ sandbox/trunk/decimal-c/_decimal.c	Fri Jun  9 18:41:29 2006
@@ -1852,6 +1852,7 @@
     int buflen, i, imax, j;
     int leftdigits, dotplace, adjexp;
     int append_E = 0, append_adjexp = 0;
+	long extra_zeros=0;
     char *p, *end;
     PyObject *ret;
 
@@ -1878,63 +1879,119 @@
         *p++ = '-';
     }
 
-    leftdigits = d->exp + d->ob_size;
-    if (engineering) {
-        dotplace = (leftdigits-1)%3+1;
-        adjexp = leftdigits -1 - (leftdigits-1)%3;
-    } else {
-        dotplace = 1;
-        adjexp = leftdigits - 1;
-    }
-    if (d->exp == 0) {
-        dotplace = -1; /* no dot */
-    } else if (d->exp < 0 && adjexp >= 0) {
-        dotplace = leftdigits;
-    } else if (d->exp < 0 && adjexp >= -6) {
-        if (!engineering) { /* eng has no leading zeros */
-            for (i = leftdigits; i < 0; i++) {
-                *p++ = '0';
-                SANITY_CHECK(p);
-            }
-            *p++ = '0';
-        }
-    } else {
-        if (d->ob_size <= dotplace)
-            dotplace = -1;
+	/* The rule is as follows, imagine you write integer:
+	 * 123456789 we want to print it, without adding post-zeros
+	 * or adding at most 6 pre-zeros that is
+	 * 0.00000123456789, if none of this can be done, then, we put dot
+	 * after first digit, and compute E *or* if engineering, then, we put
+	 * dot after 1st 2nd or 3rd digit, and assure that E is divisible by 3
+	 * huh */
+
+	/* (1) dotplace = -adjexp + d->exp + d->ob_size */
+	/* why is that like? well, d->exp moves dot right, d->ob_size moves dot right
+	 * and adjexp moves dot left */
+	adjexp = 0;
+	dotplace = d->exp + d->ob_size;
+	/* dotplace must be at most d->ob_size (no dot at all) and at last -5 (6 pre-zeros)*/
+	if(dotplace >d->ob_size || dotplace <-5)
+	{
+			/* ok, we have to put dot after 1 digit, that is dotplace = 1 
+			 * we compute adjexp from equation (1) */
+			dotplace = 1;
+			adjexp = -dotplace + d->exp + d->ob_size;
+	}
 
-        if (adjexp) {
-            append_E = 1;
-            append_adjexp = 1;
-        }
-    }
+	if(engineering)		/* we have to be sure, adjexp%3 == 0 */
+		while(adjexp%3)
+		{
+			adjexp --;
+			dotplace ++;
+			extra_zeros ++;
+		}
+
+	/* now all we have to do, is to put it to the string =] */
+
+	if(dotplace <= 0)
+	{
+		*p++ = '0';
+		*p++ = '.';
+		while(dotplace++ < 0)
+			*p++ = '0';
+		dotplace = -1;
+	}
+
+	for(i = 0;i<d->ob_size;i++)
+	{
+		if(dotplace == i)
+			*p++ = '.';
+		p += sprintf(p, "%d", _limb_get_digit(d->limbs,d->ob_size,i));
+	}
+
+	while(extra_zeros --)*p++ = '0';
+	
+	/* that was a way easier way =] */
+	
+//    if (engineering) {
+//        dotplace = (leftdigits-1)%3+1;
+//        adjexp = leftdigits -1 - (leftdigits-1)%3;
+//    } else {
+//        dotplace = 1;
+//        adjexp = leftdigits - 1;
+//    }
+//    if (d->exp == 0) {
+//        dotplace = -1; /* no dot */
+//    } else if (d->exp < 0 && adjexp >= 0) {
+//       dotplace = leftdigits;
+//    } else if (d->exp < 0 && adjexp >= -6) {
+//        if (!engineering) { /* eng has no leading zeros */
+//            for (i = leftdigits; i < 0; i++) {
+//                *p++ = '0';
+//                SANITY_CHECK(p);
+//            }
+//            *p++ = '0';
+//        }
+//    } else {
+//        if (d->ob_size <= dotplace)
+//            dotplace = -1;
+
+//        if (adjexp) {
+//            append_E = 1;
+//            append_adjexp = 1;
+//        }
+//    }
     
-    imax = d->ob_size;
-    if (dotplace > 0) {
-        imax++;
-    }
-    if (engineering) { /* eng has no leading zeros */
-        for (i = 0, j = 0; i < imax; i++) {
+//    imax = d->ob_size;
+//    if (dotplace > 0) {
+//        imax++;
+//    }
+//    if (engineering) { /* eng has no leading zeros */
+//        for (i = 0, j = 0; i < imax; i++) {
 //            if (d->digits[j] == 0) {
-			if(_limb_get_digit(d->limbs, d->ob_size, j) == 0){
-				j++;
-            } else {
-                break;
-            }
-        }
-    }
-    for (i = 0, j = 0; i < imax; i++) {
-        if (i == dotplace) {
-            *p++ = '.';
-            SANITY_CHECK(p);
-            continue;
-        } else {
+//			if(_limb_get_digit(d->limbs, d->ob_size, j) == 0){
+//				j++;
+//            } else {
+//                break;
+//            }
+//        }
+//    }
+//    for (i = 0, j = 0; i < imax; i++) {
+//        if (i == dotplace) {
+//            *p++ = '.';
+//            SANITY_CHECK(p);
+//            continue;
+//        } else {
 //            p += sprintf(p, "%d", d->digits[j]);
-			p += sprintf(p, "%d", _limb_get_digit(d->limbs, d->ob_size, j));	/* SLOW */
-			SANITY_CHECK(p);
-            j++;
-        }
-    }
+//			p += sprintf(p, "%d", _limb_get_digit(d->limbs, d->ob_size, j));	/* SLOW */
+//			SANITY_CHECK(p);
+//            j++;
+//        }
+//    }
 
+	if(adjexp)
+	{
+		append_E = 1;
+		append_adjexp = 1;
+	}
     if (append_E) {
         if (context->capitals) {
             *p++ = 'E';
@@ -1957,13 +2014,14 @@
     SANITY_CHECK(p);
     
     /* if engineering and (just a sign | empty | starts with a dot or an E) */
-    if (engineering && ((p - &outbuf[1] > (d->sign & 1)) || outbuf[1] == '.' ||
-                        outbuf[1] == 'E' || outbuf[1] == 'e')) {
-        outbuf[0] = '0';
-        p = outbuf;
-    } else {
-        p = &outbuf[1];
-    }
+//    if (engineering && ((p - &outbuf[1] > (d->sign & 1)) || outbuf[1] == '.' ||
+//                        outbuf[1] == 'E' || outbuf[1] == 'e')) {
+//        outbuf[0] = '0';
+//        p = outbuf;
+//    } else {
+//        p = &outbuf[1];
+//    }
+	p = &outbuf[1];
     SANITY_CHECK(p);
     ret = PyString_FromString(p);
     PyMem_FREE(outbuf);
@@ -2685,6 +2743,9 @@
 	long i;
 	decimalobject *new;
 
+	if(!len)
+		goto err;	/* empty string */
+	
 	if(*p == '+')
 		p++;
 	else if(*p == '-')
@@ -2693,7 +2754,7 @@
 		sign = 1;
 	}
 
-	if(*p == 'e' || *p == 'E')	/* no digits befor E */
+	if(*p == 'e' || *p == 'E')	/* no digits before E */
 		goto err;
 
 	/* now at *p is our integer with (possibly) dot */
@@ -2726,7 +2787,7 @@
 			}
 			else
 			{
-				if(dot)
+				if(dot && !e)
 					digits_after_dot ++;
 				
 				if(!first_digit && *c != '0')
@@ -2764,6 +2825,8 @@
 	exp -= digits_after_dot;
 
 	new = _new_decimalobj(type, ndigits, sign, exp);
+	if(!new)
+		return NULL;
 
 	for(i = 0; i<new->limb_count ;i++)
 		new->limbs[i] = 0;


More information about the Python-checkins mailing list