// File: /workspace/github_cpp_makefile_star2_O3/salda[P]convex_hull_of_intersections/Ouellet_hull.cpp
// Function: Ouellet_hull::compute_convex_hull(std::vector<std::pair<double, double>, std::allocator<std::pair<double, double>>>)
void Ouellet_hull::compute_convex_hull(vector<pair<double, double>> points) {
	if (points.empty())
		return;

	array<pair<pair<double, double>, pair<double, double>>, 4> initialization_extremes_for_quadrants;
	for (auto& initialization_pair : initialization_extremes_for_quadrants)
		initialization_pair.first = initialization_pair.second = points.front();
	
	for (auto& point : points) {
	    int previous_quadrant = 3;
		for (int quadrant = 0; quadrant != 4; ++quadrant) {
			if (((quadrant == 0 || quadrant == 2) && point.first == initialization_extremes_for_quadrants[previous_quadrant].second.first)
			 || ((quadrant == 1 || quadrant == 3) && point.second == initialization_extremes_for_quadrants[previous_quadrant].second.second)) {
				if ((quadrant == 0 && point.second < initialization_extremes_for_quadrants[previous_quadrant].second.second)
				 || (quadrant == 1 && point.first > initialization_extremes_for_quadrants[previous_quadrant].second.first)
				 || (quadrant == 2 && point.second > initialization_extremes_for_quadrants[previous_quadrant].second.second)
				 || (quadrant == 3 && point.first < initialization_extremes_for_quadrants[previous_quadrant].second.first))
					initialization_extremes_for_quadrants[previous_quadrant].second = point;
				else if ((quadrant == 0 && point.second > initialization_extremes_for_quadrants[previous_quadrant].first.second)
					  || (quadrant == 1 && point.first < initialization_extremes_for_quadrants[previous_quadrant].first.first)
					  || (quadrant == 2 && point.second < initialization_extremes_for_quadrants[previous_quadrant].first.second)
					  || (quadrant == 3 && point.first > initialization_extremes_for_quadrants[previous_quadrant].first.first))
					initialization_extremes_for_quadrants[quadrant].first = point;
			}
			else if ((quadrant == 0 && point.first > initialization_extremes_for_quadrants[previous_quadrant].second.first)
				  || (quadrant == 1 && point.second > initialization_extremes_for_quadrants[previous_quadrant].second.second)
				  || (quadrant == 2 && point.first < initialization_extremes_for_quadrants[previous_quadrant].second.first)
				  || (quadrant == 3 && point.second < initialization_extremes_for_quadrants[previous_quadrant].second.second)) {
				initialization_extremes_for_quadrants[previous_quadrant].second = point;
				initialization_extremes_for_quadrants[quadrant].first = point;
			}
        	previous_quadrant = quadrant;
		}
	}

	for (int quadrant = 0; quadrant != 4; ++quadrant) { // init quadrants
		quadrants[quadrant].push_back(initialization_extremes_for_quadrants[quadrant].first);
		if (initialization_extremes_for_quadrants[quadrant].first != initialization_extremes_for_quadrants[quadrant].second)
			quadrants[quadrant].push_back(initialization_extremes_for_quadrants[quadrant].second);
	}
	
	int index, indexLow, indexHi, quadrant;
	for (auto& point : points) { // filter non convex hull points
		if (point.first > initialization_extremes_for_quadrants[0].second.first && point.second > initialization_extremes_for_quadrants[0].first.second)
			quadrant = 0;
		else if (point.first < initialization_extremes_for_quadrants[1].first.first && point.second > initialization_extremes_for_quadrants[1].second.second)
			quadrant = 1;
		else if (point.first < initialization_extremes_for_quadrants[2].second.first && point.second < initialization_extremes_for_quadrants[2].first.second)
			quadrant = 2;
		else if (point.first > initialization_extremes_for_quadrants[3].first.first && point.second < initialization_extremes_for_quadrants[3].second.second)
			quadrant = 3;
		else
			continue;

		indexLow = 0;
		indexHi = quadrants[quadrant].size();

		bool breaker = false;
		while (indexLow < indexHi - 1) {
			index = ((indexHi - indexLow) >> 1) + indexLow;

			if ((quadrant == 0 && point.first <= quadrants[0][index].first && point.second <= quadrants[0][index].second)
			 || (quadrant == 1 && point.first >= quadrants[1][index].first && point.second <= quadrants[1][index].second)
			 || (quadrant == 2 && point.first >= quadrants[2][index].first && point.second >= quadrants[2][index].second)
			 || (quadrant == 3 && point.first <= quadrants[3][index].first && point.second >= quadrants[3][index].second))
				breaker = true; // no computation needed

			if ((quadrant < 2 && point.first > quadrants[quadrant][index].first) || point.first < quadrants[quadrant][index].first) { // TODO check "< 2" condition
				indexHi = index;
				continue;
			}

			if ((quadrant < 2 && point.first < quadrants[quadrant][index].first) || point.first > quadrants[quadrant][index].first) { // TODO check "< 2" condition
				indexLow = index;
				continue;
			}

			indexLow = index - 1;
			indexHi = index + 1;
			break;
		}
		if (breaker || !is_right_turn(quadrants[quadrant][indexLow], quadrants[quadrant][indexHi], point))
			continue;

		// here indexLow should contain the index where the point should be inserted if calculation does not invalidate it

		// find lower bound (remove point invalidated by the new one that comes before)
		while (indexLow > 0) {
			if (is_right_turn(quadrants[quadrant][indexLow - 1], point, quadrants[quadrant][indexLow]))
				break; // found the lower index limit of points to keep, new point should be added right after indexLow
			--indexLow;
		}

		// find upper bound (remove point invalidated by the new one that comes after)
		int maxIndexHi = quadrants[quadrant].size() - 1;
		while (indexHi < maxIndexHi) {
			if (is_right_turn(point, quadrants[quadrant][indexHi + 1], quadrants[quadrant][indexHi]))
				break; // found the higher index limit of points to keep, new point should be added right before indexHi
			++indexHi;
		}

		if (indexLow + 1 == indexHi)
			quadrants[quadrant].insert(quadrants[quadrant].begin() + indexHi, point);
		else {
			quadrants[quadrant][indexLow + 1] = point;
			if (indexLow + 2 != indexHi)
				quadrants[quadrant].erase(quadrants[quadrant].begin() + indexLow + 2, quadrants[quadrant].begin() + indexHi -1);
		}
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xc8, %rsp
movq %rdi, 0x28(%rsp)
movq (%rsi), %rax
movq 0x8(%rsi), %rcx
cmpq %rcx, %rax
je 0x4131
movq %rsi, %r15
xorps %xmm0, %xmm0
movaps %xmm0, 0xa0(%rsp)
movaps %xmm0, 0x90(%rsp)
movaps %xmm0, 0x80(%rsp)
movaps %xmm0, 0x70(%rsp)
movaps %xmm0, 0x60(%rsp)
movaps %xmm0, 0x50(%rsp)
movaps %xmm0, 0x40(%rsp)
movaps %xmm0, 0x30(%rsp)
movupd (%rax), %xmm0
movl $0x10, %edx
movupd %xmm0, 0x30(%rsp,%rdx)
movupd %xmm0, 0x20(%rsp,%rdx)
addq $0x20, %rdx
cmpq $0x90, %rdx
jne 0x3a1a
movl $0x3, %edi
xorl %edx, %edx
xorl %esi, %esi
movl %edi, %r8d
movl %esi, %edi
testl $0xfffffffd, %esi       # imm = 0xFFFFFFFD
jne 0x3a7e
movsd (%rax), %xmm0
movl %r8d, %r9d
movq %r9, %r10
shlq $0x5, %r10
ucomisd 0x40(%rsp,%r10), %xmm0
jne 0x3a7e
jp 0x3a7e
testq %rdx, %rdx
jne 0x3aa2
movsd 0x48(%rsp,%r10), %xmm1
ucomisd 0x8(%rax), %xmm1
ja 0x3b84
jmp 0x3c17
movl %edi, %r9d
orl $0x2, %r9d
cmpl $0x3, %r9d
jne 0x3b05
movsd 0x8(%rax), %xmm0
movl %r8d, %r9d
shlq $0x5, %r9
ucomisd 0x48(%rsp,%r9), %xmm0
jne 0x3b0e
jp 0x3b0e
cmpq $0x20, %rdx
jne 0x3add
movsd (%rax), %xmm0
movl %r8d, %r9d
movq %r9, %r8
shlq $0x5, %r8
ucomisd 0x40(%rsp,%r8), %xmm0
ja 0x3b84
shlq $0x5, %r9
movsd 0x30(%rsp,%r9), %xmm0
ucomisd (%rax), %xmm0
ja 0x3c37
jmp 0x3c5a
cmpq $0x40, %rdx
jne 0x3b5b
movsd 0x8(%rax), %xmm0
movl %r8d, %r9d
movq %r9, %r8
shlq $0x5, %r8
ucomisd 0x48(%rsp,%r8), %xmm0
jbe 0x3bfe
movsd (%rax), %xmm0
jmp 0x3b84
testq %rdx, %rdx
je 0x3b9a
cmpq $0x20, %rdx
jne 0x3b35
movsd 0x8(%rax), %xmm0
movl %r8d, %r8d
movq %r8, %r9
shlq $0x5, %r9
ucomisd 0x48(%rsp,%r9), %xmm0
ja 0x3bdc
jmp 0x3c5a
cmpq $0x40, %rdx
jne 0x3bb6
movl %r8d, %r8d
movq %r8, %r9
shlq $0x5, %r9
movsd 0x40(%rsp,%r9), %xmm0
ucomisd (%rax), %xmm0
ja 0x3bdc
jmp 0x3c5a
cmpq $0x60, %rdx
jne 0x3c12
movsd (%rax), %xmm0
movl %r8d, %r9d
movq %r9, %r8
shlq $0x5, %r8
movsd 0x40(%rsp,%r8), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x3c2e
shlq $0x5, %r9
leaq (%rsp,%r9), %r8
addq $0x40, %r8
movsd %xmm0, (%r8)
jmp 0x3c4f
movsd (%rax), %xmm0
movl %r8d, %r8d
movq %r8, %r9
shlq $0x5, %r9
ucomisd 0x40(%rsp,%r9), %xmm0
ja 0x3bdc
jmp 0x3c5a
cmpq $0x60, %rdx
jne 0x3c5a
movl %r8d, %r8d
movq %r8, %r9
shlq $0x5, %r9
movsd 0x48(%rsp,%r9), %xmm0
ucomisd 0x8(%rax), %xmm0
jbe 0x3c6e
shlq $0x5, %r8
movupd (%rax), %xmm0
movupd %xmm0, 0x40(%rsp,%r8)
leaq (%rsp,%rdx), %r8
addq $0x30, %r8
movlpd %xmm0, (%r8)
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
jmp 0x3c54
shlq $0x5, %r9
movsd 0x38(%rsp,%r9), %xmm0
ucomisd 0x8(%rax), %xmm0
ja 0x3c37
jmp 0x3c5a
testq %rdx, %rdx
jne 0x3c5a
movsd 0x8(%rax), %xmm0
movl %r8d, %r8d
shlq $0x5, %r8
ucomisd 0x38(%rsp,%r8), %xmm0
ja 0x3c37
jmp 0x3c5a
ucomisd 0x30(%rsp,%r8), %xmm0
jbe 0x3c6e
movq %rsi, %r8
shlq $0x5, %r8
addq %rsp, %r8
addq $0x30, %r8
movsd (%rax), %xmm0
movsd %xmm0, 0x30(%rsp,%rdx)
movsd 0x8(%rax), %xmm0
movsd %xmm0, 0x8(%r8)
incq %rsi
addq $0x20, %rdx
cmpq $0x80, %rdx
jne 0x3a3c
addq $0x10, %rax
cmpq %rcx, %rax
jne 0x3a33
xorl %ebx, %ebx
movq 0x28(%rsp), %r14
leaq (%rsp,%rbx), %rdx
addq $0x30, %rdx
movq 0x8(%r14), %rsi
cmpq 0x10(%r14), %rsi
je 0x3ca3
movupd (%rdx), %xmm0
movupd %xmm0, (%rsi)
addq $0x10, 0x8(%r14)
jmp 0x3cab
movq %r14, %rdi
callq 0x440e
movsd 0x30(%rsp,%rbx), %xmm0
ucomisd 0x40(%rsp,%rbx), %xmm0
jne 0x3ccb
jp 0x3ccb
movsd 0x38(%rsp,%rbx), %xmm0
ucomisd 0x48(%rsp,%rbx), %xmm0
jne 0x3ccb
jnp 0x3cf4
leaq (%rsp,%rbx), %rdx
addq $0x40, %rdx
movq 0x8(%r14), %rsi
cmpq 0x10(%r14), %rsi
je 0x3cec
movupd (%rdx), %xmm0
movupd %xmm0, (%rsi)
addq $0x10, 0x8(%r14)
jmp 0x3cf4
movq %r14, %rdi
callq 0x440e
addq $0x18, %r14
addq $0x20, %rbx
cmpq $0x80, %rbx
jne 0x3c82
movq (%r15), %rbx
movq 0x8(%r15), %rax
movq %rax, 0xc0(%rsp)
cmpq %rax, %rbx
je 0x4131
xorpd %xmm9, %xmm9
movsd (%rbx), %xmm0
ucomisd 0x40(%rsp), %xmm0
jbe 0x3d60
movsd 0x8(%rbx), %xmm1
ucomisd 0x38(%rsp), %xmm1
jbe 0x3d60
movq %rbx, 0x10(%rsp)
movb $0x1, %r8b
xorl %r9d, %r9d
xorl %r10d, %r10d
movq $0x0, 0x18(%rsp)
movb $0x1, %bpl
xorl %eax, %eax
jmp 0x3e1e
movsd 0x50(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x3d9d
movsd 0x8(%rbx), %xmm1
ucomisd 0x68(%rsp), %xmm1
jbe 0x3d9d
movq %rbx, 0x10(%rsp)
movl $0x1, %eax
movb $0x1, %r9b
xorl %r8d, %r8d
xorl %r10d, %r10d
movq $0x0, 0x18(%rsp)
movb $0x1, %bpl
jmp 0x3e1e
movsd 0x80(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x3ddb
movsd 0x8(%rbx), %xmm1
movsd 0x78(%rsp), %xmm2
ucomisd %xmm1, %xmm2
jbe 0x3ddb
movq %rbx, 0x10(%rsp)
movl $0x2, %eax
movb $0x1, %r10b
xorl %r8d, %r8d
xorl %r9d, %r9d
movq $0x0, 0x18(%rsp)
jmp 0x3e1c
ucomisd 0x90(%rsp), %xmm0
jbe 0x411f
movsd 0x8(%rbx), %xmm1
movsd 0xa8(%rsp), %xmm2
ucomisd %xmm1, %xmm2
jbe 0x411f
movq %rbx, 0x10(%rsp)
movl $0x3, %eax
movb $0x1, %cl
movq %rcx, 0x18(%rsp)
xorl %r8d, %r8d
xorl %r9d, %r9d
xorl %r10d, %r10d
xorl %ebp, %ebp
leaq (%rax,%rax,2), %rax
movq 0x28(%rsp), %rcx
leaq (%rcx,%rax,8), %rax
movq (%rax), %rdx
movq %rax, 0x20(%rsp)
movq 0x8(%rax), %rdi
movq %rdx, (%rsp)
subq %rdx, %rdi
shrq $0x4, %rdi
movq (%rcx), %r12
movq 0x18(%rcx), %r13
movq 0x30(%rcx), %rsi
movq 0x48(%rcx), %r15
movl $0x0, 0xc(%rsp)
movq %rdi, 0xb8(%rsp)
xorl %edx, %edx
leal -0x1(%rdi), %r14d
cmpl %r14d, %edx
jge 0x3f41
movl %edi, %eax
subl %edx, %eax
sarl %eax
addl %edx, %eax
movslq %eax, %rcx
testb %r8b, %r8b
je 0x3ea1
movq %rcx, %rbx
shlq $0x4, %rbx
movsd (%r12,%rbx), %xmm2
ucomisd %xmm0, %xmm2
jb 0x3ea1
addq %r12, %rbx
movsd 0x8(%rbx), %xmm2
ucomisd %xmm1, %xmm2
jae 0x3f05
testb %r9b, %r9b
je 0x3ec4
movq %rcx, %rbx
shlq $0x4, %rbx
ucomisd (%r13,%rbx), %xmm0
jb 0x3ec4
addq %r13, %rbx
movsd 0x8(%rbx), %xmm2
ucomisd %xmm1, %xmm2
jae 0x3f05
testb %r10b, %r10b
je 0x3ee1
movq %rcx, %rbx
shlq $0x4, %rbx
ucomisd (%rsi,%rbx), %xmm0
jb 0x3ee1
addq %rsi, %rbx
ucomisd 0x8(%rbx), %xmm1
jae 0x3f05
cmpb $0x0, 0x18(%rsp)
je 0x3f0b
movq %rcx, %rbx
shlq $0x4, %rbx
movsd (%r15,%rbx), %xmm2
ucomisd %xmm0, %xmm2
jb 0x3f0b
addq %r15, %rbx
ucomisd 0x8(%rbx), %xmm1
jb 0x3f0b
movb $0x1, %bl
movl %ebx, 0xc(%rsp)
shlq $0x4, %rcx
movq (%rsp), %r11
movsd (%r11,%rcx), %xmm2
testb %bpl, %bpl
je 0x3f26
ucomisd %xmm2, %xmm0
je 0x3f2c
jmp 0x3f3a
ucomisd %xmm0, %xmm2
ja 0x3f3a
ucomisd %xmm2, %xmm0
movl %eax, %edx
ja 0x3e67
jmp 0x3f52
movl %eax, %edi
jmp 0x3e63
testb $0x1, 0xc(%rsp)
movq 0x10(%rsp), %rbx
je 0x3f69
jmp 0x411f
testb $0x1, 0xc(%rsp)
movq 0x10(%rsp), %rbx
jne 0x411f
leal -0x1(%rax), %edx
incl %eax
movl %eax, %edi
movslq %edx, %rax
shlq $0x4, %rax
movq (%rsp), %rcx
movsd (%rcx,%rax), %xmm4
movsd 0x8(%rcx,%rax), %xmm5
movslq %edi, %r8
movq %r8, %rax
shlq $0x4, %rax
movsd (%rcx,%rax), %xmm3
movsd 0x8(%rcx,%rax), %xmm2
movapd %xmm3, %xmm6
subsd %xmm4, %xmm6
movapd %xmm1, %xmm7
subsd %xmm5, %xmm7
mulsd %xmm6, %xmm7
movapd %xmm2, %xmm6
subsd %xmm5, %xmm6
movapd %xmm0, %xmm5
subsd %xmm4, %xmm5
mulsd %xmm6, %xmm5
subsd %xmm5, %xmm7
ucomisd %xmm7, %xmm9
jbe 0x411f
movl %edx, %r9d
movl %edx, %ecx
sarl $0x1f, %ecx
andl %edx, %ecx
shlq $0x4, %r9
addq (%rsp), %r9
testl %edx, %edx
jle 0x4033
movsd -0x10(%r9), %xmm4
movsd -0x8(%r9), %xmm5
movsd (%r9), %xmm6
movsd 0x8(%r9), %xmm7
addq $-0x10, %r9
movapd %xmm0, %xmm8
subsd %xmm4, %xmm8
subsd %xmm5, %xmm7
mulsd %xmm8, %xmm7
movapd %xmm1, %xmm8
subsd %xmm5, %xmm8
subsd %xmm4, %xmm6
mulsd %xmm8, %xmm6
subsd %xmm6, %xmm7
decl %edx
ucomisd %xmm7, %xmm9
jbe 0x3fdd
incl %edx
movl %edx, %ecx
movq 0xb8(%rsp), %r9
decl %r9d
cmpl %r9d, %r8d
cmovgl %r8d, %r9d
movslq %r9d, %rdx
subq %rdx, %r8
movq (%rsp), %rdx
addq %rax, %rdx
addq $0x18, %rdx
xorl %eax, %eax
cmpq %rax, %r8
je 0x40a7
movsd -0x8(%rdx), %xmm4
movsd (%rdx), %xmm5
movapd %xmm4, %xmm6
subsd %xmm0, %xmm6
subsd %xmm1, %xmm2
mulsd %xmm6, %xmm2
movapd %xmm5, %xmm6
subsd %xmm1, %xmm6
subsd %xmm0, %xmm3
mulsd %xmm6, %xmm3
subsd %xmm3, %xmm2
decq %rax
addq $0x10, %rdx
ucomisd %xmm2, %xmm9
movapd %xmm5, %xmm2
movapd %xmm4, %xmm3
jbe 0x4058
notl %eax
addl %edi, %eax
movl %eax, %r9d
leal 0x1(%rcx), %eax
cmpl %r9d, %eax
jne 0x40cc
movslq %r9d, %rax
shlq $0x4, %rax
movq (%rsp), %rsi
addq %rax, %rsi
movq 0x20(%rsp), %rdi
movq %rbx, %rdx
callq 0x4332
jmp 0x411a
cltq
shlq $0x4, %rax
movq (%rsp), %rdx
movsd %xmm0, (%rdx,%rax)
movsd %xmm1, 0x8(%rdx,%rax)
leal 0x2(%rcx), %eax
cmpl %r9d, %eax
je 0x411f
movq %r9, %rdx
movslq %ecx, %rax
shlq $0x4, %rax
movq (%rsp), %rsi
addq %rsi, %rax
addq $0x20, %rax
movslq %edx, %rcx
shlq $0x4, %rcx
leaq (%rsi,%rcx), %rdx
addq $-0x10, %rdx
movq 0x20(%rsp), %rdi
movq %rax, %rsi
callq 0x44ee
xorpd %xmm9, %xmm9
addq $0x10, %rbx
cmpq 0xc0(%rsp), %rbx
jne 0x3d26
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop