// File: /workspace/github_c_makefile_star2_O3/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 $0x118, %rsp            # imm = 0x118
movq %rdx, 0x40(%rsp)
movl %edi, 0x8(%rsp)
movl $0xfffffc1d, %eax       # imm = 0xFFFFFC1D
xorpd %xmm1, %xmm1
xorpd %xmm0, %xmm0
movapd %xmm0, 0x90(%rsp)
ucomisd (%r9), %xmm1
jae 0x3c5f
movq %r8, %r14
movq %rcx, %r15
movq %rsi, %r13
movl 0x8(%rsp), %eax
movl %eax, %ebp
testl %eax, %eax
jle 0x3681
xorl %eax, %eax
movsd (%r15,%rax,8), %xmm0
mulsd (%r14,%rax,8), %xmm0
addsd %xmm0, %xmm1
incq %rax
cmpq %rax, %rbp
jne 0x364d
movl $0xfffffc1e, %eax       # imm = 0xFFFFFC1E
xorpd %xmm0, %xmm0
movapd %xmm1, 0x90(%rsp)
ucomisd %xmm0, %xmm1
ja 0x3c5f
movq 0x170(%rsp), %rcx
movq 0x150(%rsp), %r12
leaq 0xc(%rsp), %rax
movl $0x0, (%rax)
movq 0x40(%rsp), %rax
movsd (%rax), %xmm2
movsd 0x40(%rcx), %xmm3
movsd 0x38(%rcx), %xmm0
subsd 0x30(%rcx), %xmm0
movapd 0x90(%rsp), %xmm1
mulsd %xmm1, %xmm3
movsd %xmm3, 0x18(%rsp)
movapd %xmm0, %xmm3
addsd %xmm0, %xmm3
movsd %xmm3, 0x30(%rsp)
xorl %edx, %edx
leaq 0x10(%rsp), %rax
movq %rdx, (%rax)
leaq 0x20(%rsp), %rax
movq %rdx, (%rax)
leaq 0x50(%rsp), %rax
movsd %xmm2, (%rax)
leaq 0x60(%rsp), %rax
movsd %xmm2, 0xb0(%rsp)
movsd %xmm2, (%rax)
leaq 0x48(%rsp), %rax
movsd %xmm1, (%rax)
leaq 0x58(%rsp), %rax
movsd %xmm1, (%rax)
movapd 0x9994(%rip), %xmm2     # 0xd0b0
xorpd %xmm1, %xmm2
movapd %xmm2, 0xf0(%rsp)
movl $0x1, 0x4(%rsp)
movb $0x1, %bl
movq $0x0, 0x28(%rsp)
movq %r9, 0x38(%rsp)
movsd %xmm0, 0xa8(%rsp)
movsd 0x20(%rsp), %xmm6
testb $0x1, %bl
je 0x3774
movsd (%r9), %xmm0
movapd %xmm0, %xmm5
subsd %xmm6, %xmm5
mulsd 0x990e(%rip), %xmm5     # 0xd078
addsd %xmm0, %xmm5
movapd %xmm6, %xmm3
jmp 0x37b1
movsd 0x10(%rsp), %xmm0
movapd %xmm6, %xmm3
cmplesd %xmm0, %xmm3
movapd %xmm3, %xmm1
andpd %xmm6, %xmm1
andnpd %xmm0, %xmm3
orpd %xmm1, %xmm3
movapd %xmm0, %xmm5
cmplesd %xmm6, %xmm5
movapd %xmm5, %xmm1
andpd %xmm6, %xmm1
andnpd %xmm0, %xmm5
orpd %xmm1, %xmm5
movsd (%r9), %xmm0
movsd 0x30(%rcx), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x37c5
movsd %xmm1, (%r9)
movapd %xmm1, %xmm0
movsd 0x38(%rcx), %xmm1
ucomisd %xmm1, %xmm0
jbe 0x37d9
movsd %xmm1, (%r9)
movapd %xmm1, %xmm0
testb $0x1, %bl
jne 0x381a
ucomisd %xmm0, %xmm3
jae 0x3811
ucomisd %xmm5, %xmm0
jae 0x3811
movq 0x28(%rsp), %rax
incl %eax
cmpl %eax, 0x28(%rcx)
jle 0x3811
testl %edx, %edx
jne 0x3811
movapd %xmm5, %xmm1
subsd %xmm3, %xmm1
movsd 0x58(%rcx), %xmm2
mulsd %xmm5, %xmm2
ucomisd %xmm1, %xmm2
jb 0x381a
movsd %xmm6, (%r9)
movapd %xmm6, %xmm0
cmpl $0x0, 0x8(%rsp)
jle 0x3864
xorl %eax, %eax
movsd (%r12,%rax,8), %xmm0
movsd %xmm0, (%r13,%rax,8)
incq %rax
cmpq %rax, %rbp
jne 0x3823
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, %rbp
jne 0x383f
movsd (%r9), %xmm0
movapd %xmm6, 0x100(%rsp)
movq %rdx, 0xb8(%rsp)
movapd %xmm5, 0xd0(%rsp)
movapd %xmm3, 0xe0(%rsp)
movq 0x168(%rsp), %rax
movq 0x8(%rax), %rdi
movl (%rax), %ecx
movq %r13, %rsi
movq %r15, %rdx
callq *0x10(%rax)
movq 0x40(%rsp), %rax
movsd %xmm0, (%rax)
movq $0x0, 0x88(%rsp)
cmpl $0x0, 0x8(%rsp)
jle 0x38e6
xorpd %xmm8, %xmm8
xorl %eax, %eax
movsd (%r15,%rax,8), %xmm2
mulsd (%r14,%rax,8), %xmm2
addsd %xmm2, %xmm8
incq %rax
cmpq %rax, %rbp
jne 0x38c1
movsd %xmm8, 0x88(%rsp)
jmp 0x38eb
xorpd %xmm8, %xmm8
movq 0x38(%rsp), %r10
movq 0x170(%rsp), %rcx
movapd 0xe0(%rsp), %xmm7
movapd 0xd0(%rsp), %xmm1
movsd (%r10), %xmm4
testb $0x1, %bl
jne 0x393b
movl $0xfffffc17, %eax       # imm = 0xFFFFFC17
ucomisd %xmm4, %xmm7
jae 0x3c5f
ucomisd %xmm1, %xmm4
jae 0x3c5f
cmpl $0x0, 0xb8(%rsp)
jne 0x3c5f
movapd %xmm4, %xmm2
mulsd 0x18(%rsp), %xmm2
movapd %xmm2, %xmm3
addsd 0xb0(%rsp), %xmm3
ucomisd 0x38(%rcx), %xmm4
jne 0x3972
jp 0x3972
ucomisd %xmm0, %xmm3
jb 0x3972
movsd 0x18(%rsp), %xmm5
ucomisd %xmm8, %xmm5
jae 0x3c4c
ucomisd 0x30(%rcx), %xmm4
jne 0x3997
jp 0x3997
ucomisd %xmm3, %xmm0
movl $0xfffffc18, %eax       # imm = 0xFFFFFC18
ja 0x3c5f
ucomisd 0x18(%rsp), %xmm8
jae 0x3c5f
testb $0x1, %bl
jne 0x39b7
movapd %xmm1, %xmm4
subsd %xmm7, %xmm4
movsd 0x58(%rcx), %xmm5
mulsd %xmm1, %xmm5
ucomisd %xmm4, %xmm5
jae 0x3c53
movq 0x28(%rsp), %rax
incl %eax
movq %rax, 0x28(%rsp)
cmpl %eax, 0x28(%rcx)
jle 0x3c45
ucomisd %xmm0, %xmm3
jae 0x39e0
cmpl $0x0, 0x4(%rsp)
jne 0x3a44
xorl %ebx, %ebx
jmp 0x3b82
movapd %xmm8, %xmm5
andpd 0x96b3(%rip), %xmm5     # 0xd0a0
movsd 0x50(%rcx), %xmm4
movapd %xmm4, %xmm6
mulsd 0xf0(%rsp), %xmm6
ucomisd %xmm5, %xmm6
jae 0x3c5a
xorl %ebx, %ebx
cmpl $0x0, 0x4(%rsp)
je 0x3b82
movsd 0x40(%rcx), %xmm5
movapd %xmm5, %xmm6
cmplesd %xmm4, %xmm6
andpd %xmm6, %xmm5
andnpd %xmm4, %xmm6
orpd %xmm5, %xmm6
mulsd 0x90(%rsp), %xmm6
ucomisd %xmm6, %xmm8
jae 0x3b82
ucomisd %xmm3, %xmm0
movl $0x1, %ebx
jbe 0x3b82
movsd 0x60(%rsp), %xmm3
ucomisd %xmm0, %xmm3
jb 0x3b82
subsd %xmm2, %xmm0
movsd %xmm0, 0xc8(%rsp)
movsd 0x18(%rsp), %xmm4
movapd 0x100(%rsp), %xmm0
mulsd %xmm4, %xmm0
subsd %xmm0, %xmm3
movsd %xmm3, 0x80(%rsp)
movsd 0x50(%rsp), %xmm0
movsd 0x10(%rsp), %xmm2
mulsd %xmm4, %xmm2
subsd %xmm2, %xmm0
movsd %xmm0, 0x70(%rsp)
subsd %xmm4, %xmm8
movsd %xmm8, 0xc0(%rsp)
movsd 0x58(%rsp), %xmm0
subsd %xmm4, %xmm0
movsd %xmm0, 0x78(%rsp)
movsd 0x48(%rsp), %xmm0
subsd %xmm4, %xmm0
movsd %xmm0, 0x68(%rsp)
leaq 0x20(%rsp), %rdi
leaq 0x80(%rsp), %rsi
leaq 0x78(%rsp), %rdx
leaq 0x10(%rsp), %rcx
leaq 0x70(%rsp), %r8
leaq 0x68(%rsp), %r9
movapd %xmm7, %xmm0
leaq 0xc(%rsp), %rax
pushq %rax
leaq 0xc8(%rsp), %rax
pushq %rax
leaq 0xd8(%rsp), %rax
pushq %rax
pushq %r10
callq 0x4147
addq $0x20, %rsp
movl %eax, %edx
movsd 0x20(%rsp), %xmm0
movsd 0x18(%rsp), %xmm1
mulsd %xmm1, %xmm0
addsd 0x80(%rsp), %xmm0
movsd %xmm0, 0x60(%rsp)
movsd 0x10(%rsp), %xmm0
mulsd %xmm1, %xmm0
addsd 0x70(%rsp), %xmm0
movsd %xmm0, 0x50(%rsp)
movsd 0x78(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x58(%rsp)
movsd 0x68(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x48(%rsp)
movl $0x1, 0x4(%rsp)
jmp 0x3bc8
leaq 0x20(%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 0xc(%rsp), %rax
pushq %rax
leaq 0x90(%rsp), %rax
pushq %rax
pushq 0x50(%rsp)
pushq %r10
callq 0x4147
addq $0x20, %rsp
movl %eax, %edx
movl %ebx, 0x4(%rsp)
movb $0x1, %bl
cmpl $0x0, 0xc(%rsp)
movq 0x38(%rsp), %r9
movq 0x170(%rsp), %rcx
movsd 0xa8(%rsp), %xmm4
je 0x374a
movsd 0x30(%rsp), %xmm3
mulsd 0x9487(%rip), %xmm3     # 0xd080
movsd 0x10(%rsp), %xmm1
movsd 0x20(%rsp), %xmm2
subsd %xmm2, %xmm1
movapd %xmm1, %xmm0
andpd 0x948b(%rip), %xmm0     # 0xd0a0
xorl %ebx, %ebx
ucomisd %xmm3, %xmm0
movsd %xmm4, 0x30(%rsp)
jb 0x3741
mulsd 0x9421(%rip), %xmm1     # 0xd050
addsd %xmm2, %xmm1
movsd %xmm1, (%r9)
xorl %ebx, %ebx
movsd %xmm4, 0x30(%rsp)
jmp 0x3741
movl $0xfffffc1a, %eax       # imm = 0xFFFFFC1A
jmp 0x3c5f
movl $0xfffffc19, %eax       # imm = 0xFFFFFC19
jmp 0x3c5f
movl $0xfffffc1c, %eax       # imm = 0xFFFFFC1C
jmp 0x3c5f
movq 0x28(%rsp), %rax
addq $0x118, %rsp            # imm = 0x118
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq