// File: /workspace/github_c_makefile_star2_O3/pwelke[P]GraphMiningTools/listCycles.c
// Function: _backtrack
struct ShallowGraph* __backtrack(struct Graph* g, struct Vertex* v, struct Vertex* parent, struct Vertex* s, int allowance,
		struct ShallowGraph* currentPath, struct ShallowGraphPool* sgp) {
	int i,j;
	struct ShallowGraph *path = getShallowGraph(sgp);
	struct ShallowGraph *result = NULL;
	struct VertexList *neighbor, *idx;
	char flag = 0;


	/* while there exists a vertex $ w \in v->neighborhood $ with w > z
	 * s.t. there is a path from w to s which avoids the current path
	 */
	for (neighbor=v->neighborhood; neighbor; neighbor=neighbor->next) {

		/* this "removes" vertices that are too small from adjacency lists
		 * also, dont use the backwards edge to your parent */
		if ((neighbor->endPoint->number >= allowance) && (neighbor->endPoint != parent)) {

			/* " z < w " given some numbering of vertices. I take the one given by ->number.
			 * This only tries to find a path if the first condition holds. should be better,
			 * as the paths will be marked on vertex level. This seems to be not well elaborated
			 * right now..... shit
			 *
			 * z was a strange way to say: for each neighbor of v and even does harm, if incidence
			 * lists are not sorted by endPoint->number */
			if (findPath(neighbor->endPoint, v, s, allowance, path, sgp)) {
				struct Vertex* predecessorInPath = NULL;

				/* the current extension edge should be contained in the path */
				pushEdge(path, shallowCopyEdge(neighbor, sgp->listPool));

				i = 1;

				/* maybe this can be omitted as flag is not global any more*/
				flag = 0;

				/* mark all vertices on the current path as such, the others as others */
				/* TODO this could maybe be made faster by only traversing the vertices that are necessary with dfs */
				for (j=0; j<g->n; ++j) {
					if (g->vertices[j]) {
						g->vertices[j]->d = g->vertices[j]->visited;
					}
				}


				/* add vertices in path to the current path until a choice of ways to reach s is found */
				for (idx=path->edges; idx && (idx->endPoint != s) && !flag; idx=idx->next) {
					struct VertexList *innerVertexNeighbs;

					appendEdge(currentPath, shallowCopyEdge(idx, sgp->listPool));
					idx->endPoint->visited = idx->endPoint->d = 1;


					for (innerVertexNeighbs=idx->endPoint->neighborhood; innerVertexNeighbs; innerVertexNeighbs=innerVertexNeighbs->next) {
						if (innerVertexNeighbs->endPoint->number >= allowance) {
							/* if the endpoint of this edge is not the next vertex on path */
							if (innerVertexNeighbs->endPoint != idx->next->endPoint) {
								/* ...  or the parent */
								if (innerVertexNeighbs->endPoint->number != idx->startPoint->number) {
									/* ... and not visited yet, except if its s */
									if ((innerVertexNeighbs->endPoint->d == 0) || (innerVertexNeighbs->endPoint == s)) {

										/* search for a different way to s than the one given by path */
										flag = __DFS(innerVertexNeighbs->endPoint, idx->endPoint, s, allowance);

										if (flag) break;
									}
								}
							}
						} /* fi allowance */

						/* remember the predecessor on the current path so that recursive call to __backtrack
						 * knows, which edge not to use. */
						predecessorInPath = idx->startPoint;
					}
					++i;
				}


				/* this is where output is produced */
				if (!flag) {
					/* idx points to the edge closing the cycle, which is not yet included in the output */
					struct VertexList* closingEdge = shallowCopyEdge(idx, sgp->listPool);

					/* clone currentPath */
					struct ShallowGraph* clone = getShallowGraph(sgp);
					/* the output of this function is a cycle of shallow graphs, and addComponent
					 * expects its input, to be a cycle, too.
					 */
					clone->next = clone->prev = clone;

					for (idx=currentPath->edges; idx; idx=idx->next) {
						appendEdge(clone, shallowCopyEdge(idx, sgp->listPool));
					}

					appendEdge(clone, closingEdge);

					/* add it to the results list */
					result = addComponent(result, clone);

				} else {

					struct ShallowGraph* x = __backtrack(g, idx->startPoint, predecessorInPath, s, allowance, currentPath, sgp);
					result = addComponent(result, x);
				}


				if (currentPath->edges->startPoint == v) {
					/* if v is the first vertex in the path, dump the whole path */
					struct VertexList* tmp1 = currentPath->edges;
					struct VertexList* tmp2 = currentPath->edges;
					currentPath->edges = NULL;
					currentPath->lastEdge = NULL;
					while(tmp1) {
						tmp1 = tmp1->next;
						tmp2->endPoint->visited = 0;
						dumpVertexList(sgp->listPool, tmp2);
						tmp2=tmp1;
					}
				} else {
					/* go up to v in current path, then delete all following edges and set their visited values to 0.
					 * Also: set the pointer to the last element in path to v */
					for (idx=currentPath->edges; idx; idx=idx->next) {
						if (idx->endPoint == v) {
							struct VertexList* tmp1 = idx->next;
							struct VertexList* tmp2 = idx->next;
							idx->next = NULL;
							currentPath->lastEdge = idx;
							while(tmp1) {
								tmp1 = tmp1->next;
								tmp2->endPoint->visited = 0;
								dumpVertexList(sgp->listPool, tmp2);
								tmp2=tmp1;
							}
							break;
						}
					}
				}

				/* if we go to the next neighbor of v, we want to start a fresh path */
				dumpShallowGraph(sgp, path);
				path = getShallowGraph(sgp);
			}
		}
	}

	/* garbage collection */
	dumpShallowGraph(sgp, path);

	return result;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %r9, 0x10(%rsp)
movl %r8d, %ebp
movq %rcx, %r15
movq %rdx, %rbx
movq %rsi, %r14
movq %rdi, 0x20(%rsp)
movq 0x80(%rsp), %r13
movq %r13, %rdi
callq 0x1498d
movq %rax, %r12
movq 0x8(%r14), %rax
testq %rax, %rax
je 0xc154
movq $0x0, 0x18(%rsp)
movq %rbx, 0x30(%rsp)
movq %r14, 0x38(%rsp)
movq 0x18(%rax), %r14
cmpq %rbx, %r14
je 0xc145
cmpl %ebp, 0x18(%r14)
jl 0xc145
movq %rax, 0x28(%rsp)
movq %r14, %rdi
movq 0x38(%rsp), %rsi
movq %r15, %rdx
movl %ebp, %ecx
movq %r12, %r8
movq %r13, %r9
callq 0xbca3
movq %r13, %rbx
movl %eax, %r13d
movq %r14, %rdi
callq 0xbd60
testb %r13b, %r13b
je 0xbfd6
movq 0x10(%rbx), %rsi
movq 0x28(%rsp), %rdi
callq 0x7bec
movq %r12, 0x40(%rsp)
movq %r12, %rdi
movq %rax, %rsi
callq 0x848a
movq 0x20(%rsp), %rax
movslq (%rax), %rax
testq %rax, %rax
movl $0x1, %r12d
jle 0xbf1e
movq 0x20(%rsp), %rcx
movq 0x10(%rcx), %rcx
xorl %edx, %edx
movq (%rcx,%rdx,8), %rsi
testq %rsi, %rsi
je 0xbf16
movl 0x1c(%rsi), %edi
movl %edi, 0x28(%rsi)
incq %rdx
cmpq %rdx, %rax
jne 0xbf07
movq 0x40(%rsp), %rax
movq (%rax), %r14
testq %r14, %r14
je 0xbfde
xorl %r13d, %r13d
xorl %eax, %eax
cmpq %r15, 0x18(%r14)
je 0xbfe6
testb %al, %al
jne 0xbfe6
movq 0x80(%rsp), %rax
movq 0x10(%rax), %rsi
movq %r14, %rdi
callq 0x7bec
movq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x8916
movq 0x18(%r14), %rax
movl %r12d, 0x28(%rax)
movl %r12d, 0x1c(%rax)
movq 0x8(%rax), %rbx
testq %rbx, %rbx
je 0xbfc1
movq 0x18(%rbx), %rdi
movl 0x18(%rdi), %eax
cmpl %ebp, %eax
jl 0xbfb7
movq 0x8(%r14), %rcx
cmpq 0x18(%rcx), %rdi
je 0xbfb7
movq 0x10(%r14), %rcx
cmpl 0x18(%rcx), %eax
je 0xbfb7
cmpq %r15, %rdi
je 0xbfa5
cmpl $0x0, 0x28(%rdi)
jne 0xbfb7
movq 0x18(%r14), %rsi
movq %r15, %rdx
movl %ebp, %ecx
callq 0xbda6
testb %al, %al
jne 0xbfd2
movq 0x10(%r14), %r13
movq 0x8(%rbx), %rbx
jmp 0xbf77
xorl %eax, %eax
movq 0x8(%r14), %r14
testq %r14, %r14
jne 0xbf34
jmp 0xbfe3
movb $0x1, %al
jmp 0xbfc3
movq %rbx, %r13
jmp 0xc13b
xorl %r14d, %r14d
jmp 0xc022
xorl %r14d, %r14d
testb %al, %al
je 0xc01a
movq 0x10(%r14), %rsi
movq 0x80(%rsp), %rax
movq %rax, (%rsp)
movq 0x20(%rsp), %rdi
movq %r13, %rdx
movq %r15, %rcx
movl %ebp, %r8d
movq 0x10(%rsp), %rbx
movq %rbx, %r9
callq 0xbe29
movq %rax, %r14
jmp 0xc07e
movq 0x80(%rsp), %rbx
movq 0x10(%rbx), %rsi
movq %r14, %rdi
callq 0x7bec
movq %rax, %r12
movq %rbx, %rdi
callq 0x1498d
movq %rax, %r14
movq %rax, 0x20(%rax)
movq %rax, 0x18(%rax)
movq 0x10(%rsp), %rax
movq (%rax), %r13
testq %r13, %r13
je 0xc06e
movq 0x10(%rbx), %rsi
movq %r13, %rdi
callq 0x7bec
movq %r14, %rdi
movq %rax, %rsi
callq 0x8916
movq 0x8(%r13), %r13
jmp 0xc04c
movq %r14, %rdi
movq %r12, %rsi
callq 0x8916
movq 0x10(%rsp), %rbx
movq 0x18(%rsp), %rdi
movq %r14, %rsi
callq 0x883e
movq %rax, 0x18(%rsp)
movq (%rbx), %rsi
movq 0x38(%rsp), %r14
cmpq %r14, 0x10(%rsi)
je 0xc0ba
movq 0x80(%rsp), %r13
movq 0x8(%rsi), %rax
cmpq %r14, 0x18(%rsi)
je 0xc0ea
movq %rax, %rsi
testq %rax, %rax
jne 0xc0a6
jmp 0xc123
xorps %xmm0, %xmm0
movups %xmm0, (%rbx)
movq 0x80(%rsp), %r13
movq 0x8(%rsi), %rbx
movq 0x18(%rsi), %rax
movl $0x0, 0x1c(%rax)
movq 0x10(%r13), %rdi
callq 0x14250
movq %rbx, %rsi
testq %rbx, %rbx
jne 0xc0c8
jmp 0xc123
movq $0x0, 0x8(%rsi)
movq 0x10(%rsp), %rcx
movq %rsi, 0x8(%rcx)
testq %rax, %rax
je 0xc123
movq 0x8(%rax), %rbx
movq 0x18(%rax), %rcx
movl $0x0, 0x1c(%rcx)
movq 0x10(%r13), %rdi
movq %rax, %rsi
callq 0x14250
movq %rbx, %rax
testq %rbx, %rbx
jne 0xc100
movq %r13, %rdi
movq 0x40(%rsp), %rsi
callq 0x149f4
movq %r13, %rdi
callq 0x1498d
movq %rax, %r12
movq 0x30(%rsp), %rbx
movq 0x28(%rsp), %rax
movq 0x8(%rax), %rax
testq %rax, %rax
jne 0xbe80
jmp 0xc15d
movq $0x0, 0x18(%rsp)
movq %r13, %rdi
movq %r12, %rsi
callq 0x149f4
movq 0x18(%rsp), %rax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq