// File: /workspace/github_cpp_makefile_star2_O2/SeanChao[P]KV-Store/./skiplist.h
// Function: SkipList<unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>::skipSearch(unsigned long) const
std::shared_ptr<typename SkipList<Key, Value>::Node>
SkipList<Key, Value>::skipSearch(Key key) const {
    std::shared_ptr<Node> temp = head->succ;
    std::shared_ptr<Node> levelHead = head;  // marks the head of current level
    std::vector<Key> path;
    while (temp) {
        while ((temp->succ && temp->key <= key) || temp == levelHead) {
            temp = temp->succ;
            path.push_back(temp->key);
        }
        if (!temp->pred) {
            std::cerr << *this << '\n';
            std::cerr << "ERR with key " << key << '\n';
            std::cerr << "level head @" << levelHead << '\n';
            for (auto n = path.begin(); n != path.end(); n++) {
                std::cout << *n << '\t';
            }
            std::cout << '\n';
        }
        temp = temp->pred;

        path.push_back(temp->key);
        // find a match
        // temp->pred is to prevent visiting head's
        if (temp && temp->pred && temp->key == key && valid(temp)) {
            return temp;
        }
        // return if no lower level exists
        if (!levelHead->below) return temp;
        // go to lower level or the head of lower level
        if (temp->below) {
            temp = temp->below;
            path.push_back(temp->key);
        } else
            temp = levelHead->below;
        levelHead = levelHead->below;
        // if (!temp->below) return temp;
        // temp = temp->below;
    }
    return nullptr;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rdx, %r14
movq %rsi, %rbx
movq %rdi, 0x20(%rsp)
movq (%rsi), %rsi
addq $0x38, %rsi
movq %rsp, %r12
movq %r12, %rdi
callq 0x78e2
leaq 0x10(%rsp), %rdi
movq %rbx, 0x28(%rsp)
movq %rbx, %rsi
callq 0x78e2
xorps %xmm0, %xmm0
leaq 0x40(%rsp), %rbp
movaps %xmm0, (%rbp)
andq $0x0, 0x10(%rbp)
movq 0x71c1(%rip), %r15      # 0xefd0
pushq $0x9
popq %rbx
cmpq $0x0, (%rsp)
je 0x7fc8
movq (%rsp), %rsi
cmpq $0x0, 0x38(%rsi)
je 0x7e2d
cmpq %r14, (%rsi)
jbe 0x7e34
cmpq 0x10(%rsp), %rsi
jne 0x7e4e
addq $0x38, %rsi
movq %r12, %rdi
callq 0x787c
movq (%rsp), %rsi
movq %rbp, %rdi
callq 0x8062
jmp 0x7e1d
cmpq $0x0, 0x28(%rsi)
jne 0x7f03
movq 0x7190(%rip), %rdi      # 0xeff0
movq 0x28(%rsp), %rsi
callq 0x8082
movq %rax, %rdi
pushq $0xa
popq %rsi
callq 0x32b0
movq 0x7174(%rip), %rdi      # 0xeff0
leaq 0x2547(%rip), %rsi      # 0xa3ca
callq 0x3270
movq %rax, %rdi
movq %r14, %rsi
callq 0x31b0
movq %rax, %rdi
pushq $0xa
popq %rsi
callq 0x32b0
movq 0x714b(%rip), %rdi      # 0xeff0
leaq 0x252c(%rip), %rsi      # 0xa3d8
callq 0x3270
movq %rax, %r13
movq 0x10(%rsp), %rsi
movq %rax, %rdi
callq 0x31e0
movq %r13, %rdi
pushq $0xa
popq %rsi
callq 0x32b0
movq 0x40(%rsp), %r13
cmpq 0x48(%rsp), %r13
je 0x7ef4
movq (%r13), %rsi
movq %r15, %rdi
callq 0x31b0
movq %rax, %rdi
movl %ebx, %esi
callq 0x32b0
addq $0x8, %r13
jmp 0x7ed1
movq %r15, %rdi
pushq $0xa
popq %rsi
callq 0x32b0
movq (%rsp), %rsi
addq $0x28, %rsi
movq %r12, %rdi
callq 0x787c
movq (%rsp), %rsi
movq %rbp, %rdi
callq 0x8062
movq (%rsp), %rax
testq %rax, %rax
je 0x7f70
cmpq $0x0, 0x28(%rax)
je 0x7f70
cmpq %r14, (%rax)
jne 0x7f70
leaq 0x30(%rsp), %rdi
movq %r12, %rsi
callq 0x78e2
movq 0x30(%rsp), %rax
testq %rax, %rax
je 0x7f66
cmpq $0x0, 0x28(%rax)
je 0x7f66
movq 0x38(%rax), %r13
leaq 0x38(%rsp), %rdi
callq 0x77e6
testq %r13, %r13
je 0x7f70
jmp 0x8021
leaq 0x38(%rsp), %rdi
callq 0x77e6
movq 0x10(%rsp), %rsi
cmpq $0x0, 0x58(%rsi)
movq (%rsp), %rax
je 0x7fd5
cmpq $0x0, 0x58(%rax)
je 0x7fa4
addq $0x58, %rax
movq %r12, %rdi
movq %rax, %rsi
callq 0x787c
movq (%rsp), %rsi
movq %rbp, %rdi
callq 0x8062
jmp 0x7fb0
addq $0x58, %rsi
movq %r12, %rdi
callq 0x787c
movq 0x10(%rsp), %rsi
addq $0x58, %rsi
leaq 0x10(%rsp), %rdi
callq 0x787c
jmp 0x7e12
xorps %xmm0, %xmm0
movq 0x20(%rsp), %rbx
movups %xmm0, (%rbx)
jmp 0x7ff1
movq 0x20(%rsp), %rbx
movq %rax, (%rbx)
movq 0x8(%rsp), %rax
andq $0x0, 0x8(%rsp)
movq %rax, 0x8(%rbx)
andq $0x0, (%rsp)
leaq 0x40(%rsp), %rdi
callq 0x833c
leaq 0x18(%rsp), %rdi
callq 0x77e6
leaq 0x8(%rsp), %rdi
callq 0x77e6
movq %rbx, %rax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movaps (%rsp), %xmm0
andq $0x0, 0x8(%rsp)
movq 0x20(%rsp), %rbx
movups %xmm0, (%rbx)
jmp 0x7fec
jmp 0x8039
jmp 0x8039
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x833c
leaq 0x18(%rsp), %rdi
callq 0x77e6
leaq 0x8(%rsp), %rdi
callq 0x77e6
movq %rbx, %rdi
callq 0x33e0