Repository: JuliaMath/Roots.jl (julia)

Issue:
Problems with atol and infinite brackets
```julia
using Roots
find_zero(x->x^2-4,(0,Inf)) # 2.0 correct
find_zero(x->x^2-4,(0,Inf),atol=1) # 1.5?
find_zero(x->x^2-4,(0,Inf),atol=1e-3) # 1.5???
find_zero(x->x^2-4,(0,8),atol=1) # correct
find_zero(x->x^2-4,(0,8),atol=1e-3) # correct
```
Solutions are not within `atol` when that argument is passed for infinite brackets.

Pull request description:
Add an `assess_convergence` method for bisection that does not check `isinf_f`.

Update docs on Alefeld Potra methods about not honoring tolerances on size of f.

Close #457, Close #458

Patch:
diff --git a/Project.toml b/Project.toml
index a362a0e4..44f22f87 100644
--- a/Project.toml
+++ b/Project.toml
@@ -1,6 +1,6 @@
 name = "Roots"
 uuid = "f2b01f46-fcfa-551c-844a-d8ac1e96c665"
-version = "2.2.3"
+version = "2.2.4"
 
 [deps]
 Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"
diff --git a/src/Bracketing/alefeld_potra_shi.jl b/src/Bracketing/alefeld_potra_shi.jl
index 302ad146..e528870b 100644
--- a/src/Bracketing/alefeld_potra_shi.jl
+++ b/src/Bracketing/alefeld_potra_shi.jl
@@ -16,6 +16,9 @@ An abstract type for Alefeld-Potra-Shi type bracketing problems, as discussed in
 The `update_step` method calls a `calculateΔ` method that can be customized to turn an algorithm based on interpolation into a bracketed algorithm. See [`Roots.BracketedHalley`](@ref) for an example.
 
 This implementation deviates slightly from the printed algorithm, as it may use an initial call to `_middle` rather than a secant step, depending on the signs of ``a`` and ``b``.
+
+!!! note
+    These algorithms do not check the size of `f` for convergence, so the `atol` or `rtol` are not utilized.
 """
 =#
 abstract type AbstractAlefeldPotraShi <: AbstractBracketingMethod end
diff --git a/src/convergence.jl b/src/convergence.jl
index 28a3f946..82217b12 100644
--- a/src/convergence.jl
+++ b/src/convergence.jl
@@ -278,6 +278,17 @@ function assess_convergence(M::Any, state::AbstractUnivariateZeroState, options)
     return (:not_converged, false)
 end
 
+function assess_convergence(M::AbstractBisection, state::AbstractUnivariateZeroState, options::O) where {O <: Union{ExactOptions, XExactOptions}}
+    # return convergence_flag, boolean
+    # no check if f == ∞
+    is_exact_zero_f(M, state, options) && return (:exact_zero, true)
+    isnan_f(M, state) && return (:nan, true)
+    is_approx_zero_f(M, state, options) && return (:f_converged, true)
+    iszero_Δx(M, state, options) && return (:x_converged, true)
+    return (:not_converged, false)
+end
+
+
 # speeds up exact f values by just a bit (2% or so) over the above, so guess this is worth it.
 function assess_convergence(
     M::AbstractBracketingMethod,


Test patch:
diff --git a/test/test_find_zero.jl b/test/test_find_zero.jl
index 28c4d1e5..9e550bee 100644
--- a/test/test_find_zero.jl
+++ b/test/test_find_zero.jl
@@ -583,3 +583,13 @@ end
         @test ForwardDiff.gradient(H, [1.0, 2])[1] ≈ -0.4416107917053284
     end
 end
+
+@testset "bracketing_atol" begin
+    ## issue $457
+    f(x) = x^2 - 4
+    @test find_zero(f, (0,Inf)) ≈ 2 # 2.0 correct
+    @test find_zero(f, (0,Inf), atol=1) ≈ 1.9997558593749998
+    @test find_zero(f, (0,Inf),atol=1e-5) ≈ 1.9999998807907102
+    @test find_zero(f, (0,8), atol=1) ≈ 1.99609375
+    @test find_zero(f, (0,8), atol=1e-3) ≈ 2.0000152587890625
+end