commit a626bacf8e45af60727882250f9d3abeb15ff3cd
parent 851c70c8645fc73a7377996b27c79fa7948fe477
Author: Mattias Andrée <maandree@kth.se>
Date: Wed, 2 Mar 2016 09:59:52 +0100
Add zsets and zstr
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat:
7 files changed, 134 insertions(+), 5 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
}
}