// File: /workspace/github_cpp_makefile_star2_O3/BUSEC[P]RPKI_Downgrade_Detector/./exp.cpp
// Function: IntervalList<IPAddr>::denseIntersectWith(IntervalList<IPAddr> const&, bool)
void denseIntersectWith (const IntervalList<T> & arg, bool argDense) {
    if (arg.m.empty()) {
      m.clear();
      return;
    }
    typename map<T,T>::iterator thisIter = m.begin();
    typename map<T,T>::const_iterator argIter=arg.m.begin();
    // consider one interval from this at a time
    // loop invariant: before each iteration of the loop starts, we know that
    // 1) Every interval in m before thisIter has already been considered, and all that's left
    //    of it is only whatever intersects with arg
    // 2) Interval pointed to by thisIter and after has not been considered
    // 3) No interval before argIter itersects with thisIter (but argIter itself may)
    //
    // Therefore, we want to end the loop with argIter pointing to the first interval
    // that ends after thisIter->second
    while (thisIter!=m.end()) {
      
      if (argIter == arg.m.end()) { // If arg has nothing left, erase the rest of m and quit
        // this check is not necessary for correctness -- the code below should work correctly without this check
        // but it will probably speed things up, especially in the argDense == false case, because it will save on
        // unnecessary invocations of lower_bound.
        // So we remove all subsequent intervals of this and break out of the loop.
        do {
          T thisBegin = thisIter->first;
          thisIter++;
          m.erase(thisBegin);
        } while (thisIter != m.end());
        break;
      }
      
      T thisBegin = thisIter->first;
      T thisEnd = thisIter->second;
      bool deleteCur = true;
      
      // We now look for the first interval in arg that may intersect [thisBegin,thisEnd],
      // Specifically, the first interval that ends at or after thisBegin.
      // The search is different depending on argDense
      if (argDense)
        while (argIter != arg.m.end() && argIter->second < thisBegin)
          argIter++;
      else {
        // We do the check below because if argIter->second>=thisBegin, then we argIter is already at the right spot
        // This check is not necessary for correctness -- the code below should work correctly even if we don't check whether argIter.second<thisBegin,
        // because lower_bound will find this interval, anyway.
        // However, it is a very easy check to do and immediately tells us that we are the right spot;
        // if it works, it will save an invocation of lower bound,
        // and it is likely to work reasonably often because one would expect intervals from arg that intersect intervals
        // from this to come in sequential order a reasonable fraction of the time
        if (argIter->second<thisBegin) { // we know argIter is not at the end, so this check is safe
          argIter = arg.m.lower_bound(thisBegin);
          // argIter now points to the first interval whose start is at or after thisBegin
          // we need to also consider the previous interval, if it exists, because its end may be after thisBegin
          // So we step back, check, and step forward if the check turns up nothing
          if (argIter!=arg.m.begin()) {
            argIter--;
            if (argIter->second<thisBegin) 
              argIter++;
          }
        }
      }
      
      // Now we know argIter is at the first iterval that ends at or after thisBegin
      // Check if it overlaps thisBegin and, if so, preserve thisBegin in m
      if (argIter!=arg.m.end() && argIter->first<=thisBegin) {
        if (thisEnd<argIter->second) {
          // this case, thisIter does not change and argIter should not advance
          thisIter++;
          continue; // so we short-circuit the loop, since there's nothing else to do -- and if we didn't short circuit, we'd have to move argIter forward,
                    // which we can't do, because argIter may overlap with the next interval in m
        }
        // else
        thisIter->second = argIter->second;
        deleteCur = false;
        // argIter ends at or before thisEnd, so we can advance and still preserve the loop invariant
        argIter++; 
      }
      
      // Now argIter begins after thisBegin
      // advance it until it ends after thisEnd
      //
      // Loop invariant: before every iteration of this loop, we know
      // 1) We have intersected [thisBegin, thisEnd] with everything before argIter,
      //    but not argIter itself or anything after that
      // 2) argIter and everything after begins after thisBegin
      //
      while (argIter!=arg.m.end() && argIter->second <= thisEnd) {        
        m[argIter->first]=argIter->second;
        thisIter++; // we need to advance thisIter every time we add a new interval
        argIter++;
      }
      // now argIter points to the first interval that ends after thisEnd
      // We know for sure that it this interval begins after thisBegin
      // We need to still intersect [thisBegin, thisEnd] with it
      // To preserve the loop invariant of the outer loop, we cannot move argIter any further
      // (because it may overlap with the next interval in m)
      if(argIter!=arg.m.end() && argIter->first<=thisEnd) {
          m[argIter->first]=thisEnd;
          thisIter++; // we need to advance thisIter every time we add a new interval
      }
      thisIter++;
      if (deleteCur) m.erase(thisBegin); // erasure is safe because thisIter has moved forward of the [thisBegin, thisEnd] interval
    }
  }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movl %edx, 0x18(%rsp)
movq %rdi, %rbx
movq %rsi, 0x8(%rsp)
cmpq $0x0, 0x28(%rsi)
je 0x5c35
movq 0x18(%rbx), %r14
leaq 0x8(%rbx), %r12
cmpq %r12, %r14
je 0x5c7e
movq 0x8(%rsp), %rax
movq 0x18(%rax), %r13
leaq 0x8(%rax), %r15
movq %r12, 0x10(%rsp)
cmpq %r15, %r13
je 0x5c4b
movl 0x20(%r14), %r12d
movl %r12d, 0x20(%rsp)
movl 0x24(%r14), %ebp
cmpb $0x0, 0x18(%rsp)
je 0x5b0f
cmpl %r12d, 0x24(%r13)
jae 0x5b67
movq %r13, %rdi
callq 0x2290
movq %rax, %r13
cmpq %r15, %rax
jne 0x5af7
jmp 0x5b67
cmpl %r12d, 0x24(%r13)
jae 0x5b67
movq 0x8(%rsp), %rax
movq 0x10(%rax), %rax
movq %r15, %r13
testq %rax, %rax
je 0x5b40
movq %r15, %r13
xorl %ecx, %ecx
cmpl %r12d, 0x20(%rax)
setb %cl
cmovaeq %rax, %r13
movq 0x10(%rax,%rcx,8), %rax
testq %rax, %rax
jne 0x5b29
movq 0x8(%rsp), %rax
cmpq 0x18(%rax), %r13
je 0x5b67
movq %r13, %rdi
callq 0x2130
movq %rax, %r13
cmpl %r12d, 0x24(%rax)
jae 0x5b67
movq %r13, %rdi
callq 0x2290
movq %rax, %r13
movb $0x1, %al
cmpq %r15, %r13
je 0x5b74
cmpl %r12d, 0x20(%r13)
jbe 0x5bb7
movq 0x10(%rsp), %r12
cmpq %r15, %r13
movl %eax, 0x1c(%rsp)
je 0x5bea
leaq 0x20(%r13), %rsi
cmpl %ebp, 0x24(%r13)
ja 0x5bd1
movq %rbx, %rdi
callq 0x5c8e
movl 0x24(%r13), %ecx
movl %ecx, (%rax)
movq %r14, %rdi
callq 0x2180
movq %rax, %r14
movq %r13, %rdi
callq 0x2290
movq %rax, %r13
cmpq %r15, %rax
jne 0x5b82
jmp 0x5bea
movl 0x24(%r13), %eax
cmpl %eax, %ebp
movq 0x10(%rsp), %r12
jae 0x5c1f
movq %r14, %rdi
callq 0x2180
movq %rax, %r14
jmp 0x5c14
cmpl %ebp, (%rsi)
ja 0x5bea
movq %rbx, %rdi
callq 0x5c8e
movl %ebp, (%rax)
movq %r14, %rdi
callq 0x2180
movq %rax, %r14
movq %r14, %rdi
callq 0x2180
movq %rax, %r14
cmpb $0x0, 0x1c(%rsp)
je 0x5c14
movq %rbx, %rdi
leaq 0x20(%rsp), %rsi
callq 0x5d68
movq %rbx, %rdi
movq %rax, %rsi
callq 0x5de6
cmpq %r12, %r14
jne 0x5ada
jmp 0x5c7e
movl %eax, 0x24(%r14)
movq %r13, %rdi
callq 0x2290
movq %rax, %r13
xorl %eax, %eax
jmp 0x5b79
movq %rbx, %rdi
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x5cf4
leaq 0x24(%rsp), %r15
movl 0x20(%r14), %eax
movl %eax, 0x24(%rsp)
movq %r14, %rdi
callq 0x2180
movq %rax, %r14
movq %rbx, %rdi
movq %r15, %rsi
callq 0x5d68
movq %rbx, %rdi
movq %rax, %rsi
callq 0x5de6
cmpq %r12, %r14
jne 0x5c50
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop