// File: VanAndelInstitute[P]intent/src/edlib.cpp
// Function: buildPeq(int, unsigned char const*, int, EqualityDefinition const&)
static inline Word* buildPeq(const int alphabetLength,
                             const unsigned char* const query,
                             const int queryLength,
                             const EqualityDefinition& equalityDefinition) {
    int maxNumBlocks = ceilDiv(queryLength, WORD_SIZE);
    // table of dimensions alphabetLength+1 x maxNumBlocks. Last symbol is wildcard.
    Word* Peq = new Word[(alphabetLength + 1) * maxNumBlocks];

    // Build Peq (1 is match, 0 is mismatch). NOTE: last column is wildcard(symbol that matches anything) with just 1s
    for (unsigned char symbol = 0; symbol <= alphabetLength; symbol++) {
        for (int b = 0; b < maxNumBlocks; b++) {
            if (symbol < alphabetLength) {
                Peq[symbol * maxNumBlocks + b] = 0;
                for (int r = (b+1) * WORD_SIZE - 1; r >= b * WORD_SIZE; r--) {
                    Peq[symbol * maxNumBlocks + b] <<= 1;
                    // NOTE: We pretend like query is padded at the end with W wildcard symbols
                    if (r >= queryLength || equalityDefinition.areEqual(query[r], symbol))
                        Peq[symbol * maxNumBlocks + b] += 1;
                }
            } else { // Last symbol is wildcard, so it is all 1s
                Peq[symbol * maxNumBlocks + b] = static_cast<Word>(-1);
            }
        }
    }

    return Peq;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movl %edi, -0x4(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movq %rcx, -0x20(%rbp)
movl -0x14(%rbp), %edi
movl $0x40, %esi
callq 0x655f0
movl %eax, -0x24(%rbp)
movl -0x4(%rbp), %eax
addl $0x1, %eax
imull -0x24(%rbp), %eax
cltq
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x8040
movq %rax, -0x30(%rbp)
movb $0x0, -0x31(%rbp)
movzbl -0x31(%rbp), %eax
cmpl -0x4(%rbp), %eax
jg 0x6579a
movl $0x0, -0x38(%rbp)
movl -0x38(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x6578b
movzbl -0x31(%rbp), %eax
cmpl -0x4(%rbp), %eax
jge 0x65761
movq -0x30(%rbp), %rax
movzbl -0x31(%rbp), %ecx
imull -0x24(%rbp), %ecx
addl -0x38(%rbp), %ecx
movslq %ecx, %rcx
movq $0x0, (%rax,%rcx,8)
movl -0x38(%rbp), %eax
addl $0x1, %eax
shll $0x6, %eax
subl $0x1, %eax
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
movl -0x38(%rbp), %ecx
shll $0x6, %ecx
cmpl %ecx, %eax
jl 0x6575f
movq -0x30(%rbp), %rax
movzbl -0x31(%rbp), %ecx
imull -0x24(%rbp), %ecx
addl -0x38(%rbp), %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rdx
shlq %rdx
movq %rdx, (%rax,%rcx,8)
movl -0x3c(%rbp), %eax
cmpl -0x14(%rbp), %eax
jge 0x65734
movq -0x20(%rbp), %rdi
movq -0x10(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movb (%rax,%rcx), %al
movzbl %al, %esi
movzbl -0x31(%rbp), %edx
callq 0x68fd0
testb $0x1, %al
jne 0x65734
jmp 0x65752
movq -0x30(%rbp), %rax
movzbl -0x31(%rbp), %ecx
imull -0x24(%rbp), %ecx
addl -0x38(%rbp), %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rdx
addq $0x1, %rdx
movq %rdx, (%rax,%rcx,8)
jmp 0x65754
movl -0x3c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x656e1
jmp 0x6577b
movq -0x30(%rbp), %rax
movzbl -0x31(%rbp), %ecx
imull -0x24(%rbp), %ecx
addl -0x38(%rbp), %ecx
movslq %ecx, %rcx
movq $-0x1, (%rax,%rcx,8)
jmp 0x6577d
movl -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x38(%rbp)
jmp 0x6569f
jmp 0x6578d
movb -0x31(%rbp), %al
addb $0x1, %al
movb %al, -0x31(%rbp)
jmp 0x6568b
movq -0x30(%rbp), %rax
addq $0x40, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)