4 #include <utl/LambertW.h>
12 namespace LambertWDetail {
38 -1 +
p*(1 +
p*(-1./3));
48 -1 +
p*(1 +
p*(-1./3 +
p*(11./72)));
58 -1 +
p*(1 +
p*(-1./3 +
p*(11./72 +
p*(-43./540))));
68 -1 +
p*(1 +
p*(-1./3 +
p*(11./72 +
p*(-43./540 +
p*(769./17280)))));
78 -1 +
p*(1 +
p*(-1./3 +
p*(11./72 +
p*(-43./540 +
p*(769./17280
79 +
p*(-221./8505))))));
89 -1 +
p*(1 +
p*(-1./3 +
p*(11./72 +
p*(-43./540 +
p*(769./17280
90 +
p*(-221./8505 +
p*(680863./43545600)))))));
100 -1 +
p*(1 +
p*(-1./3 +
p*(11./72 +
p*(-43./540 +
p*(769./17280
101 +
p*(-221./8505 +
p*(680863./43545600 +
p*(-1963./204120))))))));
111 -1 +
p*(1 +
p*(-1./3 +
p*(11./72 +
p*(-43./540 +
p*(769./17280
112 +
p*(-221./8505 +
p*(680863./43545600 +
p*(-1963./204120
113 +
p*(226287557./37623398400.)))))))));
135 return a -
b +
b /
a;
144 const double ia = 1 /
a;
145 return a -
b +
b /
a * (1 + ia * 0.5*(-2 +
b));
154 const double ia = 1 /
a;
155 return a -
b +
b /
a *
158 1/6.*(6 +
b*(-9 +
b*2))
169 const double ia = 1 /
a;
170 return a -
b +
b /
a *
173 (1/6.*(6 +
b*(-9 +
b*2)) + ia *
174 1/12.*(-12 +
b*(36 +
b*(-22 +
b*3)))
186 const double ia = 1 /
a;
187 return a -
b +
b /
a *
190 (1/6.*(6 +
b*(-9 +
b*2)) + ia *
191 (1/12.*(-12 +
b*(36 +
b*(-22 +
b*3))) + ia *
192 1/60.*(60 +
b*(-300 +
b*(350 +
b*(-125 +
b*12))))
206 {
return BranchPointPolynomial<order>(eSign *
sqrt(2*(M_E*x+1))); }
215 const double logsx = log(eSign * x);
216 const double logslogsx = log(eSign * logsx);
217 return LambertWDetail::AsymptoticExpansion<order>(logsx, logslogsx);
221 static inline double RationalApproximation(
const double x);
226 {
return LogRecursionStep<order>(log(eSign * x)); }
229 static inline double Approximation(
const double x);
233 static const int eSign = 2*branch + 1;
237 {
return logsx - log(eSign * LogRecursionStep<n-1>(logsx)); }
249 return x*(60 + x*(114 + 17*x)) / (60 + x*(174 + 101*x));
262 (5.931375839364438 + x *
263 (11.392205505329132 + x *
264 (7.338883399111118 + x*0.6534490169919599)
269 (6.931373689597704 + x *
270 (16.82349461388016 + x *
271 (16.43072324143226 + x*5.115235195211697)
287 (4.790423028527326 + x *
288 (6.695945075293267 + x * 2.4243096805908033)
292 (5.790432723810737 + x *
293 (10.986445930034288 + x *
294 (7.391303898769326 + x * 1.1414723648617864)
310 (2.4450530707265568 + x *
311 (1.3436642259582265 + x *
312 (0.14844005539759195 + x * 0.0008047501729129999)
317 (3.4447089864860025 + x *
318 (3.2924898573719523 + x *
319 (0.9164600188031222 + x * 0.05306864044833221)
330 Branch<-1>::RationalApproximation<4>(
const double x)
334 (-7.814176723907436 + x *
335 (253.88810188892484 + x * 657.9493176902304)
338 (-60.43958713690808 + x *
339 (99.98567083107612 + x *
340 (682.6073999909428 + x *
341 (962.1784396969866 + x * 1477.9341280760887)
365 Branch<-1>::LogRecursionStep<0>(
const double logsx)
387 if (x < -0.32358170806015724) {
389 return numeric_limits<double>::quiet_NaN();
390 else if (x < -
kInvE+1e-5)
391 return BranchPointExpansion<5>(x);
393 return BranchPointExpansion<9>(x);
395 if (x < 0.14546954290661823)
396 return RationalApproximation<1>(x);
397 else if (x < 8.706658967856612)
398 return RationalApproximation<3>(x);
425 if (x < -0.051012917658221676) {
426 if (x < -
kInvE+1e-5) {
428 return numeric_limits<double>::quiet_NaN();
430 return BranchPointExpansion<5>(x);
432 if (x < -0.30298541769)
433 return BranchPointExpansion<9>(x);
435 return RationalApproximation<4>(x);
439 return LogRecursion<9>(x);
441 return -numeric_limits<double>::infinity();
443 return numeric_limits<double>::quiet_NaN();
454 const double ew = exp(w);
455 const double wew = w * ew;
456 const double wewx = wew - x;
457 const double w1 = w + 1;
458 return w - wewx / (ew * w1 - (w + 2) * wewx/(2*w1));
466 const double z = log(x/w) - w;
467 const double w1 = w + 1;
468 const double q = 2 * w1 * (w1 + (2/3.)*z);
469 const double eps = z / w1 * (q - z) / (q - 2*z);
470 return w * (1 +
eps);
475 double IterationStep(
const double x,
const double w)
481 for (
int i = 0; i < 100; ++i) {
482 const double ww = IterationStep(x, w);
483 if (fabs(ww - w) <=
eps)
487 cerr <<
"convergence not reached." << endl;
493 double IterationStep(
const double x,
const double w)
499 Do(
const int n,
const double x,
double w)
501 for (
int i = 0; i < n; ++i)
502 w = IterationStep(x, w);
509 Do(
const double x,
double w)
511 for (
int i = 0; i < n; ++i)
512 w = IterationStep(x, w);
516 template<
int n,
class =
void>
518 static double Recurse(
const double x,
double w)
525 static double Recurse(
const double x,
const double w)
526 {
return IterationStep(x, w); }
532 static double Recurse([[maybe_unused]]
const double x,
const double w)
564 Iterator<LambertWDetail::FritschStep>::
double AsymptoticExpansion< 5 >(const double a, const double b)
double AsymptoticExpansion< 4 >(const double a, const double b)
template double LambertWApproximation<-1 >(const double x)
static double AsymptoticExpansion(const double x)
double LambertW< 0 >(const double x)
double BranchPointPolynomial(const double p)
double AsymptoticExpansion(const double a, const double b)
double AsymptoticExpansion< 3 >(const double a, const double b)
template double LambertWApproximation< 0 >(const double x)
double BranchPointPolynomial< 5 >(const double p)
double Iterate(const double x, double w, const double eps=1e-6)
double AsymptoticExpansion< 0 >(const double a, const double b)
static double Recurse(const double x, double w)
double BranchPointPolynomial< 9 >(const double p)
double BranchPointPolynomial< 4 >(const double p)
static double Recurse(const double x, const double w)
double LambertW(const double x)
double BranchPointPolynomial< 3 >(const double p)
double LambertWApproximation(const double x)
double FritschStep(const double x, const double w)
static double BranchPointExpansion(const double x)
static double LogRecursion(const double x)
double AsymptoticExpansion< 2 >(const double a, const double b)
static double Do(const int n, const double x, double w)
double AsymptoticExpansion< 1 >(const double a, const double b)
double HalleyStep(const double x, const double w)
double BranchPointPolynomial< 6 >(const double p)
double BranchPointPolynomial< 2 >(const double p)
double BranchPointPolynomial< 8 >(const double p)
double BranchPointPolynomial< 7 >(const double p)
double BranchPointPolynomial< 1 >(const double p)
static double Recurse([[maybe_unused]] const double x, const double w)
static double Do(const double x, double w)
static double LogRecursionStep(const double logsx)