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); } }
/* * 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); } }