|
1 | 1 | struct Bisection <: AbstractBracketingAlgorithm
|
2 | 2 | end
|
3 | 3 |
|
| 4 | +mutable struct BisectionCache{uType} |
| 5 | + state::UInt8 |
| 6 | + left::uType |
| 7 | + right::uType |
| 8 | +end |
| 9 | + |
4 | 10 | function alg_cache(alg::Bisection, left, right, p, ::Val{true})
|
5 |
| - nothing |
| 11 | + BisectionCache(UInt8(0), left, right) |
6 | 12 | end
|
7 | 13 |
|
8 | 14 | function alg_cache(alg::Bisection, left, right, p, ::Val{false})
|
9 |
| - nothing |
| 15 | + BisectionCache(UInt8(0), left, right) |
10 | 16 | end
|
11 | 17 |
|
12 | 18 | """
|
|
84 | 90 | function perform_step!(solver, alg::Bisection, cache)
|
85 | 91 | @unpack f, p, left, right, fl, fr = solver
|
86 | 92 |
|
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.") |
90 | 97 |
|
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 |
109 | 134 | solver.left = mid
|
110 | 135 | 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 |
111 | 149 | else
|
112 | 150 | solver.right = mid
|
113 | 151 | solver.fr = fm
|
|
0 commit comments