// File: /workspace/github_cpp_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq %rdi, %rbx
callq 0x12634
testb %al, %al
je 0x127da
movq $0x1, 0x50(%rbx)
movq (%rbx), %rdi
movq 0x10(%rbx), %rsi
leaq 0x8(%rbx), %rdx
leaq 0x40(%rbx), %r14
movq 0x40(%rbx), %rcx
movq (%rdi), %rax
callq *0x48(%rax)
movsd 0x8(%rbx), %xmm0
movsd %xmm0, 0x10(%rsp)
movq %r14, %rdi
callq 0x13e00
addsd 0x10(%rsp), %xmm0
movq %xmm0, %rax
btrq $0x3f, %rax
movabsq $0x7ff0000000000000, %rcx # imm = 0x7FF0000000000000
cmpq %rcx, %rax
jl 0x12807
movq 0x847ee(%rip), %rdi     # 0x96fb0
leaq 0x41383(%rip), %rsi     # 0x53b4c
callq 0x9330
movq %rax, %rdi
callq 0x9170
pushq $0x4
jmp 0x127f7
movq 0x847cf(%rip), %rdi     # 0x96fb0
leaq 0x4134c(%rip), %rsi     # 0x53b34
callq 0x9330
movq %rax, %rdi
callq 0x9170
pushq $0x3
popq %rax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rbx, %rdi
callq 0x1238a
leaq 0x220(%rbx), %rdi
movq %rdi, 0x18(%rsp)
callq 0xea40
movsd 0x68(%rbx), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x1284a
movq 0x8473e(%rip), %rdi     # 0x96f70
leaq 0x41348(%rip), %rsi     # 0x53b81
callq 0x9330
movq %rax, %rdi
callq 0x9170
xorl %eax, %eax
jmp 0x127f8
cmpb $0x1, 0x58(%rbx)
jne 0x12881
leaq 0x4133a(%rip), %rdi     # 0x53b91
leaq 0x4134c(%rip), %rsi     # 0x53baa
leaq 0x4134f(%rip), %rdx     # 0x53bb4
leaq 0x41350(%rip), %rcx     # 0x53bbc
leaq 0x41355(%rip), %r8      # 0x53bc8
leaq 0x41357(%rip), %r9      # 0x53bd1
xorl %eax, %eax
callq 0x9060
leaq 0x10(%rbx), %r15
leaq 0x1e0(%rbx), %rax
movq %rax, 0x10(%rsp)
leaq 0x1f0(%rbx), %rax
movq %rax, 0x48(%rsp)
leaq 0x1d0(%rbx), %rax
movq %rax, 0x30(%rsp)
leaq 0x200(%rbx), %rax
movq %rax, 0x28(%rsp)
leaq 0x210(%rbx), %r14
pushq $0x1
popq %rbp
leaq 0x60(%rsp), %r12
pushq $0x1
popq %rax
movl %eax, 0xc(%rsp)
movq 0x48(%rsp), %rdi
movq 0x10(%rsp), %rsi
callq 0xe787
cmpq $0x1, %rbp
sete %al
orb 0x258(%rbx), %al
cmpb $0x1, %al
jne 0x128f5
movq %rbx, %rdi
callq 0x10942
jmp 0x12921
movq 0x30(%rsp), %rdi
movq %r15, %rsi
callq 0xe787
movq 0xb8(%rbx), %rsi
addq %rsi, %rsi
movq %r12, %rdi
callq 0xced2
movq 0x28(%rsp), %rdi
movq %r12, %rsi
callq 0x26bc6
movq %rbx, %rdi
callq 0x101bc
movq %rbx, %rdi
callq 0x11596
movq %r12, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x1367c
leaq 0x50(%rsp), %r13
movq %r13, %rdi
movq %r12, %rsi
callq 0x25a0a
movq %rbx, %rdi
movq %r13, %rsi
movq %rbp, %rdx
callq 0x11fc4
ucomisd 0x3ea7b(%rip), %xmm0    # 0x513e0
jne 0x1299e
jp 0x1299e
cmpq $0x0, 0xb8(%rbx)
je 0x12a8b
movq %rbx, %rdi
callq 0x12534
movq 0x845ea(%rip), %rdi     # 0x96f70
leaq 0x4124f(%rip), %rsi     # 0x53bdc
callq 0x9330
decq %rbp
decq 0x50(%rbx)
jmp 0x12a28
movsd %xmm0, 0x38(%rsp)
movq %rbx, %rdi
callq 0x12448
movsd %xmm0, 0x40(%rsp)
cmpb $0x1, 0x58(%rbx)
jne 0x129f8
movq 0x50(%rbx), %r13
movsd 0x230(%rbx), %xmm0
movsd %xmm0, 0x20(%rsp)
movq 0x18(%rsp), %rdi
callq 0xea40
movapd %xmm0, %xmm2
leaq 0x4120f(%rip), %rdi     # 0x53bee
movq %rbp, %rsi
movq %r13, %rdx
movsd 0x38(%rsp), %xmm0
movsd 0x20(%rsp), %xmm1
movb $0x3, %al
callq 0x9060
movq 0x18(%rsp), %rdi
callq 0xea40
movsd 0x68(%rbx), %xmm1
ucomisd %xmm0, %xmm1
ja 0x12a3a
movsd 0x70(%rbx), %xmm0
ucomisd 0x40(%rsp), %xmm0
ja 0x12a51
cmpq 0x60(%rbx), %rbp
jae 0x12a72
movq %rbx, %rdi
callq 0xf162
movq 0x50(%rsp), %rdi
callq 0x93c0
incq %rbp
jmp 0x128cb
cmpb $0x0, 0x58(%rbx)
je 0x12a68
movl $0x0, 0xc(%rsp)
leaq 0x59d60(%rip), %rdi     # 0x6c7af
jmp 0x12a86
cmpb $0x0, 0x58(%rbx)
je 0x12a68
movl $0x0, 0xc(%rsp)
leaq 0x59d23(%rip), %rdi     # 0x6c789
jmp 0x12a86
movl $0x0, 0xc(%rsp)
jmp 0x12a8b
pushq $0x1
popq %rax
cmpb $0x0, 0x58(%rbx)
movl %eax, 0xc(%rsp)
je 0x12a8b
leaq 0x59ce3(%rip), %rdi     # 0x6c769
callq 0x9520
movq 0x50(%rsp), %rdi
callq 0x93c0
movl 0xc(%rsp), %eax
jmp 0x127f8
jmp 0x12aa0
movq %rax, %rbx
movq 0x50(%rsp), %rdi
callq 0x93c0
movq %rbx, %rdi
callq 0x9640
nop