// File: canzarlab[P]Trajan/geno/lbfgsb.cpp
// Function: LBFGSB::solve()
SolverStatus LBFGSB::solve() {
  Scalar const INF = std::numeric_limits<Scalar>::infinity();
  if (!initFeasible()) {
    std::cout << "Prolem is not feasible." << std::endl;
    return INFEASIBLE;
  }

  _funEval = 1;
  _genoNLP.functionValueAndGradient(_x.data(), _f, _g.data());
  //    std::cout << "x " << _x.transpose() << std::endl;
  //    std::cout << "g " << _g.transpose() << std::endl;
  // check for NANs and INFs
  double sum = _f + _g.sum();
  if ((-INF < sum) && (sum < INF)) {
  } else {
    std::cout << "encountered INF or NAN in function value or gradient" << std::endl;
    return NUM_ERROR;      
  }
  projectedGradient();
  if (_projectedGradient.lpNorm<Eigen::Infinity>() < _tol) {
    std::clog << "already optimal" << std::endl;
    return SOLVED;
  }

  if (_verbose)
    printf("\n%8s %8s %14s %14s %14s\n",
        "Iteration", "FunEval", "Step Length", "FunValue", "Proj.Grad.");
  size_t k = 1;
  for (;; ++k) {
    // Backup the old state
    _workingSetOld = _workingSet;
    if (_constrained || 1 == k) {
      cauchyPoint();
    } else {
      _xCP = _x;
      _c = Vector::Zero(_S.cols() * 2);
    }

    formK();
    subsm();
    Vector deltaX = _xSubspace - _x;
    Scalar t = lineSearchMT(deltaX, k);
    if (-1 == t) {
      if (0 != _S.cols()) {
        refresh();
        std::clog << "refresh() called\n";
        --k;
        --_funEval;  // TODO remove
        continue;
      }
      //        std::cerr << "error in line search - abnormal termination" << std::endl;
      //        std::exit(EXIT_FAILURE);
      return SUBOPTIMAL;
    }
    Scalar deltaF = helper();

    if (_verbose) {
      printf(" %8lu %8lu %14.5g %14.5E %14.5E\n",
          k, _funEval, t, _fNew, _projectedGradient.lpNorm<Eigen::Infinity>());
    }

    if (_projectedGradient.lpNorm<Eigen::Infinity>() < _tol) {
      if (_verbose) printf("Directional derivative below tol\n");
      return SOLVED;
    }

    if (deltaF < _tolFun) {
      if (_verbose) printf("Change in function value below tolFun\n");
      return SOLVED;
    }

    if (k >= _maxIter) {
      if (_verbose) printf("Maximum iteration count reached\n");
      return SUBOPTIMAL;
    }

    updateB();
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x110, %rsp            # imm = 0x110
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x90(%rbp)
callq 0x26640
movq -0x90(%rbp), %rdi
movsd %xmm0, -0x18(%rbp)
callq 0x24860
testb $0x1, %al
jne 0x24a42
movq 0x17c595(%rip), %rdi    # 0x1a0fb0
leaq 0xe953c(%rip), %rsi     # 0x10df5e
callq 0xa440
movq %rax, %rdi
movq 0x17c52f(%rip), %rsi    # 0x1a0f60
callq 0xa4a0
movl $0x3, -0x4(%rbp)
jmp 0x24fab
movq -0x90(%rbp), %rdi
movq $0x1, 0x50(%rdi)
movq (%rdi), %rax
movq %rax, -0xb0(%rbp)
addq $0x10, %rdi
callq 0x13cd0
movq -0x90(%rbp), %rdi
movq %rax, -0xa8(%rbp)
movq %rdi, %rax
addq $0x8, %rax
movq %rax, -0xa0(%rbp)
addq $0x40, %rdi
callq 0x13cd0
movq -0xb0(%rbp), %rdi
movq -0xa8(%rbp), %rsi
movq -0xa0(%rbp), %rdx
movq %rax, %rcx
movq (%rdi), %rax
callq *0x48(%rax)
movq -0x90(%rbp), %rdi
movsd 0x8(%rdi), %xmm0
movsd %xmm0, -0x98(%rbp)
addq $0x40, %rdi
callq 0x29950
movaps %xmm0, %xmm1
movsd -0x98(%rbp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x20(%rbp)
movsd -0x20(%rbp), %xmm0
movsd 0xe68cb(%rip), %xmm1    # 0x10b3b0
ucomisd %xmm1, %xmm0
jbe 0x24afc
movsd 0xe68ad(%rip), %xmm0    # 0x10b3a0
ucomisd -0x20(%rbp), %xmm0
jbe 0x24afc
jmp 0x24b2a
movq 0x17c4ad(%rip), %rdi    # 0x1a0fb0
leaq 0xe946c(%rip), %rsi     # 0x10df76
callq 0xa440
movq %rax, %rdi
movq 0x17c447(%rip), %rsi    # 0x1a0f60
callq 0xa4a0
movl $0x4, -0x4(%rbp)
jmp 0x24fab
movq -0x90(%rbp), %rdi
callq 0x24490
movq -0x90(%rbp), %rdi
addq $0x220, %rdi            # imm = 0x220
callq 0x14680
movq -0x90(%rbp), %rax
movaps %xmm0, %xmm1
movsd 0x68(%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x24b8c
movq 0x17c3eb(%rip), %rdi    # 0x1a0f50
leaq 0xe943f(%rip), %rsi     # 0x10dfab
callq 0xa440
movq %rax, %rdi
movq 0x17c3e5(%rip), %rsi    # 0x1a0f60
callq 0xa4a0
movl $0x0, -0x4(%rbp)
jmp 0x24fab
movq -0x90(%rbp), %rax
testb $0x1, 0x58(%rax)
je 0x24bca
leaq 0xe941b(%rip), %rdi     # 0x10dfbb
leaq 0xe942d(%rip), %rsi     # 0x10dfd4
leaq 0xe9430(%rip), %rdx     # 0x10dfde
leaq 0xe9431(%rip), %rcx     # 0x10dfe6
leaq 0xe9436(%rip), %r8      # 0x10dff2
leaq 0xe9438(%rip), %r9      # 0x10dffb
movb $0x0, %al
callq 0xa080
movq $0x1, -0x28(%rbp)
movq -0x90(%rbp), %rdi
movq %rdi, %rsi
addq $0x1e0, %rsi            # imm = 0x1E0
addq $0x1f0, %rdi            # imm = 0x1F0
callq 0x145a0
movq -0x90(%rbp), %rax
testb $0x1, 0x258(%rax)
jne 0x24c0a
movl $0x1, %eax
cmpq -0x28(%rbp), %rax
jne 0x24c18
movq -0x90(%rbp), %rdi
callq 0x21940
jmp 0x24c6b
movq -0x90(%rbp), %rdi
movq %rdi, %rsi
addq $0x10, %rsi
addq $0x1d0, %rdi            # imm = 0x1D0
callq 0x145a0
movq -0x90(%rbp), %rdi
addq $0xa8, %rdi
callq 0x26800
movq %rax, %rsi
shlq %rsi
leaq -0x40(%rbp), %rdi
callq 0x13c30
movq -0x90(%rbp), %rdi
addq $0x200, %rdi            # imm = 0x200
leaq -0x40(%rbp), %rsi
callq 0x28100
movq -0x90(%rbp), %rdi
callq 0x20d70
movq -0x90(%rbp), %rdi
callq 0x22d60
movq -0x90(%rbp), %rdx
movq %rdx, %rsi
addq $0x210, %rsi            # imm = 0x210
addq $0x10, %rdx
leaq -0x68(%rbp), %rdi
movq %rdi, -0xc8(%rbp)
callq 0x27be0
movq -0xc8(%rbp), %rsi
leaq -0x50(%rbp), %rdi
movq %rdi, -0xc0(%rbp)
callq 0x27c50
movq -0x90(%rbp), %rdi
movq -0xc0(%rbp), %rsi
movq -0x28(%rbp), %rdx
callq 0x23f10
movsd %xmm0, -0xb8(%rbp)
jmp 0x24ce0
movsd -0xb8(%rbp), %xmm0
movsd %xmm0, -0x70(%rbp)
movsd 0xe668b(%rip), %xmm0    # 0x10b380
ucomisd -0x70(%rbp), %xmm0
jne 0x24dab
jp 0x24dab
movq -0x90(%rbp), %rdi
addq $0xa8, %rdi
callq 0x26800
movq %rax, -0xd0(%rbp)
jmp 0x24d22
movq -0xd0(%rbp), %rcx
xorl %eax, %eax
cmpq %rcx, %rax
je 0x24d98
movq -0x90(%rbp), %rdi
callq 0x246d0
jmp 0x24d3e
movq 0x17c20b(%rip), %rdi    # 0x1a0f50
leaq 0xe92ba(%rip), %rsi     # 0x10e006
callq 0xa440
jmp 0x24d53
movq -0x90(%rbp), %rax
movq -0x28(%rbp), %rcx
addq $-0x1, %rcx
movq %rcx, -0x28(%rbp)
movq 0x50(%rax), %rcx
addq $-0x1, %rcx
movq %rcx, 0x50(%rax)
movl $0x4, -0x80(%rbp)
jmp 0x24f71
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x50(%rbp), %rdi
callq 0xff40
jmp 0x24fb7
movl $0x1, -0x4(%rbp)
movl $0x1, -0x80(%rbp)
jmp 0x24f71
movq -0x90(%rbp), %rdi
callq 0x24590
movsd %xmm0, -0xd8(%rbp)
jmp 0x24dc1
movq -0x90(%rbp), %rax
movsd -0xd8(%rbp), %xmm0
movsd %xmm0, -0x88(%rbp)
testb $0x1, 0x58(%rax)
je 0x24e6a
movq -0x90(%rbp), %rdi
movq -0x28(%rbp), %rax
movq %rax, -0x100(%rbp)
movq 0x50(%rdi), %rax
movq %rax, -0xf8(%rbp)
movsd -0x70(%rbp), %xmm0
movsd %xmm0, -0xf0(%rbp)
movsd 0x230(%rdi), %xmm0
movsd %xmm0, -0xe8(%rbp)
addq $0x220, %rdi            # imm = 0x220
callq 0x14680
movsd %xmm0, -0xe0(%rbp)
jmp 0x24e32
movsd -0xe0(%rbp), %xmm2
movsd -0xe8(%rbp), %xmm1
movsd -0xf0(%rbp), %xmm0
movq -0xf8(%rbp), %rdx
movq -0x100(%rbp), %rsi
leaq 0xe91b9(%rip), %rdi     # 0x10e018
movb $0x3, %al
callq 0xa080
jmp 0x24e68
jmp 0x24e6a
movq -0x90(%rbp), %rdi
addq $0x220, %rdi            # imm = 0x220
callq 0x14680
movsd %xmm0, -0x108(%rbp)
jmp 0x24e87
movsd -0x108(%rbp), %xmm1
movq -0x90(%rbp), %rax
movsd 0x68(%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x24ed3
movq -0x90(%rbp), %rax
testb $0x1, 0x58(%rax)
je 0x24ec0
leaq 0xe9184(%rip), %rdi     # 0x10e039
xorl %eax, %eax
callq 0xa080
jmp 0x24ebe
jmp 0x24ec0
movl $0x0, -0x4(%rbp)
movl $0x1, -0x80(%rbp)
jmp 0x24f71
movq -0x90(%rbp), %rax
movsd -0x88(%rbp), %xmm1
movsd 0x70(%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x24f1c
movq -0x90(%rbp), %rax
testb $0x1, 0x58(%rax)
je 0x24f0c
leaq 0xe915a(%rip), %rdi     # 0x10e05b
xorl %eax, %eax
callq 0xa080
jmp 0x24f0a
jmp 0x24f0c
movl $0x0, -0x4(%rbp)
movl $0x1, -0x80(%rbp)
jmp 0x24f71
movq -0x90(%rbp), %rcx
movq -0x28(%rbp), %rax
cmpq 0x60(%rcx), %rax
jb 0x24f5c
movq -0x90(%rbp), %rax
testb $0x1, 0x58(%rax)
je 0x24f4c
leaq 0xe9141(%rip), %rdi     # 0x10e082
xorl %eax, %eax
callq 0xa080
jmp 0x24f4a
jmp 0x24f4c
movl $0x1, -0x4(%rbp)
movl $0x1, -0x80(%rbp)
jmp 0x24f71
movq -0x90(%rbp), %rdi
callq 0x1edc0
jmp 0x24f6a
movl $0x0, -0x80(%rbp)
leaq -0x50(%rbp), %rdi
callq 0xff40
movl -0x80(%rbp), %eax
movl %eax, -0x10c(%rbp)
testl %eax, %eax
je 0x24f98
jmp 0x24f89
movl -0x10c(%rbp), %eax
subl $0x1, %eax
je 0x24fab
jmp 0x24f96
jmp 0x24f9a
jmp 0x24f9a
movq -0x28(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x28(%rbp)
jmp 0x24bd2
movl -0x4(%rbp), %eax
addq $0x110, %rsp            # imm = 0x110
popq %rbp
retq
movq -0x78(%rbp), %rdi
callq 0xa7c0