// File: EnderGed[P]fast-random-walk/walk.cpp
// Function: main
int main(int const argc, char const * const argv[])
{
	uint64_t flags = 0;
	bool weighted = false;
	bool print = false;
	char const * input = 0;
	char const * output = 0;
	uint32_t walkLen = 0;
	uint32_t numWalks = 0;

	// Parse command line arguments
	for(int argi = 1; argi < argc; ++argi)
	{
		char const * arg = argv[argi];
		size_t len = strlen(arg);

		if(*arg == '-')
		{
			// Valid option
			++arg;
			--len;

			if(*arg == '-')
			{
				// Long option
				++arg;
				--len;

				char const * param = 0;
				int const remc = argc - argi;
				char const * const * const remv = argv + argi;

				if(!strcmp(arg, "optiTransOrder")) flags |= Graph::flag_optiTransOrder;
				else if(!strcmp(arg, "undirected")) flags |=  Graph::flag_undirected;
				else if(!strcmp(arg, "reflect")) flags |= Graph::flag_reflect;
				else if(!strcmp(arg, "weighted")) weighted = true;
				else if(!strcmp(arg, "print")) print = true;
				else if((param = readParam(remc, remv, "if"))) input = param;
				else if((param = readParam(remc, remv, "of"))) output = param;
				else if((param = readParam(remc, remv, "length"))) walkLen = toInt(param);
				else if((param = readParam(remc, remv, "walks"))) numWalks = toInt(param);
				else if(!strcmp(arg, "help"))
				{
					printHelp();
					exit(0);
				}
				else
				{
					printf("Unknown option --%s\n", arg);
					printHelp();
					exit(1);
				}
			}
			else
			{
				// Short option
				for(size_t i = 0; i < len; ++i)
				{
					switch(arg[i])
					{
						case 'o':
							flags |= Graph::flag_optiTransOrder;
							break;
						case 'p':
							print = true;
							break;
						case 'r':
							flags |= Graph::flag_reflect;
							break;
						case 'u':
							flags |= Graph::flag_undirected;
							break;
						case 'w':
							weighted = true;
							break;
						case 'h':
							printHelp();
							exit(0);
							break;
						default:
							printf("Unknown short option -%c\n", arg[i]);
							printHelp();
							exit(1);
					}
				}
			}
		}
		else
		{
			printf("Invalid option %s\n", arg);
			printHelp();
			exit(1);
		}
	}

	// Check whether all mandatory arguments are set
	if(!input) printHelp("No input file specified");
	else if(!output) printHelp("No output file specified");
	else if(!walkLen) printHelp("No walk length specified");
	else if(!numWalks) printHelp("Number of walks unspecified");

	//const uint64_t flags = Graph::flag_optiTransOrder | Graph::flag_undirected;
	std::string const fileContent(readFile(input));
	std::unique_ptr<Graph> graph(weighted ? new WeightedGraph(WeightedGraph::readGraph(fileContent, flags)) : new Graph(Graph::readGraph(fileContent, flags)));
	uint const to = graph->getNumNodes();

	if(print) printf("%s", graph->toString().c_str());

	Out out(output);
	doWalk(*graph, 0, to, walkLen, numWalks, out);

	return 0;
}

// Assembly:
subq $0x198, %rsp            # imm = 0x198
movl $0x0, 0x194(%rsp)
movl %edi, 0x190(%rsp)
movq %rsi, 0x188(%rsp)
movq $0x0, 0x180(%rsp)
movb $0x0, 0x17f(%rsp)
movb $0x0, 0x17e(%rsp)
movq $0x0, 0x170(%rsp)
movq $0x0, 0x168(%rsp)
movl $0x0, 0x164(%rsp)
movl $0x0, 0x160(%rsp)
movl $0x1, 0x15c(%rsp)
movl 0x15c(%rsp), %eax
cmpl 0x190(%rsp), %eax
jge 0xa2ba
movq 0x188(%rsp), %rax
movslq 0x15c(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x150(%rsp)
movq 0x150(%rsp), %rdi
callq 0x20c0
movq %rax, 0x148(%rsp)
movq 0x150(%rsp), %rax
movsbl (%rax), %eax
cmpl $0x2d, %eax
jne 0xa27d
movq 0x150(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x150(%rsp)
movq 0x148(%rsp), %rax
addq $-0x1, %rax
movq %rax, 0x148(%rsp)
movq 0x150(%rsp), %rax
movsbl (%rax), %eax
cmpl $0x2d, %eax
jne 0xa171
movq 0x150(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x150(%rsp)
movq 0x148(%rsp), %rax
addq $-0x1, %rax
movq %rax, 0x148(%rsp)
movq $0x0, 0x140(%rsp)
movl 0x190(%rsp), %eax
subl 0x15c(%rsp), %eax
movl %eax, 0x13c(%rsp)
movq 0x188(%rsp), %rax
movslq 0x15c(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x130(%rsp)
movq 0x150(%rsp), %rdi
leaq 0x2342(%rip), %rsi      # 0xc284
callq 0x2260
cmpl $0x0, %eax
jne 0x9f65
movq 0x180(%rsp), %rax
orq $0x2, %rax
movq %rax, 0x180(%rsp)
jmp 0xa16c
movq 0x150(%rsp), %rdi
leaq 0x231f(%rip), %rsi      # 0xc293
callq 0x2260
cmpl $0x0, %eax
jne 0x9f97
movq 0x180(%rsp), %rax
orq $0x1, %rax
movq %rax, 0x180(%rsp)
jmp 0xa16a
movq 0x150(%rsp), %rdi
leaq 0x22f8(%rip), %rsi      # 0xc29e
callq 0x2260
cmpl $0x0, %eax
jne 0x9fc9
movq 0x180(%rsp), %rax
orq $0x8, %rax
movq %rax, 0x180(%rsp)
jmp 0xa168
movq 0x150(%rsp), %rdi
leaq 0x22ce(%rip), %rsi      # 0xc2a6
callq 0x2260
cmpl $0x0, %eax
jne 0x9fef
movb $0x1, 0x17f(%rsp)
jmp 0xa166
movq 0x150(%rsp), %rdi
leaq 0x22b1(%rip), %rsi      # 0xc2af
callq 0x2260
cmpl $0x0, %eax
jne 0xa015
movb $0x1, 0x17e(%rsp)
jmp 0xa164
movl 0x13c(%rsp), %edi
movq 0x130(%rsp), %rsi
leaq 0x228a(%rip), %rdx      # 0xc2b5
callq 0xa700
movq %rax, 0x140(%rsp)
cmpq $0x0, %rax
je 0xa053
movq 0x140(%rsp), %rax
movq %rax, 0x170(%rsp)
jmp 0xa162
movl 0x13c(%rsp), %edi
movq 0x130(%rsp), %rsi
leaq 0x224f(%rip), %rdx      # 0xc2b8
callq 0xa700
movq %rax, 0x140(%rsp)
cmpq $0x0, %rax
je 0xa091
movq 0x140(%rsp), %rax
movq %rax, 0x168(%rsp)
jmp 0xa160
movl 0x13c(%rsp), %edi
movq 0x130(%rsp), %rsi
leaq 0x2214(%rip), %rdx      # 0xc2bb
callq 0xa700
movq %rax, 0x140(%rsp)
cmpq $0x0, %rax
je 0xa0d3
movq 0x140(%rsp), %rdi
callq 0x65e0
movl %eax, 0x164(%rsp)
jmp 0xa15e
movl 0x13c(%rsp), %edi
movq 0x130(%rsp), %rsi
leaq 0x21d9(%rip), %rdx      # 0xc2c2
callq 0xa700
movq %rax, 0x140(%rsp)
cmpq $0x0, %rax
je 0xa112
movq 0x140(%rsp), %rdi
callq 0x65e0
movl %eax, 0x160(%rsp)
jmp 0xa15c
movq 0x150(%rsp), %rdi
leaq 0x21a7(%rip), %rsi      # 0xc2c8
callq 0x2260
cmpl $0x0, %eax
jne 0xa137
callq 0xa7e0
xorl %edi, %edi
callq 0x2230
movq 0x150(%rsp), %rsi
leaq 0x2187(%rip), %rdi      # 0xc2cd
movb $0x0, %al
callq 0x2040
callq 0xa7e0
movl $0x1, %edi
callq 0x2230
jmp 0xa15e
jmp 0xa160
jmp 0xa162
jmp 0xa164
jmp 0xa166
jmp 0xa168
jmp 0xa16a
jmp 0xa16c
jmp 0xa27b
movq $0x0, 0x128(%rsp)
movq 0x128(%rsp), %rax
cmpq 0x148(%rsp), %rax
jae 0xa279
movq 0x150(%rsp), %rax
movq 0x128(%rsp), %rcx
movsbl (%rax,%rcx), %eax
addl $-0x68, %eax
movl %eax, %ecx
movq %rcx, 0x28(%rsp)
subl $0xf, %eax
ja 0xa22d
movq 0x28(%rsp), %rax
leaq 0x2082(%rip), %rcx      # 0xc244
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x180(%rsp), %rax
orq $0x2, %rax
movq %rax, 0x180(%rsp)
jmp 0xa25e
movb $0x1, 0x17e(%rsp)
jmp 0xa25e
movq 0x180(%rsp), %rax
orq $0x8, %rax
movq %rax, 0x180(%rsp)
jmp 0xa25e
movq 0x180(%rsp), %rax
orq $0x1, %rax
movq %rax, 0x180(%rsp)
jmp 0xa25e
movb $0x1, 0x17f(%rsp)
jmp 0xa25e
callq 0xa7e0
xorl %edi, %edi
callq 0x2230
movq 0x150(%rsp), %rax
movq 0x128(%rsp), %rcx
movsbl (%rax,%rcx), %esi
leaq 0x209a(%rip), %rdi      # 0xc2e2
movb $0x0, %al
callq 0x2040
callq 0xa7e0
movl $0x1, %edi
callq 0x2230
jmp 0xa260
movq 0x128(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x128(%rsp)
jmp 0xa17d
jmp 0xa27b
jmp 0xa2a2
movq 0x150(%rsp), %rsi
leaq 0x2070(%rip), %rdi      # 0xc2fc
movb $0x0, %al
callq 0x2040
callq 0xa7e0
movl $0x1, %edi
callq 0x2230
jmp 0xa2a4
movl 0x15c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x15c(%rsp)
jmp 0x9e36
cmpq $0x0, 0x170(%rsp)
jne 0xa2d3
leaq 0x2043(%rip), %rdi      # 0xc30f
callq 0xa8b0
jmp 0xa320
cmpq $0x0, 0x168(%rsp)
jne 0xa2ec
leaq 0x2042(%rip), %rdi      # 0xc327
callq 0xa8b0
jmp 0xa31e
cmpl $0x0, 0x164(%rsp)
jne 0xa304
leaq 0x2043(%rip), %rdi      # 0xc340
callq 0xa8b0
jmp 0xa31c
cmpl $0x0, 0x160(%rsp)
jne 0xa31a
leaq 0x2044(%rip), %rdi      # 0xc359
callq 0xa8b0
jmp 0xa31c
jmp 0xa31e
jmp 0xa320
movq 0x170(%rsp), %rsi
leaq 0x108(%rsp), %rdi
callq 0x63b0
movb 0x17f(%rsp), %al
movb $0x0, 0xe7(%rsp)
movb $0x0, 0xbf(%rsp)
movb $0x0, 0xaf(%rsp)
movb $0x0, 0x87(%rsp)
testb $0x1, %al
je 0xa3d5
movl $0x28, %edi
callq 0x21b0
movq %rax, 0x20(%rsp)
jmp 0xa371
movq 0x20(%rsp), %rax
movq %rax, 0xe8(%rsp)
movb $0x1, 0xe7(%rsp)
leaq 0xc0(%rsp), %rdi
leaq 0x108(%rsp), %rsi
callq 0x20b0
jmp 0xa39d
movq 0x20(%rsp), %rdi
movb $0x1, 0xbf(%rsp)
movq 0x180(%rsp), %rdx
leaq 0xc0(%rsp), %rsi
callq 0x7950
jmp 0xa3c1
movq 0x20(%rsp), %rax
movb $0x0, 0xe7(%rsp)
movq %rax, 0x18(%rsp)
jmp 0xa448
movl $0x20, %edi
callq 0x21b0
movq %rax, 0x10(%rsp)
jmp 0xa3e6
movq 0x10(%rsp), %rax
movq %rax, 0xb0(%rsp)
movb $0x1, 0xaf(%rsp)
leaq 0x88(%rsp), %rdi
leaq 0x108(%rsp), %rsi
callq 0x20b0
jmp 0xa412
movq 0x10(%rsp), %rdi
movb $0x1, 0x87(%rsp)
movq 0x180(%rsp), %rdx
leaq 0x88(%rsp), %rsi
callq 0x2a10
jmp 0xa436
movq 0x10(%rsp), %rax
movb $0x0, 0xaf(%rsp)
movq %rax, 0x18(%rsp)
movq 0x18(%rsp), %rsi
leaq 0x100(%rsp), %rdi
callq 0xaad0
testb $0x1, 0x87(%rsp)
jne 0xa466
jmp 0xa473
leaq 0x88(%rsp), %rdi
callq 0x2110
testb $0x1, 0xbf(%rsp)
jne 0xa47f
jmp 0xa48c
leaq 0xc0(%rsp), %rdi
callq 0x2110
leaq 0x100(%rsp), %rdi
callq 0xab00
movq %rax, %rdi
callq 0x3a10
movl %eax, 0xc(%rsp)
jmp 0xa4a7
movl 0xc(%rsp), %eax
movl %eax, 0x80(%rsp)
testb $0x1, 0x17e(%rsp)
je 0xa629
leaq 0x100(%rsp), %rdi
callq 0xab00
movq %rax, %rsi
movq (%rsi), %rax
movq 0x20(%rax), %rax
leaq 0x60(%rsp), %rdi
callq *%rax
jmp 0xa4e0
leaq 0x60(%rsp), %rdi
callq 0x20a0
movq %rax, %rsi
leaq 0x1b35(%rip), %rdi      # 0xc029
xorl %eax, %eax
callq 0x2040
jmp 0xa4fd
leaq 0x60(%rsp), %rdi
callq 0x2110
jmp 0xa629
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xf8(%rsp)
movl %eax, 0xf4(%rsp)
jmp 0xa6e1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xf8(%rsp)
movl %eax, 0xf4(%rsp)
jmp 0xa5cf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xf8(%rsp)
movl %eax, 0xf4(%rsp)
jmp 0xa5b4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xf8(%rsp)
movl %eax, 0xf4(%rsp)
jmp 0xa599
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xf8(%rsp)
movl %eax, 0xf4(%rsp)
testb $0x1, 0x87(%rsp)
jne 0xa58a
jmp 0xa597
leaq 0x88(%rsp), %rdi
callq 0x2110
jmp 0xa599
testb $0x1, 0xaf(%rsp)
jne 0xa5a5
jmp 0xa5b2
movq 0xb0(%rsp), %rdi
callq 0x2190
jmp 0xa5b4
testb $0x1, 0xbf(%rsp)
jne 0xa5c0
jmp 0xa5cd
leaq 0xc0(%rsp), %rdi
callq 0x2110
jmp 0xa5cf
testb $0x1, 0xe7(%rsp)
jne 0xa5db
jmp 0xa5e8
movq 0xe8(%rsp), %rdi
callq 0x2190
jmp 0xa6e1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xf8(%rsp)
movl %eax, 0xf4(%rsp)
jmp 0xa6d4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xf8(%rsp)
movl %eax, 0xf4(%rsp)
leaq 0x60(%rsp), %rdi
callq 0x2110
jmp 0xa6d4
movq 0x168(%rsp), %rsi
leaq 0x30(%rsp), %rdi
callq 0xab10
jmp 0xa63d
leaq 0x100(%rsp), %rdi
callq 0xab50
movq %rax, (%rsp)
jmp 0xa650
movq (%rsp), %rdi
movl 0x80(%rsp), %edx
movl 0x164(%rsp), %ecx
movl 0x160(%rsp), %r8d
xorl %esi, %esi
leaq 0x30(%rsp), %r9
callq 0xa8e0
jmp 0xa678
movl $0x0, 0x194(%rsp)
leaq 0x30(%rsp), %rdi
callq 0xab80
leaq 0x100(%rsp), %rdi
callq 0xabc0
leaq 0x108(%rsp), %rdi
callq 0x2110
movl 0x194(%rsp), %eax
addq $0x198, %rsp            # imm = 0x198
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xf8(%rsp)
movl %eax, 0xf4(%rsp)
leaq 0x30(%rsp), %rdi
callq 0xab80
leaq 0x100(%rsp), %rdi
callq 0xabc0
leaq 0x108(%rsp), %rdi
callq 0x2110
movq 0xf8(%rsp), %rdi
callq 0x22d0
nopl (%rax,%rax)