aboutsummaryrefslogtreecommitdiffstats
path: root/src/zsub.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2016-03-05 20:16:14 +0100
committerMattias Andrée <maandree@kth.se>2016-03-05 20:16:14 +0100
commit5860237d2f05f6ae45a98569b0d567c2227904c6 (patch)
treebbddb91e2a6a5e7efe7825971c726a9e4db87dd6 /src/zsub.c
parentMore detailed description of division and modulus (diff)
downloadlibzahl-5860237d2f05f6ae45a98569b0d567c2227904c6.tar.gz
libzahl-5860237d2f05f6ae45a98569b0d567c2227904c6.tar.bz2
libzahl-5860237d2f05f6ae45a98569b0d567c2227904c6.tar.xz
Fix bugs and add a randomised testing
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'src/zsub.c')
-rw-r--r--src/zsub.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/src/zsub.c b/src/zsub.c
index 8616542..5096eb0 100644
--- a/src/zsub.c
+++ b/src/zsub.c
@@ -5,28 +5,49 @@
void
zsub_unsigned(z_t a, z_t b, z_t c)
{
- int magcmp = zcmpmag(b, c);
- z_t s;
- size_t i, n;
zahl_char_t carry[] = {0, 0};
+ zahl_char_t *s;
+ size_t i, n;
+ int magcmp;
+
+ if (zzero(b)) {
+ zabs(a, c);
+ zneg(a, a);
+ return;
+ } else if (zzero(c)) {
+ zabs(a, b);
+ return;
+ } else if (a == b || a == c) {
+ /* TODO This should not be necessary. */
+ z_t tb, tc;
+ zinit(tb);
+ zinit(tc);
+ zset(tb, b);
+ zset(tc, c);
+ zsub_unsigned(a, tb, tc);
+ zfree(tb);
+ zfree(tc);
+ return;
+ }
+ magcmp = zcmpmag(b, c);
if (magcmp <= 0) {
if (magcmp == 0) {
SET_SIGNUM(a, 0);
return;
}
SET(a, c);
- *s = *b;
+ n = MIN(a->used, b->used);
+ s = b->chars;
} else {
SET(a, b);
- *s = *c;
+ n = MIN(a->used, c->used);
+ s = c->chars;
}
- n = MIN(a->used, s->used);
-
for (i = 0; i < n; i++) {
- carry[~i & 1] = carry[i & 1] ? (a->chars[i] <= s->chars[i]) : (a->chars[i] < s->chars[i]);
- a->chars[i] -= s->chars[i];
+ carry[~i & 1] = carry[i & 1] ? (a->chars[i] <= s[i]) : (a->chars[i] < s[i]);
+ a->chars[i] -= s[i];
a->chars[i] -= carry[i & 1];
}