// File: BUSEC[P]RPKI_Downgrade_Detector/./exp.cpp
// Function: IntervalList<IPAddr>::add(IPAddr, IPAddr)
void add (T begin, T end) {
    if (end<begin) // nothing to do
      return;
    
    bool needToCreateInterval = true;
    
    // we want to find if begin overlaps or starts right after with any existing interval, in which case we will need to modify
    // the end of that existing interval
    typename map<T,T>::iterator iter = m.lower_bound(begin);
    // iter now points to the first interval whose start is at or after begin
    
    // if  begin was found exactly
    if (iter!=m.end() && iter->first == begin) { // this is the interval to modify
      if (end<=iter->second) return; // [begin,end] is wholly contained within [iter->first,iter->second]
      else iter->second = end;
      iter++;
      needToCreateInterval=false;
    }

    // we need to also consider the previous interval, if it exists, because its end may be after begin, equal to begin, or equal to begin-increment,
    // in which case we need to merge it with the new interval
    else if (!m.empty() && iter!=m.begin()) {
      iter--;

      // Order here is important since iter->second+increment might 
      // overflow, we must ensure that it can not but ensuring that end is
      // greater than iter->second prior to incrementing (since 
      // end>iter->second implies that there is atleast one increment of 
      // distance beyond iter->second).
      // Before this was fixed, there was an overflow bug here
      // in the case when iter points to the last interval that ends at the last possible value of T
      // The preconditions that used to trigger this former bug
      // can be found in AddToIntervalEdgeCaseBug1Test.
    if ( end <= iter->second ) return; // [begin,end] is wholly contained within [iter->first,iter->second]
    else if (begin<=iter->second+increment) { // at this point we know end>iter->second, so iter->second is safe to increment
      iter->second = end;
      needToCreateInterval=false;
    }  
      iter++;
    } 
    
    // Now we know begin does not overlap or start right after any existing interval
    // hence we create a new interval
    if (needToCreateInterval) m[begin]=end;
    
    // we are now sure that iter points to an interval whose start is strictly greater than begin    
    // we now iterate through all the intervals that start after begin and remove them if they are covered by our
    // newly modified/created interval
    while (iter != m.end() && iter->second <= end) {
      T intervalToRemove = iter->first;
      iter++;
      m.erase(intervalToRemove);
    }
    
    // the interval that iter now points may need to be merged with the one we just added, which is iter-1
    if (iter!=m.end() && iter->first<=end+increment) { 
      // the check iter!=m.end() ensures that we quit the loop above because iter->second > end
      // since iter->second > end, we know end is at least one increment away from overflowing, so end+increment cannot overflow
      T endToSave = iter->second;
      T intervalToRemove = iter->first;
      iter--;
      iter->second = endToSave;
      m.erase(intervalToRemove);
    }
  }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xe0, %rsp
movq %rsi, -0xb0(%rbp)
movq %rdx, -0xa0(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0xa8(%rbp)
leaq -0x1c(%rbp), %rdi
callq 0x5a00
movq -0xa0(%rbp), %rdi
leaq -0x1c(%rbp), %rsi
callq 0x88b0
testb $0x1, %al
jne 0xc2cf
jmp 0xc2d4
jmp 0xc676
movq -0xa8(%rbp), %rdi
movq -0xb0(%rbp), %rsi
movb $0x1, -0x1d(%rbp)
callq 0x95e0
movq -0xa8(%rbp), %rdi
movq %rax, -0x28(%rbp)
callq 0x8740
movq %rax, -0x30(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x8710
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0xb1(%rbp)
jne 0xc31d
jmp 0xc353
leaq -0x28(%rbp), %rdi
callq 0x87d0
movq -0xb0(%rbp), %rsi
movq %rax, -0xc0(%rbp)
leaq -0x34(%rbp), %rdi
callq 0x5a00
movq -0xc0(%rbp), %rdi
leaq -0x34(%rbp), %rsi
callq 0xc6f0
movb %al, -0xb1(%rbp)
movb -0xb1(%rbp), %al
testb $0x1, %al
jne 0xc35f
jmp 0xc3c0
leaq -0x28(%rbp), %rdi
callq 0x87d0
movq %rax, %rsi
addq $0x4, %rsi
leaq -0x38(%rbp), %rdi
callq 0x5a00
movq -0xa0(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x8980
testb $0x1, %al
jne 0xc38e
jmp 0xc393
jmp 0xc676
leaq -0x28(%rbp), %rdi
callq 0x87d0
movq -0xa0(%rbp), %rcx
movl (%rcx), %ecx
movl %ecx, 0x4(%rax)
leaq -0x28(%rbp), %rdi
xorl %esi, %esi
callq 0x87f0
movq %rax, -0x40(%rbp)
movb $0x0, -0x1d(%rbp)
jmp 0xc4b5
movq -0xa8(%rbp), %rdi
callq 0x8670
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0xc1(%rbp)
jne 0xc3fe
movq -0xa8(%rbp), %rdi
callq 0x86b0
movq %rax, -0x48(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0x8710
movb %al, -0xc1(%rbp)
movb -0xc1(%rbp), %al
testb $0x1, %al
jne 0xc40d
jmp 0xc4b3
leaq -0x28(%rbp), %rdi
xorl %esi, %esi
callq 0xb1c0
movq %rax, -0x50(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x87d0
movq %rax, %rsi
addq $0x4, %rsi
leaq -0x54(%rbp), %rdi
callq 0x5a00
movq -0xa0(%rbp), %rdi
leaq -0x54(%rbp), %rsi
callq 0x8980
testb $0x1, %al
jne 0xc44b
jmp 0xc450
jmp 0xc676
leaq -0x28(%rbp), %rdi
callq 0x87d0
movq %rax, %rsi
movq -0xa8(%rbp), %rax
addq $0x4, %rsi
movl 0x30(%rax), %edx
leaq -0x58(%rbp), %rdi
callq 0xb260
movq -0xb0(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x8980
testb $0x1, %al
jne 0xc489
jmp 0xc4a2
leaq -0x28(%rbp), %rdi
callq 0x87d0
movq -0xa0(%rbp), %rcx
movl (%rcx), %ecx
movl %ecx, 0x4(%rax)
movb $0x0, -0x1d(%rbp)
jmp 0xc4a4
leaq -0x28(%rbp), %rdi
xorl %esi, %esi
callq 0x87f0
movq %rax, -0x60(%rbp)
jmp 0xc4b5
testb $0x1, -0x1d(%rbp)
je 0xc4d9
movq -0xb0(%rbp), %rsi
movq -0xa8(%rbp), %rdi
callq 0x89a0
movq -0xa0(%rbp), %rcx
movl (%rcx), %ecx
movl %ecx, (%rax)
jmp 0xc4db
movq -0xa8(%rbp), %rdi
callq 0x8740
movq %rax, -0x68(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x8710
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0xc2(%rbp)
jne 0xc509
jmp 0xc543
leaq -0x28(%rbp), %rdi
callq 0x87d0
movq -0xa0(%rbp), %rsi
addq $0x4, %rax
movq %rax, -0xd0(%rbp)
leaq -0x6c(%rbp), %rdi
callq 0x5a00
movq -0xd0(%rbp), %rdi
leaq -0x6c(%rbp), %rsi
callq 0x8980
movb %al, -0xc2(%rbp)
movb -0xc2(%rbp), %al
testb $0x1, %al
jne 0xc54f
jmp 0xc588
leaq -0x28(%rbp), %rdi
callq 0x87d0
movq %rax, %rsi
leaq -0x70(%rbp), %rdi
callq 0x5a00
leaq -0x28(%rbp), %rdi
xorl %esi, %esi
callq 0x87f0
movq -0xa8(%rbp), %rdi
movq %rax, -0x78(%rbp)
leaq -0x70(%rbp), %rsi
callq 0x8830
jmp 0xc4db
movq -0xa8(%rbp), %rdi
callq 0x8740
movq %rax, -0x80(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x8710
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0xd1(%rbp)
jne 0xc5b6
jmp 0xc5ff
leaq -0x28(%rbp), %rdi
callq 0x87d0
movq -0xa0(%rbp), %rsi
movq %rax, %rcx
movq -0xa8(%rbp), %rax
movq %rcx, -0xe0(%rbp)
movl 0x30(%rax), %edx
leaq -0x84(%rbp), %rdi
callq 0xb260
movq -0xe0(%rbp), %rdi
leaq -0x84(%rbp), %rsi
callq 0x8980
movb %al, -0xd1(%rbp)
movb -0xd1(%rbp), %al
testb $0x1, %al
jne 0xc60b
jmp 0xc676
leaq -0x28(%rbp), %rdi
callq 0x87d0
movq %rax, %rsi
addq $0x4, %rsi
leaq -0x88(%rbp), %rdi
callq 0x5a00
leaq -0x28(%rbp), %rdi
callq 0x87d0
movq %rax, %rsi
leaq -0x8c(%rbp), %rdi
callq 0x5a00
leaq -0x28(%rbp), %rdi
xorl %esi, %esi
callq 0xb1c0
movq %rax, -0x98(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x87d0
movq -0xa8(%rbp), %rdi
movl -0x88(%rbp), %ecx
movl %ecx, 0x4(%rax)
leaq -0x8c(%rbp), %rsi
callq 0x8830
addq $0xe0, %rsp
popq %rbp
retq
nop