// File: /workspace/github_c_makefile_star2_O2/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 $0x128, %rsp            # imm = 0x128
movq %r8, 0x78(%rsp)
movq %rcx, 0x70(%rsp)
movq %rdx, 0x38(%rsp)
movq %rsi, 0xb0(%rsp)
movl %edi, 0x2c(%rsp)
movl $0xfffffc1d, %eax       # imm = 0xFFFFFC1D
xorpd %xmm0, %xmm0
ucomisd (%r9), %xmm0
jae 0x22ba
movq %r9, %r15
leaq 0x120(%rsp), %r12
movq %r12, %rdi
movq 0x70(%rsp), %rsi
movq 0x78(%rsp), %rdx
movl 0x2c(%rsp), %ecx
callq 0x2dcf
movsd (%r12), %xmm0
movl $0xfffffc1e, %eax       # imm = 0xFFFFFC1E
movapd %xmm0, 0xd0(%rsp)
ucomisd 0x9db8(%rip), %xmm0     # 0xc070
jbe 0x22cc
addq $0x128, %rsp            # imm = 0x128
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x180(%rsp), %rbp
leaq 0x4(%rsp), %rax
andl $0x0, (%rax)
movq 0x38(%rsp), %rax
movsd (%rax), %xmm2
movsd 0x40(%rbp), %xmm0
movapd 0xd0(%rsp), %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, 0x10(%rsp)
movsd 0x38(%rbp), %xmm0
subsd 0x30(%rbp), %xmm0
leaq 0x8(%rsp), %rax
andq $0x0, (%rax)
leaq 0x18(%rsp), %rax
andq $0x0, (%rax)
movapd %xmm0, %xmm3
addsd %xmm0, %xmm3
movsd %xmm3, 0x30(%rsp)
leaq 0x50(%rsp), %rax
movsd %xmm2, (%rax)
leaq 0x60(%rsp), %rax
movsd %xmm2, 0xa8(%rsp)
movsd %xmm2, (%rax)
leaq 0x48(%rsp), %rax
movsd %xmm1, (%rax)
leaq 0x58(%rsp), %rax
movsd %xmm1, (%rax)
movapd 0x9d44(%rip), %xmm2     # 0xc0a0
xorpd %xmm1, %xmm2
movapd %xmm2, 0xe0(%rsp)
pushq $0x1
popq %rax
xorl %ecx, %ecx
movb $0x1, %r12b
movl %eax, (%rsp)
xorl %ebx, %ebx
movq 0x78(%rsp), %r13
movsd %xmm0, 0xa0(%rsp)
movsd 0x18(%rsp), %xmm5
testb $0x1, %r12b
je 0x23af
movsd (%r15), %xmm0
movapd %xmm0, %xmm3
subsd %xmm5, %xmm3
mulsd 0x9cd3(%rip), %xmm3     # 0xc078
addsd %xmm0, %xmm3
movapd %xmm5, %xmm2
jmp 0x23ec
movsd 0x8(%rsp), %xmm0
movapd %xmm5, %xmm2
cmplesd %xmm0, %xmm2
movapd %xmm2, %xmm1
andpd %xmm5, %xmm1
andnpd %xmm0, %xmm2
orpd %xmm1, %xmm2
movapd %xmm0, %xmm3
cmplesd %xmm5, %xmm3
movapd %xmm3, %xmm1
andpd %xmm5, %xmm1
andnpd %xmm0, %xmm3
orpd %xmm1, %xmm3
movsd (%r15), %xmm0
movsd 0x30(%rbp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x2400
movsd %xmm1, (%r15)
movapd %xmm1, %xmm0
movsd 0x38(%rbp), %xmm1
ucomisd %xmm1, %xmm0
jbe 0x2414
movsd %xmm1, (%r15)
movapd %xmm1, %xmm0
testb $0x1, %r12b
jne 0x244e
ucomisd %xmm0, %xmm2
jae 0x2449
ucomisd %xmm3, %xmm0
jae 0x2449
leal 0x1(%rbx), %eax
cmpl %eax, 0x28(%rbp)
jle 0x2449
testl %ecx, %ecx
jne 0x2449
movapd %xmm3, %xmm0
subsd %xmm2, %xmm0
movsd 0x58(%rbp), %xmm1
mulsd %xmm3, %xmm1
ucomisd %xmm0, %xmm1
jb 0x244e
movsd %xmm5, (%r15)
movapd %xmm5, 0xf0(%rsp)
movl %ecx, 0x6c(%rsp)
movq %rbx, 0xb8(%rsp)
movq 0xb0(%rsp), %r14
movq %r14, %rdi
movq 0x160(%rsp), %rsi
movl 0x2c(%rsp), %ebx
movl %ebx, %edx
movapd %xmm2, 0x110(%rsp)
movapd %xmm3, 0x100(%rsp)
callq 0x2d92
movsd (%r15), %xmm0
movq %r14, %rdi
movq %r13, %rsi
movl %ebx, %edx
callq 0x2dfb
movq 0x178(%rsp), %rax
movq 0x8(%rax), %rdi
movl (%rax), %ecx
movsd (%r15), %xmm0
movq %r14, %rsi
movq 0x70(%rsp), %r14
movq %r14, %rdx
callq *0x10(%rax)
movq 0x38(%rsp), %rax
movsd %xmm0, 0x40(%rsp)
movsd %xmm0, (%rax)
leaq 0x20(%rsp), %rdi
movq %r14, %rsi
movq %r13, %rdx
movl %ebx, %ecx
callq 0x2dcf
movapd 0x100(%rsp), %xmm1
movapd 0x110(%rsp), %xmm0
movsd (%r15), %xmm2
testb $0x1, %r12b
jne 0x2528
movl $0xfffffc17, %eax       # imm = 0xFFFFFC17
ucomisd %xmm2, %xmm0
jae 0x22ba
ucomisd %xmm1, %xmm2
jae 0x22ba
cmpl $0x0, 0x6c(%rsp)
jne 0x22ba
movapd %xmm2, %xmm6
mulsd 0x10(%rsp), %xmm6
movapd %xmm6, %xmm7
addsd 0xa8(%rsp), %xmm7
ucomisd 0x38(%rbp), %xmm2
jne 0x2562
jp 0x2562
ucomisd 0x40(%rsp), %xmm7
jb 0x2562
movsd 0x10(%rsp), %xmm3
ucomisd 0x20(%rsp), %xmm3
jae 0x2863
ucomisd 0x30(%rbp), %xmm2
jne 0x2592
jp 0x2592
movsd 0x40(%rsp), %xmm2
ucomisd %xmm7, %xmm2
movl $0xfffffc18, %eax       # imm = 0xFFFFFC18
ja 0x22ba
movsd 0x20(%rsp), %xmm2
ucomisd 0x10(%rsp), %xmm2
jae 0x22ba
testb $0x1, %r12b
jne 0x25b3
movapd %xmm1, %xmm2
subsd %xmm0, %xmm2
movsd 0x58(%rbp), %xmm3
mulsd %xmm1, %xmm3
ucomisd %xmm2, %xmm3
jae 0x286d
movq 0xb8(%rsp), %rbx
leal 0x1(%rbx), %eax
cmpl %eax, 0x28(%rbp)
jle 0x2859
movsd 0x40(%rsp), %xmm8
ucomisd %xmm8, %xmm7
jae 0x25e3
cmpl $0x0, (%rsp)
jne 0x264b
xorl %r12d, %r12d
jmp 0x27a5
movsd 0x20(%rsp), %xmm2
movapd %xmm2, %xmm4
andpd 0x9abb(%rip), %xmm4     # 0xc0b0
movsd 0x50(%rbp), %xmm3
movapd %xmm3, %xmm5
mulsd 0xe0(%rsp), %xmm5
ucomisd %xmm4, %xmm5
jae 0x22ba
xorl %r12d, %r12d
cmpl $0x0, (%rsp)
je 0x27a5
movsd 0x40(%rbp), %xmm4
movapd %xmm4, %xmm5
cmplesd %xmm3, %xmm5
andpd %xmm5, %xmm4
andnpd %xmm3, %xmm5
orpd %xmm4, %xmm5
mulsd 0xd0(%rsp), %xmm5
ucomisd %xmm5, %xmm2
jae 0x27a5
ucomisd %xmm7, %xmm8
pushq $0x1
popq %r12
jbe 0x27a5
movsd 0x60(%rsp), %xmm2
ucomisd %xmm8, %xmm2
jb 0x27a5
subsd %xmm6, %xmm8
movsd %xmm8, 0xc8(%rsp)
movsd 0x10(%rsp), %xmm4
movapd 0xf0(%rsp), %xmm3
mulsd %xmm4, %xmm3
subsd %xmm3, %xmm2
movsd %xmm2, 0x98(%rsp)
movsd 0x50(%rsp), %xmm2
movsd 0x8(%rsp), %xmm3
mulsd %xmm4, %xmm3
subsd %xmm3, %xmm2
movsd %xmm2, 0x88(%rsp)
movsd 0x20(%rsp), %xmm2
subsd %xmm4, %xmm2
movsd %xmm2, 0xc0(%rsp)
movsd 0x58(%rsp), %xmm2
subsd %xmm4, %xmm2
movsd %xmm2, 0x90(%rsp)
movsd 0x48(%rsp), %xmm2
subsd %xmm4, %xmm2
movsd %xmm2, 0x80(%rsp)
leaq 0x18(%rsp), %rdi
leaq 0x98(%rsp), %rsi
leaq 0x90(%rsp), %rdx
leaq 0x8(%rsp), %rcx
leaq 0x88(%rsp), %r8
leaq 0x80(%rsp), %r9
leaq 0x4(%rsp), %rax
pushq %rax
leaq 0xc8(%rsp), %rax
pushq %rax
leaq 0xd8(%rsp), %rax
pushq %rax
pushq %r15
callq 0x2e20
addq $0x20, %rsp
movl %eax, %ecx
movsd 0x18(%rsp), %xmm0
movsd 0x10(%rsp), %xmm1
mulsd %xmm1, %xmm0
addsd 0x98(%rsp), %xmm0
movsd %xmm0, 0x60(%rsp)
movsd 0x8(%rsp), %xmm0
mulsd %xmm1, %xmm0
addsd 0x88(%rsp), %xmm0
movsd %xmm0, 0x50(%rsp)
movsd 0x90(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x58(%rsp)
movsd 0x80(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x48(%rsp)
pushq $0x1
popq %rax
movl %eax, (%rsp)
jmp 0x27e4
leaq 0x18(%rsp), %rdi
leaq 0x60(%rsp), %rsi
leaq 0x58(%rsp), %rdx
leaq 0x8(%rsp), %rcx
leaq 0x50(%rsp), %r8
leaq 0x48(%rsp), %r9
leaq 0x4(%rsp), %rax
pushq %rax
leaq 0x28(%rsp), %rax
pushq %rax
pushq 0x48(%rsp)
pushq %r15
callq 0x2e20
addq $0x20, %rsp
movl %eax, %ecx
movl %r12d, (%rsp)
incl %ebx
cmpl $0x0, 0x4(%rsp)
movb $0x1, %r12b
movsd 0xa0(%rsp), %xmm4
je 0x2384
movsd 0x30(%rsp), %xmm3
mulsd 0x9875(%rip), %xmm3     # 0xc080
movsd 0x8(%rsp), %xmm1
movsd 0x18(%rsp), %xmm2
subsd %xmm2, %xmm1
movapd %xmm1, %xmm0
andpd 0x9889(%rip), %xmm0     # 0xc0b0
xorl %r12d, %r12d
ucomisd %xmm3, %xmm0
movsd %xmm4, 0x30(%rsp)
jb 0x237b
mulsd 0x980e(%rip), %xmm1     # 0xc050
addsd %xmm2, %xmm1
movsd %xmm1, (%r15)
xorl %r12d, %r12d
movsd %xmm4, 0x30(%rsp)
jmp 0x237b
movl $0xfffffc1a, %eax       # imm = 0xFFFFFC1A
jmp 0x22ba
movl $0xfffffc19, %eax       # imm = 0xFFFFFC19
jmp 0x22ba
movl $0xfffffc1c, %eax       # imm = 0xFFFFFC1C
jmp 0x22ba