// File: /workspace/github_cpp_makefile_star2_O1/canzarlab[P]Trajan/geno/lineSearch.cpp
// Function: dcsrch(double&, double&, double&, double, double, double, double, double, TaskType&, TMPContainer&)
void dcsrch(double & f,
            double & g,
            double & stp,
            double const ftol,
            double const gtol,
            double const xtol,
            double const stpmin,
            double const stpmax,
            TaskType & task, TMPContainer& TCON) {
  double const zero = 0.0,
               p5   = 0.5,
               p66  = 0.66,
               xtrapl = 1.1,
               xtrapu = 4.0;
  //static bool brackt;
  //static int stage;
  //static double finit, fx, fy, ginit,gtest, gx, gy,
  //              stx,sty,stmin,stmax,width,width1;
  double ftest,fm,fxm,fym, gm,gxm,gym;

      if (task == TaskType::START) {

//       Check the input arguments for errors.

         if (stp < stpmin) {
          task = TaskType::ERROR;
          std::cerr << "ERROR: STP < STPMIN" << std::endl;
         }
         if (stp > stpmax) {
          //task = TaskType::ERROR;
          stp = stpmax;
          std::cerr << "ERROR: STP > STPMAX" << std::endl;
         } 
         if (g >= zero) {
          task = TaskType::ERROR;
          std::cerr << "ERROR: INITIAL G >= ZERO" << std::endl;
         }
         if (ftol < zero) {
          task = TaskType::ERROR;
          std::cerr << "ERROR: FTOL < ZERO" << std::endl;
         }
         if (gtol < zero) {
          task = TaskType::ERROR;
          std::cerr << "ERROR: GTOL < ZERO" << std::endl;
         }
         if (xtol < zero) {
          task = TaskType::ERROR;
          std::cerr << "ERROR: XTOL < ZERO" << std::endl;
         }
         if (stpmin < zero) {
          task = TaskType::ERROR;
          std::cerr << "ERROR: STPMIN < ZERO" << std::endl;
         }
         if (stpmax < stpmin) {
          task = TaskType::ERROR;
          std::cerr << "ERROR: STPMAX < STPMIN" << std::endl;
         }

//        Exit if there are errors on input.

         if (task == TaskType::ERROR)
          return;

//        Initialize local variables.

         TCON.brackt = false;
         TCON.stage = 1;
         TCON.finit = f;
         TCON.ginit = g;
         TCON.gtest = ftol*TCON.fy;
         TCON.width = stpmax - stpmin;
         TCON.width1 = TCON.width/p5;

//        The variables stx, fx, gx contain the values of the step, 
//        function, and derivative at the best step. 
//        The variables sty, fy, gy contain the value of the step, 
//        function, and derivative at sty.
//        The variables stp, f, g contain the values of the step, 
//        function, and derivative at stp.

         TCON.stx = zero;
         TCON.fx = TCON.finit;
         TCON.gx = TCON.ginit;
         TCON.sty = zero;
         TCON.fy = TCON.finit;
         TCON.gy = TCON.ginit;
         TCON.stmin = zero;
         TCON.stmax = stp + xtrapu*stp;
         task = TaskType::FG;

         return;

      }

//     If psi(stp) <= 0 and f'(stp) >= 0 for some step, then the
//     algorithm enters the second stage.

      ftest = TCON.finit + stp*TCON.gtest;
      if (TCON.stage == 1 && f <= ftest && g >= zero) 
        TCON.stage = 2;

//     Test for warnings.

      if (TCON.brackt && (stp <= TCON.stmin || stp >= TCON.stmax)) {
        task = TaskType::WARNING;
//        std::cerr << "ROUNDING ERRORS PREVENT PROGRESS\n";
      }
      if (TCON.brackt && TCON.stmax - TCON.stmin <= xtol*TCON.stmax) {
        task = TaskType::WARNING;
//        std::cerr << "XTOL TEST SATISFIED\n";
      }
      if (stp == stpmax && f <= ftest && g <= TCON.gtest) {
        task = TaskType::WARNING;
//        std::cerr << "STP = STPMAX\n";
      }
      if (stp == stpmin && (f > ftest || g >= TCON.gtest)) {
        task = TaskType::WARNING;
//        std::cerr << "STP = STPMIN\n";
      }
//     Test for convergence.

/*
      printf("f = %15.15g \n", f);
      printf("ftest = %15.15g\n", ftest);
      std::cout << "f " << f << std::endl;
      std::cout << "ftest " << ftest << std::endl;
      std::cout << "fabs(g) " << std::fabs(g) << std::endl;
      std::cout << "gtol*ginit " << gtol * (-ginit) << std::endl;
*/
//      if (f <= ftest && std::fabs(g) <= gtol * (-TCON.ginit))
      double eps = 1E-6;
      if (f <= ftest + eps*(std::fabs(ftest) + 1) && std::fabs(g) <= gtol * (-TCON.ginit)) 
        task = TaskType::CONVERGENCE;

//     Test for termination.

      if (task == TaskType::WARNING || task == TaskType::CONVERGENCE)
        return;

//     A modified function is used to predict the step during the
//     first TCON.stage if a lower function value has been obtained but 
//     the decrease is not sufficient.

      if (TCON.stage == 1 && f <= TCON.fx && f > ftest) {
//        Define the modified function and derivative values.
         fm = f - stp*TCON.gtest;
         fxm = TCON.fx - TCON.stx*TCON.gtest;
         fym = TCON.fy - TCON.sty*TCON.gtest;
         gm = g - TCON.gtest;
         gxm = TCON.gx - TCON.gtest;
         gym = TCON.gy - TCON.gtest;
//        Call dcstep to update stx, sty, and to compute the new step.
//	 std::cout << "called dcstep 1" << std::endl;
         dcstep(TCON.stx,fxm,gxm,TCON.sty,fym,gym,stp,fm,gm,TCON.brackt,TCON.stmin,TCON.stmax);
//        Reset the function and derivative values for f.
         TCON.fx = fxm + TCON.stx*TCON.gtest;
         TCON.fy = fym + TCON.sty*TCON.gtest;
         TCON.gx = gxm + TCON.gtest;
         TCON.gy = gym + TCON.gtest;
      } else {

//       Call dcstep to update stx, sty, and to compute the new step.
//	std::cout << "called dcstep 2" << std::endl;
        dcstep(TCON.stx,TCON.fx,TCON.gx,TCON.sty,TCON.fy,TCON.gy,stp,f,g,TCON.brackt,TCON.stmin,TCON.stmax);
	//	std::cout << "stx = " << stx << std::endl;
	//	std::cout << "fx  = " << fx << std::endl;
	//	std::cout << "gx  = " << gx << std::endl;
	//	std::cout << "sty = " << sty << std::endl;
	//	std::cout << "fy  = " << fy << std::endl;
	//	std::cout << "gy  = " << gy << std::endl;
	//	std::cout << "stp = " << stp << std::endl;
	//	std::cout << "f   = " << f << std::endl;
	//	std::cout << "g   = " << g << std::endl;
	//	std::cout << "stmin = " << stmin << std::endl;
	//	std::cout << "stmax = " << stmax << std::endl;
      }
//     Decide if a bisection step is needed.

      if (TCON.brackt) {
	//	std::cout << "brackt true" << std::endl;
         if (std::fabs(TCON.sty-TCON.stx) >= p66*TCON.width1) stp = TCON.stx + p5*(TCON.sty - TCON.stx);
         TCON.width1 = TCON.width;
         TCON.width = std::fabs(TCON.sty-TCON.stx);
      }

//     Set the minimum and maximum steps allowed for stp.

      if (TCON.brackt) {
         TCON.stmin = std::min(TCON.stx,TCON.sty);
         TCON.stmax = std::max(TCON.stx,TCON.sty);
      } else {
         TCON.stmin = stp + xtrapl*(stp - TCON.stx);
         TCON.stmax = stp + xtrapu*(stp - TCON.stx);
      }
// 
//     Force the step to be within the bounds stpmax and stpmin.
// 
      stp = std::max(stp,stpmin);
      stp = std::min(stp,stpmax);

//     If further progress is not possible, let stp be the best
//     point obtained during the search.

      if ((TCON.brackt && (stp <= TCON.stmin || stp >= TCON.stmax))
          || (TCON.brackt && TCON.stmax-TCON.stmin <= xtol*TCON.stmax)) {
	//	std::cout << "no further progress" << std::endl;
	stp = TCON.stx;
      }

//     Obtain another function and derivative.

      task = TaskType::FG;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %r8, %r14
movq %rcx, %rbx
movsd %xmm2, 0x10(%rsp)
movapd %xmm1, %xmm9
movq %rdx, %r15
movq %rsi, %r13
movq %rdi, %r12
cmpl $0x0, (%rcx)
movsd %xmm4, 0x8(%rsp)
je 0x2e264
movsd (%r15), %xmm5
movsd 0x28(%r14), %xmm2
movapd %xmm5, %xmm8
mulsd %xmm2, %xmm8
movsd 0x8(%r14), %xmm7
addsd %xmm8, %xmm7
cmpl $0x1, 0x4(%r14)
movsd (%r13), %xmm1
jne 0x2e070
ucomisd (%r12), %xmm7
jb 0x2e070
xorpd %xmm0, %xmm0
ucomisd %xmm0, %xmm1
jb 0x2e070
movl $0x2, 0x4(%r14)
movb (%r14), %al
cmpb $0x1, %al
jne 0x2e0b7
movsd 0x50(%r14), %xmm0
ucomisd %xmm5, %xmm0
jae 0x2e08b
ucomisd 0x58(%r14), %xmm5
jb 0x2e091
movl $0x3, (%rbx)
testb %al, %al
je 0x2e0b7
movsd 0x58(%r14), %xmm0
movapd %xmm0, %xmm6
subsd 0x50(%r14), %xmm6
mulsd 0x10(%rsp), %xmm0
ucomisd %xmm6, %xmm0
jb 0x2e0b7
movl $0x3, (%rbx)
ucomisd %xmm4, %xmm5
movsd (%r12), %xmm0
jne 0x2e0d7
jp 0x2e0d7
ucomisd %xmm0, %xmm7
jb 0x2e0d7
ucomisd %xmm1, %xmm2
jb 0x2e0d7
movl $0x3, (%rbx)
ucomisd %xmm3, %xmm5
jne 0x2e0f1
jp 0x2e0f1
ucomisd %xmm7, %xmm0
ja 0x2e0eb
ucomisd %xmm2, %xmm1
jb 0x2e0f1
movl $0x3, (%rbx)
movapd 0x2e2f7(%rip), %xmm5    # 0x5c3f0
andpd %xmm7, %xmm5
addsd 0x2e2a3(%rip), %xmm5    # 0x5c3a8
mulsd 0x40fc3(%rip), %xmm5    # 0x6f0d0
addsd %xmm7, %xmm5
ucomisd %xmm0, %xmm5
jb 0x2e142
movapd 0x2e2d1(%rip), %xmm5    # 0x5c3f0
movsd 0x20(%r14), %xmm6
xorpd 0x2e2b3(%rip), %xmm6    # 0x5c3e0
andpd %xmm1, %xmm5
mulsd %xmm9, %xmm6
ucomisd %xmm5, %xmm6
jb 0x2e142
movl $0x4, (%rbx)
movl (%rbx), %eax
addl $-0x3, %eax
cmpl $0x2, %eax
jb 0x2e74a
movsd %xmm3, (%rsp)
cmpl $0x1, 0x4(%r14)
jne 0x2e5d1
movsd 0x10(%r14), %xmm5
ucomisd %xmm0, %xmm5
jb 0x2e5d1
ucomisd %xmm7, %xmm0
jbe 0x2e5d1
subsd %xmm8, %xmm0
leaq 0x40(%r14), %rdi
movsd 0x40(%r14), %xmm3
mulsd %xmm2, %xmm3
subsd %xmm3, %xmm5
leaq 0x28(%rsp), %rax
movsd %xmm5, (%rax)
movq %rax, %rsi
movsd 0x18(%r14), %xmm3
leaq 0x48(%r14), %rcx
movsd 0x48(%r14), %xmm4
mulsd %xmm2, %xmm4
subsd %xmm4, %xmm3
leaq 0x40(%rsp), %r13
movsd %xmm3, (%r13)
subsd %xmm2, %xmm1
movsd 0x30(%r14), %xmm3
subsd %xmm2, %xmm3
leaq 0x38(%rsp), %rbp
movsd %xmm3, (%rbp)
movsd 0x38(%r14), %xmm3
subsd %xmm2, %xmm3
leaq 0x30(%rsp), %r12
movsd %xmm3, (%r12)
movsd 0x50(%r14), %xmm2
movsd 0x58(%r14), %xmm3
movq %rbp, %rdx
movq %r13, %r8
movq %r12, %r9
pushq %r14
pushq %r15
callq 0x2d7fc
addq $0x10, %rsp
movsd 0x28(%r14), %xmm0
movsd 0x40(%r14), %xmm1
mulsd %xmm0, %xmm1
leaq 0x28(%rsp), %rax
addsd (%rax), %xmm1
movsd %xmm1, 0x10(%r14)
movsd 0x48(%r14), %xmm1
mulsd %xmm0, %xmm1
addsd (%r13), %xmm1
movsd %xmm1, 0x18(%r14)
movsd (%rbp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x30(%r14)
addsd (%r12), %xmm0
movsd %xmm0, 0x38(%r14)
jmp 0x2e602
movsd %xmm9, 0x20(%rsp)
movsd %xmm0, 0x18(%rsp)
movsd %xmm3, (%rsp)
ucomisd (%r15), %xmm3
jbe 0x2e2cc
movl $0x1, (%rbx)
movq 0x59d66(%rip), %rbp     # 0x87ff0
leaq 0x40e57(%rip), %rsi     # 0x6f0e8
movl $0x13, %edx
movq %rbp, %rdi
callq 0x93a0
movq (%rbp), %rax
movq -0x18(%rax), %rdi
addq %rbp, %rdi
movl $0xa, %esi
callq 0x9320
movsbl %al, %esi
movq %rbp, %rdi
callq 0x9040
movq %rax, %rdi
callq 0x9220
movsd 0x8(%rsp), %xmm4
movsd (%r15), %xmm0
ucomisd %xmm4, %xmm0
jbe 0x2e31f
movsd %xmm4, (%r15)
movq 0x59d0d(%rip), %rbp     # 0x87ff0
leaq 0x40e12(%rip), %rsi     # 0x6f0fc
movl $0x13, %edx
movq %rbp, %rdi
callq 0x93a0
movq (%rbp), %rax
movq -0x18(%rax), %rdi
addq %rbp, %rdi
movl $0xa, %esi
callq 0x9320
movsbl %al, %esi
movq %rbp, %rdi
callq 0x9040
movq %rax, %rdi
callq 0x9220
movsd (%r13), %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x2e37c
movl $0x1, (%rbx)
movq 0x59cb4(%rip), %rbp     # 0x87ff0
leaq 0x40dcd(%rip), %rsi     # 0x6f110
movl $0x18, %edx
movq %rbp, %rdi
callq 0x93a0
movq (%rbp), %rax
movq -0x18(%rax), %rdi
addq %rbp, %rdi
movl $0xa, %esi
callq 0x9320
movsbl %al, %esi
movq %rbp, %rdi
callq 0x9040
movq %rax, %rdi
callq 0x9220
xorpd %xmm1, %xmm1
ucomisd 0x18(%rsp), %xmm1
jbe 0x2e3cd
movl $0x1, (%rbx)
movq 0x59c5f(%rip), %rbp     # 0x87ff0
leaq 0x40d91(%rip), %rsi     # 0x6f129
movl $0x12, %edx
movq %rbp, %rdi
callq 0x93a0
movq (%rbp), %rax
movq -0x18(%rax), %rdi
addq %rbp, %rdi
movl $0xa, %esi
callq 0x9320
movsbl %al, %esi
movq %rbp, %rdi
callq 0x9040
movq %rax, %rdi
callq 0x9220
xorpd %xmm0, %xmm0
ucomisd 0x20(%rsp), %xmm0
jbe 0x2e426
movl $0x1, (%rbx)
movq 0x59c0a(%rip), %rbp     # 0x87ff0
leaq 0x40d4f(%rip), %rsi     # 0x6f13c
movl $0x12, %edx
movq %rbp, %rdi
callq 0x93a0
movq (%rbp), %rax
movq -0x18(%rax), %rdi
addq %rbp, %rdi
movl $0xa, %esi
callq 0x9320
movsbl %al, %esi
movq %rbp, %rdi
callq 0x9040
movq %rax, %rdi
callq 0x9220
xorpd %xmm0, %xmm0
ucomisd 0x10(%rsp), %xmm0
jbe 0x2e477
movl $0x1, (%rbx)
movq 0x59bb5(%rip), %rbp     # 0x87ff0
leaq 0x40d0d(%rip), %rsi     # 0x6f14f
movl $0x12, %edx
movq %rbp, %rdi
callq 0x93a0
movq (%rbp), %rax
movq -0x18(%rax), %rdi
addq %rbp, %rdi
movl $0xa, %esi
callq 0x9320
movsbl %al, %esi
movq %rbp, %rdi
callq 0x9040
movq %rax, %rdi
callq 0x9220
xorpd %xmm0, %xmm0
movsd (%rsp), %xmm3
ucomisd %xmm3, %xmm0
jbe 0x2e4d4
movl $0x1, (%rbx)
movq 0x59b5d(%rip), %rbp     # 0x87ff0
leaq 0x40cc8(%rip), %rsi     # 0x6f162
movl $0x14, %edx
movq %rbp, %rdi
callq 0x93a0
movq (%rbp), %rax
movq -0x18(%rax), %rdi
addq %rbp, %rdi
movl $0xa, %esi
callq 0x9320
movsbl %al, %esi
movq %rbp, %rdi
callq 0x9040
movq %rax, %rdi
callq 0x9220
movsd (%rsp), %xmm3
movsd 0x8(%rsp), %xmm2
ucomisd %xmm2, %xmm3
jbe 0x2e534
movl $0x1, (%rbx)
movq 0x59b03(%rip), %rbp     # 0x87ff0
leaq 0x40c83(%rip), %rsi     # 0x6f177
movl $0x16, %edx
movq %rbp, %rdi
callq 0x93a0
movq (%rbp), %rax
movq -0x18(%rax), %rdi
addq %rbp, %rdi
movl $0xa, %esi
callq 0x9320
movsbl %al, %esi
movq %rbp, %rdi
callq 0x9040
movq %rax, %rdi
callq 0x9220
movsd (%rsp), %xmm3
movsd 0x8(%rsp), %xmm2
cmpl $0x1, (%rbx)
je 0x2e74a
movb $0x0, (%r14)
movl $0x1, 0x4(%r14)
movsd (%r12), %xmm0
movsd %xmm0, 0x8(%r14)
movsd (%r13), %xmm1
movsd %xmm1, 0x20(%r14)
movsd 0x18(%rsp), %xmm4
mulsd 0x18(%r14), %xmm4
movsd %xmm4, 0x28(%r14)
subsd %xmm3, %xmm2
movsd %xmm2, 0x60(%r14)
addsd %xmm2, %xmm2
movsd %xmm2, 0x68(%r14)
movq $0x0, 0x40(%r14)
movsd %xmm0, 0x10(%r14)
movsd %xmm1, 0x30(%r14)
xorpd %xmm2, %xmm2
movupd %xmm2, 0x48(%r14)
movsd %xmm0, 0x18(%r14)
movsd %xmm1, 0x38(%r14)
movsd (%r15), %xmm0
movsd 0x40b22(%rip), %xmm1    # 0x6f0e0
mulsd %xmm0, %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x58(%r14)
jmp 0x2e744
leaq 0x40(%r14), %rdi
leaq 0x10(%r14), %rsi
leaq 0x30(%r14), %rdx
leaq 0x48(%r14), %rcx
leaq 0x18(%r14), %r8
leaq 0x38(%r14), %r9
movsd 0x50(%r14), %xmm2
movsd 0x58(%r14), %xmm3
pushq %r14
pushq %r15
callq 0x2d7fc
addq $0x10, %rsp
movb (%r14), %al
cmpb $0x1, %al
movsd 0x8(%rsp), %xmm4
movsd (%rsp), %xmm5
jne 0x2e6af
movsd 0x40(%r14), %xmm0
movsd 0x48(%r14), %xmm1
subsd %xmm0, %xmm1
movapd 0x2ddc0(%rip), %xmm2    # 0x5c3f0
andpd %xmm1, %xmm2
movsd 0x68(%r14), %xmm3
mulsd 0x40a86(%rip), %xmm3    # 0x6f0c8
ucomisd %xmm3, %xmm2
jb 0x2e659
mulsd 0x2dd78(%rip), %xmm1    # 0x5c3c8
addsd %xmm0, %xmm1
movsd %xmm1, (%r15)
movsd 0x48(%r14), %xmm0
movsd 0x60(%r14), %xmm1
movsd %xmm1, 0x68(%r14)
subsd 0x40(%r14), %xmm0
andpd 0x2dd77(%rip), %xmm0    # 0x5c3f0
movlpd %xmm0, 0x60(%r14)
testb %al, %al
je 0x2e6af
leaq 0x40(%r14), %rcx
movsd 0x40(%r14), %xmm0
movsd 0x48(%r14), %xmm1
ucomisd %xmm0, %xmm1
leaq 0x48(%r14), %rdx
minsd %xmm0, %xmm1
movsd %xmm1, 0x50(%r14)
cmovaq %rdx, %rcx
movsd (%rcx), %xmm0
jmp 0x2e6ed
movsd (%r15), %xmm0
movsd 0x40(%r14), %xmm1
movapd %xmm0, %xmm2
subsd %xmm1, %xmm2
mulsd 0x40a0e(%rip), %xmm2    # 0x6f0d8
addsd %xmm0, %xmm2
movsd %xmm2, 0x50(%r14)
movsd (%r15), %xmm2
movapd %xmm2, %xmm0
subsd %xmm1, %xmm0
mulsd 0x409f7(%rip), %xmm0    # 0x6f0e0
addsd %xmm2, %xmm0
movsd %xmm0, 0x58(%r14)
maxsd (%r15), %xmm5
minsd %xmm5, %xmm4
movsd %xmm4, (%r15)
testb %al, %al
je 0x2e744
movsd 0x50(%r14), %xmm0
ucomisd %xmm4, %xmm0
jae 0x2e739
ucomisd 0x58(%r14), %xmm4
jae 0x2e739
testb %al, %al
je 0x2e744
movsd 0x58(%r14), %xmm0
movsd 0x10(%rsp), %xmm1
mulsd %xmm0, %xmm1
subsd 0x50(%r14), %xmm0
ucomisd %xmm0, %xmm1
jb 0x2e744
movsd 0x40(%r14), %xmm0
movsd %xmm0, (%r15)
movl $0x2, (%rbx)
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nopl (%rax)