// File: /workspace/github_c_makefile_star2_O3/pwelke[P]GraphMiningTools/cs_Outerplanar.c
// Function: _getCycleAndDiagonals
struct ShallowGraph* __getCycleAndDiagonals(struct Graph* g, struct ShallowGraphPool* sgp) {
	/* data structures described by Mitchell[1979] */
	struct ShallowGraph* list = getShallowGraph(sgp);
	struct ShallowGraph* pairs = getShallowGraph(sgp);
	struct ShallowGraph* edges = getGraphEdges(g, sgp);
	struct VertexList* node = NULL;
	struct VertexList* pair = NULL;
	/* data structures for canonical string computation */
	struct ShallowGraph* hamiltonianCycle = getShallowGraph(sgp);
	struct ShallowGraph* diagonals = getShallowGraph(sgp);
	/* data structures for sorting */
	struct VertexList** edgeArray;
	struct VertexList** pairArray;
	/* indices */
	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);
		dumpShallowGraph(sgp, hamiltonianCycle);
		dumpShallowGraph(sgp, diagonals);
		return NULL;
	}

	/* 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);
		dumpShallowGraph(sgp, hamiltonianCycle);
		dumpShallowGraph(sgp, diagonals);
		return NULL;
	}

	/*
	 * 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));
			}
		}

		/* canonical string: add the edges to hamiltonianCycle, if they are no triangulation
		 * edges (artificial or original!). Which is recorded in ->used */
		if (!v->neighborhood->used) {
			appendEdge(hamiltonianCycle, shallowCopyEdge(v->neighborhood, sgp->listPool));
		}
		if (!v->neighborhood->next->used) {
			appendEdge(hamiltonianCycle, shallowCopyEdge(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 {
				/* it the edge is an original edge of g, it is a diagonal and will be stored in
				 * diagonals (if that has not already been done). */
				for (idx=near->neighborhood; idx; idx=idx->next) {
					if (idx->endPoint == next) {
						if (!idx->flag && !idx->used) {
							appendEdge(diagonals, shallowCopyEdge(idx, sgp->listPool));
						}
						break;
					}
				}
			}
		} 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);
			} else {
				/* it the edge is an original edge of g, it is a diagonal and will be stored in
				 * diagonals (if that has not already been done). */
				for (idx=near->neighborhood; idx; idx=idx->next) {
					if (idx->endPoint == next) {
						if (!idx->flag && !idx->used) {
							appendEdge(diagonals, shallowCopyEdge(idx, sgp->listPool));
						}
						break;
					}
				}
			}
		}

		pushEdge(pairs, pair);

		/* canonical string: mark the new edge as triangulation edge via ->used */
		for (idx=near->neighborhood; idx; idx=idx->next) {
			if (idx->endPoint == next) {
				idx->used = 1;
			}
		}
		for (idx=next->neighborhood; idx; idx=idx->next) {
			if (idx->endPoint == near) {
				idx->used = 1;
			}
		}

		/* 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 the edges in
		 * hamiltonianCycle point to the vertices. We need them for the computation
		 * of the actual cycle. so 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);
			dumpShallowGraph(sgp, hamiltonianCycle);
			dumpShallowGraph(sgp, diagonals);
			return NULL;
		}



		/* 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);
			dumpShallowGraph(sgp, hamiltonianCycle);
			dumpShallowGraph(sgp, diagonals);
			return NULL;
		}
	}

	/* 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;
		}
	}

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

	/* create canonical string of this block or return NULL,
	 * if the block is not outerplanar */
	if (found) {
		struct VertexList* e;
		struct VertexList* lastEdge = NULL;

		/* delete all edges that remain in g. That is exactly one. Store one copy of it
		 * in case that this edge belongs to the hamiltonian cycle. */
		for (i=0; i<g->n; ++i) {
			if (g->vertices[i]->neighborhood) {
				dumpVertexListRecursively(sgp->listPool, lastEdge);
				lastEdge = g->vertices[i]->neighborhood;
				g->vertices[i]->neighborhood = NULL;
			}
		}

		/* add edges in hamiltonianCycle to g */
		while ((e = popEdge(hamiltonianCycle))) {
			e->next = e->startPoint->neighborhood;
			e->startPoint->neighborhood = e;

			e = inverseEdge(e, sgp->listPool);
			e->next = e->startPoint->neighborhood;
			e->startPoint->neighborhood = e;
		}

		/* hamiltonianCycle is now empty and g is a undirected cycle.
		 * Now obtain a ShallowGraph where edges are ordered correctly. */
		for (e=g->vertices[0]->neighborhood; e; e=e->endPoint->neighborhood) {

			/* remove e from the adjacency list of its startpoint */
			e->startPoint->neighborhood = e->next;
			e->next = NULL;

			/* remove inverse edge of e from adjacency list of e's endpoint
			 * remember: a vertex has exactly two neighbors except in the
			 * last iteration of this loop */
			if (e->endPoint->neighborhood->endPoint == e->startPoint) {
				struct VertexList* tmp = e->endPoint->neighborhood;
				e->endPoint->neighborhood = e->endPoint->neighborhood->next;
				dumpVertexList(sgp->listPool, tmp);
			} else {
				dumpVertexList(sgp->listPool, e->endPoint->neighborhood->next);
				e->endPoint->neighborhood->next = NULL;
			}

			/* add e to hamiltonianCycle */
			appendEdge(hamiltonianCycle, e);
		}

		/* in case the reducion phase of this algorithm reduced the last triangle
		 * onto an edge on the hamiltonian cycle of g, this edge is not yet contained
		 * in hamiltonianCycle. We have stored it in lastEdge. Add it. */
		if (hamiltonianCycle->edges->startPoint != hamiltonianCycle->lastEdge->endPoint) {
			if (hamiltonianCycle->lastEdge->endPoint == lastEdge->startPoint) {
				appendEdge(hamiltonianCycle, lastEdge);
			} else {
				appendEdge(hamiltonianCycle, inverseEdge(lastEdge, sgp->listPool));
				dumpVertexList(sgp->listPool, lastEdge);
			}
		} else {
			dumpVertexList(sgp->listPool, lastEdge);
		}

		/* special case:
		 * TODO needs theoretical background
		 * if diagonals contains exactly one edge, it may be the case that this edge is
		 * contained in the hamiltonian cycle and has to be removed.
		 * If so, this edge has been lastEdge above and is stored in
		 * hamiltonianCycle->lastEdge, we have to check for inverse edges, too. */
		if (diagonals->m == 1) {
			if ((diagonals->edges->startPoint == hamiltonianCycle->lastEdge->startPoint)
					&& (diagonals->edges->endPoint == hamiltonianCycle->lastEdge->endPoint)) {
				dumpVertexList(sgp->listPool, popEdge(diagonals));
			}
			if ((diagonals->edges->startPoint == hamiltonianCycle->lastEdge->endPoint)
					&& (diagonals->edges->endPoint == hamiltonianCycle->lastEdge->startPoint)) {
				dumpVertexList(sgp->listPool, popEdge(diagonals));
			}
		}

		/* now hamiltonianCycle is a cycle and
		 * diagonals contains the diagonals of the block. hurra! */
		hamiltonianCycle->next = diagonals;
		return hamiltonianCycle;


	} else {
		/* g is not outerplanar. return NULL. */
		dumpShallowGraph(sgp, hamiltonianCycle);
		dumpShallowGraph(sgp, diagonals);
		return NULL;
	}

	return NULL;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rsi, %rbx
movq %rdi, %r12
movq %rsi, %rdi
callq 0x1498d
movq %rax, %rbp
movq %rbx, %rdi
callq 0x1498d
movq %rax, 0x18(%rsp)
movq %r12, %rdi
movq %rbx, %rsi
callq 0x83ed
movq %rax, 0x10(%rsp)
movq %rbx, %rdi
callq 0x1498d
movq %rax, %r13
movq %rbx, %rdi
callq 0x1498d
movq %rax, 0x20(%rsp)
cmpl $0x0, (%r12)
jle 0x68d1
xorl %r14d, %r14d
xorl %r15d, %r15d
movq 0x10(%r12), %rax
movq (%rax,%r14,8), %rdi
testq %rdi, %rdi
je 0x68c3
incl %r15d
callq 0x7ce2
testb %al, %al
je 0x68c3
movq 0x10(%rbx), %rdi
callq 0x141f1
movq 0x10(%r12), %rcx
movq (%rcx,%r14,8), %rcx
movq %rcx, 0x18(%rax)
movq %rbp, %rdi
movq %rax, %rsi
callq 0x848a
movq 0x10(%r12), %rax
movq (%rax,%r14,8), %rax
movl $0x1, 0x28(%rax)
incq %r14
movslq (%r12), %rax
cmpq %rax, %r14
jl 0x6878
jmp 0x68d4
xorl %r15d, %r15d
leal -0x3(,%r15,2), %eax
cmpl %eax, 0x4(%r12)
jg 0x68e9
cmpl $0x2, 0x10(%rbp)
jge 0x693b
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x149f4
movq %rbx, %rdi
movq 0x18(%rsp), %rsi
callq 0x149f4
movq %rbx, %rdi
movq 0x10(%rsp), %rsi
callq 0x149f4
movq %rbx, %rdi
movq %r13, %rsi
callq 0x149f4
movq %rbx, %rdi
movq 0x20(%rsp), %rsi
callq 0x149f4
xorl %r13d, %r13d
movq %r13, %rax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpl $0x3, %r15d
movq %r13, 0x30(%rsp)
movq %rbp, 0x28(%rsp)
jge 0x6959
movq $0x0, 0x8(%rsp)
jmp 0x6c70
addl $-0x2, %r15d
movq %rbp, %rcx
movl $0x1, %eax
movq %rax, 0x38(%rsp)
movq (%rcx), %rcx
movq %rcx, 0x40(%rsp)
movq 0x18(%rcx), %r13
movq 0x8(%r13), %rdi
movq 0x8(%rdi), %rax
movq 0x18(%rdi), %rbp
movq 0x18(%rax), %r14
cmpl $0x0, 0x24(%rdi)
je 0x69b2
movl 0x18(%r13), %eax
movq 0x10(%rbx), %rsi
cmpl 0x18(%rbp), %eax
jge 0x69a0
callq 0x7bec
jmp 0x69a5
callq 0x7c08
movq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x8916
movq 0x8(%r13), %rax
movq 0x8(%rax), %rdi
cmpl $0x0, 0x24(%rdi)
je 0x69e7
movl 0x18(%r13), %eax
movq 0x10(%rbx), %rsi
cmpl 0x18(%r14), %eax
jge 0x69d5
callq 0x7bec
jmp 0x69da
callq 0x7c08
movq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x8916
movq 0x8(%r13), %rdi
cmpl $0x0, 0x20(%rdi)
jne 0x6a0b
movq 0x10(%rbx), %rsi
callq 0x7bec
movq 0x30(%rsp), %rdi
movq %rax, %rsi
callq 0x8916
movq 0x8(%r13), %rdi
movq 0x8(%rdi), %rdi
cmpl $0x0, 0x20(%rdi)
jne 0x6a2b
movq 0x10(%rbx), %rsi
callq 0x7bec
movq 0x30(%rsp), %rdi
movq %rax, %rsi
callq 0x8916
movq 0x10(%rbx), %rdi
callq 0x141f1
movl 0x18(%rbp), %ecx
cmpl 0x18(%r14), %ecx
movq %rax, 0x8(%rsp)
jge 0x6a71
movq %rbp, 0x10(%rax)
movq %r14, 0x18(%rax)
movq %rbp, %rdi
movq %r14, %rsi
callq 0x7ccd
movq %rbp, %rdi
testb %al, %al
je 0x6aca
movq 0x8(%rdi), %rdi
testq %rdi, %rdi
je 0x6b48
cmpq %r14, 0x18(%rdi)
jne 0x6a5c
jmp 0x6a9e
movq %r14, 0x10(%rax)
movq %rbp, 0x18(%rax)
movq %rbp, %rdi
movq %r14, %rsi
callq 0x7ccd
movq %rbp, %rdi
testb %al, %al
je 0x6b06
movq 0x8(%rdi), %rdi
testq %rdi, %rdi
je 0x6b48
cmpq %r14, 0x18(%rdi)
jne 0x6a8b
cmpl $0x0, 0x24(%rdi)
jne 0x6b48
cmpl $0x0, 0x20(%rdi)
jne 0x6b48
movq 0x10(%rbx), %rsi
callq 0x7bec
movq 0x20(%rsp), %rdi
movq %rax, %rsi
callq 0x8916
jmp 0x6b48
movq 0x10(%rbx), %rsi
movq 0x8(%rsp), %rdi
callq 0x7bec
movl $0x1, %ecx
movl %ecx, 0x24(%rax)
movq %rbp, %rdi
movq %rax, %rsi
callq 0x7cfe
movq 0x10(%rbx), %rsi
movq 0x8(%rsp), %rdi
callq 0x7c08
movl $0x1, %ecx
movl %ecx, 0x24(%rax)
movq %r14, %rdi
jmp 0x6b40
movq 0x10(%rbx), %rsi
movq 0x8(%rsp), %rdi
callq 0x7bec
movl $0x1, %ecx
movl %ecx, 0x24(%rax)
movq %r14, %rdi
movq %rax, %rsi
callq 0x7cfe
movq 0x10(%rbx), %rsi
movq 0x8(%rsp), %rdi
callq 0x7c08
movl $0x1, %ecx
movl %ecx, 0x24(%rax)
movq %rbp, %rdi
movq %rax, %rsi
callq 0x7cfe
movq 0x18(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x848a
movq 0x8(%rbp), %rax
testq %rax, %rax
je 0x6b73
cmpq %r14, 0x18(%rax)
jne 0x6b6d
movl $0x1, 0x20(%rax)
movq 0x8(%rax), %rax
jmp 0x6b5b
movq 0x8(%r14), %rax
testq %rax, %rax
je 0x6b8f
cmpq %rbp, 0x18(%rax)
jne 0x6b89
movl $0x1, 0x20(%rax)
movq 0x8(%rax), %rax
jmp 0x6b77
movq 0x10(%rbx), %rdx
movq %rbp, %rdi
movq %r13, %rsi
callq 0x7d0b
movq %rbp, %rdi
callq 0x7ce2
testb %al, %al
je 0x6bd1
cmpl $0x0, 0x28(%rbp)
jne 0x6bd1
movq 0x10(%rbx), %rdi
callq 0x141f1
movq %rbp, 0x18(%rax)
movq 0x28(%rsp), %rdi
movq %rax, %rsi
callq 0x8916
movl $0x1, 0x28(%rbp)
movq 0x10(%rbx), %rdx
movq %r14, %rdi
movq %r13, %rsi
callq 0x7d0b
movq %r14, %rdi
callq 0x7ce2
testb %al, %al
je 0x6c15
cmpl $0x0, 0x28(%r14)
jne 0x6c15
movq 0x10(%rbx), %rdi
callq 0x141f1
movq %r14, 0x18(%rax)
movq 0x28(%rsp), %rdi
movq %rax, %rsi
callq 0x8916
movl $0x1, 0x28(%r14)
movq 0x10(%rbx), %rdi
movq 0x8(%r13), %rsi
callq 0x1427a
movq $0x0, 0x8(%r13)
movq %rbp, %rdi
movq %r14, %rsi
callq 0x7c74
cmpl $0x2, %eax
jge 0x6e6e
movq 0x28(%rsp), %rbp
movl 0x10(%rbp), %eax
movq 0x38(%rsp), %rdx
subl %edx, %eax
cmpl $0x1, %eax
movq 0x30(%rsp), %r13
jle 0x68e9
leal 0x1(%rdx), %eax
movq 0x40(%rsp), %rcx
addq $0x8, %rcx
cmpl %r15d, %edx
jne 0x6965
movq %rbx, 0x38(%rsp)
movq 0x10(%rbx), %rsi
movq 0x8(%rsp), %rdi
callq 0x7bec
movq 0x10(%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 0x6cc6
xorl %eax, %eax
movq 0x10(%rsp), %rcx
movq (%rcx), %rcx
movq %rcx, (%r14,%rax,8)
incq %rax
addq $0x8, %rcx
cmpq %rax, %rbx
jne 0x6cb3
movq 0x18(%rsp), %rax
movslq 0x10(%rax), %r13
leaq (,%r13,8), %rdi
callq 0x1190
movq %rax, %r15
testq %r13, %r13
jle 0x6cfe
xorl %eax, %eax
movq 0x18(%rsp), %rcx
movq (%rcx), %rcx
movq %rcx, (%r15,%rax,8)
incq %rax
addq $0x8, %rcx
cmpq %rax, %r13
jne 0x6ceb
leaq -0x1235(%rip), %rbp     # 0x5ad0
movl $0x8, %edx
movq %r15, %rdi
movq %r13, %rsi
movq %rbp, %rcx
callq 0x1080
movq 0x10(%rsp), %rax
movslq 0x10(%rax), %rsi
movl $0x8, %edx
movq %r14, 0x8(%rsp)
movq %r14, %rdi
movq %rbp, %rcx
callq 0x1080
movq 0x18(%rsp), %rax
cmpl $0x0, 0x10(%rax)
jle 0x6d94
xorl %r14d, %r14d
xorl %ebx, %ebx
leaq (%r15,%r14,8), %r13
movslq %ebx, %rbx
movq 0x8(%rsp), %rax
leaq (%rax,%rbx,8), %rbp
movq %r13, %rdi
movq %rbp, %rsi
callq 0x5ad0
incq %rbx
addq $0x8, %rbp
testl %eax, %eax
jg 0x6d56
addq $-0x8, %rbp
movq %r13, %rdi
movq %rbp, %rsi
callq 0x5ad0
testl %eax, %eax
jne 0x6e2e
incq %r14
movq 0x18(%rsp), %rax
movslq 0x10(%rax), %rax
cmpq %rax, %r14
jl 0x6d46
movq 0x38(%rsp), %rbx
movq %rbx, %rdi
movq 0x28(%rsp), %rsi
callq 0x149f4
movq %rbx, %rdi
movq 0x18(%rsp), %rsi
callq 0x149f4
movq %rbx, %rdi
movq 0x10(%rsp), %rsi
callq 0x149f4
movq 0x8(%rsp), %rdi
callq 0x1030
movq %r15, %rdi
callq 0x1030
movl (%r12), %eax
testl %eax, %eax
movq 0x30(%rsp), %r13
jle 0x6ea2
movq 0x10(%r12), %rcx
xorl %r15d, %r15d
xorl %r14d, %r14d
movq (%rcx,%r15,8), %rdx
cmpq $0x0, 0x8(%rdx)
je 0x6e1e
movq 0x10(%rbx), %rdi
movq %r14, %rsi
callq 0x1427a
movq 0x10(%r12), %rcx
movq (%rcx,%r15,8), %rax
movq 0x8(%rax), %r14
movq $0x0, 0x8(%rax)
movl (%r12), %eax
incq %r15
movslq %eax, %rdx
cmpq %rdx, %r15
jl 0x6dee
jmp 0x6ed3
movq 0x38(%rsp), %rbx
movq %rbx, %rdi
movq 0x28(%rsp), %rsi
callq 0x149f4
movq %rbx, %rdi
movq 0x18(%rsp), %rsi
callq 0x149f4
movq %rbx, %rdi
movq 0x10(%rsp), %rsi
callq 0x149f4
movq 0x8(%rsp), %rdi
callq 0x1030
movq %r15, %rdi
callq 0x1030
jmp 0x6e95
movq %rbx, %rdi
movq 0x28(%rsp), %rsi
callq 0x149f4
movq %rbx, %rdi
movq 0x18(%rsp), %rsi
callq 0x149f4
movq %rbx, %rdi
movq 0x10(%rsp), %rsi
callq 0x149f4
movq %rbx, %rdi
movq 0x30(%rsp), %rsi
jmp 0x6914
xorl %r14d, %r14d
jmp 0x6ed3
movq 0x10(%rax), %rcx
movq 0x8(%rcx), %rdx
movq %rdx, 0x8(%rax)
movq %rax, 0x8(%rcx)
movq 0x10(%rbx), %rsi
movq %rax, %rdi
callq 0x7c08
movq 0x10(%rax), %rcx
movq 0x8(%rcx), %rdx
movq %rdx, 0x8(%rax)
movq %rax, 0x8(%rcx)
movq %r13, %rdi
callq 0x88ee
testq %rax, %rax
jne 0x6ea7
movq 0x10(%r12), %rax
movq (%rax), %rax
movq 0x8(%rax), %r15
testq %r15, %r15
je 0x6f54
movq 0x8(%r15), %rax
movq 0x10(%r15), %rcx
movq %rax, 0x8(%rcx)
movq $0x0, 0x8(%r15)
movq 0x18(%r15), %rax
movq 0x8(%rax), %rsi
cmpq %rcx, 0x18(%rsi)
je 0x6f32
movq 0x10(%rbx), %rdi
movq 0x8(%rsi), %rsi
callq 0x14250
movq 0x18(%r15), %rax
movq 0x8(%rax), %rax
movq $0x0, 0x8(%rax)
jmp 0x6f43
movq 0x8(%rsi), %rcx
movq %rcx, 0x8(%rax)
movq 0x10(%rbx), %rdi
callq 0x14250
movq %r13, %rdi
movq %r15, %rsi
callq 0x8916
movq 0x18(%r15), %rax
jmp 0x6ee8
movq (%r13), %rcx
movq 0x8(%r13), %rax
movq 0x18(%rax), %rax
cmpq %rax, 0x10(%rcx)
je 0x6f96
cmpq 0x10(%r14), %rax
movq 0x20(%rsp), %r15
je 0x6fa9
movq 0x10(%rbx), %rsi
movq %r14, %rdi
callq 0x7c08
movq %r13, %rdi
movq %rax, %rsi
callq 0x8916
movq 0x10(%rbx), %rdi
movq %r14, %rsi
callq 0x14250
jmp 0x6fb4
movq 0x10(%rbx), %rdi
movq %r14, %rsi
callq 0x14250
movq 0x20(%rsp), %r15
jmp 0x6fb4
movq %r13, %rdi
movq %r14, %rsi
callq 0x8916
cmpl $0x1, 0x10(%r15)
jne 0x701f
movq (%r15), %rax
movq 0x10(%rax), %rdx
movq 0x8(%r13), %rcx
cmpq 0x10(%rcx), %rdx
jne 0x6ff8
movq 0x18(%rax), %rsi
cmpq 0x18(%rcx), %rsi
jne 0x6ff8
movq 0x10(%rbx), %r14
movq %r15, %rdi
callq 0x88ee
movq %r14, %rdi
movq %rax, %rsi
callq 0x14250
movq (%r15), %rax
movq 0x10(%rax), %rdx
movq 0x8(%r13), %rcx
cmpq 0x18(%rcx), %rdx
jne 0x701f
movq 0x18(%rax), %rax
cmpq 0x10(%rcx), %rax
jne 0x701f
movq 0x10(%rbx), %rbx
movq %r15, %rdi
callq 0x88ee
movq %rbx, %rdi
movq %rax, %rsi
callq 0x14250
movq %r15, 0x18(%r13)
jmp 0x6929