// File: /workspace/github_cpp_makefile_star2_O2/Matheus-Aguilar[P]Huffman/Huffman.cpp
// Function: HuffmanTree::build(int const*)
void HuffmanTree::build(const int freq[256]){

    //Copying the frequencies
    for(int i = 0; i < 256; ++i)
        this->freq[i] = freq[i];

    //Priority queue of frequencies and roots to mantain the order of the trees
    priority_queue<pair<int, Node *>> pq;
    
    //Adding characters that appear at least once in the string
    for(int i = 0; i < 256; ++i){
        if(this->freq[i] > 0){
            //Priority and root the tree
            pq.push(make_pair(-freq[i], new Node(i)));
        }
    }

    //If the string is empty
    if(pq.size() == 0){
        root = NULL;
        return;
    }

    //Keeps merging trees until there is just one
    while(pq.size() > 1){
        
        //Remove the two ones without the highest priority
        pair<int, Node *> topTree1 = pq.top();
        pq.pop();
        pair<int, Node *> topTree2 = pq.top();
        pq.pop();

        /*Merge both nodes into a bigger tree*/

        //Add the frequencies of the smaller trees roots into the merged one
        pair<int, Node *> mergedTree = make_pair(topTree1.first + topTree2.first, new Node(0));
        //Highest priority tree becomes left child
        mergedTree.second->left = topTree1.second; 
        //Second highest becomes right child
        mergedTree.second->right = topTree2.second; 
        //Merged tree becomes the parent of the smaller ones
        topTree1.second->parent = topTree2.second->parent = mergedTree.second;

        //Add the merged node into the priority queue
        pq.push(mergedTree);
    }

    //Define the root of the Huffman Tree as the merge of all character trees
    root = pq.top().second;

    /*Build character codes*/

    /*File with only one type of character. This is a special case
    because the decompresion algorithm assumes that the root has at
    least one child*/
    if(root->left == NULL && root->right == NULL){
        code[root->character].push_back(0); //The code is 0 by default
        Node *aux = root; //Save the merged result
        root = new Node(0); //Set a new root of the tree
        root->left = aux; //Update the left child of the root
        return;
    }
    
    /*More than one type of character cases*/
    vector<bool> codeString;
    buildCodes(root, codeString); //Start from the root to build codes
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rsi, %r14
movq %rdi, %rbx
pushq $0x2
popq %rax
cmpq $0x102, %rax            # imm = 0x102
je 0x20d2
movl -0x8(%r14,%rax,4), %ecx
movl %ecx, (%rbx,%rax,4)
incq %rax
jmp 0x20bd
xorps %xmm0, %xmm0
movq %rsp, %r15
andq $0x0, 0x10(%r15)
movaps %xmm0, (%r15)
xorl %ebp, %ebp
leaq 0x20(%rsp), %r13
cmpq $0x100, %rbp            # imm = 0x100
je 0x2130
cmpl $0x0, 0x8(%rbx,%rbp,4)
jle 0x212b
movl (%r14,%rbp,4), %r12d
pushq $0x20
popq %rdi
callq 0x1100
negl %r12d
andq $0x0, 0x10(%rax)
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movb %bpl, 0x18(%rax)
movl %r12d, 0x20(%rsp)
movq %rax, 0x28(%rsp)
movq %r15, %rdi
movq %r13, %rsi
callq 0x252c
incq %rbp
jmp 0x20e8
movq (%rsp), %rax
movq 0x8(%rsp), %rcx
cmpq %rax, %rcx
je 0x21f7
movq %rsp, %r14
subq %rax, %rcx
cmpq $0x11, %rcx
jb 0x21b4
movl (%rax), %ebp
movq 0x8(%rax), %r13
movq %r14, %rdi
callq 0x2542
movq (%rsp), %rax
movl (%rax), %r12d
movq 0x8(%rax), %r15
movq %r14, %rdi
callq 0x2542
pushq $0x20
popq %rdi
callq 0x1100
andq $0x0, 0x10(%rax)
addl %ebp, %r12d
movb $0x0, 0x18(%rax)
movl %r12d, 0x20(%rsp)
movq %rax, 0x28(%rsp)
movq %r13, (%rax)
movq %r15, 0x8(%rax)
movq %rax, 0x10(%r15)
movq %rax, 0x10(%r13)
movq %r14, %rdi
leaq 0x20(%rsp), %rsi
callq 0x255a
movq (%rsp), %rax
movq 0x8(%rsp), %rcx
jmp 0x2145
movq 0x8(%rax), %rsi
movq %rsi, (%rbx)
cmpq $0x0, (%rsi)
jne 0x21c8
cmpq $0x0, 0x8(%rsi)
je 0x2212
leaq 0x20(%rsp), %rdx
andq $0x0, (%rdx)
andl $0x0, 0x8(%rdx)
andq $0x0, 0x10(%rdx)
andl $0x0, 0x18(%rdx)
andq $0x0, 0x20(%rdx)
movq %rbx, %rdi
callq 0x233e
leaq 0x20(%rsp), %rdi
callq 0x19c8
jmp 0x21fb
andq $0x0, (%rbx)
movq %rsp, %rdi
callq 0x2624
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movzbl 0x18(%rsi), %eax
imulq $0x28, %rax, %rax
leaq (%rbx,%rax), %rdi
addq $0x408, %rdi            # imm = 0x408
xorl %esi, %esi
callq 0x196c
movq (%rbx), %r14
pushq $0x20
popq %rdi
callq 0x1100
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%rax)
movb $0x0, 0x18(%rax)
movq %rax, (%rbx)
movq %r14, (%rax)
jmp 0x21fb
jmp 0x2265
jmp 0x2265
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0x19c8
jmp 0x2268
jmp 0x2265
jmp 0x2265
jmp 0x2265
jmp 0x2265
movq %rax, %rbx
movq %rsp, %rdi
callq 0x2624
movq %rbx, %rdi
callq 0x11b0