// File: 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
movq %rsp, %rbp
subq $0x170, %rsp            # imm = 0x170
movb %dl, %al
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
andb $0x1, %al
movb %al, -0x11(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x110(%rbp)
movq -0x10(%rbp), %rdi
callq 0x8670
testb $0x1, %al
jne 0x8144
jmp 0x8155
movq -0x110(%rbp), %rdi
callq 0x8690
jmp 0x8665
movq -0x110(%rbp), %rdi
callq 0x86b0
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rdi
callq 0x86e0
movq %rax, -0x28(%rbp)
movq -0x110(%rbp), %rdi
callq 0x8740
movq %rax, -0x30(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x8710
testb $0x1, %al
jne 0x8198
jmp 0x8665
movq -0x10(%rbp), %rdi
callq 0x87a0
movq %rax, -0x38(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x8770
testb $0x1, %al
jne 0x81b8
jmp 0x8214
jmp 0x81ba
leaq -0x20(%rbp), %rdi
callq 0x87d0
movq %rax, %rsi
leaq -0x3c(%rbp), %rdi
callq 0x5a00
leaq -0x20(%rbp), %rdi
xorl %esi, %esi
callq 0x87f0
movq -0x110(%rbp), %rdi
movq %rax, -0x48(%rbp)
leaq -0x3c(%rbp), %rsi
callq 0x8830
movq -0x110(%rbp), %rdi
callq 0x8740
movq %rax, -0x50(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0x8710
testb $0x1, %al
jne 0x81ba
jmp 0x8665
leaq -0x20(%rbp), %rdi
callq 0x87d0
movq %rax, %rsi
leaq -0x54(%rbp), %rdi
callq 0x5a00
leaq -0x20(%rbp), %rdi
callq 0x87d0
movq %rax, %rsi
addq $0x4, %rsi
leaq -0x58(%rbp), %rdi
callq 0x5a00
movb $0x1, -0x59(%rbp)
testb $0x1, -0x11(%rbp)
je 0x82d6
jmp 0x8252
movq -0x10(%rbp), %rdi
callq 0x87a0
movq %rax, -0x68(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x8860
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x111(%rbp)
jne 0x827d
jmp 0x82b4
leaq -0x28(%rbp), %rdi
callq 0x8890
addq $0x4, %rax
movq %rax, -0x120(%rbp)
leaq -0x6c(%rbp), %rdi
leaq -0x54(%rbp), %rsi
callq 0x5a00
movq -0x120(%rbp), %rdi
leaq -0x6c(%rbp), %rsi
callq 0x88b0
movb %al, -0x111(%rbp)
movb -0x111(%rbp), %al
testb $0x1, %al
jne 0x82c0
jmp 0x82d1
leaq -0x28(%rbp), %rdi
xorl %esi, %esi
callq 0x88d0
movq %rax, -0x78(%rbp)
jmp 0x8252
jmp 0x83bc
leaq -0x28(%rbp), %rdi
callq 0x8890
addq $0x4, %rax
movq %rax, -0x128(%rbp)
leaq -0x7c(%rbp), %rdi
leaq -0x54(%rbp), %rsi
callq 0x5a00
movq -0x128(%rbp), %rdi
leaq -0x7c(%rbp), %rsi
callq 0x88b0
testb $0x1, %al
jne 0x8310
jmp 0x83ba
movq -0x10(%rbp), %rdi
leaq -0x54(%rbp), %rsi
callq 0x8910
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rdi
callq 0x86e0
movq %rax, -0x90(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x8860
testb $0x1, %al
jne 0x8355
jmp 0x83b8
leaq -0x28(%rbp), %rdi
xorl %esi, %esi
callq 0x8940
movq %rax, -0x98(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x8890
addq $0x4, %rax
movq %rax, -0x130(%rbp)
leaq -0x9c(%rbp), %rdi
leaq -0x54(%rbp), %rsi
callq 0x5a00
movq -0x130(%rbp), %rdi
leaq -0x9c(%rbp), %rsi
callq 0x88b0
testb $0x1, %al
jne 0x83a4
jmp 0x83b6
leaq -0x28(%rbp), %rdi
xorl %esi, %esi
callq 0x88d0
movq %rax, -0xa8(%rbp)
jmp 0x83b8
jmp 0x83ba
jmp 0x83bc
movq -0x10(%rbp), %rdi
callq 0x87a0
movq %rax, -0xb0(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
callq 0x8860
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x131(%rbp)
jne 0x83ed
jmp 0x8426
leaq -0x28(%rbp), %rdi
callq 0x8890
movq %rax, -0x140(%rbp)
leaq -0xb4(%rbp), %rdi
leaq -0x54(%rbp), %rsi
callq 0x5a00
movq -0x140(%rbp), %rdi
leaq -0xb4(%rbp), %rsi
callq 0x8980
movb %al, -0x131(%rbp)
movb -0x131(%rbp), %al
testb $0x1, %al
jne 0x8435
jmp 0x84ba
leaq -0x28(%rbp), %rdi
callq 0x8890
movq %rax, %rsi
addq $0x4, %rsi
leaq -0xb8(%rbp), %rdi
callq 0x5a00
leaq -0x58(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
callq 0x88b0
testb $0x1, %al
jne 0x8467
jmp 0x847e
leaq -0x20(%rbp), %rdi
xorl %esi, %esi
callq 0x87f0
movq %rax, -0xc0(%rbp)
jmp 0x8172
leaq -0x28(%rbp), %rdi
callq 0x8890
movq %rax, -0x148(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x87d0
movq -0x148(%rbp), %rcx
movl 0x4(%rcx), %ecx
movl %ecx, 0x4(%rax)
movb $0x0, -0x59(%rbp)
leaq -0x28(%rbp), %rdi
xorl %esi, %esi
callq 0x88d0
movq %rax, -0xc8(%rbp)
jmp 0x84bc
movq -0x10(%rbp), %rdi
callq 0x87a0
movq %rax, -0xd0(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
callq 0x8860
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x149(%rbp)
jne 0x84ed
jmp 0x852a
leaq -0x28(%rbp), %rdi
callq 0x8890
addq $0x4, %rax
movq %rax, -0x158(%rbp)
leaq -0xd4(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x5a00
movq -0x158(%rbp), %rdi
leaq -0xd4(%rbp), %rsi
callq 0x8980
movb %al, -0x149(%rbp)
movb -0x149(%rbp), %al
testb $0x1, %al
jne 0x8536
jmp 0x8593
leaq -0x28(%rbp), %rdi
callq 0x8890
movq %rax, -0x160(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x8890
movq -0x110(%rbp), %rdi
movq %rax, %rsi
callq 0x89a0
movq -0x160(%rbp), %rcx
movl 0x4(%rcx), %ecx
movl %ecx, (%rax)
leaq -0x20(%rbp), %rdi
xorl %esi, %esi
callq 0x87f0
movq %rax, -0xe0(%rbp)
leaq -0x28(%rbp), %rdi
xorl %esi, %esi
callq 0x88d0
movq %rax, -0xe8(%rbp)
jmp 0x84bc
movq -0x10(%rbp), %rdi
callq 0x87a0
movq %rax, -0xf0(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0xf0(%rbp), %rsi
callq 0x8860
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x161(%rbp)
jne 0x85c4
jmp 0x85fd
leaq -0x28(%rbp), %rdi
callq 0x8890
movq %rax, -0x170(%rbp)
leaq -0xf4(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x5a00
movq -0x170(%rbp), %rdi
leaq -0xf4(%rbp), %rsi
callq 0x8980
movb %al, -0x161(%rbp)
movb -0x161(%rbp), %al
testb $0x1, %al
jne 0x8609
jmp 0x8638
leaq -0x28(%rbp), %rdi
callq 0x8890
movq -0x110(%rbp), %rdi
movq %rax, %rsi
callq 0x89a0
movl -0x58(%rbp), %ecx
movl %ecx, (%rax)
leaq -0x20(%rbp), %rdi
xorl %esi, %esi
callq 0x87f0
movq %rax, -0x100(%rbp)
leaq -0x20(%rbp), %rdi
xorl %esi, %esi
callq 0x87f0
movq %rax, -0x108(%rbp)
testb $0x1, -0x59(%rbp)
je 0x8660
movq -0x110(%rbp), %rdi
leaq -0x54(%rbp), %rsi
callq 0x8830
jmp 0x8172
addq $0x170, %rsp            # imm = 0x170
popq %rbp
retq
nop