commit 3728c12ecbe308092b213f1b664303a48858a2b8
Author: Mattias Andrée <maandree_AT_kth.se>
AuthorDate: Thu Mar 3 12:47:39 2016 +0100
Commit: Mattias Andrée <maandree_AT_kth.se>
CommitDate: Thu Mar 3 12:47:39 2016 +0100
Add zbset
Signed-off-by: Mattias Andrée <maandree_AT_kth.se>
diff --git a/man/zand.3 b/man/zand.3
index f7be535..c4875bc 100644
--- a/man/zand.3
+++ b/man/zand.3
_AT_@ -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
_AT_@ -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
_AT_@ -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
_AT_@ -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
index 57586ef..6876c3d 100644
--- a/man/zlsb.3
+++ b/man/zlsb.3
_AT_@ -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
index a9c993c..e9192ad 100644
--- a/man/zlsh.3
+++ b/man/zlsh.3
_AT_@ -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
index 99d7b40..f84de6b 100644
--- a/man/znot.3
+++ b/man/znot.3
_AT_@ -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
index fe7f27f..301a3ea 100644
--- a/man/zor.3
+++ b/man/zor.3
_AT_@ -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
index 8e06180..905a262 100644
--- a/man/zrsh.3
+++ b/man/zrsh.3
_AT_@ -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
index f7cd19c..28c2a4a 100644
--- a/man/zxor.3
+++ b/man/zxor.3
_AT_@ -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
_AT_@ -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
_AT_@ -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
index 4f2a2c8..8f91809 100644
--- a/zahl.h
+++ b/zahl.h
_AT_@ -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. */
Received on Thu Mar 03 2016 - 14:00:16 CET
This archive was generated by hypermail 2.3.0
: Thu Mar 03 2016 - 14:12:19 CET