libzahl

big integer library
git clone git://git.suckless.org/libzahl
Log | Files | Refs | README | LICENSE

commit 3728c12ecbe308092b213f1b664303a48858a2b8
parent 56680b5fa737dd7aa1cd7446cad62f5b1da2235c
Author: Mattias Andrée <maandree@kth.se>
Date:   Thu,  3 Mar 2016 12:47:39 +0100

Add zbset

Signed-off-by: Mattias Andrée <maandree@kth.se>

Diffstat:
Mman/zand.3 | 1+
Aman/zbset.3 | 39+++++++++++++++++++++++++++++++++++++++
Mman/zbtest.3 | 1+
Mman/zinit.3 | 1+
Mman/zlsb.3 | 1+
Mman/zlsh.3 | 1+
Mman/znot.3 | 1+
Mman/zor.3 | 1+
Mman/zrsh.3 | 1+
Mman/zxor.3 | 1+
Asrc/zbset.c | 48++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/zbtest.c | 4++--
Mzahl.h | 3+++
13 files changed, 101 insertions(+), 2 deletions(-)

diff --git a/man/zand.3 b/man/zand.3 @@ -27,5 +27,6 @@ with non-unique parameters. .BR zrsh (3), .BR zsplit (3), .BR zbtest (3), +.BR zbset (3), .BR zlsb (3), .BR zbits (3) diff --git a/man/zbset.3 b/man/zbset.3 @@ -0,0 +1,39 @@ +.TH ZBSET 3 libzahl +.SH NAME +zbset - Set, clear, or flip a bit in a big integer +.SH SYNOPSIS +.nf +#include <zahl.h> + +void zbset(z_t \fIa\fP, z_t \fIb\fP, size_t \fIindex\fP, int \fIset\fP); +.fi +.SH DESCRIPTION +.B zbset +either sets, clears, or flips the bit with the selected +.I index +in +.IR b , +and stores the result in +.IR a . +.P +The bit is set if +.IR "(set>0)" , +clear if +.IR "(set==0)" , +and flipped if +.IR "(set<0)" . +.P +It is safe to call +.B zbset +with non-unique parameters. +.SH SEE ALSO +.BR zbtest (3), +.BR zand (3), +.BR zor (3), +.BR zxor (3), +.BR znot (3), +.BR zlsh (3), +.BR zrsh (3), +.BR zsplit (3), +.BR zlsb (3), +.BR zbits (3) diff --git a/man/zbtest.3 b/man/zbtest.3 @@ -17,6 +17,7 @@ is set in .B zbtest returns 1 if the bit is set, or 0 otherwise. .SH SEE ALSO +.BR zbset (3), .BR zand (3), .BR zor (3), .BR zxor (3), diff --git a/man/zinit.3 b/man/zinit.3 @@ -37,6 +37,7 @@ typedef struct { .BR zbits (3), .BR zlsb (3), .BR zbtest (3), +.BR zbset (3), .BR zand (3), .BR zor (3), .BR zxor (3), diff --git a/man/zlsb.3 b/man/zlsb.3 @@ -28,5 +28,6 @@ is zero. .SH SEE ALSO .BR zbits (3), .BR zbtest (3), +.BR zbset (3), .BR znot (3), .BR zrsh (3) diff --git a/man/zlsh.3 b/man/zlsh.3 @@ -28,5 +28,6 @@ with .BR ztrunc (3), .BR zsplit (3), .BR zbtest (3), +.BR zbset (3), .BR zlsb (3), .BR zbits (3) diff --git a/man/znot.3 b/man/znot.3 @@ -44,5 +44,6 @@ sign-and-magnitude. .BR zrsh (3), .BR zsplit (3), .BR zbtest (3), +.BR zbset (3), .BR zlsb (3), .BR zbits (3) diff --git a/man/zor.3 b/man/zor.3 @@ -27,5 +27,6 @@ with non-unique parameters. .BR zrsh (3), .BR zsplit (3), .BR zbtest (3), +.BR zbset (3), .BR zlsb (3), .BR zbits (3) diff --git a/man/zrsh.3 b/man/zrsh.3 @@ -28,5 +28,6 @@ with .BR ztrunc (3), .BR zsplit (3), .BR zbtest (3), +.BR zbset (3), .BR zlsb (3), .BR zbits (3) diff --git a/man/zxor.3 b/man/zxor.3 @@ -27,5 +27,6 @@ with non-unique parameters. .BR zrsh (3), .BR zsplit (3), .BR zbtest (3), +.BR zbset (3), .BR zlsb (3), .BR zbits (3) diff --git a/src/zbset.c b/src/zbset.c @@ -0,0 +1,48 @@ +/* See LICENSE file for copyright and license details. */ +#include "internals" + +#include <stdlib.h> +#include <string.h> + + +void +zbset(z_t a, z_t b, size_t bit, int action) +{ + zahl_char_t x = 1; + size_t chars; + + chars = FLOOR_BITS_TO_CHARS(bit); + bit = BITS_IN_LAST_CHAR(bit); + x <<= bit; + + if (a != b) + zset(a, b); + + if (action) { + if (zzero(a)) { + a->used = 0; + SET_SIGNUM(a, 1); + } + if (a->used <= chars) { + if (a->alloced <= chars) { + a->alloced = chars + 1; + a->chars = realloc(a->chars, a->alloced * sizeof(*(a->chars))); + } + memset(a->chars + a->used, 0, (chars - a->used + 1) * sizeof(*(a->chars))); + } + } + + if (action > 0) { + a->chars[chars] |= x; + return; + } else if (action < 0) { + a->chars[chars] ^= x; + } else if (a->used > chars) { + a->chars[chars] &= ~x; + } + + while (a->used && !a->chars[a->used - 1]) + a->used--; + if (!a->used) + SET_SIGNUM(a, 0); +} diff --git a/src/zbtest.c b/src/zbtest.c @@ -9,10 +9,10 @@ zbtest(z_t a, size_t bit) if (zzero(a)) return 0; - chars = bit >> LB_BITS_PER_CHAR; + chars = FLOOR_BITS_TO_CHARS(bit); if (chars >= a->used) return 0; - bit &= BITS_PER_CHAR - 1; + bit = BITS_IN_LAST_CHAR(bit); return (a->chars[chars] >> bit) & 1; } diff --git a/zahl.h b/zahl.h @@ -100,6 +100,9 @@ void zsplit(z_t, z_t, z_t, size_t); /* a := c >> d, b := c - (a << d) */ size_t zbits(z_t); /* ⌊log₂ |a|⌋ + 1, 1 if a = 0 */ size_t zlsb(z_t); /* Index of first set bit, SIZE_MAX if none are set. */ +/* If d > 0: a := b | (1 << c), f d = 0: a := b & ~(1 << c), if d < 0: a := b ^ (1 << c) */ +void zbset(z_t, z_t, size_t, int); + /* Number theory. */