Skip to content

Commit 786338b

Browse files
committed
newton(): make logic to keep previous "roots" more straight-forward
1 parent 5e621bd commit 786338b

File tree

1 file changed

+35
-7
lines changed

1 file changed

+35
-7
lines changed

src/quantilealgs.jl

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,44 @@ quantile_bisect(d::ContinuousUnivariateDistribution, p::Real) =
4747
# Distribution, with Application to the Inverse Gaussian Distribution
4848
# http://www.statsci.org/smyth/pubs/qinvgaussPreprint.pdf
4949

50+
mutable struct ValueAndPredecessor{T}
51+
storage::Tuple{T,T}
52+
53+
function ValueAndPredecessor{T}(storage::Tuple{T,T}) where {T}
54+
return new(storage)
55+
end
56+
57+
function ValueAndPredecessor{T}() where {T}
58+
storage = Tuple{T,T}((T(NaN),T(NaN)))
59+
return new(storage)
60+
end
61+
62+
function Base.push!(huh::ValueAndPredecessor{T}, e::T) where {T}
63+
huh.storage = Tuple{T,T}((huh.storage[2], e))
64+
end
65+
66+
function Base.getindex(ValueAndPredecessor::ValueAndPredecessor{T}, delay::Int)::T where {T}
67+
return ValueAndPredecessor.storage[length(ValueAndPredecessor.storage) + delay]
68+
end
69+
end
70+
71+
# if starting at mode, Newton is convergent for any unimodal continuous distribution, see:
72+
# Göknur Giner, Gordon K. Smyth (2014)
73+
# A Monotonically Convergent Newton Iteration for the Quantiles of any Unimodal
74+
# Distribution, with Application to the Inverse Gaussian Distribution
75+
# http://www.statsci.org/smyth/pubs/qinvgaussPreprint.pdf
76+
5077
function newton(f, xs::T=mode(d), tol::Real=1e-12) where {T}
5178
converged(a,b) = abs(a-b) <= max(abs(a),abs(b)) * tol
52-
x = xs + f(xs)
53-
@assert typeof(x) === T
54-
x0 = T(xs)
55-
while !converged(x, x0)
56-
x0 = x
57-
x = x0 + f(x0)
79+
x = ValueAndPredecessor{T}()
80+
push!(x, xs)
81+
push!(x, x[0] + f(x[0]))
82+
while !converged(x[0], x[-1])
83+
df = f(x[0])
84+
r = x[0] + df
85+
push!(x, r)
5886
end
59-
return x
87+
return x[0]
6088
end
6189

6290
function quantile_newton(d::ContinuousUnivariateDistribution, p::Real, xs::Real=mode(d), tol::Real=1e-12)

0 commit comments

Comments
 (0)