// File: /workspace/github_cpp_makefile_star2_O1/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, %r15
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, %r14
movl %ecx, 0xc(%rsp)
testl %ecx, %ecx
je 0xc56b
movq 0x30a77(%rip), %rdi     # 0x3cf80
leaq 0x1cc7a(%rip), %rsi     # 0x2918a
movl $0x8, %edx
callq 0xb540
movq (%r15), %rsi
movq 0x8(%r15), %rdx
movq 0x30a58(%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 %r15, %rdi
movq 0x28(%rsp), %rsi
movl %r14d, %edx
callq 0xc139
testb %al, %al
je 0xc7b1
cmpq $0x0, 0x58(%rsp)
jle 0xc6f2
xorl %r13d, %r13d
leaq 0x38(%rsp), %rbp
leaq 0x60(%rsp), %r14
movq %rbp, %rdi
movq 0x28(%rsp), %rsi
movq %r13, %rdx
movq 0x80(%rsp), %rcx
callq 0xb4c0
movq %r14, %rdi
movq %rbp, %rsi
callq 0xb5a0
movq 0x38(%rsp), %rdi
leaq 0x48(%rsp), %rax
cmpq %rax, %rdi
je 0xc5db
movq 0x48(%rsp), %rsi
incq %rsi
callq 0xb480
movq %r14, %rbx
movq %r14, %rdi
movq %r15, %rsi
movq 0x30(%rsp), %rdx
callq 0xc29a
movq %rax, %r14
cmpb $0x0, 0xc(%rsp)
je 0xc6a7
movl $0xc, %edx
movq 0x30978(%rip), %rdi     # 0x3cf80
leaq 0x1cbe3(%rip), %rsi     # 0x291f2
callq 0xb540
movq 0x30965(%rip), %rdi     # 0x3cf80
movq %r13, %rsi
callq 0xb1d0
movq %rax, %r12
movl $0xa, %edx
movq %rax, %rdi
leaq 0x1cbca(%rip), %rsi     # 0x291ff
callq 0xb540
movq %r12, %rdi
movq %r14, %rsi
callq 0xb1d0
movq %rax, %r12
movl $0x9, %edx
movq %rax, %rdi
leaq 0x1cbb3(%rip), %rsi     # 0x2920a
callq 0xb540
movq (%r15), %rsi
movq 0x8(%r15), %rdx
movq %r12, %rdi
callq 0xb540
movb $0xa, 0x38(%rsp)
movl $0x1, %edx
movq %rax, %rdi
movq %rbp, %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 %rbp, %rsi
callq 0xb540
cmpq 0x30(%rsp), %r14
jg 0xc6e1
movq %r14, 0x38(%rsp)
movq %r13, 0x40(%rsp)
movq 0x18(%rsp), %rsi
cmpq 0x20(%rsp), %rsi
je 0xc6d4
movups 0x38(%rsp), %xmm0
movups %xmm0, (%rsi)
addq $0x10, 0x18(%rsp)
jmp 0xc6e1
leaq 0x10(%rsp), %rdi
movq %rbp, %rdx
callq 0x1f4cc
incq %r13
cmpq %r13, 0x58(%rsp)
movq %rbx, %r14
jne 0xc59c
movq 0x10(%rsp), %rbx
movq 0x18(%rsp), %r14
cmpq %r14, %rbx
je 0xc72e
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 0x1f60b
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1f6be
cmpb $0x0, 0xc(%rsp)
je 0xc79f
movq 0x10(%rsp), %r12
movq 0x18(%rsp), %r13
cmpq %r13, %r12
je 0xc79f
movq 0x30835(%rip), %rbx     # 0x3cf80
leaq 0x38(%rsp), %r14
movq (%r12), %rsi
movq 0x8(%r12), %r15
movq %rbx, %rdi
callq 0xb1d0
movb $0x3a, 0x38(%rsp)
movl $0x1, %edx
movq %rax, %rdi
movq %r14, %rsi
callq 0xb540
movq %rax, %rdi
movq %r15, %rsi
callq 0xb1d0
movb $0xa, 0x38(%rsp)
movl $0x1, %edx
movq %rax, %rdi
movq %r14, %rsi
callq 0xb540
addq $0x10, %r12
cmpq %r13, %r12
jne 0xc750
movq 0x10(%rsp), %rax
cmpq 0x18(%rsp), %rax
je 0xc820
movq 0x8(%rax), %r15
jmp 0xc827
movq $-0x1, %r15
cmpb $0x0, 0xc(%rsp)
je 0xc827
movq 0x307ba(%rip), %rdi     # 0x3cf80
leaq 0x1c9c6(%rip), %rsi     # 0x29193
movl $0x23, %edx
callq 0xb540
movq 0x307a2(%rip), %rdi     # 0x3cf80
movl %r14d, %esi
callq 0xb7c0
movq %rax, %r14
leaq 0x1c9c7(%rip), %rsi     # 0x291b7
movl $0x3a, %edx
movq %rax, %rdi
callq 0xb540
movq %r14, %rdi
movq 0x30(%rsp), %rsi
callq 0xb1d0
leaq 0x1ccc9(%rip), %rsi     # 0x294da
movl $0x1, %edx
movq %rax, %rdi
callq 0xb540
jmp 0xc827
movq $-0x1, %r15
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0xc83e
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0xb480
movq 0x60(%rsp), %rdi
leaq 0x70(%rsp), %rax
cmpq %rax, %rdi
je 0xc85a
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
jmp 0xc877
jmp 0xc877
jmp 0xc877
jmp 0xc877
movq %rax, %rbx
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0xc891
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0xb480
movq 0x60(%rsp), %rdi
leaq 0x70(%rsp), %rax
cmpq %rax, %rdi
je 0xc8ad
movq 0x70(%rsp), %rsi
incq %rsi
callq 0xb480
movq %rbx, %rdi
callq 0xb7d0