lambertw, all branches, Cas code
|
02-04-2024, 07:34 PM
(This post was last modified: 02-04-2024 10:55 PM by Albert Chan.)
Post: #1
|
|||
|
|||
lambertw, all branches, Cas code
Python W, version 4, translated for HP Prime Cas, with some differences.
Code: #cas Cas> lambertw(-0.3678) → −0.979360714958 Cas> lambertw(-0.3678,-1) → −1.02092723941 Cas> lambertw(3+4i, 5) → −1.81700589185+30.713334137*i Cas> lambertw(3+4i, -5) → −1.75476362795−28.8571010474*i |
|||
02-05-2024, 12:46 AM
(This post was last modified: 02-05-2024 09:30 PM by Albert Chan.)
Post: #2
|
|||
|
|||
RE: lambertw, all branches, Cas code
(02-04-2024 07:34 PM)Albert Chan Wrote: z := ln(y) - (y-1-x)/y; // = lnp1(x); Technically lnp1(x) == ln(1+x) + correction lnp1(x) might even be implemented this way, see latest Free42 function C.LN1+X However, HP Prime have trouble getting accurate result, if x is tiny. lnp1(x) = 2*atanh(y) = 2*(y + y^3/3 + y^5/5 + ...), where y=x/(x+2) Cas> x := -4e-16+5e-8i Cas> 2*(y := x/(x+2)) 8.5e−16+0.00000005*i Cas> 2*atanh(y) 13.3226762955e−16+0.00000005*i Cas> lnp1(x) 12.5e−16+0.00000005*i Cas> y:=x+1 Cas> ln(y) - (y-1-x)/y 9.3226762955e−16+0.00000005*i atanh/lnp1/ln are all bad, but ln(1+x) + correction version seems better (at least for this case) Hopefully, these numerical bugs would get fixed. For comparison, this is HP71B (can't test LOGP1, because it does not support complex type) >complex x,y >x = (-4e-16,5e-8) >y = x/(2+x) >2*y (8.5E-16,.00000005) >2*ATANH(y) (8.5E-16,.00000005) >y = 1+x >LN(y) - (y-1-x)/y (8.5E-16,.00000005) >LN(y)*x/(y-1) ! Kahan's log1p way, return x if y=1 (8.5E-16,.00000005) |
|||
02-06-2024, 01:44 PM
(This post was last modified: 02-06-2024 10:36 PM by Albert Chan.)
Post: #3
|
|||
|
|||
RE: lambertw, all branches, Cas code
I experimented ln / lnp1 for real agrument.
First, some reference numbers, using lua lua> p48 = fn'x: local hi,lo = bit.split(x); bit.join(hi, lo-lo%32)' -- Lua to Prime float lua> m48 = fn'x: trunc(frexp(x) * 2^48)' -- HP Prime mantissa bits lua> x = p48(.1) lua> y = p48(1+x) lua> m48(x) 225179981368524 lua> m48(log1p(x)) 214619445125685 lua> m48(log(y)) 214619445125674 lua> m48(p48(log(y)) - p48((y-1-x)/y)) -- simulate HP Prime float operation. 214619445125684 Cas> m48(x) := trunc(x * 2^(48-frexp(x)[2])) Cas> x := .1 Cas> y := 1+x Cas> m48(x) 225179981368524 Cas> m48(lnp1(x)) 214619445125630 Cas> m48(ln(y)) 214619445125674 Cas> m48(ln(y)-(y-1-x)/y) 214619445125684 Strange, lnp1(x) is worse than ln(1+x), even without correction. Update: I tried this on XCas 1.9.0-31 (mingw win32) I was expecting same result, since both use 48-bits truncated float. XCas> log1p(.1) - ln(1+.1) → 4.88498130835e-15 XCas> ans() * 2^51 → 11. XCas log1p(.1) gives exactly lua reference, 74 + 11 = 85. lnp1(.1) bug is only for HP Prime, error = 85 - 30 = 55 ULP I discovered 2 more HP Prime bugs, during experimentation. 1.) round(x) likely defined as floor(x+0.5), even if x is an integer. I was expecting symmetry, round(x) = sign(x)*round(|x|), like C++ round Not matching others is not a bug, but round an integer to something else is. Cas> m := float(m48(x)) Cas> round( m) → 225179981368524 Cas> -round(-m) → 225179981368523 2.) frexp(x) may lose its mantissa. This is why m48 not defined as trunc(frexp(x)[1] * 2^48) Cas> frexp(1e-12) → [0., -39] |
|||
« Next Oldest | Next Newest »
|
User(s) browsing this thread: 2 Guest(s)