// File: /workspace/github_cpp_makefile_star2_O3/ParkerLab[P]cta/src/cta.cpp
// Function: align(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, long long, bool)
long long int align(const std::string& seq1, const std::string& seq2, long long int max_edit_distance, bool verbose = false) {
    long long int seq1_length = seq1.size();
    long long int seq2_length = seq2.size();
    std::string window;
    long long int distance = -1;
    long long int best_position = -1;
    std::vector<std::pair<long long int, long long int>> alignments;

    int min_shared_kmer_size = seq1_length / (max_edit_distance + 1); // For two strings to have edit distance <= max_edit_distance, they must share a kmer of at least this size

    if (verbose) {
        std::cout << "align: \n" << seq1 << '\n' << seq2 << '\n';
    }

    if (!shares_kmer(seq1, seq2, min_shared_kmer_size)) {
        if (verbose) {
            std::cout << "align: no shared kmer of length >= " << min_shared_kmer_size << " between these sequences, so cannot have edit distance <= " << max_edit_distance << "\n";
        }
        return best_position;
    }

    for (long long int i = 0; i < seq2_length; i++) {
        window = seq2.substr(i, seq1_length);
        distance = levenshtein_distance(window, seq1, max_edit_distance);

        if (verbose) {
            std::cout << "at position " << i << " distance " << distance << " between\n" << seq1 << '\n' << window << '\n';
        }

        if (distance <= max_edit_distance) {
            alignments.push_back(std::pair<long long int, long long int>(distance, i));
        }
    }

    std::sort(alignments.begin(), alignments.end());
    if (verbose) {
        for (auto it : alignments ) {
            std::cout << it.first << ':' << it.second << '\n';
        }
    }

    if (!alignments.empty()) {
        best_position = alignments[0].second;
    }

    return best_position;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movq %rdx, %r8
movq %rdi, %r12
movq 0x8(%rdi), %rax
movq %rsi, 0x28(%rsp)
movq 0x8(%rsi), %rdx
movq %rdx, 0x58(%rsp)
leaq 0x70(%rsp), %rdx
movq %rdx, -0x10(%rdx)
xorl %esi, %esi
movq %rsi, -0x8(%rdx)
movb $0x0, (%rdx)
movq %rsi, 0x20(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x10(%rsp)
movq %r8, 0x30(%rsp)
leaq 0x1(%r8), %rsi
movq %rax, 0x80(%rsp)
cqto
idivq %rsi
movq %rax, %rbx
movl %ecx, 0xc(%rsp)
testl %ecx, %ecx
je 0xc5cc
movq 0x30a18(%rip), %rdi     # 0x3cf80
leaq 0x1cc4b(%rip), %rsi     # 0x291ba
movl $0x8, %edx
callq 0xb540
movq (%r12), %rsi
movq 0x8(%r12), %rdx
movq 0x309f7(%rip), %rdi     # 0x3cf80
callq 0xb540
leaq 0x38(%rsp), %rsi
movb $0xa, (%rsi)
movl $0x1, %edx
movq %rax, %rdi
callq 0xb540
movq 0x28(%rsp), %rcx
movq (%rcx), %rsi
movq 0x8(%rcx), %rdx
movq %rax, %rdi
callq 0xb540
leaq 0x38(%rsp), %rsi
movb $0xa, (%rsi)
movl $0x1, %edx
movq %rax, %rdi
callq 0xb540
movq %r12, %rdi
movq 0x28(%rsp), %rsi
movl %ebx, %edx
callq 0xc138
testb %al, %al
je 0xc79f
cmpq $0x0, 0x58(%rsp)
jle 0xc753
xorl %ebp, %ebp
leaq 0x38(%rsp), %rbx
leaq 0x60(%rsp), %r15
movq %rbx, %rdi
movq 0x28(%rsp), %rsi
movq %rbp, %rdx
movq 0x80(%rsp), %rcx
callq 0xb4c0
movq %r15, %rdi
movq %rbx, %rsi
callq 0xb5a0
movq 0x38(%rsp), %rdi
leaq 0x48(%rsp), %rax
cmpq %rax, %rdi
je 0xc63a
movq 0x48(%rsp), %rsi
incq %rsi
callq 0xb480
movq %r15, %r14
movq %r15, %rdi
movq %r12, %rsi
movq 0x30(%rsp), %rdx
callq 0xc28f
movq %rax, %r15
cmpb $0x0, 0xc(%rsp)
je 0xc708
movl $0xc, %edx
movq 0x30919(%rip), %rdi     # 0x3cf80
leaq 0x1cbb4(%rip), %rsi     # 0x29222
callq 0xb540
movq 0x30906(%rip), %rdi     # 0x3cf80
movq %rbp, %rsi
callq 0xb1d0
movq %rax, %r13
movl $0xa, %edx
movq %rax, %rdi
leaq 0x1cb9b(%rip), %rsi     # 0x2922f
callq 0xb540
movq %r13, %rdi
movq %r15, %rsi
callq 0xb1d0
movq %rax, %r13
movl $0x9, %edx
movq %rax, %rdi
leaq 0x1cb84(%rip), %rsi     # 0x2923a
callq 0xb540
movq (%r12), %rsi
movq 0x8(%r12), %rdx
movq %r13, %rdi
callq 0xb540
movb $0xa, 0x38(%rsp)
movl $0x1, %edx
movq %rax, %rdi
movq %rbx, %rsi
callq 0xb540
movq 0x60(%rsp), %rsi
movq 0x68(%rsp), %rdx
movq %rax, %rdi
callq 0xb540
movb $0xa, 0x38(%rsp)
movl $0x1, %edx
movq %rax, %rdi
movq %rbx, %rsi
callq 0xb540
cmpq 0x30(%rsp), %r15
jg 0xc742
movq %r15, 0x38(%rsp)
movq %rbp, 0x40(%rsp)
movq 0x18(%rsp), %rsi
cmpq 0x20(%rsp), %rsi
je 0xc735
movups 0x38(%rsp), %xmm0
movups %xmm0, (%rsi)
addq $0x10, 0x18(%rsp)
jmp 0xc742
leaq 0x10(%rsp), %rdi
movq %rbx, %rdx
callq 0x1f4d6
incq %rbp
cmpq %rbp, 0x58(%rsp)
movq %r14, %r15
jne 0xc5fb
movq 0x10(%rsp), %rbx
movq 0x18(%rsp), %r14
cmpq %r14, %rbx
je 0xc814
movq %r14, %rax
subq %rbx, %rax
sarq $0x4, %rax
bsrq %rax, %rdx
xorl $0x3f, %edx
addl %edx, %edx
xorq $0x7e, %rdx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1f615
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1f6c8
movq 0x10(%rsp), %r14
movq 0x18(%rsp), %rbx
jmp 0xc817
movq $-0x1, %r15
cmpb $0x0, 0xc(%rsp)
je 0xc894
movq 0x307c8(%rip), %rdi     # 0x3cf80
leaq 0x1ca04(%rip), %rsi     # 0x291c3
movl $0x23, %edx
callq 0xb540
movq 0x307b0(%rip), %rdi     # 0x3cf80
movl %ebx, %esi
callq 0xb7c0
movq %rax, %rbx
leaq 0x1ca06(%rip), %rsi     # 0x291e7
movl $0x3a, %edx
movq %rax, %rdi
callq 0xb540
movq %rbx, %rdi
movq 0x30(%rsp), %rsi
callq 0xb1d0
leaq 0x1cd08(%rip), %rsi     # 0x2950a
movl $0x1, %edx
movq %rax, %rdi
callq 0xb540
jmp 0xc894
movq %rbx, %r14
cmpq %rbx, %r14
setne %al
movl 0xc(%rsp), %ecx
andb %al, %cl
cmpb $0x1, %cl
jne 0xc88b
movq 0x30751(%rip), %r15     # 0x3cf80
leaq 0x38(%rsp), %r12
movq (%r14), %rsi
movq 0x8(%r14), %r13
movq %r15, %rdi
callq 0xb1d0
movb $0x3a, 0x38(%rsp)
movl $0x1, %edx
movq %rax, %rdi
movq %r12, %rsi
callq 0xb540
movq %rax, %rdi
movq %r13, %rsi
callq 0xb1d0
movb $0xa, 0x38(%rsp)
movl $0x1, %edx
movq %rax, %rdi
movq %r12, %rsi
callq 0xb540
addq $0x10, %r14
cmpq %rbx, %r14
jne 0xc834
movq 0x10(%rsp), %r14
movq 0x18(%rsp), %rbx
cmpq %rbx, %r14
je 0xc8df
movq 0x8(%r14), %r15
movq 0x10(%rsp), %r14
testq %r14, %r14
je 0xc8ae
movq 0x20(%rsp), %rsi
subq %r14, %rsi
movq %r14, %rdi
callq 0xb480
movq 0x60(%rsp), %rdi
leaq 0x70(%rsp), %rax
cmpq %rax, %rdi
je 0xc8ca
movq 0x70(%rsp), %rsi
incq %rsi
callq 0xb480
movq %r15, %rax
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq $-0x1, %r15
jmp 0xc899
jmp 0xc8f0
jmp 0xc8f0
jmp 0xc8f0
jmp 0xc8f0
movq %rax, %rbx
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0xc90a
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0xb480
movq 0x60(%rsp), %rdi
leaq 0x70(%rsp), %rax
cmpq %rax, %rdi
je 0xc926
movq 0x70(%rsp), %rsi
incq %rsi
callq 0xb480
movq %rbx, %rdi
callq 0xb7d0