@@ -47,16 +47,44 @@ quantile_bisect(d::ContinuousUnivariateDistribution, p::Real) =
47
47
# Distribution, with Application to the Inverse Gaussian Distribution
48
48
# http://www.statsci.org/smyth/pubs/qinvgaussPreprint.pdf
49
49
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
+
50
77
function newton (f, xs:: T = mode (d), tol:: Real = 1e-12 ) where {T}
51
78
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)
58
86
end
59
- return x
87
+ return x[ 0 ]
60
88
end
61
89
62
90
function quantile_newton (d:: ContinuousUnivariateDistribution , p:: Real , xs:: Real = mode (d), tol:: Real = 1e-12 )
0 commit comments