// File: /workspace/github_c_makefile_star2_O2/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 $0x48, %rsp
movq %rsi, %r12
movq %rdi, %r14
movq %rsi, %rdi
callq 0x117e9
movq %rax, %rbp
movq %r12, %rdi
callq 0x117e9
movq %rax, 0x8(%rsp)
movq %r14, %rdi
movq %r12, %rsi
callq 0x6172
movq %rax, 0x10(%rsp)
xorl %r15d, %r15d
xorl %ebx, %ebx
movslq (%r14), %rax
cmpq %rax, %r15
jge 0x13f43
movq 0x10(%r14), %rax
movq (%rax,%r15,8), %rdi
testq %rdi, %rdi
je 0x13f3e
incl %ebx
callq 0x5b10
testb %al, %al
je 0x13f3e
movq 0x10(%r12), %rdi
callq 0x11307
movq 0x10(%r14), %rcx
movq (%rcx,%r15,8), %rcx
movq %rcx, 0x18(%rax)
movq %rbp, %rdi
movq %rax, %rsi
callq 0x61e7
movq 0x10(%r14), %rax
movq (%rax,%r15,8), %rax
movl $0x1, 0x28(%rax)
incq %r15
jmp 0x13eee
leal -0x3(,%rbx,2), %eax
cmpl %eax, 0x4(%r14)
jle 0x13f75
movq %r12, %rdi
movq %rbp, %rsi
callq 0x1184e
movq %r12, %rdi
movq 0x8(%rsp), %rsi
callq 0x1184e
movq %r12, %rdi
movq 0x10(%rsp), %rsi
jmp 0x142f2
cmpl $0x2, 0x10(%rbp)
movq 0x10(%rsp), %r15
jge 0x13f8b
movq %r12, %rdi
movq %rbp, %rsi
jmp 0x142da
cmpl $0x3, %ebx
pushq $0x2
popq %rax
cmovgel %ebx, %eax
movq %rax, 0x30(%rsp)
pushq $-0x1
popq %rcx
xorl %ebx, %ebx
movq %rbp, %rdx
movq %r12, 0x20(%rsp)
movq %rbp, 0x18(%rsp)
movq 0x30(%rsp), %rax
addl %ecx, %eax
cmpl $0x1, %eax
je 0x141bf
movq %rcx, 0x40(%rsp)
movq (%rdx), %rdx
movq %rdx, 0x38(%rsp)
movq 0x18(%rdx), %r13
movq 0x8(%r13), %rdi
movq 0x8(%rdi), %rax
movq 0x18(%rdi), %rbp
movq 0x18(%rax), %r14
cmpl $0x0, 0x24(%rdi)
je 0x14007
movl 0x18(%r13), %eax
movq 0x10(%r12), %rsi
cmpl 0x18(%rbp), %eax
jge 0x13ff7
callq 0x5a28
jmp 0x13ffc
callq 0x5a44
movq %r15, %rdi
movq %rax, %rsi
callq 0x6620
movq 0x8(%r13), %rax
movq 0x8(%rax), %rdi
cmpl $0x0, 0x24(%rdi)
je 0x1403b
movl 0x18(%r13), %eax
movq 0x10(%r12), %rsi
cmpl 0x18(%r14), %eax
jge 0x1402b
callq 0x5a28
jmp 0x14030
callq 0x5a44
movq %r15, %rdi
movq %rax, %rsi
callq 0x6620
movq 0x10(%r12), %rdi
callq 0x11307
movq %rax, %rbx
movl 0x18(%rbp), %eax
cmpl 0x18(%r14), %eax
jge 0x1406c
movq %rbp, 0x10(%rbx)
movq %r14, 0x18(%rbx)
movq %rbp, %rdi
movq %r14, %rsi
callq 0x5afb
movq %rbp, %r12
movq %r14, %rcx
jmp 0x14085
movq %r14, 0x10(%rbx)
movq %rbp, 0x18(%rbx)
movq %rbp, %rdi
movq %r14, %rsi
callq 0x5afb
movq %r14, %r12
movq %rbp, %rcx
testb %al, %al
jne 0x140d4
movq %rcx, 0x28(%rsp)
movq 0x20(%rsp), %r15
movq 0x10(%r15), %rsi
movq %rbx, %rdi
callq 0x5a28
pushq $0x1
popq %rcx
movl %ecx, 0x24(%rax)
movq %r12, %rdi
movq %rax, %rsi
callq 0x5b2c
movq 0x10(%r15), %rsi
movq 0x10(%rsp), %r15
movq %rbx, %rdi
callq 0x5a44
pushq $0x1
popq %rcx
movl %ecx, 0x24(%rax)
movq 0x28(%rsp), %rdi
movq %rax, %rsi
callq 0x5b2c
movq 0x8(%rsp), %rdi
movq %rbx, %rsi
callq 0x61e7
movq 0x20(%rsp), %r12
movq 0x10(%r12), %rdx
movq %rbp, %rdi
movq %r13, %rsi
callq 0x5b39
movq %rbp, %rdi
callq 0x5b10
testb %al, %al
je 0x1412a
cmpl $0x0, 0x28(%rbp)
jne 0x1412a
movq 0x10(%r12), %rdi
callq 0x11307
movq %rbp, 0x18(%rax)
movq 0x18(%rsp), %rdi
movq %rax, %rsi
callq 0x6620
movl $0x1, 0x28(%rbp)
movq 0x10(%r12), %rdx
movq %r14, %rdi
movq %r13, %rsi
callq 0x5b39
movq %r14, %rdi
callq 0x5b10
testb %al, %al
je 0x14170
cmpl $0x0, 0x28(%r14)
jne 0x14170
movq 0x10(%r12), %rdi
callq 0x11307
movq %r14, 0x18(%rax)
movq 0x18(%rsp), %rdi
movq %rax, %rsi
callq 0x6620
movl $0x1, 0x28(%r14)
movq 0x10(%r12), %rdi
movq 0x8(%r13), %rsi
callq 0x1138e
andq $0x0, 0x8(%r13)
movq %rbp, %rdi
movq %r14, %rsi
callq 0x5aae
cmpl $0x2, %eax
jge 0x142d2
movq 0x18(%rsp), %rbp
movl 0x10(%rbp), %eax
movq 0x40(%rsp), %rcx
addl %ecx, %eax
cmpl $0x1, %eax
jle 0x13f80
movq 0x38(%rsp), %rdx
addq $0x8, %rdx
decl %ecx
jmp 0x13fab
movq 0x10(%r12), %rsi
movq %rbx, %rdi
callq 0x5a28
movq %r15, %rdi
movq %rax, %rsi
callq 0x6620
movslq 0x10(%r15), %rbx
movq %rbx, %rdi
shlq $0x3, %rdi
callq 0x1180
movq %rax, %r14
xorl %eax, %eax
testl %ebx, %ebx
movl $0x0, %ecx
cmovgl %ebx, %ecx
cmpq %rax, %rcx
je 0x1420b
movq (%r15), %r15
movq %r15, (%r14,%rax,8)
incq %rax
addq $0x8, %r15
jmp 0x141f6
movq 0x8(%rsp), %rbx
movslq 0x10(%rbx), %r13
leaq (,%r13,8), %rdi
callq 0x1180
movq %rax, %r15
xorl %eax, %eax
testl %r13d, %r13d
movl $0x0, %ecx
cmovgl %r13d, %ecx
movq %rbx, %rdx
cmpq %rax, %rcx
je 0x1424a
movq (%rdx), %rdx
movq %rdx, (%r15,%rax,8)
incq %rax
addq $0x8, %rdx
jmp 0x14235
leaq -0x10761(%rip), %rbx    # 0x3af0
pushq $0x8
popq %r12
movq %r15, %rdi
movq %r13, %rsi
movq %r12, %rdx
movq %rbx, %rcx
callq 0x1080
movq 0x10(%rsp), %rax
movslq 0x10(%rax), %rsi
movq %r14, %rdi
movq %r12, %rdx
movq 0x20(%rsp), %r12
movq %rbx, %rcx
callq 0x1080
xorl %ebx, %ebx
xorl %ebp, %ebp
movq 0x8(%rsp), %rax
movslq 0x10(%rax), %rax
cmpq %rax, %rbx
jge 0x1430a
leaq (%r15,%rbx,8), %r12
movslq %ebp, %rbp
leaq (%r14,%rbp,8), %r13
movq %r12, %rdi
movq %r13, %rsi
callq 0x3af0
incq %rbp
addq $0x8, %r13
testl %eax, %eax
jg 0x1429f
addq $-0x8, %r13
movq %r12, %rdi
movq %r13, %rsi
callq 0x3af0
testl %eax, %eax
jne 0x1430f
incq %rbx
movq 0x20(%rsp), %r12
jmp 0x14286
movq %r12, %rdi
movq 0x18(%rsp), %rsi
callq 0x1184e
movq %r12, %rdi
movq 0x8(%rsp), %rsi
callq 0x1184e
movq %r12, %rdi
movq %r15, %rsi
callq 0x1184e
xorl %ebp, %ebp
movl %ebp, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movb $0x1, %bpl
jmp 0x14316
xorl %ebp, %ebp
movq 0x20(%rsp), %r12
movq %r12, %rdi
movq 0x18(%rsp), %rsi
callq 0x1184e
movq %r12, %rdi
movq 0x8(%rsp), %rsi
callq 0x1184e
movq %r12, %rdi
movq 0x10(%rsp), %rsi
callq 0x1184e
movq %r14, %rdi
callq 0x1030
movq %r15, %rdi
callq 0x1030
jmp 0x142f9