// File: prophyle[P]prophasm/src/prophasm.cpp
// Function: int find_intersection<std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>>(std::vector<std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>, std::allocator<std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>>> const&, std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>&)
int32_t find_intersection(const std::vector<_set_T> &sets, _set_T &intersection){
	assert(sets.size()>0);

	/*
		1) Find the smallest set from sets.
	*/

	int32_t min=std::numeric_limits<int32_t>::max();
	int32_t i_min=-1;

	//std::cerr << "searching min" << std::endl;

	for(int32_t i=0;i<static_cast<int32_t>(sets.size());i++){
		if (static_cast<int32_t>(sets[i].size())<min){
			min=sets[i].size();
			i_min=i;
			//std::cerr << "new min" << i << std::endl;
		}
	}

	assert(i_min != std::numeric_limits<int32_t>::max() && i_min!=-1);

	/*
		2) Take it as the intersection.
	*/

	//std::cerr << "2" << std::endl;

	intersection.clear();
	//std::cerr << "2.1" << std::endl;
	std::copy(
		sets[i_min].cbegin(), sets[i_min].cend(),
		std::inserter(intersection,intersection.end())
	);

	/*
		3) Remove elements from intersection present in other sets.
	*/

	for(const _set_T &current_set : sets) {

		for(auto it = intersection.begin(); it !=intersection.end();){

			if(current_set.find(*it) == current_set.cend()){
				it=intersection.erase(it);
			}
			else{
				++it;
			}
		}
	}

	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xd0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rdi
callq 0xa1e0
cmpq $0x0, %rax
jbe 0x5964
jmp 0x5983
leaq 0x6e5e(%rip), %rdi      # 0xc7c9
leaq 0x6d94(%rip), %rsi      # 0xc706
movl $0x172, %edx            # imm = 0x172
leaq 0x6e59(%rip), %rcx      # 0xc7d7
callq 0x3180
callq 0xa210
movl %eax, -0x14(%rbp)
movl $0xffffffff, -0x18(%rbp) # imm = 0xFFFFFFFF
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
movl %eax, -0xac(%rbp)
movq -0x8(%rbp), %rdi
callq 0xa1e0
movq %rax, %rcx
movl -0xac(%rbp), %eax
cmpl %ecx, %eax
jge 0x59fd
movq -0x8(%rbp), %rdi
movslq -0x1c(%rbp), %rsi
callq 0xa220
movq %rax, %rdi
callq 0x5900
cmpl -0x14(%rbp), %eax
jge 0x59f0
movq -0x8(%rbp), %rdi
movslq -0x1c(%rbp), %rsi
callq 0xa220
movq %rax, %rdi
callq 0x5900
movl %eax, -0x14(%rbp)
movl -0x1c(%rbp), %eax
movl %eax, -0x18(%rbp)
jmp 0x59f2
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x5999
movl -0x18(%rbp), %eax
movl %eax, -0xb4(%rbp)
callq 0xa210
movl -0xb4(%rbp), %ecx
movl %eax, %edx
xorl %eax, %eax
cmpl %edx, %ecx
movb %al, -0xad(%rbp)
je 0x5a2c
cmpl $-0x1, -0x18(%rbp)
setne %al
movb %al, -0xad(%rbp)
movb -0xad(%rbp), %al
testb $0x1, %al
jne 0x5a38
jmp 0x5a3a
jmp 0x5a59
leaq 0x6e04(%rip), %rdi      # 0xc845
leaq 0x6cbe(%rip), %rsi      # 0xc706
movl $0x185, %edx            # imm = 0x185
leaq 0x6d83(%rip), %rcx      # 0xc7d7
callq 0x3180
movq -0x10(%rbp), %rdi
callq 0x8500
movq -0x8(%rbp), %rdi
movslq -0x18(%rbp), %rsi
callq 0xa220
movq %rax, %rdi
callq 0xa2c0
movq %rax, -0x28(%rbp)
movq -0x8(%rbp), %rdi
movslq -0x18(%rbp), %rsi
callq 0xa220
movq %rax, %rdi
callq 0xa2f0
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xc0(%rbp)
movq -0x10(%rbp), %rdi
callq 0xa360
movq -0xc0(%rbp), %rdi
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rsi
callq 0xa320
movq %rax, -0x40(%rbp)
movq %rdx, -0x38(%rbp)
movq -0x28(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x40(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0xa240
movq %rax, -0x58(%rbp)
movq %rdx, -0x50(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rdi
callq 0xa390
movq %rax, -0x68(%rbp)
movq -0x60(%rbp), %rdi
callq 0xa3c0
movq %rax, -0x70(%rbp)
leaq -0x68(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0xa3f0
testb $0x1, %al
jne 0x5b19
jmp 0x5bfc
leaq -0x68(%rbp), %rdi
callq 0xa430
movq %rax, -0x78(%rbp)
movq -0x10(%rbp), %rdi
callq 0xa450
movq %rax, -0x80(%rbp)
movq -0x10(%rbp), %rdi
callq 0xa360
movq %rax, -0x88(%rbp)
leaq -0x80(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0xa480
testb $0x1, %al
jne 0x5b5c
jmp 0x5bec
movq -0x78(%rbp), %rax
movq %rax, -0xc8(%rbp)
leaq -0x80(%rbp), %rdi
callq 0xa510
movq -0xc8(%rbp), %rdi
movq %rax, %rsi
callq 0xa4e0
movq %rax, -0x90(%rbp)
movq -0x78(%rbp), %rdi
callq 0xa2f0
movq %rax, -0x98(%rbp)
leaq -0x90(%rbp), %rdi
leaq -0x98(%rbp), %rsi
callq 0xa4b0
testb $0x1, %al
jne 0x5baf
jmp 0x5bde
movq -0x10(%rbp), %rdi
movq -0x80(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq -0xa8(%rbp), %rsi
callq 0xa540
movq %rax, -0xa0(%rbp)
movq -0xa0(%rbp), %rax
movq %rax, -0x80(%rbp)
jmp 0x5be7
leaq -0x80(%rbp), %rdi
callq 0xa580
jmp 0x5b33
jmp 0x5bee
leaq -0x68(%rbp), %rdi
callq 0xa5b0
jmp 0x5b03
xorl %eax, %eax
addq $0xd0, %rsp
popq %rbp
retq
nopw (%rax,%rax)