double solve(
    /* Solves equation (*f)(x) = 0 on x in [a,b]. Uses half interval method. */
    /* Requires that (*f)(a) and (*f)(b) have opposite signs.               */
    /* Returns code=0 if signs are opposite.                                */
    /* Returns code=1 if signs are both positive.                           */
    /* Returns code=1 if signs are both negative.                           */
    double (*f)(double), /* pointer to function to be solved */
    double a,            /* minimum value of solution */
    double b,            /* maximum value of solution */
    double err,          /* accuracy of solution */
    int *code            /* error code */
)
{
    int signa, signb, signc;
    double fa, fb, fc, c;
    double dist;

    fa = (*f)(a);
    signa = fa > 0;
    fb = (*f)(b);
    signb = fb > 0;

    /* check starting conditions */
    if (signa == signb) {
        if (signa == 1)
            *code = 1;
        else
            *code = -1;
        return (0.0);
    }
    else
        *code = 0;

    /* half interval search */
    if ((dist = b - a) < 0)
        dist = -dist;
    while (dist > err) {
        c = (b + a) / 2;
        fc = (*f)(c);
        signc = fc > 0;
        if (signa == signc) {
            a = c;
            fa = fc;
        }
        else {
            b = c;
            fb = fc;
        }
        if ((dist = b - a) < 0)
            dist = -dist;
    }

    /* linear interpolation */
    if ((fb - fa) == 0)
        return (a);
    else {
        c = (a * fb - b * fa) / (fb - fa);
        return (c);
    }
}
