// File: /workspace/github_c_makefile_star2_O1/debbiemarkslab[P]plmc/src/lib/lbfgs.c
// Function: line_search_morethuente
static int line_search_morethuente(
    int n,
    lbfgsfloatval_t *x,
    lbfgsfloatval_t *f,
    lbfgsfloatval_t *g,
    lbfgsfloatval_t *s,
    lbfgsfloatval_t *stp,
    const lbfgsfloatval_t* xp,
    const lbfgsfloatval_t* gp,
    lbfgsfloatval_t *wa,
    callback_data_t *cd,
    const lbfgs_parameter_t *param
    )
{
    int count = 0;
    int brackt, stage1, uinfo = 0;
    lbfgsfloatval_t dg;
    lbfgsfloatval_t stx, fx, dgx;
    lbfgsfloatval_t sty, fy, dgy;
    lbfgsfloatval_t fxm, dgxm, fym, dgym, fm, dgm;
    lbfgsfloatval_t finit, ftest1, dginit, dgtest;
    lbfgsfloatval_t width, prev_width;
    lbfgsfloatval_t stmin, stmax;

    /* Check the input parameters for errors. */
    if (*stp <= 0.) {
        return LBFGSERR_INVALIDPARAMETERS;
    }

    /* Compute the initial gradient in the search direction. */
    vecdot(&dginit, g, s, n);

    /* Make sure that s points to a descent direction. */
    if (0 < dginit) {
        return LBFGSERR_INCREASEGRADIENT;
    }

    /* Initialize local variables. */
    brackt = 0;
    stage1 = 1;
    finit = *f;
    dgtest = param->ftol * dginit;
    width = param->max_step - param->min_step;
    prev_width = 2.0 * width;

    /*
        The variables stx, fx, dgx contain the values of the step,
        function, and directional derivative at the best step.
        The variables sty, fy, dgy contain the value of the step,
        function, and derivative at the other endpoint of
        the interval of uncertainty.
        The variables stp, f, dg contain the values of the step,
        function, and derivative at the current step.
    */
    stx = sty = 0.;
    fx = fy = finit;
    dgx = dgy = dginit;

    for (;;) {
        /*
            Set the minimum and maximum steps to correspond to the
            present interval of uncertainty.
         */
        if (brackt) {
            stmin = min2(stx, sty);
            stmax = max2(stx, sty);
        } else {
            stmin = stx;
            stmax = *stp + 4.0 * (*stp - stx);
        }

        /* Clip the step in the range of [stpmin, stpmax]. */
        if (*stp < param->min_step) *stp = param->min_step;
        if (param->max_step < *stp) *stp = param->max_step;

        /*
            If an unusual termination is to occur then let
            stp be the lowest point obtained so far.
         */
        if ((brackt && ((*stp <= stmin || stmax <= *stp) || param->max_linesearch <= count + 1 || uinfo != 0)) || (brackt && (stmax - stmin <= param->xtol * stmax))) {
            *stp = stx;
        }

        /*
            Compute the current value of x:
                x <- x + (*stp) * s.
         */
        veccpy(x, xp, n);
        vecadd(x, s, *stp, n);

        /* Evaluate the function and gradient values. */
        *f = cd->proc_evaluate(cd->instance, x, g, cd->n, *stp);
        vecdot(&dg, g, s, n);

        ftest1 = finit + *stp * dgtest;
        ++count;

        /* Test for errors and convergence. */
        if (brackt && ((*stp <= stmin || stmax <= *stp) || uinfo != 0)) {
            /* Rounding errors prevent further progress. */
            return LBFGSERR_ROUNDING_ERROR;
        }
        if (*stp == param->max_step && *f <= ftest1 && dg <= dgtest) {
            /* The step is the maximum value. */
            return LBFGSERR_MAXIMUMSTEP;
        }
        if (*stp == param->min_step && (ftest1 < *f || dgtest <= dg)) {
            /* The step is the minimum value. */
            return LBFGSERR_MINIMUMSTEP;
        }
        if (brackt && (stmax - stmin) <= param->xtol * stmax) {
            /* Relative width of the interval of uncertainty is at most xtol. */
            return LBFGSERR_WIDTHTOOSMALL;
        }
        if (param->max_linesearch <= count) {
            /* Maximum number of iteration. */
            return LBFGSERR_MAXIMUMLINESEARCH;
        }
        if (*f <= ftest1 && fabs(dg) <= param->gtol * (-dginit)) {
            /* The sufficient decrease condition and the directional derivative condition hold. */
            return count;
        }

        /*
            In the first stage we seek a step for which the modified
            function has a nonpositive value and nonnegative derivative.
         */
        if (stage1 && *f <= ftest1 && min2(param->ftol, param->gtol) * dginit <= dg) {
            stage1 = 0;
        }

        /*
            A modified function is used to predict the step only if
            we have not obtained a step for which the modified
            function has a nonpositive function value and nonnegative
            derivative, and if a lower function value has been
            obtained but the decrease is not sufficient.
         */
        if (stage1 && ftest1 < *f && *f <= fx) {
            /* Define the modified function and derivative values. */
            fm = *f - *stp * dgtest;
            fxm = fx - stx * dgtest;
            fym = fy - sty * dgtest;
            dgm = dg - dgtest;
            dgxm = dgx - dgtest;
            dgym = dgy - dgtest;

            /*
                Call update_trial_interval() to update the interval of
                uncertainty and to compute the new step.
             */
            uinfo = update_trial_interval(
                &stx, &fxm, &dgxm,
                &sty, &fym, &dgym,
                stp, &fm, &dgm,
                stmin, stmax, &brackt
                );

            /* Reset the function and gradient values for f. */
            fx = fxm + stx * dgtest;
            fy = fym + sty * dgtest;
            dgx = dgxm + dgtest;
            dgy = dgym + dgtest;
        } else {
            /*
                Call update_trial_interval() to update the interval of
                uncertainty and to compute the new step.
             */
            uinfo = update_trial_interval(
                &stx, &fx, &dgx,
                &sty, &fy, &dgy,
                stp, f, &dg,
                stmin, stmax, &brackt
                );
        }

        /*
            Force a sufficient decrease in the interval of uncertainty.
         */
        if (brackt) {
            if (0.66 * prev_width <= fabs(sty - stx)) {
                *stp = stx + 0.5 * (sty - stx);
            }
            prev_width = width;
            width = fabs(sty - stx);
        }
    }

    return LBFGSERR_LOGICERROR;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x108, %rsp            # imm = 0x108
movq %rdx, 0x40(%rsp)
movl $0xfffffc1d, %eax       # imm = 0xFFFFFC1D
xorpd %xmm0, %xmm0
ucomisd (%r9), %xmm0
jae 0x415f
movq %r8, %r14
movq %rcx, %r15
movq %rsi, %r13
movl %edi, %r12d
testl %edi, %edi
xorpd %xmm1, %xmm1
jle 0x4147
xorl %eax, %eax
movsd (%r15,%rax,8), %xmm0
mulsd (%r14,%rax,8), %xmm0
addsd %xmm0, %xmm1
incq %rax
cmpq %rax, %r12
jne 0x412f
movl $0xfffffc1e, %eax       # imm = 0xFFFFFC1E
xorpd %xmm0, %xmm0
movapd %xmm1, 0xc0(%rsp)
ucomisd %xmm0, %xmm1
jbe 0x4171
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x160(%rsp), %rcx
movq 0x140(%rsp), %rbp
leaq 0x4(%rsp), %rax
movl $0x0, (%rax)
movq 0x40(%rsp), %rax
movsd (%rax), %xmm2
movsd 0x40(%rcx), %xmm0
movapd 0xc0(%rsp), %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, 0x18(%rsp)
movsd 0x38(%rcx), %xmm0
subsd 0x30(%rcx), %xmm0
movapd %xmm0, %xmm3
addsd %xmm0, %xmm3
movsd %xmm3, 0x30(%rsp)
xorl %edx, %edx
leaq 0x10(%rsp), %rax
movq %rdx, (%rax)
leaq 0x8(%rsp), %rax
movq %rdx, (%rax)
leaq 0x50(%rsp), %rax
movsd %xmm2, (%rax)
leaq 0x60(%rsp), %rax
movsd %xmm2, 0xa0(%rsp)
movsd %xmm2, (%rax)
leaq 0x48(%rsp), %rax
movsd %xmm1, (%rax)
leaq 0x58(%rsp), %rax
movsd %xmm1, (%rax)
movapd 0x9ea4(%rip), %xmm2     # 0xe0b0
xorpd %xmm1, %xmm2
movapd %xmm2, 0xf0(%rsp)
movl $0x1, %ebx
movq $0x0, 0x28(%rsp)
movq %r9, 0x38(%rsp)
movl %edi, 0x24(%rsp)
movsd %xmm0, 0x98(%rsp)
movl %ebx, 0x6c(%rsp)
movl 0x4(%rsp), %ebx
movsd 0x8(%rsp), %xmm3
testl %ebx, %ebx
je 0x4285
movsd 0x10(%rsp), %xmm0
movapd %xmm3, %xmm1
cmplesd %xmm0, %xmm1
movapd %xmm1, %xmm2
andpd %xmm3, %xmm2
andnpd %xmm0, %xmm1
orpd %xmm2, %xmm1
movapd %xmm0, %xmm2
cmplesd %xmm3, %xmm2
andpd %xmm2, %xmm3
andnpd %xmm0, %xmm2
orpd %xmm3, %xmm2
movapd %xmm1, %xmm3
jmp 0x429e
movsd (%r9), %xmm0
movapd %xmm0, %xmm2
subsd %xmm3, %xmm2
mulsd 0x9dde(%rip), %xmm2     # 0xe078
addsd %xmm0, %xmm2
movsd 0x30(%rcx), %xmm0
ucomisd (%r9), %xmm0
jbe 0x42af
movsd %xmm0, (%r9)
movsd 0x38(%rcx), %xmm0
movsd (%r9), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x42c4
movsd %xmm0, (%r9)
testl %ebx, %ebx
je 0x430f
movsd (%r9), %xmm0
ucomisd %xmm0, %xmm3
jae 0x4304
ucomisd %xmm2, %xmm0
jae 0x4304
movq 0x28(%rsp), %rax
incl %eax
cmpl %eax, 0x28(%rcx)
jle 0x4304
testl %edx, %edx
jne 0x4304
testl %ebx, %ebx
je 0x430f
movapd %xmm2, %xmm0
subsd %xmm3, %xmm0
movsd 0x58(%rcx), %xmm1
mulsd %xmm2, %xmm1
ucomisd %xmm0, %xmm1
jb 0x430f
movsd 0x8(%rsp), %xmm0
movsd %xmm0, (%r9)
testl %edi, %edi
jle 0x432a
xorl %eax, %eax
movsd (%rbp,%rax,8), %xmm0
movsd %xmm0, (%r13,%rax,8)
incq %rax
cmpq %rax, %r12
jne 0x4315
movq %rdx, 0xa8(%rsp)
movapd %xmm2, 0xd0(%rsp)
movapd %xmm3, 0xe0(%rsp)
testl %edi, %edi
jle 0x436f
movsd (%r9), %xmm0
xorl %eax, %eax
movsd (%r14,%rax,8), %xmm1
mulsd %xmm0, %xmm1
addsd (%r13,%rax,8), %xmm1
movsd %xmm1, (%r13,%rax,8)
incq %rax
cmpq %rax, %r12
jne 0x434f
movq 0x158(%rsp), %rax
movq 0x8(%rax), %rdi
movl (%rax), %ecx
movsd (%r9), %xmm0
movq %r13, %rsi
movq %r15, %rdx
callq *0x10(%rax)
movq 0x40(%rsp), %rax
movsd %xmm0, (%rax)
movq $0x0, 0x90(%rsp)
cmpl $0x0, 0x24(%rsp)
jle 0x43e9
xorpd %xmm8, %xmm8
xorl %eax, %eax
movq 0x160(%rsp), %rdx
movapd 0xe0(%rsp), %xmm7
movsd (%r15,%rax,8), %xmm2
mulsd (%r14,%rax,8), %xmm2
addsd %xmm2, %xmm8
incq %rax
cmpq %rax, %r12
jne 0x43bf
movsd %xmm8, 0x90(%rsp)
movq 0x38(%rsp), %r10
jmp 0x4404
xorpd %xmm8, %xmm8
movq 0x38(%rsp), %r10
movq 0x160(%rsp), %rdx
movapd 0xe0(%rsp), %xmm7
movapd 0xd0(%rsp), %xmm1
movsd (%r10), %xmm4
testl %ebx, %ebx
je 0x443d
movl $0xfffffc17, %eax       # imm = 0xFFFFFC17
ucomisd %xmm4, %xmm7
jae 0x415f
ucomisd %xmm1, %xmm4
jae 0x415f
cmpl $0x0, 0xa8(%rsp)
jne 0x415f
movapd %xmm4, %xmm2
mulsd 0x18(%rsp), %xmm2
movapd %xmm2, %xmm3
addsd 0xa0(%rsp), %xmm3
ucomisd 0x38(%rdx), %xmm4
jne 0x4474
jp 0x4474
ucomisd %xmm0, %xmm3
jb 0x4474
movsd 0x18(%rsp), %xmm5
ucomisd %xmm8, %xmm5
jae 0x474b
ucomisd 0x30(%rdx), %xmm4
jne 0x4499
jp 0x4499
ucomisd %xmm3, %xmm0
movl $0xfffffc18, %eax       # imm = 0xFFFFFC18
ja 0x415f
ucomisd 0x18(%rsp), %xmm8
jae 0x415f
testl %ebx, %ebx
je 0x44b8
movapd %xmm1, %xmm4
subsd %xmm7, %xmm4
movsd 0x58(%rdx), %xmm5
mulsd %xmm1, %xmm5
ucomisd %xmm4, %xmm5
jae 0x4755
movq 0x28(%rsp), %rax
incl %eax
movq %rax, 0x28(%rsp)
cmpl %eax, 0x28(%rdx)
jle 0x4741
ucomisd %xmm0, %xmm3
jb 0x44f8
movapd %xmm8, %xmm4
andpd 0x9bc0(%rip), %xmm4     # 0xe0a0
movsd 0x50(%rdx), %xmm5
mulsd 0xf0(%rsp), %xmm5
ucomisd %xmm4, %xmm5
jae 0x475f
cmpl $0x0, 0x6c(%rsp)
sete %al
setne %cl
movl $0x0, %ebx
movb %cl, %bl
je 0x454e
ucomisd %xmm0, %xmm3
jb 0x454e
movsd 0x40(%rdx), %xmm4
movsd 0x50(%rdx), %xmm5
movapd %xmm4, %xmm6
cmplesd %xmm5, %xmm6
andpd %xmm6, %xmm4
andnpd %xmm5, %xmm6
orpd %xmm4, %xmm6
mulsd 0xc0(%rsp), %xmm6
xorl %ebx, %ebx
ucomisd %xmm6, %xmm8
jae 0x454c
movl $0x1, %ebx
xorl %eax, %eax
jmp 0x454e
movb $0x1, %al
testb %al, %al
je 0x4599
leaq 0x8(%rsp), %rdi
leaq 0x60(%rsp), %rsi
leaq 0x58(%rsp), %rdx
leaq 0x10(%rsp), %rcx
leaq 0x50(%rsp), %r8
leaq 0x48(%rsp), %r9
movapd %xmm7, %xmm0
leaq 0x4(%rsp), %rax
pushq %rax
leaq 0x98(%rsp), %rax
pushq %rax
pushq 0x50(%rsp)
pushq %r10
callq 0x4c3d
addq $0x20, %rsp
movl %eax, %edx
jmp 0x46c6
ucomisd %xmm3, %xmm0
jbe 0x4552
movsd 0x60(%rsp), %xmm3
ucomisd %xmm0, %xmm3
jb 0x4552
subsd %xmm2, %xmm0
movsd %xmm0, 0xb8(%rsp)
movsd 0x8(%rsp), %xmm0
movsd 0x18(%rsp), %xmm4
mulsd %xmm4, %xmm0
subsd %xmm0, %xmm3
movsd %xmm3, 0x88(%rsp)
movsd 0x50(%rsp), %xmm0
movsd 0x10(%rsp), %xmm2
mulsd %xmm4, %xmm2
subsd %xmm2, %xmm0
movsd %xmm0, 0x78(%rsp)
subsd %xmm4, %xmm8
movsd %xmm8, 0xb0(%rsp)
movsd 0x58(%rsp), %xmm0
subsd %xmm4, %xmm0
movsd %xmm0, 0x80(%rsp)
movsd 0x48(%rsp), %xmm0
subsd %xmm4, %xmm0
movsd %xmm0, 0x70(%rsp)
leaq 0x8(%rsp), %rdi
leaq 0x88(%rsp), %rsi
leaq 0x80(%rsp), %rdx
leaq 0x10(%rsp), %rcx
leaq 0x78(%rsp), %r8
leaq 0x70(%rsp), %r9
movapd %xmm7, %xmm0
leaq 0x4(%rsp), %rax
pushq %rax
leaq 0xb8(%rsp), %rax
pushq %rax
leaq 0xc8(%rsp), %rax
pushq %rax
pushq %r10
callq 0x4c3d
addq $0x20, %rsp
movl %eax, %edx
movsd 0x8(%rsp), %xmm0
movsd 0x18(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd 0x88(%rsp), %xmm0
movsd 0x10(%rsp), %xmm1
mulsd %xmm2, %xmm1
addsd 0x78(%rsp), %xmm1
movsd %xmm0, 0x60(%rsp)
movsd %xmm1, 0x50(%rsp)
movsd 0x80(%rsp), %xmm0
addsd %xmm2, %xmm0
movsd %xmm0, 0x58(%rsp)
movsd 0x70(%rsp), %xmm0
addsd %xmm2, %xmm0
movsd %xmm0, 0x48(%rsp)
cmpl $0x0, 0x4(%rsp)
movq 0x38(%rsp), %r9
movl 0x24(%rsp), %edi
movq 0x160(%rsp), %rcx
movsd 0x98(%rsp), %xmm4
je 0x4239
movsd 0x30(%rsp), %xmm3
mulsd 0x9987(%rip), %xmm3     # 0xe080
movsd 0x10(%rsp), %xmm1
movsd 0x8(%rsp), %xmm2
subsd %xmm2, %xmm1
movapd %xmm1, %xmm0
andpd 0x998b(%rip), %xmm0     # 0xe0a0
ucomisd %xmm3, %xmm0
movsd %xmm4, 0x30(%rsp)
jb 0x4230
mulsd 0x9923(%rip), %xmm1     # 0xe050
addsd %xmm2, %xmm1
movsd %xmm1, (%r9)
movsd %xmm4, 0x30(%rsp)
jmp 0x4230
movl $0xfffffc1a, %eax       # imm = 0xFFFFFC1A
jmp 0x415f
movl $0xfffffc19, %eax       # imm = 0xFFFFFC19
jmp 0x415f
movl $0xfffffc1c, %eax       # imm = 0xFFFFFC1C
jmp 0x415f
movq 0x28(%rsp), %rax
jmp 0x415f