diff options
Diffstat (limited to 'src/zrsh.c')
| -rw-r--r-- | src/zrsh.c | 48 |
1 files changed, 48 insertions, 0 deletions
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)); +} |
