// File: grmauri[P]pmm/pmm.cpp
// Function: busca_tabu(int, double, tSolucao&, double&, double&)
void busca_tabu(const int tam_lista, const double tempo_max, Solucao &s, double &tempo_melhor, double &tempo_total)
{
    clock_t hI, hF;
    Solucao s_vizinha;
    int flag, pos, mocOri, foOri, melViz, melObj, melMoc, melPos, qtd_lista, **lista_tabu;
    printf("\n\n>>> EXECUTANDO A BT...\n\n");
    hI = clock();
    heuConAle(s);
    calcFO(s);
    hF = clock();
    tempo_melhor = ((double)(hF - hI))/CLOCKS_PER_SEC;
    #ifdef DBG
        printf("FO: %d\tTempo: %.2f\n", s.funObj, tempo_melhor);
    #endif
    tempo_total = tempo_melhor;
    memcpy(&s_vizinha, &s, sizeof(s));
    //---------------------------
    // Criar a lista tabu - linha 1 guarda o objeto, e linha 2 guarda a mochila
    lista_tabu = new int*[2];
    lista_tabu[0] = new int[tam_lista];
    lista_tabu[1] = new int[tam_lista];
    qtd_lista = 0;
    //---------------------------
    while(tempo_total < tempo_max)
    {
        //---------------------------
        // Verificar a melhor vizinha
        melViz = -INT_MAX;
        flag = -1; // todos os vizinhos na lista e nao ha melhora
        for(int j = 0; j < numObj; j++)
        {
            mocOri = s_vizinha.vetIdMocObj[j];
            foOri = s_vizinha.funObj;
            for(int i = -1; i < numMoc; i++)
            {
                if(i != s_vizinha.vetIdMocObj[j])
                {
                    s_vizinha.vetIdMocObj[j] = i;
                    calcFO(s_vizinha);
                    pos = procurar_lista(lista_tabu, qtd_lista, j, i);
                    if(pos != -1) // esta na lista tabu
                    {
                        if(s_vizinha.funObj > s.funObj) // vizinha melhor que a melhor
                        {
                            flag = 0; // esta na lista tabu, mas e melhor do que a melhor
                            melViz = s_vizinha.funObj;
                            melMoc = i;
                            melObj = j;
                            melPos = pos; // posicao na lista tabu
                        }
                    }
                    else // nao esta na lista
                    {
                        if(s_vizinha.funObj > melViz)
                        {
                            flag = 1; // melhor vizinha que nao esta na lista tabu
                            melViz = s_vizinha.funObj;
                            melMoc = i;
                            melObj = j;
                            melPos = -1; // nao esta na lista tabu
                        }
                    }
                }
            }
            s_vizinha.vetIdMocObj[j] = mocOri;
            s_vizinha.funObj = foOri;
        }
        //---------------------------
        // Atualizar a lista e gerar a melhor vizinha
        if(flag == -1) // todos os vizinhos na lista e nenhuma melhora encontrada, entao aplica-se o primeiro movimento da lista (FIFO)
        {
            melObj = lista_tabu[0][0];
            melMoc = lista_tabu[1][0];
            s_vizinha.vetIdMocObj[melObj] = melMoc;
            calcFO(s_vizinha);
            remover_lista(lista_tabu, qtd_lista, 0);
        }
        else
        {
            if(flag == 0) // vizinha melhor que a melhor solucao, entao remove-se o movimento que gerou a vizinha
                remover_lista(lista_tabu, qtd_lista, melPos);
            else // movimento que gerou a vizinha nao esta na lista, entao deve-se inserir
                inserir_lista(lista_tabu, qtd_lista, tam_lista, melObj, melMoc);
            s_vizinha.vetIdMocObj[melObj] = melMoc;
            s_vizinha.funObj = melViz;
        }
        //--------------------------------------
        // Atualizar a melhor solucao
        if(s_vizinha.funObj > s.funObj)
        {
            memcpy(&s, &s_vizinha, sizeof(s_vizinha));
            hF = clock();
            tempo_melhor = ((double)(hF - hI))/CLOCKS_PER_SEC;
            #ifdef DBG
                printf("FO: %d\tTempo: %.2f\n", s.funObj, tempo_melhor);
            #endif
        }
        //--------------------------------------
        hF = clock();
        tempo_total = ((double)hF - hI)/CLOCKS_PER_SEC;
    }
    delete[] lista_tabu[0];
    delete[] lista_tabu[1];
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x920, %rsp            # imm = 0x920
movl %edi, -0x4(%rbp)
movsd %xmm0, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
leaq 0x389c(%rip), %rdi      # 0x70e2
movb $0x0, %al
callq 0x2050
callq 0x2100
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rdi
callq 0x4690
movq -0x18(%rbp), %rdi
callq 0x46f0
callq 0x2100
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
subq -0x30(%rbp), %rax
cvtsi2sd %rax, %xmm0
movsd 0x37aa(%rip), %xmm1     # 0x7030
divsd %xmm1, %xmm0
movq -0x20(%rbp), %rax
movsd %xmm0, (%rax)
movq -0x18(%rbp), %rax
movl 0x898(%rax), %esi
movq -0x20(%rbp), %rax
movsd (%rax), %xmm0
leaq 0x3823(%rip), %rdi      # 0x70ce
movb $0x1, %al
callq 0x2050
movq -0x20(%rbp), %rax
movsd (%rax), %xmm0
movq -0x28(%rbp), %rax
movsd %xmm0, (%rax)
movq -0x18(%rbp), %rsi
leaq -0x8d4(%rbp), %rdi
movl $0x89c, %edx            # imm = 0x89C
callq 0x2140
movl $0x10, %edi
callq 0x2030
movq %rax, -0x900(%rbp)
movslq -0x4(%rbp), %rax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, %rcx
movq -0x900(%rbp), %rax
movq %rcx, (%rax)
movslq -0x4(%rbp), %rax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, %rcx
movq -0x900(%rbp), %rax
movq %rcx, 0x8(%rax)
movl $0x0, -0x8f8(%rbp)
movq -0x28(%rbp), %rax
movsd (%rax), %xmm1
movsd -0x10(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x3c7a
movl $0x80000001, -0x8e8(%rbp) # imm = 0x80000001
movl $0xffffffff, -0x8d8(%rbp) # imm = 0xFFFFFFFF
movl $0x0, -0x904(%rbp)
movl -0x904(%rbp), %eax
cmpl 0x680c(%rip), %eax      # 0xa1a4
jge 0x3b11
movslq -0x904(%rbp), %rax
movl -0x80c(%rbp,%rax,4), %eax
movl %eax, -0x8e0(%rbp)
movl -0x3c(%rbp), %eax
movl %eax, -0x8e4(%rbp)
movl $0xffffffff, -0x908(%rbp) # imm = 0xFFFFFFFF
movl -0x908(%rbp), %eax
cmpl 0x67d7(%rip), %eax      # 0xa1a8
jge 0x3ae0
movl -0x908(%rbp), %eax
movslq -0x904(%rbp), %rcx
cmpl -0x80c(%rbp,%rcx,4), %eax
je 0x3aca
movl -0x908(%rbp), %ecx
movslq -0x904(%rbp), %rax
movl %ecx, -0x80c(%rbp,%rax,4)
leaq -0x8d4(%rbp), %rdi
callq 0x46f0
movq -0x900(%rbp), %rdi
movl -0x8f8(%rbp), %esi
movl -0x904(%rbp), %edx
movl -0x908(%rbp), %ecx
callq 0x4880
movl %eax, -0x8dc(%rbp)
cmpl $-0x1, -0x8dc(%rbp)
je 0x3a86
movl -0x3c(%rbp), %eax
movq -0x18(%rbp), %rcx
cmpl 0x898(%rcx), %eax
jle 0x3a84
movl $0x0, -0x8d8(%rbp)
movl -0x3c(%rbp), %eax
movl %eax, -0x8e8(%rbp)
movl -0x908(%rbp), %eax
movl %eax, -0x8f0(%rbp)
movl -0x904(%rbp), %eax
movl %eax, -0x8ec(%rbp)
movl -0x8dc(%rbp), %eax
movl %eax, -0x8f4(%rbp)
jmp 0x3ac8
movl -0x3c(%rbp), %eax
cmpl -0x8e8(%rbp), %eax
jle 0x3ac6
movl $0x1, -0x8d8(%rbp)
movl -0x3c(%rbp), %eax
movl %eax, -0x8e8(%rbp)
movl -0x908(%rbp), %eax
movl %eax, -0x8f0(%rbp)
movl -0x904(%rbp), %eax
movl %eax, -0x8ec(%rbp)
movl $0xffffffff, -0x8f4(%rbp) # imm = 0xFFFFFFFF
jmp 0x3ac8
jmp 0x3aca
jmp 0x3acc
movl -0x908(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x908(%rbp)
jmp 0x39c5
movl -0x8e0(%rbp), %ecx
movslq -0x904(%rbp), %rax
movl %ecx, -0x80c(%rbp,%rax,4)
movl -0x8e4(%rbp), %eax
movl %eax, -0x3c(%rbp)
movl -0x904(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x904(%rbp)
jmp 0x398c
cmpl $-0x1, -0x8d8(%rbp)
jne 0x3b76
movq -0x900(%rbp), %rax
movq (%rax), %rax
movl (%rax), %eax
movl %eax, -0x8ec(%rbp)
movq -0x900(%rbp), %rax
movq 0x8(%rax), %rax
movl (%rax), %eax
movl %eax, -0x8f0(%rbp)
movl -0x8f0(%rbp), %ecx
movslq -0x8ec(%rbp), %rax
movl %ecx, -0x80c(%rbp,%rax,4)
leaq -0x8d4(%rbp), %rdi
callq 0x46f0
movq -0x900(%rbp), %rdi
leaq -0x8f8(%rbp), %rsi
xorl %edx, %edx
callq 0x48f0
jmp 0x3bda
cmpl $0x0, -0x8d8(%rbp)
jne 0x3b9a
movq -0x900(%rbp), %rdi
movl -0x8f4(%rbp), %edx
leaq -0x8f8(%rbp), %rsi
callq 0x48f0
jmp 0x3bbd
movq -0x900(%rbp), %rdi
movl -0x4(%rbp), %edx
movl -0x8ec(%rbp), %ecx
movl -0x8f0(%rbp), %r8d
leaq -0x8f8(%rbp), %rsi
callq 0x4970
movl -0x8f0(%rbp), %ecx
movslq -0x8ec(%rbp), %rax
movl %ecx, -0x80c(%rbp,%rax,4)
movl -0x8e8(%rbp), %eax
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
movq -0x18(%rbp), %rcx
cmpl 0x898(%rcx), %eax
jle 0x3c48
movq -0x18(%rbp), %rdi
leaq -0x8d4(%rbp), %rsi
movl $0x89c, %edx            # imm = 0x89C
callq 0x2140
callq 0x2100
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
subq -0x30(%rbp), %rax
cvtsi2sd %rax, %xmm0
movsd 0x3414(%rip), %xmm1     # 0x7030
divsd %xmm1, %xmm0
movq -0x20(%rbp), %rax
movsd %xmm0, (%rax)
movq -0x18(%rbp), %rax
movl 0x898(%rax), %esi
movq -0x20(%rbp), %rax
movsd (%rax), %xmm0
leaq 0x348d(%rip), %rdi      # 0x70ce
movb $0x1, %al
callq 0x2050
callq 0x2100
movq %rax, -0x38(%rbp)
cvtsi2sdq -0x38(%rbp), %xmm0
cvtsi2sdq -0x30(%rbp), %xmm1
subsd %xmm1, %xmm0
movsd 0x33c7(%rip), %xmm1     # 0x7030
divsd %xmm1, %xmm0
movq -0x28(%rbp), %rax
movsd %xmm0, (%rax)
jmp 0x3957
movq -0x900(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x910(%rbp)
cmpq $0x0, %rax
je 0x3c9d
movq -0x910(%rbp), %rdi
callq 0x2200
movq -0x900(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x918(%rbp)
cmpq $0x0, %rax
je 0x3cc1
movq -0x918(%rbp), %rdi
callq 0x2200
addq $0x920, %rsp            # imm = 0x920
popq %rbp
retq
nopw (%rax,%rax)