// File: /workspace/github_cpp_makefile_star2_O1/DavidNKraemer[P]convex-hull/cvhull/GrahamScan.cpp
// Function: ams562::GrahamScan::apply(std::vector<ams562::Point2D, std::allocator<ams562::Point2D>>&, std::vector<ams562::Point2D, std::allocator<ams562::Point2D>>&) const
void GrahamScan::apply(std::vector<Point2D> &pc, std::vector<Point2D> &ch) const {

    //
    // First find the lowest point by using std::max_element
    // if there are ties, pick the most left one
    auto sw_iterator = std::min_element(
        pc.begin(), 
        pc.end(),

        // comparison function returns true if p1 is lower than p2
        is_lower);

    //
    // Then, swap that point with the first element in pc
    std::iter_swap(pc.begin(), sw_iterator);

    //
    // Next step is to sort the 2nd point to the last point in pc
    // by polar angle with the first point in pc
    // Note that the first point in pc is the lowest point in the
    // point cloud. std::sort
    std::sort(pc.begin() + 1, 
        pc.end(), 
        [&pc](Point2D p1, Point2D p2) {
        return pc[0].orientation(p1, p2) < 0; 
        }
        );

    //
    // Push back the first and second points to the back
    // of ch, push_back of ch should be used
    ch.push_back(*pc.begin());
    ch.push_back(*(pc.begin() + 1));

    //
    // Bonus, I do the cur for you

    auto cur = pc.begin() + 2;
    while (cur != pc.end()) {
      //
      // Get the last 2 points in ch by using iterators
      // note that you can start with ch.end(), be aware
      // of the position of ch.end()

      auto ch_ult = ch.end() - 1; // ultimate
      auto ch_pen = ch.end() - 2; // penultimate

      //
      // Compute the orientation information of ch's last1
      // last2 and cur

      //
      // if cur is to left of last1_last2
      // then push cur to ch
      if (is_left(*cur, *ch_pen, *ch_ult)) {
        ch.push_back(*cur);
        cur ++;
      }

      //
      // else if cur is collinear and cur lies futher
      // replace the last point of ch by cur
      else if (is_collinear(*cur, *ch_pen, *ch_ult)) {
        *ch_ult = *cur;
        cur ++;
      }

      //
      // else, pop the last point back from ch
      // and keep ch unchanged
      else {
        ch.pop_back();
      }
    }
  }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdx, %rbx
movq %rsi, %r14
movq (%rsi), %r12
movq 0x8(%rsi), %r15
cmpq %r15, %r12
sete %cl
leaq 0x8(%r12), %rax
cmpq %r15, %rax
sete %dl
orb %cl, %dl
movq %r12, %rdx
jne 0x33cb
movq %r12, %rcx
movl (%rax), %edx
movl 0x4(%rax), %esi
xorl %edi, %edi
cmpl (%rcx), %edx
setl %dil
xorl %r8d, %r8d
cmpl 0x4(%rcx), %esi
setl %r8b
cmovel %edi, %r8d
movq %rax, %rdx
testb %r8b, %r8b
jne 0x33bf
movq %rcx, %rdx
addq $0x8, %rax
movq %rdx, %rcx
cmpq %r15, %rax
jne 0x3399
movq (%r12), %rax
movl (%rdx), %ecx
movl %ecx, (%r12)
movl 0x4(%rdx), %ecx
movl %ecx, 0x4(%r12)
movq %rax, (%rdx)
leaq 0x8(%r12), %r13
cmpq %r15, %r13
je 0x3454
movq %r15, %rbp
subq %r13, %rbp
movq %rbp, %rax
sarq $0x3, %rax
bsrq %rax, %rdx
xorl $0x3f, %edx
addl %edx, %edx
xorq $0x7e, %rdx
movq %r13, %rdi
movq %r15, %rsi
movq %r14, %rcx
callq 0x34f3
cmpq $0x81, %rbp
jl 0x3446
addq $0x88, %r12
movq %r13, %rdi
movq %r12, %rsi
movq %r14, %rdx
callq 0x3949
cmpq %r15, %r12
je 0x3454
movq %r12, %rdi
movq %r14, %rsi
callq 0x39f2
addq $0x8, %r12
jmp 0x3430
movq %r13, %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x3949
movq (%r14), %rsi
movq %rbx, %rdi
callq 0x2e26
movq (%r14), %rsi
addq $0x8, %rsi
movq %rbx, %rdi
callq 0x2e26
movq (%r14), %r15
addq $0x10, %r15
cmpq 0x8(%r14), %r15
je 0x34e4
movq 0x8(%rbx), %rax
movl (%r15), %ecx
movl 0x4(%r15), %edx
movl -0x10(%rax), %esi
movl -0xc(%rax), %edi
movl -0x8(%rax), %r8d
movl %r8d, %r10d
subl %esi, %r10d
movl %edx, %r9d
subl %edi, %r9d
imull %r9d, %r10d
movl %ecx, %r11d
subl %esi, %r11d
subl -0x4(%rax), %edi
imull %r11d, %edi
addl %edi, %r10d
js 0x34c9
subl %r8d, %esi
imull %r9d, %esi
cmpl %esi, %edi
jne 0x34da
movl %ecx, -0x8(%rax)
movl %edx, -0x4(%rax)
addq $0x8, %r15
jmp 0x3475
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2e26
addq $0x8, %r15
jmp 0x3475
addq $-0x8, %rax
movq %rax, 0x8(%rbx)
jmp 0x3475
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq