commit a626bacf8e45af60727882250f9d3abeb15ff3cd
Author:     Mattias Andrée <[email protected]>
AuthorDate: Wed Mar 2 09:59:52 2016 +0100
Commit:     Mattias Andrée <[email protected]>
CommitDate: Wed Mar 2 10:03:25 2016 +0100

    Add zsets and zstr
    
    Signed-off-by: Mattias Andrée <[email protected]>

diff --git a/man/zstr_length.3 b/man/zstr_length.3
index 01f2048..9cb0f72 100644
--- a/man/zstr_length.3
+++ b/man/zstr_length.3
@@ -10,7 +10,7 @@ size_t zstr_length(z_t \fIa\fP, unsigned long long 
int\fIradix\fP);
 .SH DESCRIPTION
 .B zstr_length
 calculates the number of digits required to
-to represent the absolute value of
+to represent
 .I a
 in the selected
 .IR radix .
diff --git a/src/internals.h b/src/internals.h
index a544924..f911680 100644
--- a/src/internals.h
+++ b/src/internals.h
@@ -12,11 +12,19 @@
        X(libzahl_tmp_cmp)\
        X(libzahl_tmp_str_num)\
        X(libzahl_tmp_str_mag)\
-       X(libzahl_tmp_str_div)
+       X(libzahl_tmp_str_div)\
+       X(libzahl_tmp_str_rem)
+
+#define LIST_CONSTS\
+       X(libzahl_const_1e19, zsetu, 10000000000000000000ULL) /* The largest 
power of 10 < 2⁶⁴. */\
+       X(libzahl_const_1e9,  zsetu, 1000000000ULL)           /* The largest 
power of 10 < 2³². */
 
 #define X(x)  extern z_t x;
 LIST_TEMPS
 #undef X
+#define X(x, f, v)  extern z_t x;
+LIST_CONSTS
+#undef X
 
 extern jmp_buf libzahl_jmp_buf;
 extern int libzahl_set_up;
diff --git a/src/zsets.c b/src/zsets.c
new file mode 100644
index 0000000..12669b9
--- /dev/null
+++ b/src/zsets.c
@@ -0,0 +1,47 @@
+/* See LICENSE file for copyright and license details. */
+#include "internals"
+
+#include <errno.h>
+
+
+int
+zsets(z_t a, const char *str)
+{
+       unsigned long long int temp = 0;
+       int neg = (*str == '-');
+       const char *str_end;
+
+       str += neg || (*str == '+');
+
+       if (!*str) {
+               errno = EINVAL;
+               return -1;
+       }
+       for (str_end = str; *str_end; str_end++) {
+               if (!isdigit(*str_end)) {
+                       errno = EINVAL;
+                       return -1;
+               }
+       }
+
+       SET_SIGNUM(a, 0);
+
+       switch ((str_end - str) % 19) {
+               while (*str) {
+#define X(n)\
+                       temp *= 10, temp += *str++ & 15;\
+               case n:
+               X(18) X(17) X(16) X(15) X(14) X(13) X(12) X(11) X(10)
+               X(9) X(8) X(7) X(6) X(5) X(4) X(3) X(2) X(1) X(0)
+#undef X
+                       zmul(a, a, libzahl_const_1e19);
+                       zsetu(libzahl_tmp_str_num, temp);
+                       zadd(a, a, libzahl_tmp_str_num);
+                       temp = 0;
+               }
+       }
+
+       if (neg)
+               SET_SIGNUM(a, -zsignum(a));
+       return 0;
+}
diff --git a/src/zsetup.c b/src/zsetup.c
index 2aadbba..f7c1912 100644
--- a/src/zsetup.c
+++ b/src/zsetup.c
@@ -4,6 +4,9 @@
 #define X(x)  z_t x;
 LIST_TEMPS
 #undef X
+#define X(x, f, v)  z_t x;
+LIST_CONSTS
+#undef X
 
 jmp_buf libzahl_jmp_buf;
 int libzahl_set_up = 0;
@@ -16,8 +19,13 @@ zsetup(jmp_buf env)
 
        if (!libzahl_set_up) {
                libzahl_set_up = 1;
-#define X(x)  zinit(zahl_tmp_##x);
+#define X(x)\
+               zinit(x);
                LIST_TEMPS;
 #undef X
+#define X(x, f, v)\
+               zinit(x), f(x, v);
+               LIST_CONSTS;
+#undef X
        }
 }
diff --git a/src/zstr.c b/src/zstr.c
new file mode 100644
index 0000000..a1d4d13
--- /dev/null
+++ b/src/zstr.c
@@ -0,0 +1,61 @@
+/* See LICENSE file for copyright and license details. */
+#include "internals"
+
+#define num  libzahl_tmp_str_num
+#define rem  libzahl_tmp_str_rem
+
+/* All 9 you see here is derived from that 10⁹ is the largest
+ * power of than < 2³², and 32 is the number of bits in
+ * zahl_char_t. If zahl_char_t is chanced, the value 9, and
+ * the cast to unsigned long must be changed accordingly. */
+
+
+char *
+zstr(z_t a, char *b)
+{
+       size_t n;
+       char overridden;
+       int neg;
+
+       if (zzero(a)) {
+               if (!b) {
+                       b = malloc(2);
+                       if (!b)
+                               FAILURE_JUMP();
+               }
+               b[0] = '0';
+               b[1] = 0;
+               return b;
+       }
+
+       n = zstr_length(a, 10);
+       if (!b) {
+               b = malloc(n + 1);
+               if (!b)
+                       FAILURE_JUMP();
+       }
+
+       neg = zsignum(a) < 0;
+       zabs(num, a);
+       n -= neg;
+       n = n > 9 ? (n - 9) : 0;
+       b[0] = '-';
+       b += neg;
+       overridden = 0;
+
+       for (;;) {
+               zdivmod(num, rem, num, libzahl_const_1e9);
+               if (!zzero(num)) {
+                       sprintf(b + n, "%09lu", (unsigned long)(rem->chars[0]));
+                       b[n + 9] = overridden;
+                       overridden = b[n + (9 - 1)];
+                       n = n > 9 ? (n - 9) : 0;
+               } else {
+                       n += sprintf(b + n, "%lu", (unsigned 
long)(rem->chars[0]));
+                       b[n] = overridden;
+                       break;
+               }
+       }
+
+       return b - neg;
+}
diff --git a/src/zstr_length.c b/src/zstr_length.c
index 4edabb0..f959ea3 100644
--- a/src/zstr_length.c
+++ b/src/zstr_length.c
@@ -24,5 +24,5 @@ zstr_length(z_t a, unsigned long long int radix)
                size_total += size_temp;
                zdiv(num, num, div);
        }
-       return size_total;
+       return size_total + (zsignum(a) < 0);
 }
diff --git a/src/zunsetup.c b/src/zunsetup.c
index 0f766e1..e2d91f6 100644
--- a/src/zunsetup.c
+++ b/src/zunsetup.c
@@ -7,8 +7,13 @@ zunsetup(jmp_buf env)
 {
        if (libzahl_set_up) {
                libzahl_set_up = 0;
-#define X(x)  zfree(zahl_tmp_##x);
+#define X(x)\
+               zfree(x);
                LIST_TEMPS;
 #undef X
+#define X(x, f, v)\
+               zfree(x);
+               LIST_CONSTS;
+#undef X
        }
 }

Reply via email to