ex-2/fancier: use optimised Lambert W
This commit is contained in:
parent
391be195d0
commit
6ccaff5bbd
@ -40,6 +40,23 @@
|
|||||||
* the computation of Euler's constant, Jean-Pierre Demailly.
|
* the computation of Euler's constant, Jean-Pierre Demailly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Approximation of the Lambert W(x) function at large values
|
||||||
|
* where x = 5π/9 10^(2D + 1). The expression of x has been
|
||||||
|
* inlined and optimized to avoid overflowing on large D.
|
||||||
|
*
|
||||||
|
* Note: from x>10 this is an overestimate of W(x), which is
|
||||||
|
* good for the application below.
|
||||||
|
*
|
||||||
|
* source: "On the Lambert W function", Corless et al.
|
||||||
|
*/
|
||||||
|
double lambertW_large(size_t digits) {
|
||||||
|
double L1 = log(5*M_PI/9) + (2*digits + 1)*log(10);
|
||||||
|
double L2 = log(L1);
|
||||||
|
return L1 - L2 + L2/L1 + (L2 - 2)/(2*L1*L1)
|
||||||
|
+ L2*(3*L2*L2*L2 - 22*L2*L2 + 36*L2 - 12)/(12*L1*L1*L1*L1);
|
||||||
|
}
|
||||||
|
|
||||||
/* `mpq_dec_str(z, n)`
|
/* `mpq_dec_str(z, n)`
|
||||||
* returns the decimal representation of the
|
* returns the decimal representation of the
|
||||||
* rational z as a string, up to n digits.
|
* rational z as a string, up to n digits.
|
||||||
@ -525,7 +542,7 @@ int main(int argc, char** argv) {
|
|||||||
// requested decimal digits
|
// requested decimal digits
|
||||||
size_t D = atol(argv[1]);
|
size_t D = atol(argv[1]);
|
||||||
// Brent-McMillan number N
|
// Brent-McMillan number N
|
||||||
size_t N = gsl_sf_lambert_W0(5*M_PI/9*pow(10, 2*D + 1))/16 + 1;
|
size_t N = lambertW_large(D)/16 + 1;
|
||||||
|
|
||||||
mpq_t exact, indicator;
|
mpq_t exact, indicator;
|
||||||
mpq_inits(exact, indicator, NULL);
|
mpq_inits(exact, indicator, NULL);
|
||||||
|
Loading…
Reference in New Issue
Block a user