On 09/15/2012 01:49 AM, Torbjorn Granlund wrote:
For general seq use, I suppose we should do away with `incr' and instead use a general `add'. Below is a suggested implementation, and as bonus also a `sub'.Like `incr', `add' needs an extra byte if space, since if the end value is within the increment from a power of 10, a number with one more digit than the end value will be created. Implementing negative values is a bit tricky. If a-b is wanted and a< b, one must of course compute b-a and separately store a minus sign. I just write a `sub' function, not any code actually handling negative numbers. The function `add' is reasonably well-tested. The function `sub' is minimally tested (but as a trivial edit of `add' it might b correct anyway). void add (string *st, string *incr) { size_t lens, leni; long i; int d, cy; char *s, *si; lens = st->len; leni = incr->len; s = st->str; if (lens< leni) { size_t xtra = leni - lens; memmove (s + xtra, s, lens); /* make space at beginning */ memset (s, '0', xtra); /* pad with zeros at beginning */ lens = leni; /* target string same size as `incr' */ } s += lens; si = incr->str + leni; /* Add `incr' to `st'. */ cy = 0; for (i = leni - 1; i>= 0; i--) { d = *--s + *--si - '0' + cy; cy = d> '9'; d -= 10 * cy; *s = d; } /* Propagate carry. */ if (cy != 0) { for (i = lens - leni - 1; i>= 0; i--) { d = *--s + 1; if (d != '0' + 10) { *s = d; return; } *s = '0'; } /* Carry beyond first string char, extend. */ lens++; memmove (s + 1, s, lens); *s = '1'; } st->len = lens; } void sub (string *st, string *incr) { size_t lens, leni; long i; int d, cy; char *s, *si; lens = st->len; leni = incr->len; s = st->str; if (lens< leni) abort (); s += lens; si = incr->str + leni; /* Add `incr' to `st'. */ cy = 0; for (i = leni - 1; i>= 0; i--) { d = *--s - *--si + '0' - cy; cy = d< '0'; d += 10 * cy; *s = d; } /* Propagate carry. */ if (cy != 0) { for (i = lens - leni - 1; i>= 0; i--) { d = *--s - 1; if (d != '0' - 1) { *s = d; return; } *s = '9'; } /* Borrow beyond first string char, error. */ abort (); } st->len = lens; }
Cool thanks! For comparison here is an add function that used to be in coreutils: http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=blob;f=src/getlimits.c;hb=a2be861b#l81 cheers, Pádraig.
