[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