diff options
Diffstat (limited to '')
| -rw-r--r-- | src/zstr.c | 46 |
1 files changed, 44 insertions, 2 deletions
@@ -12,6 +12,48 @@ * the cast to unsigned long long must be changed accordingly. */ +#define S1(P) P"0" P"1" P"2" P"3" P"4" P"5" P"6" P"7" P"8" P"9" +#define S2(P) S1(P"0")S1(P"1")S1(P"2")S1(P"3")S1(P"4")S1(P"5")S1(P"6")S1(P"7")S1(P"8")S1(P"9") + + +static inline O2 void +sprintint_fix(char *buf, zahl_char_t v) +{ + const char *partials = S2(""); + uint16_t *buffer = (uint16_t *)(buf + 1); + + buffer[8] = *(uint16_t *)(partials + 2 * (v % 100)), v /= 100; + buffer[7] = *(uint16_t *)(partials + 2 * (v % 100)), v /= 100; + buffer[6] = *(uint16_t *)(partials + 2 * (v % 100)), v /= 100; + buffer[5] = *(uint16_t *)(partials + 2 * (v % 100)), v /= 100; + buffer[4] = *(uint16_t *)(partials + 2 * (v % 100)), v /= 100; + buffer[3] = *(uint16_t *)(partials + 2 * (v % 100)), v /= 100; + buffer[2] = *(uint16_t *)(partials + 2 * (v % 100)), v /= 100; + buffer[1] = *(uint16_t *)(partials + 2 * (v % 100)), v /= 100; + buffer[0] = *(uint16_t *)(partials + 2 * (v % 100)), v /= 100; + *buf = '0' + v; + buf[19] = 0; +} + +static inline void +cmemmove(char *d, const char *s, long n) +{ + while (n--) + *d++ = *s++; +} + +static inline size_t +sprintint_min(char *buf, zahl_char_t v) +{ + long i = 0, j; + sprintint_fix(buf, v); + for (; buf[i] == '0'; i++); + cmemmove(buf, buf + i, j = 19 - i); + buf[j] = 0; + return j; +} + + char * zstr(z_t a, char *b) { @@ -42,12 +84,12 @@ zstr(z_t a, char *b) for (;;) { zdivmod(num, rem, num, libzahl_const_1e19); if (likely(!zzero(num))) { - sprintf(b + n, "%019llu", zzero(rem) ? 0ULL : (unsigned long long)(rem->chars[0])); + sprintint_fix(b + n, zzero(rem) ? 0 : rem->chars[0]); b[n + 19] = overridden; overridden = b[n]; n = n > 19 ? (n - 19) : 0; } else { - len = (size_t)sprintf(buf, "%llu", (unsigned long long)(rem->chars[0])); + len = sprintint_min(buf, rem->chars[0]); if (overridden) buf[len] = b[n + len]; memcpy(b + n, buf, len + 1); |
