// File: /workspace/github_cpp_makefile_star2_O2/estan[P]tsp/tsp.cpp
// Function: twoOpt(std::vector<unsigned short, std::allocator<unsigned short>>&, Matrix<unsigned int> const&, Matrix<unsigned short> const&, std::vector<unsigned short, std::allocator<unsigned short>>&, unsigned int&, unsigned int)
inline void twoOpt(vector<uint16_t>& tour, const Matrix<uint32_t>& d,
        const Matrix<uint16_t>& neighbor, vector<uint16_t> &position,
        uint32_t& max, uint32_t min) {
    size_t N = d.rows(); // Number of cities.

    // Candidate edges uv, wz and their positions in tour.
    uint16_t u, v, w, z;
    size_t u_i, v_i, w_i, z_i;

    bool locallyOptimal = false;
    while (!locallyOptimal) {
        locallyOptimal = true;

        // For each edge uv.
        for (u_i = 0, v_i = 1; u_i < N; ++u_i, ++v_i) {
            u = tour[u_i];
            v = tour[v_i % N];

            // For each edge wz (w k:th closest neighbor of u).
            for (size_t k = 0; k < neighbor.cols(); ++k) {
                w_i = position[neighbor[u][k]];
                z_i = w_i + 1;
                w = tour[w_i];
                z = tour[z_i % N];

                if (v == w || z == u) {
                    continue; // Skip adjacent edges.
                }

                // d[u][w] + min is a lower bound on new length.
                // d[u][v] + max is an upper bound on old length.
                if (d[u][w] + min > d[u][v] + max) {
                    break; // Go to next edge uv.
                }

                if (d[u][w] + d[v][z] < d[u][v] + d[w][z]) {
                    //   --u w--        --u-w->
                    //      X     ===>
                    //   <-z v->        <-z-v--
                    reverse(tour, v_i % N, w_i, position);
                    max = maximum(max, d[u][w], d[v][z]);
                    locallyOptimal = false;
                    break;
                }
            }
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movq %r9, 0x58(%rsp)
movq %r8, 0x28(%rsp)
movq %rcx, 0x20(%rsp)
movq %rdx, 0x38(%rsp)
movq %rdi, 0x10(%rsp)
movq %rsi, 0x18(%rsp)
movq 0x18(%rsi), %rsi
movb $0x1, %dil
pushq $0x1
popq %rdx
xorl %ecx, %ecx
cmpq %rsi, %rcx
jae 0x2468
movl %edi, 0xc(%rsp)
movq 0x10(%rsp), %rax
movq (%rax), %r8
movq %rcx, 0x50(%rsp)
movzwl (%r8,%rcx,2), %ecx
movq %rdx, 0x48(%rsp)
movq %rdx, %rax
xorl %edx, %edx
divq %rsi
movq 0x38(%rsp), %rax
movq 0x20(%rax), %r15
movq %r15, %r10
imulq %rcx, %r10
addq %r10, %r10
addq (%rax), %r10
movq %rdx, 0x40(%rsp)
movzwl (%r8,%rdx,2), %r13d
movq 0x20(%rsp), %rax
movq (%rax), %r11
movq 0x18(%rsp), %rax
movq (%rax), %rdx
movq 0x20(%rax), %rdi
movq %rdi, %rax
movq %rcx, 0x30(%rsp)
imulq %rcx, %rax
leaq (%rdx,%rax,4), %rax
movq %rax, 0x80(%rsp)
movq 0x28(%rsp), %rax
movl (%rax), %eax
movq %rax, 0x78(%rsp)
movq %rdi, 0x68(%rsp)
movq %rdi, %rax
imulq %r13, %rax
movq %rdx, 0x70(%rsp)
leaq (%rdx,%rax,4), %rax
movq %rax, 0x60(%rsp)
xorl %ebx, %ebx
cmpq %rbx, %r15
je 0x2482
movzwl (%r10,%rbx,2), %eax
movzwl (%r11,%rax,2), %ecx
leaq 0x1(%rcx), %rax
movzwl (%r8,%rcx,2), %r14d
xorl %edx, %edx
divq %rsi
cmpw %r14w, %r13w
je 0x2460
movl %edx, %eax
movzwl (%r8,%rax,2), %ebp
cmpw 0x30(%rsp), %bp
je 0x2460
movq %rsi, %r12
movq 0x80(%rsp), %rdi
movl (%rdi,%r14,4), %eax
movq 0x58(%rsp), %rdx
leal (%rax,%rdx), %esi
movl (%rdi,%r13,4), %edx
movq 0x78(%rsp), %rdi
addl %edx, %edi
cmpl %edi, %esi
ja 0x247f
movzwl %bp, %ebp
leal (,%rbp,4), %esi
movq 0x60(%rsp), %rdi
addl (%rdi,%rsi), %eax
movq 0x68(%rsp), %rdi
imulq %r14, %rdi
movq %r11, %r9
movq 0x70(%rsp), %r11
leaq (%r11,%rdi,4), %rdi
movq %r9, %r11
addl (%rsi,%rdi), %edx
cmpl %edx, %eax
movq %r12, %rsi
jb 0x2488
incq %rbx
jmp 0x23d1
pushq $0x1
popq %rdx
movl $0x0, %ecx
testb $0x1, %dil
movb $0x1, %dil
je 0x2331
jmp 0x24f4
movq %r12, %rsi
movl 0xc(%rsp), %edi
jmp 0x24df
movq 0x10(%rsp), %rdi
movq 0x40(%rsp), %rsi
movq %rcx, %rdx
movq 0x20(%rsp), %rcx
callq 0x3186
movq 0x18(%rsp), %rcx
movq (%rcx), %rax
movq 0x20(%rcx), %rcx
movq 0x30(%rsp), %rdx
imulq %rcx, %rdx
leaq (%rax,%rdx,4), %rdx
imulq %rcx, %r13
leaq (%rax,%r13,4), %rax
movl (%rdx,%r14,4), %ecx
movl (%rax,%rbp,4), %eax
movq 0x28(%rsp), %rsi
movl (%rsi), %edx
cmpl %eax, %ecx
cmoval %ecx, %eax
cmpl %eax, %edx
cmoval %edx, %eax
movl %eax, (%rsi)
movq %r12, %rsi
xorl %edi, %edi
movq 0x50(%rsp), %rcx
incq %rcx
movq 0x48(%rsp), %rdx
incq %rdx
jmp 0x2331
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq