15#ifndef _utl_LambertW_h_
16#define _utl_LambertW_h_
23 template<
typename Float,
class Tag,
unsigned int order>
26 static inline Float
Coeff(
const Float x);
30 template<
typename Float,
class Tag,
unsigned int order>
32 static Float
Recurse(
const Float term,
const Float x)
36 static Float
Eval(
const Float x)
41 static Float
Recurse(
const Float term,
const Float x,
const Float y)
43 static Float
Eval(
const Float x,
const Float y)
48 template<
typename Float,
class Tag>
50 static Float
Recurse(
const Float term,
const Float x)
52 static Float
Eval(
const Float x)
55 static Float
Recurse(
const Float term,
const Float x,
const Float y)
57 static Float
Eval(
const Float x,
const Float y)
62#define HORNER_COEFF(_Tag_, _i_, _c_) \
63 template<typename Float> struct Polynomial<Float, _Tag_, _i_> { static Float Coeff() { return Float(_c_); } }
64#define HORNER_COEFF2(_Tag_, _i_, _c_y_) \
65 template<typename Float> struct Polynomial<Float, _Tag_, _i_> { static Float Coeff(const Float y) { return Float(_c_y_); } }
68#define HORNER0(F, x, c0) (F)(c0)
69#define HORNER1(F, x, c1, c0) HORNER0(F, x, (F)(c1)*(x) + (F)(c0) )
70#define HORNER2(F, x, c2, c1, c0) HORNER1(F, x, (F)(c2)*(x) + (F)(c1), c0)
71#define HORNER3(F, x, c3, c2, c1, c0) HORNER2(F, x, (F)(c3)*(x) + (F)(c2), c1, c0)
72#define HORNER4(F, x, c4, c3, c2, c1, c0) HORNER3(F, x, (F)(c4)*(x) + (F)(c3), c2, c1, c0)
73#define HORNER5(F, x, c5, c4, c3, c2, c1, c0) HORNER4(F, x, (F)(c5)*(x) + (F)(c4), c3, c2, c1, c0)
74#define HORNER6(F, x, c6, c5, c4, c3, c2, c1, c0) HORNER5(F, x, (F)(c6)*(x) + (F)(c5), c4, c3, c2, c1, c0)
75#define HORNER7(F, x, c7, c6, c5, c4, c3, c2, c1, c0) HORNER6(F, x, (F)(c7)*(x) + (F)(c6), c5, c4, c3, c2, c1, c0)
76#define HORNER8(F, x, c8, c7, c6, c5, c4, c3, c2, c1, c0) HORNER7(F, x, (F)(c8)*(x) + (F)(c7), c6, c5, c4, c3, c2, c1, c0)
77#define HORNER9(F, x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0) HORNER8(F, x, (F)(c9)*(x) + (F)(c8), c7, c6, c5, c4, c3, c2, c1, c0)
82#define Y2(d1, c12, d2) \
84#define Y3(d1, c12, d2, c23, d3) \
85 Y2(Y2(d1, c12, d2), c23, d3)
86#define Y4(d1, c12, d2, c23, d3, c34, d4) \
87 Y3(d1, c12, d2, c23, Y2(d3, c34, d4))
88#define Y5(d1, c12, d2, c23, d3, c34, d4, c45, d5) \
89 Y4(Y2(d1, c12, d2), c23, d3, c34, d4, c45, d5)
90#define Y6(d1, c12, d2, c23, d3, c34, d4, c45, d5, c56, d6) \
91 Y5(d1, c12, d2, c23, d3, c34, d4, c45, Y2(d5, c56, d6))
92#define Y7(d1, c12, d2, c23, d3, c34, d4, c45, d5, c56, d6, c67, d7) \
93 Y6(d1, c12, d2, c23, Y2(d3, c34, d4), c45, d5, c56, d6, c67, d7)
120 template<
unsigned int order>
155 template<
typename Float,
int order>
164 template<
typename Float,
int branch,
int order>
167 static Float
Step(
const Float logsx)
171 template<
typename Float,
int branch>
173 static Float
Step(
const Float logsx) {
return logsx; }
177 template<
typename Float,
int branch>
190 const Float logsx = log(
eSign * x);
191 const Float logslogsx = log(
eSign * logsx);
207 template<
typename Float>
212 const Float ew = exp(w);
213 const Float wew = w * ew;
214 const Float wewx = wew - x;
215 const Float w1 = w + 1;
216 return w - wewx / (ew * w1 - (w + 2) * wewx/(2*w1));
220 template<
typename Float>
225 const Float z = log(x/w) - w;
226 const Float w1 = w + 1;
227 const Float q = 2 * w1 * (w1 + Float(2./3)*z);
228 const Float eps = z / w1 * (q - z) / (q - 2*z);
229 return w * (1 + eps);
233 template<
typename Float>
238 const Float y = x * exp(-w);
239 const Float f0 = w - y;
240 const Float f1 = 1 + y;
241 const Float f00 = f0*f0;
242 const Float f11 = f1*f1;
243 const Float f0y = f0*y;
244 return w - 4*f0*(6*f1*(f11 + f0y) + f00*y) / (f11*(24*f11 + 36*f0y) + f00*(6*y*y + 8*f1*y + f0y));
250 double IterationStep(
const Float x,
const Float w)
254 template<
int n,
class =
void>
263 static Float
Recurse(
const Float x,
const Float w) {
return IterationStep(x, w); }
269 static Float
Recurse(
const Float x,
const Float w) {
return w; }
277 template<
typename Float,
int branch,
int n>
283 template<
typename Float>
286 {
return x *
HORNER4(Float, x, 0.07066247420543414, 2.4326814530577687, 6.39672835731526, 4.663365025836821, 0.99999908757381) /
287 HORNER4(Float, x, 1.2906660139511692, 7.164571775410987, 10.559985088953114, 5.66336307375819, 1); }
291 template<
typename Float>
294 {
const Float y = log(Float(0.5)*x) - 2;
295 return 2 + y *
HORNER3(Float, y, 0.00006979269679670452, 0.017110368846615806, 0.19338607770900237, 0.6666648896499793) /
296 HORNER2(Float, y, 0.0188060684652668, 0.23451269827133317, 1); }
300 template<
typename Float>
303 {
return HORNER4(Float, x, -2793.4565508841197, -1987.3632221106518, 385.7992853617571, 277.2362778379572, -7.840776922133643) /
304 HORNER4(Float, x, 280.6156995997829, 941.9414019982657, 190.64429338894644, -63.93540494358966, 1); }
308 template<
typename Float>
311 {
const Float y = log(-x);
313 HORNER3(Float, y, 0.16415668298255184, -3.334873920301941, 2.4831415860003747, 4.173424474574879) /
314 HORNER3(Float, y, 0.031239411487374164, -1.2961659693400076, 4.517178492772906, 1)
319 template<
typename Float>
322 {
const Float y = log(-x);
324 HORNER4(Float, y, 0.000026987243254533254, -0.007692106448267341, 0.28793461719300206, -1.5267058884647018, -0.5370669268991288) /
325 HORNER4(Float, y, 3.6006502104930343e-6, -0.0015552463555591487, 0.08801194682489769, -0.8973922357575583, 1)
330 template<
typename Float>
334 HORNER4(Float, x, 988.0070769375508, 1619.8111957356814, 989.2017745708083, 266.9332506485452, 26.875022558546036) /
335 HORNER4(Float, x, -205.50469464210596, -270.0440832897079, -109.554245632316, -11.275355431307334, 1)
365 LambertW<-1>(
const double x)
388 template double LambertW<-1>(
const double x);
400 case -1:
return LambertW<-1>(x);
402 default:
return std::numeric_limits<double>::quiet_NaN();
#define HORNER3(F, x, c3, c2, c1, c0)
#define HORNER2(F, x, c2, c1, c0)
#define HORNER_COEFF(_Tag_, _i_, _c_)
#define HORNER_COEFF2(_Tag_, _i_, _c_y_)
#define HORNER4(F, x, c4, c3, c2, c1, c0)
#define Y5(d1, c12, d2, c23, d3, c34, d4, c45, d5)
#define Y7(d1, c12, d2, c23, d3, c34, d4, c45, d5, c56, d6, c67, d7)
static Float AsymptoticExpansion(const Float x)
static Float LogRecursion(const Float x)
static Float BranchPointExpansion(const Float x)
double LambertW(const double x)
Float FritschStep(const Float x, const Float w)
Float HalleyStep(const Float x, const Float w)
double LambertW< 0 >(const double x)
Float AsymptoticExpansionImpl(const Float a, const Float b)
Float SchroederStep(const Float x, const Float w)
static Float Eval(const Float x)
static Float Eval(const Float x, const Float y)
static Float Recurse(const Float term, const Float x)
static Float Recurse(const Float term, const Float x, const Float y)
static Float Recurse(const Float term, const Float x)
static Float EvalAlt(const Float x)
static Float RecurseAlt(const Float term, const Float x)
static Float Eval(const Float x, const Float y)
static Float Eval(const Float x)
static Float Recurse(const Float term, const Float x, const Float y)
static Float Recurse(const Float x, const Float w)
static Float Recurse(const Float x, const Float w)
static Float Recurse(const Float x, Float w)
static Float Step(const Float logsx)
static Float Step(const Float logsx)
static Float Approximation(const Float x)
static Float Approximation(const Float x)
static Float Approximation(const Float x)
static Float Approximation(const Float x)
static Float Approximation(const Float x)
static Float Approximation(const Float x)
static Float Approximation(const Float x)
static Float Coeff(const Float x)