double lambertwn1(double y)
{
    if (y < 0.0)
    {
        if (y > M_E_INV)
        {
            register double x;
            /* Make a first guess */
            if (y < -0.02)
            {
                const double x2 = 2.0 * (1.0 + M_E*y);
                x = sqrt(x2);
                x = - (5.0/3.0) - (2.0/3.0)*M_E*y
                    - x * (1 + x2 * ((11.0/72.0) + (43.0/540.0)*x));
            }
            else
            {
                const double z = log(-y);
                /*
                 * We check here for z close to or less than -log(realmax).
                 * Since halley() fails by overflow, we use loglambertwn1()
                 * instead.
                 */
                if (z < -700) return -loglambertwn1(-z);
                x = z + log(-z);
            }
            /* Halley's method */
            return halley(x, y);
        }
        else if (y == M_E_INV)
        {
            /* Tip of branch */
            return -1.0;
        }
        else
        {
            /* Argument out of range */
            return outofrange("lambertwn1", y);
        }
    }
    else if (y == 0.0)
    {
        /* -Inf */
        /* return -1.0/0.0; -- won't compile on microsoft */
        return -1e100;
    }
    else
    {
        /* Argument out of range */
        return outofrange("lambertwn1", y);
    }
}
示例#2
0
/*
 * decode_path: decode encoded path name.
 *
 *	i)	path	encoded path name
 *	r)		decoded path name
 */
char *
decode_path(const unsigned char *path)
{
	STATIC_STRBUF(sb);
	const unsigned char *p;

	if (strchr((const char *)path, '%') == NULL)
		return (char *)path;
	strbuf_clear(sb);
	for (p = path; *p; p++) {
		if (*p == '%') {
			unsigned char c1, c2;
			c1 = *++p;
			c2 = *++p;
			if (outofrange(c1) || outofrange(c2))
				die("decode_path: unexpected character. (%%%c%c)", c1, c2);
			strbuf_putc(sb, h2int(c1) * 16 + h2int(c2));
		} else
			strbuf_putc(sb, *p);
	}
	return strbuf_value(sb);
}
double lambertw0(double y)
{
    if (y == 0.0)
    {
        return 0.0;
    }
    else if (y > M_E_INV)
    {
        register double x;
        /* Make a first guess */
        if (y < 0.0)
        {
            x = 2.0 * (1.0 + M_E*y);
            x = -1.0 - x/3.0 + sqrt(x) * (1 + x * (11.0/72.0));
        }
        else if (y < 1.0)
        {
            x = y;
        }
        else if (y == 1.0)
        {
            return W01;
        }
        else
        {
            const double logy = log(y);
            /*
             * For very large y, halley() can fail by overflow, so use the
             * Newton-Rhapson part in loglambertw0() instead.  Note that the
             * +Inf case is handled here.
             */
            if (logy > 40) return loglambertw0(-logy);
            x = fabs(log(logy));
        }
        /* Halley's method */
        return halley(x, y);
    }
    else if (y == M_E_INV)
    {
        /* Tip of branch */
        return -1.0;
    }
    else
    {
        /* Argument out of range */
        return outofrange("lambertw0", y);
    }
}
double loglambertwn1(double y)
{
    if (y > 1.0)
    {
        if (y > 6e+17)
        {
            /* For very large y, exp dominates */
            return y;
        }
        else if (y < 20.0)
        {
            /* For moderately small y, just use lambertwn1 */
            return -lambertwn1(-exp(-y));
        }
        else
        {
            /* Newton-Rhapson */
            register double oldx = y + log(y);
            register double x = oldx * (1 - log(oldx) - y) / (1 - oldx);
            /*
             * For y >= 20, the initial guess for x above is guaranteed to be
             * too small.  By considering the signs of the first and second
             * derivatives, we know we've run out of numeric precision when
             * x >= oldx.
             */
            do
            {
                oldx = x;
                x = x * (1 - log(x) - y) / (1 - x);
            }
            while (oldx - x > EPSILON);
            return x;
        }
    }
    else if (y == 1.0)
    {
        /* Tip of branch */
        return 1.0;
    }
    else
    {
        /* Argument out of range */
        return outofrange("loglambertwn1", y);
    }
}