// File: /workspace/github_cpp_makefile_star2_O3/EduBic[P]TSP-MetaheuristicSolvers/./neighborimprovement.h
// Function: FirstImprovement::execute(TSP const&, TSPSolution const&, move&)
double execute(const TSP& tsp , const TSPSolution& currSol, TSPMove& move) {
        //cout << endl << endl << "-------------- find neighbor --------------";


        double bestCostVariation = tsp.infinite;

        for ( uint a = 1 ; a < currSol.sequence.size() - 2 ; a++ ) {

            int h = currSol.sequence[a-1];
            int i = currSol.sequence[a];

            for ( uint b = a + 1 ; b < currSol.sequence.size() - 1 ; b++ ) {
                int j = currSol.sequence[b];
                int l = currSol.sequence[b+1];

                // incremental evaluation --> bestCostVariation (instead of best cost)
                double neighCostVariation = - tsp.cost[h][i] - tsp.cost[j][l]
                                            + tsp.cost[h][j] + tsp.cost[i][l];

                if (neighCostVariation < bestCostVariation ) {
                    // neighbor better of precedent neighbors
                    bestCostVariation = neighCostVariation;
                    move.from = a;
                    move.to = b;

                    double currentBestValueFound = currSol.evaluateObjectiveFunction(tsp);

                    // on first improvement exit
                    //cout << endl << "Move from " << a << " to " << b;
                    //cout << "\tNeighbor Value = " << currentBestValueFound + bestCostVariation << " - CurrentBestValue = " << currentBestValueFound;
                    if (currentBestValueFound + bestCostVariation < currentBestValueFound) {
                        //cout << "\tIt's an improvement, chose it!" << endl;
                        //cout << "------------------------" << endl;
                        return bestCostVariation;
                    }
                }
            }
        }

        //cout << endl << "------------------------------" << endl;
        return bestCostVariation;
    }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rcx, 0x28(%rsp)
movq %rsi, 0x10(%rsp)
movsd 0x20(%rsi), %xmm0
movq (%rdx), %rax
movq 0x8(%rdx), %rcx
movq %rcx, %rsi
subq %rax, %rsi
andq $-0x8, %rsi
cmpq $0x8, %rsi
je 0x7c62
movq %rdx, 0x20(%rsp)
movl $0x1, %r10d
movl $0x1, %ebx
movl $0x3, %r8d
movapd 0x796(%rip), %xmm1      # 0x82d0
movq 0x20(%rsp), %r15
movl %r10d, %r11d
movq %rbx, %rsi
leal 0x1(%r11), %r10d
movl %r10d, %ebx
movq %rcx, %rdx
subq %rax, %rdx
sarq $0x2, %rdx
leaq -0x1(%rdx), %rdi
cmpq %rbx, %rdi
jbe 0x7c4c
movl %r10d, 0x8(%rsp)
movslq (%rax,%rsi,4), %r12
leal -0x1(%r11), %edx
movslq (%rax,%rdx,4), %rdx
leaq (%rdx,%rdx,2), %rbp
leaq (%r12,%r12,2), %r13
movl %r8d, 0xc(%rsp)
movl %r8d, %edx
movq %rbx, 0x18(%rsp)
movslq (%rax,%rbx,4), %rsi
movl %edx, %ebx
movslq (%rax,%rbx,4), %rdi
movq 0x10(%rsp), %r8
movq 0x8(%r8), %r8
movq (%r8,%rbp,8), %r9
movsd (%r9,%r12,8), %xmm2
xorpd %xmm1, %xmm2
leaq (%rsi,%rsi,2), %r10
movq (%r8,%r10,8), %r10
subsd (%r10,%rdi,8), %xmm2
addsd (%r9,%rsi,8), %xmm2
movq (%r8,%r13,8), %rsi
addsd (%rsi,%rdi,8), %xmm2
ucomisd %xmm2, %xmm0
jbe 0x7c1a
decl %edx
movq 0x28(%rsp), %rax
movq %r11, %r14
movl %r11d, (%rax)
movl %edx, 0x4(%rax)
movq %r15, %rdi
movq 0x10(%rsp), %rsi
movapd %xmm2, 0x30(%rsp)
callq 0x52e0
movapd 0x30(%rsp), %xmm2
movapd %xmm2, %xmm1
addsd %xmm0, %xmm1
ucomisd %xmm1, %xmm0
ja 0x7c5e
movq (%r15), %rax
movq 0x8(%r15), %rcx
movapd %xmm2, %xmm0
movapd 0x6b9(%rip), %xmm1      # 0x82d0
movq %r14, %r11
movq %rcx, %rsi
subq %rax, %rsi
sarq $0x2, %rsi
decq %rsi
leal 0x1(%rbx), %edx
cmpq %rbx, %rsi
ja 0x7b89
movq %rcx, %rdx
subq %rax, %rdx
sarq $0x2, %rdx
movl 0xc(%rsp), %r8d
movq 0x18(%rsp), %rbx
movl 0x8(%rsp), %r10d
addq $-0x2, %rdx
incl %r8d
cmpq %rbx, %rdx
ja 0x7b3f
jmp 0x7c62
movapd %xmm2, %xmm0
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop