diff options
| author | Mattias Andrée <maandree@kth.se> | 2016-03-02 21:37:15 +0100 |
|---|---|---|
| committer | Mattias Andrée <maandree@kth.se> | 2016-03-02 21:37:15 +0100 |
| commit | 7335af89f48b7e144022ca0c50858554fd143818 (patch) | |
| tree | a9258ffbc68ba3cadd1f8bafa58168220b744db4 /src | |
| parent | ztrunc: fix bug: bits > .used may lead to incorrect truncation (diff) | |
| download | libzahl-7335af89f48b7e144022ca0c50858554fd143818.tar.gz libzahl-7335af89f48b7e144022ca0c50858554fd143818.tar.bz2 libzahl-7335af89f48b7e144022ca0c50858554fd143818.tar.xz | |
Add zlsh and zrsh
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'src')
| -rw-r--r-- | src/zlsh.c | 51 | ||||
| -rw-r--r-- | src/zrsh.c | 48 |
2 files changed, 99 insertions, 0 deletions
diff --git a/src/zlsh.c b/src/zlsh.c new file mode 100644 index 0000000..bc1aa0b --- /dev/null +++ b/src/zlsh.c @@ -0,0 +1,51 @@ +/* See LICENSE file for copyright and license details. */ +#include "internals" + +#include <stdlib.h> +#include <string.h> + + +void +zlsh(z_t a, z_t b, size_t bits) +{ + size_t i, chars, cbits; + zahl_char_t carry[] = {0, 0}; + + if (zzero(b)) { + SET_SIGNUM(a, 0); + return; + } + if (!bits) { + if (a != b) + zset(a, b); + return; + } + + chars = FLOOR_BITS_TO_CHARS(bits); + bits = BITS_IN_LAST_CHAR(bits) + cbits = BITS_PER_CHAR - 1 - bits; + + a->used = b->used + chars; + if (a->alloced < a->used) { + a->alloced = a->used; + a->chars = realloc(a->chars, a->used * sizeof(*(a->chars))); + } + (a == b ? memmove : memcpy)(a->chars + chars, b->chars, a->used * sizeof(*(a->chars))); + memset(a->chars, 0, chars * sizeof(*(a->chars))); + + for (i = chars; i < a->used; i++) { + carry[~i & 1] = a->chars[i] >> cbits; + a->chars[i] <<= bits; + a->chars[i] |= carry[i & 1]; + } + if (carry[i & 1]) { + if (a->alloced == a->used) { + a->alloced <<= 1; + a->chars = realloc(a->chars, a->alloced * sizeof(*(a->chars))); + } + a->chars[i] = carry[i & 1]; + a->used++; + } + + SET_SIGNUM(a, zsignum(b)); +} diff --git a/src/zrsh.c b/src/zrsh.c new file mode 100644 index 0000000..649ebb3 --- /dev/null +++ b/src/zrsh.c @@ -0,0 +1,48 @@ +/* See LICENSE file for copyright and license details. */ +#include "internals" + +#include <stdlib.h> +#include <string.h> + + +void +zrsh(z_t a, z_t b, size_t bits) +{ + size_t i, chars, cbits; + + if (!bits) { + if (a != b) + zset(a, b); + return; + } + + chars = FLOOR_BITS_TO_CHARS(bits); + + if (zzero(b) || chars >= b->used || zbits(b) <= bits) { + SET_SIGNUM(a, 0); + return; + } + + bits = BITS_IN_LAST_CHAR(bits) + cbits = BITS_PER_CHAR - 1 - bits; + + if (chars && a == b) { + a->used -= chars; + memmove(a->chars, a->chars + chars, a->used * sizeof(*(a->chars))); + } else if (a != b) { + a->used = b->used - chars; + if (a->alloced < a->used) { + a->alloced = a->used; + a->chars = realloc(a->chars, a->used * sizeof(*(a->chars))); + } + memcpy(a->chars, b->chars + chars, a->used * sizeof(*(a->chars))); + } + + a->chars[0] >>= bits; + for (i = 1; i < a->used; i++) { + a->chars[i - 1] |= a->chars[i] >> cbits; + a->chars[i] >>= bits; + } + + SET_SIGNUM(a, zsignum(b)); +} |
