commit 787dbbf337bb238bea30d66d4bf43907bca20e19
parent ee47da9c3992a846f3fb236e7796dbb88d44819c
Author: Mattias Andrée <maandree@kth.se>
Date: Tue, 1 Mar 2016 19:22:26 +0100
Add zcmp, zcmpi, zcmpu, zcmpmag, zset, zseti, and zsetu
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat:
8 files changed, 131 insertions(+), 12 deletions(-)
diff --git a/src/internals.h b/src/internals.h
@@ -7,18 +7,7 @@
#define BITS_IN_LAST_CHAR(bits) ((bits) & (BITS_PER_CHAR - 1))
#define LIST_TEMPS\
- X(libzahl_tmp_a)\
- X(libzahl_tmp_b)\
- X(libzahl_tmp_c)\
- X(libzahl_tmp_d)\
- X(libzahl_tmp_e)\
- X(libzahl_tmp_f)\
- X(libzahl_tmp_g)\
- X(libzahl_tmp_i)\
- X(libzahl_tmp_j)\
- X(libzahl_tmp_k)\
- X(libzahl_tmp_l)\
- X(libzahl_tmp_m)
+ X(libzahl_tmp_cmp)
#define X(x) extern z_t x;
LIST_TEMPS
@@ -28,3 +17,5 @@ extern jmp_buf libzahl_jmp_buf;
extern int libzahl_set_up;
#define FAILURE_JUMP() (longjmp(libzahl_jmp_buf, 1))
+
+#define SET_SIGNUM(a, signum) ((a)->sign = (signum))
diff --git a/src/zcmp.c b/src/zcmp.c
@@ -0,0 +1,11 @@
+/* See LICENSE file for copyright and license details. */
+#include "internals"
+
+
+int
+zcmp(z_t a, z_t b)
+{
+ if (zsignum(a) != zsignum(b))
+ return zsignum(a) < zsignum(b) ? -1 : zsignum(a) > zsignum(b);
+ return zsignum(a) * zcmpmag(a, b);
+}
diff --git a/src/zcmpi.c b/src/zcmpi.c
@@ -0,0 +1,14 @@
+/* See LICENSE file for copyright and license details. */
+#include "internals"
+
+
+int
+zcmpi(z_t a, long long int b)
+{
+ if (!b)
+ return zsignum(a);
+ if (zzero(a))
+ return b > 0 ? -1 : b < 0;
+ zseti(zahl_tmp_cmp, b);
+ return zcmp(a, zahl_tmp_cmp);
+}
diff --git a/src/zcmpmag.c b/src/zcmpmag.c
@@ -0,0 +1,29 @@
+/* See LICENSE file for copyright and license details. */
+#include "internals"
+
+
+int
+zcmpmag(z_t a, z_t b)
+{
+ size_t i, j;
+ if (zzero(a))
+ return -!zzero(b);
+ if (zzero(b))
+ return 1;
+ i = a->used - 1;
+ j = b->used - 1;
+ for (; i > j; i--) {
+ if (a->chars[i])
+ return +1;
+ a->used--;
+ }
+ for (; j > i; j--) {
+ if (b->chars[j])
+ return -1;
+ b->used--;
+ }
+ for (; i; i--)
+ if (a->chars[i] != b->chars[i])
+ return (a->chars[i] > b->chars[i]) * 2 - 1;
+ return a->chars[0] < b->chars[0] ? -1 : a->chars[0] > b->chars[0];
+}
diff --git a/src/zcmpu.c b/src/zcmpu.c
@@ -0,0 +1,14 @@
+/* See LICENSE file for copyright and license details. */
+#include "internals"
+
+
+int
+zcmpu(z_t a, unsigned long long int b)
+{
+ if (!b)
+ return zsignum(a);
+ if (zsignum(a) <= 0)
+ return -1;
+ zsetu(zahl_tmp_cmp, b);
+ return zcmp(a, zahl_tmp_cmp);
+}
diff --git a/src/zset.c b/src/zset.c
@@ -0,0 +1,22 @@
+/* See LICENSE file for copyright and license details. */
+#include "internals"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+void
+zset(z_t a, z_t b)
+{
+ if (zzero(b)) {
+ SET_SIGNUM(a, 0);
+ } else {
+ if (a->alloced < b->alloced) {
+ a->alloced = b->alloced;
+ a->chars = realloc(a->chars, b->alloced * sizeof(*(a->chars)));
+ }
+ a->sign = b->sign;
+ a->used = b->used;
+ memcpy(a->chars, b->chars, b->used * sizeof(*(a->chars)));
+ }
+}
diff --git a/src/zseti.c b/src/zseti.c
@@ -0,0 +1,14 @@
+/* See LICENSE file for copyright and license details. */
+#include "internals"
+
+
+void
+zseti(z_t a, long long int b)
+{
+ if (b >= 0) {
+ zsetu(a, (unsigned long long int)b);
+ } else {
+ zsetu(a, (unsigned long long int)-b);
+ SET_SIGNUM(a, -1);
+ }
+}
diff --git a/src/zsetu.c b/src/zsetu.c
@@ -0,0 +1,24 @@
+/* See LICENSE file for copyright and license details. */
+#include "internals"
+
+#define CHARS_PER_TYPE(t) (sizeof(t) / (BITS_PER_CHAR >> 3))
+
+
+void
+zsetu(z_t a, unsigned long long int b)
+{
+ if (!b) {
+ SET_SIGNUM(a, 0);
+ return;
+ }
+ if (a->alloced < CHARS_PER_TYPE(b)) {
+ a->alloced = CHARS_PER_TYPE(b);
+ a->chars = realloc(a->chars, CHARS_PER_TYPE(b) * sizeof(*(a->chars)))
+ }
+ SET_SIGNUM(a, 1);
+ a->used = 0;
+ while (b) {
+ a->chars[a->used++] = (uint32_t)b;
+ b >>= BITS_PER_CHAR;
+ }
+}