Skip to content

Commit c90b502

Browse files
alystAlexey Stukalov
authored andcommitted
rename omega => LambertW.Omega and update its def
using the code from JuliaMath/IrrationalConstants.jl/issues/12 No __init__() section is required
1 parent 4f8b18b commit c90b502

File tree

4 files changed

+52
-55
lines changed

4 files changed

+52
-55
lines changed

docs/src/functions_list.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,5 @@ SpecialFunctions.logabsbeta
7171
SpecialFunctions.logabsbinomial
7272
SpecialFunctions.lambertw
7373
SpecialFunctions.lambertwbp
74-
SpecialFunctions.omega
74+
SpecialFunctions.LambertW.Ω
7575
```

src/SpecialFunctions.jl

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,8 @@ export
7979
cosint,
8080
lbinomial,
8181
lambertw,
82-
lambertwbp
83-
84-
const omega_const_bf_ = Ref{BigFloat}()
85-
function __init__()
86-
# allocate storage for this BigFloat constant each time this module is loaded
87-
omega_const_bf_[] =
88-
parse(BigFloat,"0.5671432904097838729999686622103555497538157871865125081351310792230457930866845666932194")
89-
end
82+
lambertwbp,
83+
LambertW
9084

9185
include("bessel.jl")
9286
include("erf.jl")

src/lambertw.jl

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ _lambertw(x::Irrational, k::Integer, maxits::Integer) = _lambertw(float(x), k, m
3737
function _lambertw(x::Union{Integer, Rational}, k::Integer, maxits::Integer)
3838
if k == 0
3939
x == 0 && return float(zero(x))
40-
x == 1 && return convert(typeof(float(x)), omega) # must be a more efficient way
40+
x == 1 && return convert(typeof(float(x)), LambertW.Omega) # must be a more efficient way
4141
end
4242
return _lambertw(float(x), k, maxits)
4343
end
@@ -141,54 +141,44 @@ function lambertw_root_finding(z::T, x0::T, maxits::Integer) where T <: Number
141141
return x
142142
end
143143

144-
### omega constant
144+
### Lambert's Omega constant
145145

146-
const _omega_const = 0.567143290409783872999968662210355
147-
148-
# The BigFloat `omega_const_bf_` is set via a literal in the function __init__ to prevent a segfault
149-
150-
# compute omega constant via root finding
151-
# We could compute higher precision. This converges very quickly.
152-
function omega_const(::Type{BigFloat})
153-
precision(BigFloat) <= 256 && return omega_const_bf_[]
146+
# compute BigFloat Omega constant at arbitrary precision
147+
function compute_lambertw_Omega()
148+
oc = BigFloat("0.5671432904097838729999686622103555497538157871865125081351310792230457930866845666932194")
149+
precision(oc) <= 256 && return oc
150+
# iteratively improve the precision
151+
# see https://en.wikipedia.org/wiki/Omega_constant#Computation
154152
myeps = eps(BigFloat)
155-
oc = omega_const_bf_[]
156-
for i in 1:100
153+
for _ in 1:1000
157154
nextoc = (1 + oc) / (1 + exp(oc))
158-
abs(oc - nextoc) <= myeps && break
155+
abs(oc - nextoc) <= myeps && return oc
159156
oc = nextoc
160157
end
158+
@warn "Omega precision is less than current BigFloat precision ($(precision(BigFloat)))"
161159
return oc
162160
end
163161

164-
"""
165-
omega
166-
ω
162+
# "private" declaration of Omega constant
163+
Base.@irrational lambertw_Omega 0.567143290409783872999968662210355 compute_lambertw_Omega()
167164

168-
The constant defined by `ω exp(ω) = 1`.
165+
module LambertW
169166

170-
# Example
171-
```jldoctest
172-
julia> ω
173-
ω = 0.5671432904097...
174-
175-
julia> omega
176-
ω = 0.5671432904097...
167+
"""
168+
Lambert's Omega (*Ω*) constant.
177169
178-
julia> ω * exp(ω)
179-
1.0
170+
Lambert's *Ω* is the solution to *W(Ω) = 1* equation,
171+
where *W(t) = t exp(t)* is the
172+
[Lambert's *W* function](https://en.wikipedia.org/wiki/Lambert_W_function).
180173
181-
julia> big(omega)
182-
5.67143290409783872999968662210355549753815787186512508135131079223045793086683e-01
183-
```
174+
# See also
175+
* https://en.wikipedia.org/wiki/Omega_constant
176+
* [`lambertw()`][@ref SpecialFunctions.lambertw]
184177
"""
185-
const ω = Irrational{:ω}()
186-
@doc (@doc ω) omega = ω
178+
const Ω = Irrational{:lambertw_Omega}()
179+
const Omega = Ω # ASCII alias
187180

188-
Base.Float64(::Irrational{:ω}) = _omega_const
189-
Base.Float32(::Irrational{:ω}) = Float32(_omega_const)
190-
Base.Float16(::Irrational{:ω}) = Float16(_omega_const)
191-
Base.BigFloat(::Irrational{:ω}) = omega_const(BigFloat)
181+
end
192182

193183
### Expansion about branch point x = -1/e
194184

test/lambertw.jl

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ using IrrationalConstants
1919

2020
# could return math const e, but this would break type stability
2121
@test @inferred(lambertw(1)) isa AbstractFloat
22+
@test @inferred(lambertw(1)) == float(LambertW.Omega)
23+
@test @inferred(lambertw(big(1))) == big(LambertW.Omega)
2224
@test @inferred(lambertw(MathConstants.e, 0)) == 1
2325

2426
## value at branch point where real branches meet
@@ -87,19 +89,30 @@ end
8789
@test z W*exp(W) atol=BigFloat(10)^(-70)
8890
end
8991

90-
### ω constant
92+
@testset "LambertW.Omega" begin
93+
@test isapprox(LambertW.Ω * exp(LambertW.Ω), 1)
94+
@test LambertW.Omega === LambertW.Ω
9195

92-
## get ω from recursion and compare to value from lambertw
93-
let sp = precision(BigFloat)
94-
setprecision(512)
95-
@test lambertw(big(1)) == big(SpecialFunctions.omega)
96-
setprecision(sp)
97-
end
96+
# lower than default precision
97+
setprecision(BigFloat, 196) do
98+
o = big(LambertW.Ω)
99+
@test precision(o) == 196
100+
@test isapprox(o * exp(o), 1, atol=eps(BigFloat))
101+
102+
oalias = big(LambertW.Omega)
103+
@test o == oalias
104+
end
98105

99-
@test lambertw(1) == float(SpecialFunctions.omega)
100-
@test convert(Float16, SpecialFunctions.omega) == convert(Float16, 0.5674)
101-
@test convert(Float32, SpecialFunctions.omega) == 0.56714326f0
102-
@test lambertw(BigInt(1)) == big(SpecialFunctions.omega)
106+
# higher than default precision
107+
setprecision(BigFloat, 2048) do
108+
o = big(LambertW.Ω)
109+
@test precision(o) == 2048
110+
@test isapprox(o * exp(o), 1, atol=eps(BigFloat))
111+
112+
oalias = big(LambertW.Omega)
113+
@test o == oalias
114+
end
115+
end
103116

104117
### expansion about branch point
105118
@testset "lambertwbp()" begin

0 commit comments

Comments
 (0)