Open James103 opened 5 months ago
I've added some debug lines to the d_lambertw
function to try to trace down the cause of this issue.
The cause appears to be that ew
(derived from w.neg().exp()
where w
is Decimal.ln(z)
assuming the principal branch) is not completely cancelled out by z
when it normally is at these large numbers, causing z.mul(ew)
to be some large number (≈ ee17) instead of 1, which then causes later calculations during that same iteration to break and the final result to be many thousands of orders of magnitude higher than what it should be.
Although z.mul(Decimal.ln(z).neg().exp())
$= z e^{-\ln(z)}$ simplifies to 1 for all z
, it can in practice be very far away from 1 (like ee17 units off) due to incomplete cancellation of the number z
and its reciprocal calculated with Decimal.ln(z).neg().exp()
.
d_lambertw
output when running code in OP using the principal branch EDIT: Found it! Change this line in the https://github.com/Patashu/break_eternity.js/blob/96901974c175cb28f66c7164a5a205cdda783872/src/index.ts#L346
d_lambertw
function:By replacing
EDIT 2: The above fix does not appear to converge for smaller numbers (layer 1). A better solution may be needed.z.mul(ew)
in the .sub()
call of wewz = w.sub(z.mul(ew))
with 1
, which is what it simplifies to after undoing the substitutions. Note: Only tested with certain numbers in the principal branch; needs testing for the real non-principal branch and over a wider range of numbers.
When running the following:
the output is
The second value is many orders of magnitude higher that of the first and third values, effectively a large spike. The correct answer for the second expression is approximately midway between the first value and the third value.
Some more test cases, all of which return incorrect values
``` W(ee31.965173139544905) == 3.590892194141079e6229 W(ee31.752610949621566) == 3.296534240252085e3818 W(ee31.913848146747807) == 1.5268311171822413e5535 W(ee31.640295850532457) == 2.2637793318601247e2948 W(ee31.764948764454818) == 3.5762246079696114e3928 W(ee31.652926931263902) == 2.3139757541974464e3035 W(ee31.929958343490664) == 2.332630066079301e5744 W(ee31.98205373630235) == 2.878867493568092e6476 W(ee31.98283664180519) == 1.3960688507821357e6488 W(ee31.787391560044053) == 8.01963757821285e4136 W(ee31.823874021678865) == 2.7187091896742213e4499 W(ee31.825232704314676) == 3.4104034609250986e4513 W(ee31.863878434083848) == 3.8176698551518697e4933 W(ee31.918276882779058) == 8.276372977284206e5591 W(ee31.669172925011136) == 1.151060360788823e3151 W(ee31.909157710719125) == 5.305882880703211e5475 W(ee31.954588884894793) == 3.7058668964725516e6079 W(ee31.690265691504234) == 7.565092881039769e3307 W(ee31.696486703711212) == 4.0107213474029315e3355 W(ee31.907517771777723) == 1.2214311038222574e5455 ```Code to generate the above test cases
```javascript let count = 0; while (count < 100) { const n = Math.random() * 3 + 30 const Wn = Decimal.lambertw("ee" + n) if (Wn.gt(1e40)) { console.log("W(ee"+n+") == "+Wn.toString()) count++ } else count+=(1/1024) } ```