Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 28 additions & 21 deletions src/minmax.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,34 @@
return z1, z2
end

### minimum and maximum
# The default implemented in Julia have several issues for the Arb type.
# See https://github.com/JuliaLang/julia/issues/45932.
# Note that it works fine for Mag and Arf.

# Is is possible to fix the Base implementation by overloading some
# internal methods.
if VERSION < v"1.13.0-DEV.536"
### minimum and maximum
# The default implemented in Julia have several issues for the Arb type.
# See https://github.com/JuliaLang/julia/issues/45932.
# Note that it works fine for Mag and Arf.

# The default implementation in Base is not correct for Arb
Base._fast(::typeof(min), x::ArbOrRef, y::ArbOrRef) = min(x, y)
Base._fast(::typeof(min), x::ArbOrRef, y) = min(x, y)
Base._fast(::typeof(min), x, y::ArbOrRef) = min(x, y)
Base._fast(::typeof(max), x::ArbOrRef, y::ArbOrRef) = max(x, y)
Base._fast(::typeof(max), x::ArbOrRef, y) = max(x, y)
Base._fast(::typeof(max), x, y::ArbOrRef) = max(x, y)
# Handle ambiguous methods
Base._fast(::typeof(min), x::ArbOrRef, y::AbstractFloat) = min(x, y)
Base._fast(::typeof(min), x::AbstractFloat, y::ArbOrRef) = min(x, y)
Base._fast(::typeof(max), x::ArbOrRef, y::AbstractFloat) = max(x, y)
Base._fast(::typeof(max), x::AbstractFloat, y::ArbOrRef) = max(x, y)
# Is is possible to fix the Base implementation by overloading some
# internal methods.

# Arf and Arb don't have signed zeros
Base.isbadzero(::typeof(min), x::Union{ArfOrRef,ArbOrRef}) = false
Base.isbadzero(::typeof(max), x::Union{ArfOrRef,ArbOrRef}) = false
# The default implementation in Base is not correct for Arb
Base._fast(::typeof(min), x::ArbOrRef, y::ArbOrRef) = min(x, y)
Base._fast(::typeof(min), x::ArbOrRef, y) = min(x, y)
Base._fast(::typeof(min), x, y::ArbOrRef) = min(x, y)

Check warning on line 33 in src/minmax.jl

View check run for this annotation

Codecov / codecov/patch

src/minmax.jl#L32-L33

Added lines #L32 - L33 were not covered by tests
Base._fast(::typeof(max), x::ArbOrRef, y::ArbOrRef) = max(x, y)
Base._fast(::typeof(max), x::ArbOrRef, y) = max(x, y)
Base._fast(::typeof(max), x, y::ArbOrRef) = max(x, y)

Check warning on line 36 in src/minmax.jl

View check run for this annotation

Codecov / codecov/patch

src/minmax.jl#L35-L36

Added lines #L35 - L36 were not covered by tests
# Handle ambiguous methods
Base._fast(::typeof(min), x::ArbOrRef, y::AbstractFloat) = min(x, y)
Base._fast(::typeof(min), x::AbstractFloat, y::ArbOrRef) = min(x, y)

Check warning on line 39 in src/minmax.jl

View check run for this annotation

Codecov / codecov/patch

src/minmax.jl#L39

Added line #L39 was not covered by tests
Base._fast(::typeof(max), x::ArbOrRef, y::AbstractFloat) = max(x, y)
Base._fast(::typeof(max), x::AbstractFloat, y::ArbOrRef) = max(x, y)

Check warning on line 41 in src/minmax.jl

View check run for this annotation

Codecov / codecov/patch

src/minmax.jl#L41

Added line #L41 was not covered by tests

# Arf and Arb don't have signed zeros
Base.isbadzero(::typeof(min), x::Union{ArfOrRef,ArbOrRef}) = false
Base.isbadzero(::typeof(max), x::Union{ArfOrRef,ArbOrRef}) = false
else
# The special handling for minimum and maximum was removed in
# https://github.com/JuliaLang/julia/pull/58267 and it is hence no
# longer necessary to work around it.
end
65 changes: 36 additions & 29 deletions test/minmax.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@
end

@testset "minimum/maximum/extrema" begin
# See https://github.com/JuliaLang/julia/issues/45932 for
# discussions about the issues with the Base implementation
# Before 1.13 the implementation of minimum and maximum lead
# to several issues, see
# https://github.com/JuliaLang/julia/issues/45932 for
# discussions about the issues with the Base implementation.
# Since https://github.com/JuliaLang/julia/pull/58267 the
# special implementation of minimum and maximum is removed and
# the fallback implementation plays well with Arb.

# Currently there is no special implementation of extrema, the
# default implementation works well. But to help find future
Expand Down Expand Up @@ -54,7 +59,7 @@
@test iszero(extrema(identity, A)[1])
@test iszero(extrema(identity, -A)[2])

# Fails with default implementation due to Base._fast
# Before 1.13 these fails with default implementation due to Base._fast
A = [Arb(0); [setball(Arb, 0, i) for i in reverse(0:257)]]
@test Arblib.contains(minimum(A), -257)
@test Arblib.contains(maximum(A), 257)
Expand Down Expand Up @@ -84,8 +89,8 @@
@test maximum(AbstractFloat[Arb(0); fill(1.0, 257)]) == 1
@test extrema(AbstractFloat[Arb(0); fill(1.0, 257)]) == (0, 1)

# Fails with default implementation due to both short circuit
# and Base._fast
# Before 1.13 these fails with the default implementation due
# to both short circuit and Base._fast
A = [setball(Arb, 0, i) for i = 0:1000]
@test Arblib.contains(minimum(A), -1000)
@test Arblib.contains(maximum(A), 1000)
Expand All @@ -97,32 +102,34 @@
@test Arblib.contains(extrema(identity, A)[1], -1000)
@test Arblib.contains(extrema(identity, A)[2], 1000)

@test !Base.isbadzero(min, zero(Mag))
@test !Base.isbadzero(min, zero(Arf))
@test !Base.isbadzero(min, zero(Arb))
@test !Base.isbadzero(min, Arblib.radref(zero(Arb)))
@test !Base.isbadzero(min, Arblib.midref(zero(Arb)))
@test !Base.isbadzero(min, Arblib.realref(zero(Acb)))
if VERSION < v"1.13.0-DEV.536"
@test !Base.isbadzero(min, zero(Mag))
@test !Base.isbadzero(min, zero(Arf))
@test !Base.isbadzero(min, zero(Arb))
@test !Base.isbadzero(min, Arblib.radref(zero(Arb)))
@test !Base.isbadzero(min, Arblib.midref(zero(Arb)))
@test !Base.isbadzero(min, Arblib.realref(zero(Acb)))

@test !Base.isbadzero(max, zero(Mag))
@test !Base.isbadzero(max, zero(Arf))
@test !Base.isbadzero(max, zero(Arb))
@test !Base.isbadzero(max, Arblib.radref(zero(Arb)))
@test !Base.isbadzero(max, Arblib.midref(zero(Arb)))
@test !Base.isbadzero(max, Arblib.realref(zero(Acb)))
@test !Base.isbadzero(max, zero(Mag))
@test !Base.isbadzero(max, zero(Arf))
@test !Base.isbadzero(max, zero(Arb))
@test !Base.isbadzero(max, Arblib.radref(zero(Arb)))
@test !Base.isbadzero(max, Arblib.midref(zero(Arb)))
@test !Base.isbadzero(max, Arblib.realref(zero(Acb)))

@test !Base.isgoodzero(min, zero(Mag))
@test !Base.isgoodzero(min, zero(Arf))
@test !Base.isgoodzero(min, zero(Arb))
@test !Base.isgoodzero(min, Arblib.radref(zero(Arb)))
@test !Base.isgoodzero(min, Arblib.midref(zero(Arb)))
@test !Base.isgoodzero(min, Arblib.realref(zero(Acb)))
@test !Base.isgoodzero(min, zero(Mag))
@test !Base.isgoodzero(min, zero(Arf))
@test !Base.isgoodzero(min, zero(Arb))
@test !Base.isgoodzero(min, Arblib.radref(zero(Arb)))
@test !Base.isgoodzero(min, Arblib.midref(zero(Arb)))
@test !Base.isgoodzero(min, Arblib.realref(zero(Acb)))

@test !Base.isgoodzero(max, zero(Mag))
@test !Base.isgoodzero(max, zero(Arf))
@test !Base.isgoodzero(max, zero(Arb))
@test !Base.isgoodzero(max, Arblib.radref(zero(Arb)))
@test !Base.isgoodzero(max, Arblib.midref(zero(Arb)))
@test !Base.isgoodzero(max, Arblib.realref(zero(Acb)))
@test !Base.isgoodzero(max, zero(Mag))
@test !Base.isgoodzero(max, zero(Arf))
@test !Base.isgoodzero(max, zero(Arb))
@test !Base.isgoodzero(max, Arblib.radref(zero(Arb)))
@test !Base.isgoodzero(max, Arblib.midref(zero(Arb)))
@test !Base.isgoodzero(max, Arblib.realref(zero(Acb)))
end
end
end
Loading