// File: /workspace/github_cpp_makefile_star2_O2/flastest[P]HeterogeneousParallelDijkstra/parallel_workloads.cc
// Function: get_min_graph_time_for_given_amount_of_threads(bool, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
time_type get_min_graph_time_for_given_amount_of_threads(bool TEST_DEBUG, int num_threads, int num_tests, std::string graph_name)
{
	time_type min_time = 2147483647;

	if (TEST_DEBUG) 
	{
		std::cout<<"loading graph from a graph"<<std::endl;
		std::cout << "num threads: " << num_threads<< " num tests: "<<num_tests<<std::endl; 
	}
	graph_t g = cit_graph_from_file(graph_name,true);
	
	//number of nodes in g
	int num_nodes = num_vertices(g);

	//get a source node...
	vertex_descriptor s = vertex(1, g);

	predecessor_map_t pred;


	//get the results from the BGL to compare against
	std::vector<vertex_descriptor> p_BGL(num_nodes);

	std::vector<int> BGL_results = testBGL ( g,  s, p_BGL);
		
	distance_map_t parallel_results;


	for (int i = 0 ; i < num_tests; i++)
	{
		if(TEST_DEBUG) std::cout << "test " << i << " of "<< num_tests << std::endl;
		auto startTime = chrono::high_resolution_clock::now();
		parallel_results = parallel_dijkstra(g, s, pred, num_threads);
		auto endTime = chrono::high_resolution_clock::now();

		float t = chrono::duration_cast<std::chrono::microseconds>( endTime - startTime ).count();

		for (int i = 0 ; i < num_nodes; i++)
		{
			// if(TEST_DEBUG)
			// {	
			// 	std::cout<<"test number "<<i<<std::endl;
			// 	std::cout<<"comparing " <<parallel_results[i] <<" and "<<BGL_results[i]<<std::endl;
			// }
			if(parallel_results[i] != BGL_results[i])
			{
				//std::cout<<"testing parallel_results: " << parallel_results[i] <<" and " <<"BGL_results: " <<BGL_results[i]<<std::endl;
				if(parallel_results[i] != INFINITY && (BGL_results[i] !=  2147483647 || BGL_results[i] !=  -2147483647))
				{	
					std::cout<<"ERROR: parallel dijkstra produced different result than BGL"<<std::endl;
					return -1;
				}
			}
			
			//not sure if I need to check predecessors because they might be different even with functioning code
		}

		min_time = t < min_time ? t : min_time; 
	}
	//if (TEST_DEBUG)std::cout<< "results are:"<<std::endl << print_dijkstra_results(g, parallel_results) <<std::endl;
	return min_time;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x178, %rsp            # imm = 0x178
movq %rcx, %r15
movl %edx, %ebp
movl %esi, 0xc(%rsp)
movl %edi, 0x14(%rsp)
testl %edi, %edi
je 0x8224
movq 0xedf7(%rip), %r14      # 0x16fc8
leaq 0x612e(%rip), %rsi      # 0xe306
movq %r14, %rdi
callq 0x4290
movq %rax, %rdi
callq 0x4150
leaq 0x615d(%rip), %rsi      # 0xe34c
movq %r14, %rdi
callq 0x4290
movq %rax, %rdi
movl 0xc(%rsp), %esi
callq 0x4460
leaq 0x6150(%rip), %rsi      # 0xe35a
movq %rax, %rdi
callq 0x4290
movq %rax, %rdi
movl %ebp, %esi
callq 0x4460
movq %rax, %rdi
callq 0x4150
leaq 0xc0(%rsp), %r14
movq %r14, %rdi
movq %r15, %rsi
callq 0x4330
leaq 0x58(%rsp), %rdi
pushq $0x1
popq %rdx
movq %r14, %rsi
callq 0xd6d0
leaq 0xc0(%rsp), %rdi
callq 0x4120
movq 0x78(%rsp), %rbx
subq 0x70(%rsp), %rbx
leaq 0xe8(%rsp), %rax
andl $0x0, (%rax)
andq $0x0, 0x8(%rax)
shrq $0x5, %rbx
movq $0x1, 0x20(%rsp)
movq %rax, 0x10(%rax)
movq %rax, 0x18(%rax)
andq $0x0, 0x20(%rax)
movslq %ebx, %rsi
leaq 0x40(%rsp), %rdi
leaq 0x90(%rsp), %rdx
callq 0x899c
leaq 0x110(%rsp), %rdi
leaq 0x58(%rsp), %rsi
callq 0x89ee
movq 0x20(%rsp), %rdx
leaq 0x28(%rsp), %rdi
leaq 0x110(%rsp), %rsi
leaq 0x40(%rsp), %rcx
callq 0x4a63
leaq 0x110(%rsp), %rdi
callq 0x8a32
leaq 0x98(%rsp), %rax
andl $0x0, (%rax)
andq $0x0, 0x8(%rax)
movq %rax, 0x10(%rax)
movq %rax, 0x18(%rax)
andq $0x0, 0x20(%rax)
xorl %r12d, %r12d
testl %ebx, %ebx
cmovlel %r12d, %ebx
testl %ebp, %ebp
movl $0x0, %r15d
movl %ebp, 0x10(%rsp)
cmovgl %ebp, %r15d
movl $0x7fffffff, %r14d      # imm = 0x7FFFFFFF
leaq 0x148(%rsp), %r13
leaq 0x90(%rsp), %rbp
cmpl %r15d, %r12d
je 0x8463
movl %r14d, 0x1c(%rsp)
cmpb $0x0, 0x14(%rsp)
je 0x837a
movq 0xec88(%rip), %rdi      # 0x16fc8
leaq 0x6020(%rip), %rsi      # 0xe367
callq 0x4290
movq %rax, %rdi
movl %r12d, %esi
callq 0x4460
movq %rax, %rdi
leaq 0x600c(%rip), %rsi      # 0xe36d
callq 0x4290
movq %rax, %rdi
movl 0x10(%rsp), %esi
callq 0x4460
movq %rax, %rdi
callq 0x4150
callq 0x4050
movq %rax, %r14
movq %r13, %rdi
leaq 0x58(%rsp), %rsi
leaq 0x20(%rsp), %rdx
leaq 0xe0(%rsp), %rcx
movl 0xc(%rsp), %r8d
callq 0xba1d
movq %rbp, %rdi
movq %r13, %rsi
callq 0x8f04
movq %r13, %rdi
callq 0x8ef0
callq 0x4050
subq %r14, %rax
cqto
movl $0x3e8, %ecx            # imm = 0x3E8
idivq %rcx
cvtsi2ss %rax, %xmm0
movss %xmm0, 0x18(%rsp)
xorl %r14d, %r14d
cmpq %r14, %rbx
je 0x8427
movq %r14, 0x148(%rsp)
movq %rbp, %rdi
movq %r13, %rsi
callq 0x88ac
movq 0x28(%rsp), %rcx
cvtsi2ssl (%rcx,%r14,4), %xmm0
movss (%rax), %xmm1
ucomiss %xmm0, %xmm1
jne 0x8402
jnp 0x8422
movq %r14, 0x148(%rsp)
movq %rbp, %rdi
movq %r13, %rsi
callq 0x88ac
movss (%rax), %xmm0
ucomiss 0x5d00(%rip), %xmm0     # 0xe120
jb 0x8444
incq %r14
jmp 0x83d4
cvtsi2ssl 0x1c(%rsp), %xmm0
movss 0x18(%rsp), %xmm1
minss %xmm0, %xmm1
cvttss2si %xmm1, %r14d
incl %r12d
jmp 0x8324
movq 0xeb7d(%rip), %rdi      # 0x16fc8
leaq 0x5f20(%rip), %rsi      # 0xe372
callq 0x4290
movq %rax, %rdi
callq 0x4150
pushq $-0x1
popq %r14
leaq 0x90(%rsp), %rdi
callq 0x8ef0
leaq 0x28(%rsp), %rdi
callq 0x930c
leaq 0x40(%rsp), %rdi
callq 0x9c58
leaq 0xe0(%rsp), %rdi
callq 0x8fb4
leaq 0x58(%rsp), %rdi
callq 0x8a32
movl %r14d, %eax
addq $0x178, %rsp            # imm = 0x178
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
leaq 0x110(%rsp), %rdi
callq 0x8a32
jmp 0x8500
movq %rax, %rbx
jmp 0x8500
movq %rax, %rbx
jmp 0x850a
movq %rax, %rbx
leaq 0xc0(%rsp), %rdi
callq 0x4120
jmp 0x8521
jmp 0x84e6
jmp 0x84e6
jmp 0x84e6
jmp 0x84e6
movq %rax, %rbx
leaq 0x90(%rsp), %rdi
callq 0x8ef0
leaq 0x28(%rsp), %rdi
callq 0x930c
leaq 0x40(%rsp), %rdi
callq 0x9c58
leaq 0xe0(%rsp), %rdi
callq 0x8fb4
leaq 0x58(%rsp), %rdi
callq 0x8a32
movq %rbx, %rdi
callq 0x4470