aboutsummaryrefslogtreecommitdiffstats
path: root/src/zstr.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/zstr.c46
1 files changed, 44 insertions, 2 deletions
diff --git a/src/zstr.c b/src/zstr.c
index c82ec89..f919dc8 100644
--- a/src/zstr.c
+++ b/src/zstr.c
@@ -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);