diff options
| -rw-r--r-- | man/zand.3 | 1 | ||||
| -rw-r--r-- | man/zbset.3 | 39 | ||||
| -rw-r--r-- | man/zbtest.3 | 1 | ||||
| -rw-r--r-- | man/zinit.3 | 1 | ||||
| -rw-r--r-- | man/zlsb.3 | 1 | ||||
| -rw-r--r-- | man/zlsh.3 | 1 | ||||
| -rw-r--r-- | man/znot.3 | 1 | ||||
| -rw-r--r-- | man/zor.3 | 1 | ||||
| -rw-r--r-- | man/zrsh.3 | 1 | ||||
| -rw-r--r-- | man/zxor.3 | 1 | ||||
| -rw-r--r-- | src/zbset.c | 48 | ||||
| -rw-r--r-- | src/zbtest.c | 4 | ||||
| -rw-r--r-- | zahl.h | 3 |
13 files changed, 101 insertions, 2 deletions
@@ -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 new file mode 100644 index 0000000..afa006f --- /dev/null +++ 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 index ee3562a..63c2fba 100644 --- 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 index bbae9e3..4e1d750 100644 --- 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), @@ -28,5 +28,6 @@ is zero. .SH SEE ALSO .BR zbits (3), .BR zbtest (3), +.BR zbset (3), .BR znot (3), .BR 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) @@ -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) @@ -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) @@ -28,5 +28,6 @@ with .BR ztrunc (3), .BR zsplit (3), .BR zbtest (3), +.BR zbset (3), .BR zlsb (3), .BR zbits (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 new file mode 100644 index 0000000..6833e5f --- /dev/null +++ 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 index 8e9f8ff..8ad0d94 100644 --- 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; } @@ -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. */ |
