// File: 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
movq %rsp, %rbp
subq $0x110, %rsp            # imm = 0x110
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x10(%rbp), %rdi
callq 0x55c0
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5520
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rdi
movq -0x30(%rbp), %rsi
leaq -0xd0(%rip), %rdx       # 0x5aa0
callq 0x7080
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rdi
callq 0x55c0
movq %rax, -0x38(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0x70d0
movq -0x10(%rbp), %rdi
callq 0x55c0
movq %rax, -0x50(%rbp)
leaq -0x50(%rbp), %rdi
movl $0x1, %esi
callq 0x7110
movq %rax, -0x48(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5520
movq %rax, -0x58(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x48(%rbp), %rdi
movq -0x58(%rbp), %rsi
movq -0x60(%rbp), %rdx
callq 0x5e60
movq -0x18(%rbp), %rax
movq %rax, -0x100(%rbp)
movq -0x10(%rbp), %rdi
callq 0x55c0
movq %rax, -0x68(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x7150
movq -0x100(%rbp), %rdi
movq %rax, %rsi
callq 0x4150
movq -0x18(%rbp), %rax
movq %rax, -0xf8(%rbp)
movq -0x10(%rbp), %rdi
callq 0x55c0
movq %rax, -0x78(%rbp)
leaq -0x78(%rbp), %rdi
movl $0x1, %esi
callq 0x7110
movq %rax, -0x70(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x7150
movq -0xf8(%rbp), %rdi
movq %rax, %rsi
callq 0x4150
movq -0x10(%rbp), %rdi
callq 0x55c0
movq %rax, -0x88(%rbp)
leaq -0x88(%rbp), %rdi
movl $0x2, %esi
callq 0x7110
movq %rax, -0x80(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5520
movq %rax, -0x90(%rbp)
leaq -0x80(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x7170
testb $0x1, %al
jne 0x5ca0
jmp 0x5e55
movq -0x18(%rbp), %rdi
callq 0x5520
movq %rax, -0xa0(%rbp)
leaq -0xa0(%rbp), %rdi
movl $0x1, %esi
callq 0x71b0
movq %rax, -0x98(%rbp)
movq -0x18(%rbp), %rdi
callq 0x5520
movq %rax, -0xb0(%rbp)
leaq -0xb0(%rbp), %rdi
movl $0x2, %esi
callq 0x71b0
movq %rax, -0xa8(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x7150
movq %rax, %rsi
leaq -0xb8(%rbp), %rdi
callq 0x5170
leaq -0xa8(%rbp), %rdi
callq 0x7150
movq %rax, %rsi
leaq -0xc0(%rbp), %rdi
callq 0x5170
leaq -0x98(%rbp), %rdi
callq 0x7150
movq %rax, %rsi
leaq -0xc8(%rbp), %rdi
callq 0x5170
leaq -0xb8(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
leaq -0xc8(%rbp), %rdx
callq 0x5a10
testb $0x1, %al
jne 0x5d5e
jmp 0x5d98
movq -0x18(%rbp), %rax
movq %rax, -0x108(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x7150
movq -0x108(%rbp), %rdi
movq %rax, %rsi
callq 0x4150
leaq -0x80(%rbp), %rdi
xorl %esi, %esi
callq 0x71f0
movq %rax, -0xd0(%rbp)
jmp 0x5e50
leaq -0x80(%rbp), %rdi
callq 0x7150
movq %rax, %rsi
leaq -0xd8(%rbp), %rdi
callq 0x5170
leaq -0xa8(%rbp), %rdi
callq 0x7150
movq %rax, %rsi
leaq -0xe0(%rbp), %rdi
callq 0x5170
leaq -0x98(%rbp), %rdi
callq 0x7150
movq %rax, %rsi
leaq -0xe8(%rbp), %rdi
callq 0x5170
leaq -0xd8(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
leaq -0xe8(%rbp), %rdx
callq 0x5a40
testb $0x1, %al
jne 0x5e06
jmp 0x5e45
leaq -0x80(%rbp), %rdi
callq 0x7150
movq %rax, -0x110(%rbp)
leaq -0x98(%rbp), %rdi
callq 0x7150
movq -0x110(%rbp), %rsi
movq %rax, %rdi
callq 0x7230
leaq -0x80(%rbp), %rdi
xorl %esi, %esi
callq 0x71f0
movq %rax, -0xf0(%rbp)
jmp 0x5e4e
movq -0x18(%rbp), %rdi
callq 0x7260
jmp 0x5e50
jmp 0x5c77
addq $0x110, %rsp            # imm = 0x110
popq %rbp
retq
nop