shithub: asif

Download patch

ref: bad4d8986b497e23c9b245660830578e60818611
parent: 669bbb705f203f03b8cc04026e232ec9b3f40eb8
author: qwx <qwx@sciops.net>
date: Fri Apr 8 21:51:52 EDT 2022

pheap: fix another problem in cutting pairs from the graph + debugging

--- a/asif.h
+++ b/asif.h
@@ -75,6 +75,7 @@
 	Pairheap *left;
 	Pairheap *right;
 };
+void	printqueue(Pairheap**);
 void	nukequeue(Pairheap**);
 Pairheap*	popqueue(Pairheap**);
 void	decreasekey(Pairheap*, double, Pairheap**);
@@ -96,6 +97,7 @@
 	Lognone,
 	Logdebug,
 	Logtrace,
+	Logparanoid,
 };
 extern int debuglevel;
 
--- a/pheap.c
+++ b/pheap.c
@@ -7,9 +7,23 @@
  * (1986).  */
 
 static void
+checkheap(Pairheap *p, Pairheap *queue)
+{
+	Pairheap *q;
+
+	if(p == nil || queue == nil)
+		return;
+	if(p == queue)
+		fprint(2, "pheap::checkheap %#p\n", p);
+	assert(p == queue || p->parent != nil && p->parent != p);
+	for(q=p; q!=nil; q=q->right)
+		checkheap(q->left, queue);
+}
+
+static void
 printright(Pairheap *p, int level)
 {
-	int i, j;
+	int i;
 	Pairheap *q;
 
 	if(p == nil)
@@ -17,7 +31,7 @@
 	fprint(2, "(\n");
 	for(i=0; i<level; i++)
 		fprint(2, "\t");
-	for(q=p, j=0; q!=nil; q=q->right, j++){
+	for(q=p; q!=nil; q=q->right){
 		fprint(2, "[%#p,%.5f]", q, q->n);
 		printright(q->left, level+1);
 	}
@@ -26,21 +40,30 @@
 		fprint(2, "\t");
 	fprint(2, ")");
 }
-static void
-printqueue(Pairheap *p)
+void
+printqueue(Pairheap **queue)
 {
-	if(debuglevel == 0)
+	if(queue == nil)
 		return;
-	if(p == nil)
-		return;
-	fprint(2, "pheap ");
-	printright(p, 1);
+	fprint(2, "pheap::printqueue %#p ", *queue);
+	printright(*queue, 1);
 	fprint(2, "\n");
 }
 
+static void
+debugqueue(Pairheap **queue)
+{
+	if(debuglevel < Logtrace || queue == nil)
+		return;
+	printqueue(queue);
+	checkheap(*queue, *queue);
+}
+
 static Pairheap *
 mergequeue(Pairheap *a, Pairheap *b)
 {
+	dprint(Logtrace, "pheap::mergequeue %#p %.6f b %#p %.6f\n",
+		a, a->n, b, b!=nil ? b->n : NaN());
 	if(b == nil)
 		return a;
 	else if(a->n < b->n){
@@ -57,21 +80,27 @@
 }
 
 static Pairheap *
-mergepairs(Pairheap *a)
+mergepairs(Pairheap *a, Pairheap *q)
 {
 	Pairheap *b, *c;
 
 	if(a == nil)
 		return nil;
+	if(a->parent != nil && a->parent->left == a)
+		a->parent->left = nil;
 	a->parent = nil;
+	assert(a->parent == nil || a->parent->left != a);
 	b = a->right;
 	if(b == nil)
 		return a;
 	a->right = nil;
+	if(b->parent != nil && b->parent->left == b)
+		b->parent->left = nil;
 	b->parent = nil;
+	assert(b->parent == nil || b->parent->left != b);
 	c = b->right;
 	b->right = nil;
-	return mergequeue(mergequeue(a, b), mergepairs(c));
+	return mergequeue(mergequeue(a, b), mergepairs(c, q));
 }
 
 void
@@ -79,8 +108,11 @@
 {
 	Pairheap *p;
 
-	while((p = popqueue(queue)) != nil)
+	dprint(Logtrace, "pheap::nukequeue %#p\n", queue);
+	while((p = popqueue(queue)) != nil){
+		debugqueue(&p);
 		free(p);
+	}
 }
 
 Pairheap *
@@ -92,7 +124,8 @@
 	if(p == nil)
 		return nil;
 	dprint(Logtrace, "pheap::popqueue %#p %.6f\n", p, p->n);
-	*queue = mergepairs(p->left);
+	*queue = mergepairs(p->left, p);
+	debugqueue(queue);
 	return p;
 }
 
@@ -104,16 +137,19 @@
 	dprint(Logtrace, "pheap::decreasekey %#p %.6f Δ %.6f\n", p, p->n, Δ);
 	p->n -= Δ;
 	if(p->parent != nil && p->n < p->parent->n){
+		assert(p->parent->left != nil);
 		if(p->parent->left == p)
-			p->parent->left = nil;
+			p->parent->left = p->right;
 		else{
-			for(q=p->parent->left; q->right!=p; q=q->right)
-				;
+			for(q=p->parent->left; q!=nil && q!=p; q=q->right)
+				if(q->right == p)
+					break;
 			assert(q != nil);
 			q->right = p->right;
 		}
 		p->parent = nil;
 		*queue = mergequeue(p, *queue);
+		debugqueue(queue);
 	}
 }
 
@@ -125,7 +161,8 @@
 	p = emalloc(sizeof *p);
 	p->n = n;
 	p->aux = aux;
-	*queue = mergequeue(p, *queue);
 	dprint(Logtrace, "pheap::pushqueue %#p %.6f\n", p, p->n);
+	*queue = mergequeue(p, *queue);
+	debugqueue(queue);
 	return p;
 }