summary refs log tree commit diff
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2017-01-04 19:22:31 -0500
committerQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2017-01-04 19:22:31 -0500
commit7918c9411c01027b096c60c2e245c36591b0076b (patch)
treef6ee173e6510ebee20cba7104273c1c635708608
parentb976b2da5c88eed0c47bfbe2cf457330bcb93fa3 (diff)
downloadroux-7918c9411c01027b096c60c2e245c36591b0076b.tar.gz
improve performance of bsiter()
-rw-r--r--util.c49
1 files changed, 40 insertions, 9 deletions
diff --git a/util.c b/util.c
index 5c54c12..380f139 100644
--- a/util.c
+++ b/util.c
@@ -275,6 +275,32 @@ popcnt(bits b)
 	return b & 0xff;
 }
 
+inline static int
+firstbit(bits b)
+{
+	int n;
+
+	n = 0;
+	if (!(b & 0xffffffff)) {
+		n += 32;
+		b >>= 32;
+	}
+	if (!(b & 0xffff)) {
+		n += 16;
+		b >>= 16;
+	}
+	if (!(b & 0xff)) {
+		n += 8;
+		b >>= 8;
+	}
+	if (!(b & 0xf)) {
+		n += 4;
+		b >>= 4;
+	}
+	n += (char[16]){4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0}[b & 0xf];
+	return n;
+}
+
 uint
 bscount(BSet *bs)
 {
@@ -349,18 +375,23 @@ bszero(BSet *bs)
 int
 bsiter(BSet *bs, int *elt)
 {
-	uint i;
+	bits b;
+	uint t, i;
 
-	for (i=*elt;; i++) {
-		while (i < bsmax(bs) && !bs->t[i/NBit])
-			i = (i + NBit) & -NBit;
-		if (i >= bsmax(bs))
+	i = *elt;
+	t = i/NBit;
+	if (t >= bs->nt)
+		return 0;
+	b = bs->t[t];
+	b &= ~(BIT(i%NBit) - 1);
+	while (!b) {
+		++t;
+		if (t >= bs->nt)
 			return 0;
-		if (bshas(bs, i)) {
-			*elt = i;
-			return 1;
-		}
+		b = bs->t[t];
 	}
+	*elt = NBit*t + firstbit(b);
+	return 1;
 }
 
 void