// File: mateuz[P]MTS-LS1/source/main.cpp
// Function: mts_ls1(Benchmarks*, unsigned int, std::vector<double, std::allocator<double>>&)
void mts_ls1(Benchmarks * bench, unsigned maxevals, vector<double>& sol){
  //unsigned int n_dim = ndim;
  unsigned totalevals = 0;
  double best_fitness = bench->compute(sol.data());

  vector<double> SR(sol.size());
  for( unsigned i = 0; i < SR.size(); i++ ){
    SR[i] = (bench->getMaxX() - bench->getMinX()) * 0.4;
  }

  LSresult result;
  LSresult current_best = {sol, best_fitness, 0};

  vector<double> improvement(dim, 0.0);

  vector<double> dim_sorted(dim);
  iota(dim_sorted.begin(), dim_sorted.end(), 0);

  double improve;
  //warm-up
  if( totalevals < maxevals ){
    next_permutation(dim_sorted.begin(), dim_sorted.end());
    for( auto it = dim_sorted.begin(); it != dim_sorted.end(); it++ ){
      result = mts_ls1_improve_dim(bench, sol, best_fitness, *it, SR);
      totalevals += result.evals;
      improve = max(current_best.fitness - result.fitness, 0.0);
      improvement[*it] = improve;

      if( improve > 0.0 ){
        printf("[1] %.10lf > %.10lf ~ improve: %.20lf\n", current_best.fitness, result.fitness, improve);
        current_best = result;
      } else {
        SR[*it] /= 2.0f;
      }
    }
  }

  iota(dim_sorted.begin(), dim_sorted.end(), 0);
  sort(dim_sorted.begin(), dim_sorted.end(), [&](unsigned i1, unsigned i2) { return improvement[i1] > improvement[i2]; });

  int i, d = 0, next_d, next_i;
  while( totalevals < maxevals ){
    i = dim_sorted[d];
    result = mts_ls1_improve_dim(bench, current_best.solution, current_best.fitness, i, SR);
    totalevals += result.evals;
    improve = max(current_best.fitness - result.fitness, 0.0);
    improvement[i] = improve;
    next_d = (d+1)%dim;
    next_i = dim_sorted[next_d];

    if( improve > 0.0 ){
      printf("[2] %.10lf > %.10lf ~ improve: %.20lf\n", current_best.fitness, result.fitness, improve);
      current_best = result;

      if( improvement[i] < improvement[next_i] ){
        iota(dim_sorted.begin(), dim_sorted.end(), 0);
        sort(dim_sorted.begin(), dim_sorted.end(), [&](unsigned i1, unsigned i2) { return improvement[i1] > improvement[i2]; });
      }
    } else {
      SR[i] /= 2.0;
      d = next_d;
      if( SR[i] < 1e-15 ){
        SR[i] = (bench->getMaxX() - bench->getMinX()) * 0.4;
      }
    }
  }
  sol = current_best.solution;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2e0, %rsp            # imm = 0x2E0
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movl $0x0, -0x1c(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x218(%rbp)
movq -0x18(%rbp), %rdi
callq 0xfee0
movq -0x218(%rbp), %rdi
movq %rax, %rsi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movsd %xmm0, -0x28(%rbp)
movq -0x18(%rbp), %rdi
callq 0x101b0
movq %rax, -0x210(%rbp)
leaq -0x41(%rbp), %rdi
movq %rdi, -0x208(%rbp)
callq 0x101d0
movq -0x210(%rbp), %rsi
movq -0x208(%rbp), %rdx
leaq -0x40(%rbp), %rdi
callq 0x101f0
jmp 0xc9b2
leaq -0x41(%rbp), %rdi
callq 0x10260
movl $0x0, -0x58(%rbp)
movl -0x58(%rbp), %eax
movq %rax, -0x220(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x101b0
movq %rax, %rcx
movq -0x220(%rbp), %rax
cmpq %rcx, %rax
jae 0xca83
movq -0x8(%rbp), %rdi
callq 0x72f0
movl %eax, -0x224(%rbp)
jmp 0xc9f9
movq -0x8(%rbp), %rdi
callq 0x72d0
movl %eax, -0x228(%rbp)
jmp 0xca0a
movl -0x228(%rbp), %ecx
movl -0x224(%rbp), %eax
subl %ecx, %eax
cvtsi2sd %eax, %xmm0
movsd 0x67e4(%rip), %xmm1     # 0x13208
mulsd %xmm1, %xmm0
movsd %xmm0, -0x230(%rbp)
movl -0x58(%rbp), %eax
movl %eax, %esi
leaq -0x40(%rbp), %rdi
callq 0xfe40
movsd -0x230(%rbp), %xmm0
movsd %xmm0, (%rax)
movl -0x58(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x58(%rbp)
jmp 0xc9c2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x41(%rbp), %rdi
callq 0x10260
jmp 0xd2d9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0xd2d0
leaq -0x80(%rbp), %rdi
callq 0x10280
movq -0x18(%rbp), %rsi
leaq -0xa8(%rbp), %rdi
callq 0xfd50
jmp 0xca9e
movsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x90(%rbp)
movl $0x0, -0x88(%rbp)
movl 0xd70d(%rip), %eax      # 0x1a1c8
movq %rax, -0x240(%rbp)
movq $0x0, -0xc8(%rbp)
leaq -0xc9(%rbp), %rdi
movq %rdi, -0x238(%rbp)
callq 0x101d0
movq -0x240(%rbp), %rsi
movq -0x238(%rbp), %rcx
leaq -0xc0(%rbp), %rdi
leaq -0xc8(%rbp), %rdx
callq 0x102a0
jmp 0xcb03
leaq -0xc9(%rbp), %rdi
callq 0x10260
movl 0xd6b3(%rip), %eax      # 0x1a1c8
movq %rax, -0x250(%rbp)
leaq -0xe9(%rbp), %rdi
movq %rdi, -0x248(%rbp)
callq 0x101d0
movq -0x250(%rbp), %rsi
movq -0x248(%rbp), %rdx
leaq -0xe8(%rbp), %rdi
callq 0x101f0
jmp 0xcb4b
leaq -0xe9(%rbp), %rdi
callq 0x10260
leaq -0xe8(%rbp), %rdi
movq %rdi, -0x258(%rbp)
callq 0x10380
movq -0x258(%rbp), %rdi
movq %rax, -0xf8(%rbp)
callq 0x103b0
movq %rax, -0x100(%rbp)
movq -0xf8(%rbp), %rdi
movq -0x100(%rbp), %rsi
xorl %edx, %edx
callq 0x10320
jmp 0xcb9b
movl -0x1c(%rbp), %eax
cmpl -0xc(%rbp), %eax
jae 0xce92
leaq -0xe8(%rbp), %rdi
movq %rdi, -0x260(%rbp)
callq 0x10380
movq -0x260(%rbp), %rdi
movq %rax, -0x110(%rbp)
callq 0x103b0
movq %rax, -0x118(%rbp)
movq -0x110(%rbp), %rdi
movq -0x118(%rbp), %rsi
callq 0x103e0
jmp 0xcbe9
leaq -0xe8(%rbp), %rdi
callq 0x10380
movq %rax, -0x120(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0x103b0
movq %rax, -0x128(%rbp)
leaq -0x120(%rbp), %rdi
leaq -0x128(%rbp), %rsi
callq 0x10420
testb $0x1, %al
jne 0xcc2b
jmp 0xce90
movq -0x8(%rbp), %rax
movq %rax, -0x278(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x270(%rbp)
movsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x268(%rbp)
leaq -0x120(%rbp), %rdi
callq 0x10460
movq -0x278(%rbp), %rsi
movq -0x270(%rbp), %rdx
movsd -0x268(%rbp), %xmm0
cvttsd2si (%rax), %rax
movl %eax, %ecx
leaq -0x150(%rbp), %rdi
leaq -0x40(%rbp), %r8
callq 0xc490
jmp 0xcc89
leaq -0x80(%rbp), %rdi
leaq -0x150(%rbp), %rsi
movq %rsi, -0x288(%rbp)
callq 0x10480
movq -0x288(%rbp), %rdi
callq 0x104c0
movl -0x60(%rbp), %ecx
movl -0x1c(%rbp), %eax
addl %ecx, %eax
movl %eax, -0x1c(%rbp)
movsd -0x90(%rbp), %xmm0
movsd -0x68(%rbp), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, -0x158(%rbp)
movq $0x0, -0x160(%rbp)
leaq -0x158(%rbp), %rdi
leaq -0x160(%rbp), %rsi
callq 0xfea0
movq %rax, -0x280(%rbp)
jmp 0xccf7
movq -0x280(%rbp), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x108(%rbp)
movsd -0x108(%rbp), %xmm0
movsd %xmm0, -0x290(%rbp)
leaq -0x120(%rbp), %rdi
callq 0x10460
movsd (%rax), %xmm0
movsd 0x64de(%rip), %xmm2     # 0x13210
movaps %xmm0, %xmm1
subsd %xmm2, %xmm1
cvttsd2si %xmm1, %rax
cvttsd2si %xmm0, %rsi
movq %rsi, %rcx
sarq $0x3f, %rcx
andq %rcx, %rax
orq %rax, %rsi
leaq -0xc0(%rbp), %rdi
callq 0xfe40
movsd -0x290(%rbp), %xmm0
movsd %xmm0, (%rax)
movsd -0x108(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0xce21
movsd -0x90(%rbp), %xmm0
movsd -0x68(%rbp), %xmm1
movsd -0x108(%rbp), %xmm2
leaq 0x64b7(%rip), %rdi      # 0x13250
movb $0x3, %al
callq 0x3050
jmp 0xcda2
leaq -0xa8(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x104e0
jmp 0xcdb4
jmp 0xce74
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0xd2c7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0xc9(%rbp), %rdi
callq 0x10260
jmp 0xd2bb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0xe9(%rbp), %rdi
callq 0x10260
jmp 0xd2af
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0x10150
jmp 0xd2af
leaq -0x120(%rbp), %rdi
callq 0x10460
movsd (%rax), %xmm0
movsd 0x63d7(%rip), %xmm2     # 0x13210
movaps %xmm0, %xmm1
subsd %xmm2, %xmm1
cvttsd2si %xmm1, %rax
cvttsd2si %xmm0, %rsi
movq %rsi, %rcx
sarq $0x3f, %rcx
andq %rcx, %rax
orq %rax, %rsi
leaq -0x40(%rbp), %rdi
callq 0xfe40
movsd (%rax), %xmm0
movsd 0x6394(%rip), %xmm1     # 0x13200
divsd %xmm1, %xmm0
movsd %xmm0, (%rax)
jmp 0xce76
leaq -0x120(%rbp), %rdi
xorl %esi, %esi
callq 0x10520
movq %rax, -0x168(%rbp)
jmp 0xcbfc
jmp 0xce92
leaq -0xe8(%rbp), %rdi
movq %rdi, -0x298(%rbp)
callq 0x10380
movq -0x298(%rbp), %rdi
movq %rax, -0x170(%rbp)
callq 0x103b0
movq %rax, -0x178(%rbp)
movq -0x170(%rbp), %rdi
movq -0x178(%rbp), %rsi
xorl %edx, %edx
callq 0x10320
jmp 0xced6
leaq -0xe8(%rbp), %rdi
movq %rdi, -0x2a0(%rbp)
callq 0x10380
movq -0x2a0(%rbp), %rdi
movq %rax, -0x180(%rbp)
callq 0x103b0
movq %rax, -0x188(%rbp)
leaq -0xc0(%rbp), %rax
movq %rax, -0x190(%rbp)
movq -0x180(%rbp), %rdi
movq -0x188(%rbp), %rsi
movq -0x190(%rbp), %rdx
callq 0xd2f0
jmp 0xcf2d
movl $0x0, -0x198(%rbp)
movl -0x1c(%rbp), %eax
cmpl -0xc(%rbp), %eax
jae 0xd25e
movslq -0x198(%rbp), %rsi
leaq -0xe8(%rbp), %rdi
callq 0xfe40
cvttsd2si (%rax), %eax
movl %eax, -0x194(%rbp)
movq -0x8(%rbp), %rsi
movsd -0x90(%rbp), %xmm0
movl -0x194(%rbp), %ecx
leaq -0x1c8(%rbp), %rdi
leaq -0xa8(%rbp), %rdx
leaq -0x40(%rbp), %r8
callq 0xc490
jmp 0xcf8b
leaq -0x80(%rbp), %rdi
leaq -0x1c8(%rbp), %rsi
movq %rsi, -0x2b0(%rbp)
callq 0x10480
movq -0x2b0(%rbp), %rdi
callq 0x104c0
movl -0x60(%rbp), %ecx
movl -0x1c(%rbp), %eax
addl %ecx, %eax
movl %eax, -0x1c(%rbp)
movsd -0x90(%rbp), %xmm0
movsd -0x68(%rbp), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, -0x1d0(%rbp)
movq $0x0, -0x1d8(%rbp)
leaq -0x1d0(%rbp), %rdi
leaq -0x1d8(%rbp), %rsi
callq 0xfea0
movq %rax, -0x2a8(%rbp)
jmp 0xcff9
movq -0x2a8(%rbp), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x108(%rbp)
movsd -0x108(%rbp), %xmm0
movsd %xmm0, -0x2b8(%rbp)
movslq -0x194(%rbp), %rsi
leaq -0xc0(%rbp), %rdi
callq 0xfe40
movsd -0x2b8(%rbp), %xmm0
movsd %xmm0, (%rax)
movl -0x198(%rbp), %eax
addl $0x1, %eax
xorl %edx, %edx
divl 0xd17c(%rip)            # 0x1a1c8
movl %edx, -0x19c(%rbp)
movslq -0x19c(%rbp), %rsi
leaq -0xe8(%rbp), %rdi
callq 0xfe40
cvttsd2si (%rax), %eax
movl %eax, -0x1a0(%rbp)
movsd -0x108(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0xd1a5
movsd -0x90(%rbp), %xmm0
movsd -0x68(%rbp), %xmm1
movsd -0x108(%rbp), %xmm2
leaq 0x61d7(%rip), %rdi      # 0x13277
movb $0x3, %al
callq 0x3050
jmp 0xd0a9
leaq -0xa8(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x104e0
jmp 0xd0bb
movslq -0x194(%rbp), %rsi
leaq -0xc0(%rbp), %rdi
callq 0xfe40
movsd (%rax), %xmm0
movsd %xmm0, -0x2c0(%rbp)
movslq -0x1a0(%rbp), %rsi
leaq -0xc0(%rbp), %rdi
callq 0xfe40
movsd -0x2c0(%rbp), %xmm1
movsd (%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0xd1a0
leaq -0xe8(%rbp), %rdi
movq %rdi, -0x2c8(%rbp)
callq 0x10380
movq -0x2c8(%rbp), %rdi
movq %rax, -0x1e0(%rbp)
callq 0x103b0
movq %rax, -0x1e8(%rbp)
movq -0x1e0(%rbp), %rdi
movq -0x1e8(%rbp), %rsi
xorl %edx, %edx
callq 0x10320
jmp 0xd147
leaq -0xe8(%rbp), %rdi
movq %rdi, -0x2d0(%rbp)
callq 0x10380
movq -0x2d0(%rbp), %rdi
movq %rax, -0x1f0(%rbp)
callq 0x103b0
movq %rax, -0x1f8(%rbp)
leaq -0xc0(%rbp), %rax
movq %rax, -0x200(%rbp)
movq -0x1f0(%rbp), %rdi
movq -0x1f8(%rbp), %rsi
movq -0x200(%rbp), %rdx
callq 0xd340
jmp 0xd19e
jmp 0xd1a0
jmp 0xd259
movslq -0x194(%rbp), %rsi
leaq -0x40(%rbp), %rdi
callq 0xfe40
movsd (%rax), %xmm0
movsd 0x603f(%rip), %xmm1     # 0x13200
divsd %xmm1, %xmm0
movsd %xmm0, (%rax)
movl -0x19c(%rbp), %eax
movl %eax, -0x198(%rbp)
movslq -0x194(%rbp), %rsi
leaq -0x40(%rbp), %rdi
callq 0xfe40
movsd 0x600b(%rip), %xmm0     # 0x131f8
ucomisd (%rax), %xmm0
jbe 0xd257
movq -0x8(%rbp), %rdi
callq 0x72f0
movl %eax, -0x2d4(%rbp)
jmp 0xd204
movq -0x8(%rbp), %rdi
callq 0x72d0
movl %eax, -0x2d8(%rbp)
jmp 0xd215
movl -0x2d8(%rbp), %ecx
movl -0x2d4(%rbp), %eax
subl %ecx, %eax
cvtsi2sd %eax, %xmm0
movsd 0x5fd9(%rip), %xmm1     # 0x13208
mulsd %xmm1, %xmm0
movsd %xmm0, -0x2e0(%rbp)
movslq -0x194(%rbp), %rsi
leaq -0x40(%rbp), %rdi
callq 0xfe40
movsd -0x2e0(%rbp), %xmm0
movsd %xmm0, (%rax)
jmp 0xd259
jmp 0xcf37
movq -0x18(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0xff00
jmp 0xd270
leaq -0xe8(%rbp), %rdi
callq 0x10150
leaq -0xc0(%rbp), %rdi
callq 0x10150
leaq -0xa8(%rbp), %rdi
callq 0x104c0
leaq -0x80(%rbp), %rdi
callq 0x104c0
leaq -0x40(%rbp), %rdi
callq 0x10150
addq $0x2e0, %rsp            # imm = 0x2E0
popq %rbp
retq
leaq -0xc0(%rbp), %rdi
callq 0x10150
leaq -0xa8(%rbp), %rdi
callq 0x104c0
leaq -0x80(%rbp), %rdi
callq 0x104c0
leaq -0x40(%rbp), %rdi
callq 0x10150
movq -0x50(%rbp), %rdi
callq 0x3320
nopw %cs:(%rax,%rax)