// File: /workspace/github_c_makefile_star2_O3/pwelke[P]GraphMiningTools/outerplanar.c
// Function: isOuterplanarBlock
char isOuterplanarBlock(struct Graph* g, struct ShallowGraphPool* sgp) {
	struct ShallowGraph* list = getShallowGraph(sgp);
	struct ShallowGraph* pairs = getShallowGraph(sgp);
	struct ShallowGraph* edges = getGraphEdges(g, sgp);
	struct VertexList* node = NULL;
	struct VertexList* pair = NULL;
	struct VertexList** edgeArray;
	struct VertexList** pairArray;
	struct VertexList* idx;
	int i, j, k;
	int n = 0;
	char found;


	/*
	 * Get a list "list" of vertices of degree 2 and mark them as such in the graph
	 * by setting ->d = 1. Also, count the number of not-NULL vertices.
	 * This is useful if the algorithm gets some "induced subgraph" where some
	 * vertices are not used.
	 */
	for (i=0; i<g->n; ++i) {
		if (g->vertices[i]) {

			++n;

			/* if vertex has degree 2, add it to list and mark it as such */
			if (isDegreeTwoVertex(g->vertices[i])) {
				struct VertexList* e = getVertexList(sgp->listPool);
				e->endPoint = g->vertices[i];
				pushEdge(list, e);

				g->vertices[i]->d = 1;
			}
		}
	}

	/* first check. number of edges ok ? */
	if (g->m > 2 * n - 3) {
		/* printf("incorrect edge count\n"); */
		dumpShallowGraph(sgp, list);
		dumpShallowGraph(sgp, pairs);
		dumpShallowGraph(sgp, edges);
		return 0;
	}

	/* second check: enough vertices of degree 2? */
	if (list->m < 2) {
		/* printf("not enough vertices of degree 2\n"); */
		dumpShallowGraph(sgp, list);
		dumpShallowGraph(sgp, pairs);
		dumpShallowGraph(sgp, edges);
		return 0;
	}

	/*
	 * Successively remove vertices of degree 2
	 */
	for (i=1, node=list->edges; /*node && */  (i<=n-2);  ++i, node=node->next) {

		struct Vertex* v = node->endPoint;

		/* near and next are the two vertices adjacent to node */
		struct Vertex* near = v->neighborhood->endPoint;
		struct Vertex* next = v->neighborhood->next->endPoint;

		/* if the edges leading to near and next are artificial triangulation
		 * edges that were added below in a previous step, add them to the
		 * edges list. Do it s.t. startPoint->number <= endPoint->number, as
		 * there will be lexicographic sorting */
		if (v->neighborhood->flag) {
			if (v->number < near->number) {
				appendEdge(edges, shallowCopyEdge(v->neighborhood, sgp->listPool));
			} else {
				appendEdge(edges, inverseEdge(v->neighborhood, sgp->listPool));
			}
		}
		if (v->neighborhood->next->flag) {
			if (v->number < next->number) {
				appendEdge(edges, shallowCopyEdge(v->neighborhood->next, sgp->listPool));
			} else {
				appendEdge(edges, inverseEdge(v->neighborhood->next, sgp->listPool));
			}
		}


		/* add the pair (near, next) to pairs list, sort lexicographically
		 we have to add pair to the adjacency list of the graph, if this edge
		 does not already exist. Mark newly added edges in the flag tag. */
		pair = getVertexList(sgp->listPool);

		if (near->number < next->number) {

			pair->startPoint = near;
			pair->endPoint = next;

			/* this is for the case where g is not maximal outerplanar and
			 * a "triangulation edge" is added */
			if (!isIncident(near, next)) {
				struct VertexList* tmp = shallowCopyEdge(pair, sgp->listPool);
				tmp->flag = 1;
				addEdge(near, tmp);

				tmp = inverseEdge(pair, sgp->listPool);
				tmp->flag = 1;
				addEdge(next, tmp);
			}
		} else {

			pair->startPoint = next;
			pair->endPoint = near;

			/* this is for the case where g is not maximal outerplanar and
			 * a "triangulation edge" is added */
			if (!isIncident(near, next)) {
				struct VertexList* tmp = shallowCopyEdge(pair, sgp->listPool);
				tmp->flag = 1;
				addEdge(next, tmp);

				tmp =  inverseEdge(pair, sgp->listPool);
				tmp->flag = 1;
				addEdge(near, tmp);
			}
		}

		pushEdge(pairs, pair);

		/* remove node from Graph, check if one of the neighbors
		 * becomes degree two vertex. If it is not already in list
		 * (which is encoded in ->d), add it to list.
		 *
		 * TODO ?
		 * BUG: not degree two vertex, but 2-vertex. this is a difference
		 * But 2-vertices make no sense in the context of ops */
		removeEdge(near, v, sgp->listPool);
		if (isDegreeTwoVertex(near)) {
			if (!near->d) {
				struct VertexList* e = getVertexList(sgp->listPool);
				e->endPoint = near;
				/* printf("add %i to list of deg 2 vertices\n", near->number); */
				appendEdge(list, e);
				near->d = 1;
			}
		}

		removeEdge(next, v, sgp->listPool);
		if (isDegreeTwoVertex(next)) {
			if (!next->d) {
				struct VertexList* e = getVertexList(sgp->listPool);
				/* printf("add %i to list of deg 2 vertices\n", next->number); */
				e->endPoint = next;
				appendEdge(list, e);
				next->d = 1;
			}
		}


		/* Here, the vertex should be removed from the graph,
		 * but isMaximalOuterplanar has no pointer to a VertexPool. Thus we
		 * only dump the neighborhood of v. */
		dumpVertexListRecursively(sgp->listPool, v->neighborhood);
		v->neighborhood = NULL;


		/* this part may be omitted as it seems to be the case that
		 * "searching the list of pairs for an occurrence of something that
		 * is not in the list of edges includes an abort if there are e.g.
		 * two copies of an edge in pairs, but only one copy f that edge in
		 * edges.
		 *
		 * mistake in the paper. one has to check, if the new edge
		 * is not contained in more than two triangles. As one triangle
		 * is already deleted by removing v there can be only one other
		 * triangle left without violation of this condition in the former
		 * graph */
		if (commonNeighborCount(near, next) > 1) {
			/* printf("removing node %i creates an edge that lies on more than two triangles\n", node->endPoint->number); */
			dumpShallowGraph(sgp, list);
			dumpShallowGraph(sgp, pairs);
			dumpShallowGraph(sgp, edges);
			return 0;
		}



		/* at this point, node->endPoint should be dumped, but this is not necessary
		 * as it is not considered any more and can be handled when dumping the whole
		 * graph
		dumpVertexList(sgp->listPool, popEdge(list)); */

		if (list->m - i < 2) {
			/* printf("removing node %i leaves not enough degree 2 vertices\n", node->endPoint->number); */
			dumpShallowGraph(sgp, list);
			dumpShallowGraph(sgp, pairs);
			dumpShallowGraph(sgp, edges);
			return 0;
		}
	}

	/* add the last edge (near, next) to edges */
	appendEdge(edges, shallowCopyEdge(pair, sgp->listPool));

	/* check for occurrence of something in pairs, that is not in edges
	 * for this, sort the two lists in lexicographic order and sweep through
	 * the two arrays afterwards */
	edgeArray = malloc(edges->m * sizeof(struct VertexList*));
	for (i=0, idx=edges->edges; i<edges->m; ++i, idx=idx->next) {
		edgeArray[i] = idx;
	}

	pairArray = malloc(pairs->m * sizeof(struct VertexList*));
	for (i=0, idx=pairs->edges; i<pairs->m; ++i, idx=idx->next) {
		pairArray[i] = idx;
	}

	qsort(pairArray, pairs->m, sizeof(struct VertexList*), &compareDirectedEdges);
	qsort(edgeArray, edges->m, sizeof(struct VertexList*), &compareDirectedEdges);


	/* sweep */
	for (j=0, k=0, found=1; j<pairs->m; ++j) {

		/* increment currentEdge as long as it is lex. smaller than sweeper. */
		for (; compareDirectedEdges(&(pairArray[j]), &(edgeArray[k])) > 0; ++k);

		/* check if the two are equal */
		if (compareDirectedEdges(&(pairArray[j]), &(edgeArray[k])) == 0) {
			++k;
			continue;

		} else {
			/* this is bad, g is no mop */
			found = 0;
			break;
		}
	}

	/* garbage collection */
	dumpShallowGraph(sgp, list);
	dumpShallowGraph(sgp, pairs);
	dumpShallowGraph(sgp, edges);
	free(edgeArray);
	free(pairArray);

	return found;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rsi, %r15
movq %rdi, %r14
movq %rsi, %rdi
callq 0x1498d
movq %rax, %rbp
movq %r15, %rdi
callq 0x1498d
movq %rax, 0x8(%rsp)
movq %r14, %rdi
movq %r15, %rsi
callq 0x83ed
movq %rax, (%rsp)
cmpl $0x0, (%r14)
jle 0x16e50
xorl %ebx, %ebx
xorl %r12d, %r12d
movq 0x10(%r14), %rax
movq (%rax,%rbx,8), %rdi
testq %rdi, %rdi
je 0x16e43
incl %r12d
callq 0x7ce2
testb %al, %al
je 0x16e43
movq 0x10(%r15), %rdi
callq 0x141f1
movq 0x10(%r14), %rcx
movq (%rcx,%rbx,8), %rcx
movq %rcx, 0x18(%rax)
movq %rbp, %rdi
movq %rax, %rsi
callq 0x848a
movq 0x10(%r14), %rax
movq (%rax,%rbx,8), %rax
movl $0x1, 0x28(%rax)
incq %rbx
movslq (%r14), %rax
cmpq %rax, %rbx
jl 0x16dfb
jmp 0x16e53
xorl %r12d, %r12d
leal -0x3(,%r12,2), %eax
cmpl %eax, 0x4(%r14)
jg 0x16e67
cmpl $0x2, 0x10(%rbp)
jge 0x16ea0
movq %r15, %rdi
movq %rbp, %rsi
callq 0x149f4
movq %r15, %rdi
movq 0x8(%rsp), %rsi
callq 0x149f4
movq %r15, %rdi
movq (%rsp), %rsi
callq 0x149f4
xorl %r12d, %r12d
movl %r12d, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpl $0x3, %r12d
movq %r15, 0x20(%rsp)
movq %rbp, 0x10(%rsp)
jge 0x16ebe
movq $0x0, 0x18(%rsp)
jmp 0x170d7
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
movq %rbp, %rbx
movq %rcx, 0x30(%rsp)
movq (%rbx), %rbx
movq 0x18(%rbx), %r13
movq 0x8(%r13), %rdi
movq 0x8(%rdi), %rax
movq 0x18(%rdi), %rbp
movq 0x18(%rax), %r14
cmpl $0x0, 0x24(%rdi)
je 0x16f0d
movl 0x18(%r13), %eax
movq 0x10(%r15), %rsi
cmpl 0x18(%rbp), %eax
jge 0x16efc
callq 0x7bec
jmp 0x16f01
callq 0x7c08
movq (%rsp), %rdi
movq %rax, %rsi
callq 0x8916
movq 0x8(%r13), %rax
movq 0x8(%rax), %rdi
cmpl $0x0, 0x24(%rdi)
je 0x16f41
movl 0x18(%r13), %eax
movq 0x10(%r15), %rsi
cmpl 0x18(%r14), %eax
jge 0x16f30
callq 0x7bec
jmp 0x16f35
callq 0x7c08
movq (%rsp), %rdi
movq %rax, %rsi
callq 0x8916
movq 0x10(%r15), %rdi
callq 0x141f1
movq %rax, %r15
movl 0x18(%rbp), %eax
cmpl 0x18(%r14), %eax
jge 0x16f71
movq %rbp, 0x10(%r15)
movq %r14, 0x18(%r15)
movq %rbp, %rdi
movq %r14, %rsi
callq 0x7ccd
movq %rbp, %rdx
movq %r14, %rcx
jmp 0x16f8a
movq %r14, 0x10(%r15)
movq %rbp, 0x18(%r15)
movq %rbp, %rdi
movq %r14, %rsi
callq 0x7ccd
movq %r14, %rdx
movq %rbp, %rcx
testb %al, %al
jne 0x16fe4
movq %rdx, 0x28(%rsp)
movq %rcx, 0x18(%rsp)
movq 0x20(%rsp), %rax
movq 0x10(%rax), %rsi
movq %r15, %rdi
callq 0x7bec
movl $0x1, %ecx
movl %ecx, 0x24(%rax)
movq 0x28(%rsp), %rdi
movq %rax, %rsi
callq 0x7cfe
movq 0x20(%rsp), %rax
movq 0x10(%rax), %rsi
movq %r15, %rdi
callq 0x7c08
movl $0x1, %ecx
movl %ecx, 0x24(%rax)
movq 0x18(%rsp), %rdi
movq %rax, %rsi
callq 0x7cfe
movq 0x8(%rsp), %rdi
movq %r15, 0x18(%rsp)
movq %r15, %rsi
callq 0x848a
movq 0x20(%rsp), %r15
movq 0x10(%r15), %rdx
movq %rbp, %rdi
movq %r13, %rsi
callq 0x7d0b
movq %rbp, %rdi
callq 0x7ce2
testb %al, %al
je 0x1703d
cmpl $0x0, 0x28(%rbp)
jne 0x1703d
movq 0x10(%r15), %rdi
callq 0x141f1
movq %rbp, 0x18(%rax)
movq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x8916
movl $0x1, 0x28(%rbp)
movq 0x10(%r15), %rdx
movq %r14, %rdi
movq %r13, %rsi
callq 0x7d0b
movq %r14, %rdi
callq 0x7ce2
testb %al, %al
je 0x17081
cmpl $0x0, 0x28(%r14)
jne 0x17081
movq 0x10(%r15), %rdi
callq 0x141f1
movq %r14, 0x18(%rax)
movq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x8916
movl $0x1, 0x28(%r14)
movq 0x10(%r15), %rdi
movq 0x8(%r13), %rsi
callq 0x1427a
movq $0x0, 0x8(%r13)
movq %rbp, %rdi
movq %r14, %rsi
callq 0x7c74
cmpl $0x2, %eax
jge 0x17237
movq 0x10(%rsp), %rbp
movl 0x10(%rbp), %eax
movq 0x30(%rsp), %rcx
addl %ecx, %eax
cmpl $0x1, %eax
jle 0x16e67
addq $0x8, %rbx
leal (%r12,%rcx), %eax
decl %eax
decl %ecx
cmpl $0x1, %eax
jne 0x16ec6
movq 0x10(%r15), %rsi
movq 0x18(%rsp), %rdi
callq 0x7bec
movq (%rsp), %rbx
movq %rbx, %rdi
movq %rax, %rsi
callq 0x8916
movslq 0x10(%rbx), %rbx
leaq (,%rbx,8), %rdi
callq 0x1190
movq %rax, %r14
testq %rbx, %rbx
jle 0x17126
xorl %eax, %eax
movq (%rsp), %rcx
movq (%rcx), %rcx
movq %rcx, (%r14,%rax,8)
incq %rax
addq $0x8, %rcx
cmpq %rax, %rbx
jne 0x17113
movq 0x8(%rsp), %rax
movslq 0x10(%rax), %r13
leaq (,%r13,8), %rdi
callq 0x1190
movq %rax, %r15
testq %r13, %r13
jle 0x1715e
xorl %eax, %eax
movq 0x8(%rsp), %rcx
movq (%rcx), %rcx
movq %rcx, (%r15,%rax,8)
incq %rax
addq $0x8, %rcx
cmpq %rax, %r13
jne 0x1714b
leaq -0x11695(%rip), %r12    # 0x5ad0
movl $0x8, %edx
movq %r15, %rdi
movq %r13, %rsi
movq %r12, %rcx
callq 0x1080
movq (%rsp), %rax
movslq 0x10(%rax), %rsi
movl $0x8, %edx
movq %r14, %rdi
movq %r12, %rcx
callq 0x1080
movb $0x1, %r12b
movq 0x8(%rsp), %rax
cmpl $0x0, 0x10(%rax)
jle 0x171f9
xorl %ebx, %ebx
xorl %ebp, %ebp
leaq (%r15,%rbx,8), %r12
movslq %ebp, %rbp
leaq (%r14,%rbp,8), %r13
movq %r12, %rdi
movq %r13, %rsi
callq 0x5ad0
incq %rbp
addq $0x8, %r13
testl %eax, %eax
jg 0x171ad
addq $-0x8, %r13
movq %r12, %rdi
movq %r13, %rsi
callq 0x5ad0
testl %eax, %eax
jne 0x171f1
incq %rbx
movq 0x8(%rsp), %rax
movslq 0x10(%rax), %rax
cmpq %rax, %rbx
jl 0x171a2
movq 0x10(%rsp), %rbp
movb $0x1, %r12b
jmp 0x171f9
xorl %r12d, %r12d
movq 0x10(%rsp), %rbp
movq 0x20(%rsp), %rbx
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x149f4
movq %rbx, %rdi
movq 0x8(%rsp), %rsi
callq 0x149f4
movq %rbx, %rdi
movq (%rsp), %rsi
callq 0x149f4
movq %r14, %rdi
callq 0x1030
movq %r15, %rdi
callq 0x1030
jmp 0x16e8e
movq %r15, %rdi
movq 0x10(%rsp), %rsi
jmp 0x16e6d