49
49
function ITP (; scaled_k1:: Real = 0.2 , k2:: Real = 2 , n0:: Int = 10 )
50
50
scaled_k1 < 0 && error (" Hyper-parameter κ₁ should not be negative" )
51
51
n0 < 0 && error (" Hyper-parameter n₀ should not be negative" )
52
- if k2 < 1 || k2 > ( 1.5 + sqrt (5 ) / 2 )
52
+ if ! ( 1 <= k2 <= 1.5 + sqrt (5 ) / 2 )
53
53
throw (ArgumentError (" Hyper-parameter κ₂ should be between 1 and 1 + ϕ where \
54
54
ϕ ≈ 1.618... is the golden ratio" ))
55
55
end
56
56
return ITP (scaled_k1, k2, n0)
57
57
end
58
58
59
- function CommonSolve. solve (
59
+ @muladd function CommonSolve. solve (
60
60
prob:: IntervalNonlinearProblem , alg:: ITP , args... ;
61
61
maxiters = 1000 , abstol = nothing , verbose:: Bool = true , kwargs...
62
62
)
63
63
@assert ! SciMLBase. isinplace (prob) " `ITP` only supports out-of-place problems."
64
64
65
65
f = Base. Fix2 (prob. f, prob. p)
66
- left, right = prob. tspan
66
+ left, right = minmax ( prob. tspan)
67
67
fl, fr = f (left), f (right)
68
68
69
69
abstol = NonlinearSolveBase. get_tolerance (
@@ -93,42 +93,38 @@ function CommonSolve.solve(
93
93
94
94
ϵ = abstol
95
95
k2 = alg. k2
96
- k1 = alg. scaled_k1 * abs (right - left)^ (1 - k2)
96
+ span = right - left
97
+ k1 = alg. scaled_k1 * span^ (1 - k2) # k1 > 0
97
98
n0 = alg. n0
98
- n_h = ceil (log2 (abs (right - left) / (2 * ϵ)))
99
- mid = (left + right) / 2
100
- x_f = left + (right - left) * (fl / (fl - fr))
101
- xt = left
102
- xp = left
103
- r = zero (left) # minmax radius
104
- δ = zero (left) # truncation error
105
- σ = 1.0
106
- ϵ_s = ϵ * 2 ^ (n_h + n0)
99
+ n_h = exponent (span / (2 * ϵ)) + 1
100
+ ϵ_s = ϵ * exp2 (n_h + n0)
107
101
108
102
i = 1
109
103
while i ≤ maxiters
110
- span = abs (right - left)
104
+ span = right - left
105
+ mid = (left + right) / 2
111
106
r = ϵ_s - (span / 2 )
112
107
δ = k1 * span^ k2
113
108
114
- x_f = left + (right - left) * (fl / (fl - fr)) # Interpolation Step
109
+ x_f = left + span * (fl / (fl - fr)) # Interpolation Step
115
110
116
- diff = mid - x_f
117
- σ = sign (diff)
118
- xt = ifelse (δ ≤ diff, x_f + σ * δ, mid) # Truncation Step
111
+ diff = abs (mid - x_f)
112
+ xt = ifelse (δ ≤ diff, x_f + copysign (δ, diff), mid) # Truncation Step
119
113
120
- xp = ifelse (abs (xt - mid) ≤ r, xt, mid - σ * r ) # Projection Step
114
+ xp = ifelse (abs (xt - mid) ≤ r, xt, mid - copysign (r, diff) ) # Projection Step
121
115
122
- if abs ((left - right) / 2 ) < ϵ
116
+ if span < 2 ϵ
123
117
return SciMLBase. build_solution (
124
118
prob, alg, xt, f (xt); retcode = ReturnCode. Success, left, right
125
119
)
126
120
end
127
121
128
122
# update
129
- tmin, tmax = minmax (xt, xp)
130
- xp ≥ tmax && (xp = prevfloat (tmax))
131
- xp ≤ tmin && (xp = nextfloat (tmin))
123
+ if isless (xt, xp)
124
+ xp = prevloat (xp)
125
+ else
126
+ xp = nextfloat (xp)
127
+ end
132
128
yp = f (xp)
133
129
yps = yp * sign (fr)
134
130
T0 = zero (yps)
@@ -143,10 +139,9 @@ function CommonSolve.solve(
143
139
end
144
140
145
141
i += 1
146
- mid = (left + right) / 2
147
142
ϵ_s /= 2
148
143
149
- if Impl . nextfloat_tdir (left, prob . tspan ... ) == right
144
+ if nextfloat (left) == right
150
145
return SciMLBase. build_solution (
151
146
prob, alg, right, fr; retcode = ReturnCode. FloatingPointLimit, left, right
152
147
)
0 commit comments