// File: /workspace/github_cpp_makefile_star2_O2/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
subq $0x38, %rsp
movq %rdx, %rbx
movq %rsi, %r14
movq (%rsi), %rdi
movq 0x8(%rsi), %rsi
leaq -0x33(%rip), %rdx       # 0x2f69
callq 0x3594
movq (%r14), %r15
movq (%rax), %rcx
movq (%r15), %rdx
movq %rcx, (%r15)
movq %rdx, (%rax)
leaq 0x8(%r15), %r13
movq 0x8(%r14), %r12
cmpq %r12, %r13
je 0x3027
movq %r12, %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 %r12, %rsi
movq %r14, %rcx
callq 0x30f8
cmpq $0x81, %rbp
jl 0x3019
addq $0x88, %r15
movq %r13, %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x3487
cmpq %r12, %r15
je 0x3027
movq %r15, %rdi
movq %r14, %rsi
callq 0x34fb
addq $0x8, %r15
jmp 0x3003
movq %r13, %rdi
movq %r12, %rsi
movq %r14, %rdx
callq 0x3487
movq (%r14), %rsi
movq %rbx, %rdi
callq 0x2a90
movq (%r14), %rsi
addq $0x8, %rsi
movq %rbx, %rdi
callq 0x2a90
movq (%r14), %r15
addq $0x10, %r15
leaq 0x20(%rsp), %rbp
leaq 0x8(%rsp), %r13
cmpq 0x8(%r14), %r15
je 0x30e9
movq 0x8(%rbx), %r12
movq (%r15), %rax
movq %rax, 0x30(%rsp)
movq -0x10(%r12), %rax
movq %rax, 0x28(%rsp)
movq -0x8(%r12), %rax
movq %rax, 0x20(%rsp)
leaq 0x30(%rsp), %rdi
leaq 0x28(%rsp), %rsi
movq %rbp, %rdx
callq 0x2f44
testb %al, %al
jne 0x30cb
movq (%r15), %rax
movq %rax, 0x18(%rsp)
movq -0x10(%r12), %rax
movq %rax, 0x10(%rsp)
movq -0x8(%r12), %rax
movq %rax, 0x8(%rsp)
leaq 0x18(%rsp), %rdi
leaq 0x10(%rsp), %rsi
movq %r13, %rdx
callq 0x2f4f
testb %al, %al
jne 0x30d8
addq $-0x8, 0x8(%rbx)
jmp 0x3052
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2a90
jmp 0x30e0
movq (%r15), %rax
movq %rax, -0x8(%r12)
addq $0x8, %r15
jmp 0x3052
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq