Skip to content

Commit c998ed5

Browse files
committed
three phase bisection
1 parent 80353af commit c998ed5

File tree

1 file changed

+61
-23
lines changed

1 file changed

+61
-23
lines changed

src/bisection.jl

Lines changed: 61 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
struct Bisection <: AbstractBracketingAlgorithm
22
end
33

4+
mutable struct BisectionCache{uType}
5+
state::UInt8
6+
left::uType
7+
right::uType
8+
end
9+
410
function alg_cache(alg::Bisection, left, right, p, ::Val{true})
5-
nothing
11+
BisectionCache(UInt8(0), left, right)
612
end
713

814
function alg_cache(alg::Bisection, left, right, p, ::Val{false})
9-
nothing
15+
BisectionCache(UInt8(0), left, right)
1016
end
1117

1218
"""
@@ -84,30 +90,62 @@ end
8490
function perform_step!(solver, alg::Bisection, cache)
8591
@unpack f, p, left, right, fl, fr = solver
8692

87-
fzero = zero(fl)
88-
fl * fr > fzero && error("Bracket became non-containing in between iterations. This could mean that "
89-
+ "input function crosses the x axis multiple times. Bisection is not the right method to solve this.")
93+
if cache.state == 0
94+
fzero = zero(fl)
95+
fl * fr > fzero && error("Bracket became non-containing in between iterations. This could mean that "
96+
+ "input function crosses the x axis multiple times. Bisection is not the right method to solve this.")
9097

91-
mid = (left + right) / 2.0
92-
93-
if right == mid || right == mid
94-
solver.force_stop = true
95-
solver.retcode = :FloatingPointLimit
96-
return
97-
end
98-
99-
fm = f(mid, p)
100-
101-
if iszero(fm)
102-
# todo: phase 2 bisection similar to the raw method
103-
solver.force_stop = true
104-
solver.left = mid
105-
solver.fl = fm
106-
solver.retcode = :ExactSolutionAtLeft
107-
else
108-
if sign(fm) == sign(fl)
98+
mid = (left + right) / 2.0
99+
100+
if left == mid || right == mid
101+
solver.force_stop = true
102+
solver.retcode = :FloatingPointLimit
103+
return
104+
end
105+
106+
fm = f(mid, p)
107+
108+
if iszero(fm)
109+
cache.state = 1
110+
cache.right = mid
111+
cache.left = mid
112+
else
113+
if sign(fm) == sign(fl)
114+
solver.left = mid
115+
solver.fl = fm
116+
else
117+
solver.right = mid
118+
solver.fr = fm
119+
end
120+
end
121+
elseif cache.state == 1
122+
mid = (left + cache.right) / 2.0
123+
124+
if cache.right == mid || left == mid
125+
cache.state = 2
126+
return
127+
end
128+
129+
fm = f(mid, p)
130+
131+
if iszero(fm)
132+
cache.right = mid
133+
else
109134
solver.left = mid
110135
solver.fl = fm
136+
end
137+
else
138+
mid = (cache.left + right) / 2.0
139+
140+
if right == mid || cache.left == mid
141+
solver.force_stop = true
142+
return
143+
end
144+
145+
fm = f(mid, p)
146+
147+
if iszero(fm)
148+
cache.left = mid
111149
else
112150
solver.right = mid
113151
solver.fr = fm

0 commit comments

Comments
 (0)