# This file is part of the IntervalArithmetic.jl package; MIT licensed

"""
    widened(x)

widens the lowest and highest bounds of `x` to the previous and next representable floating-point numbers, respectively.

It implements `nextOut` from the IEEE 1788-2015 standard.
"""
widened(x::Interval{T}) where {T<:AbstractFloat} =
    unsafe_interval(prevfloat(x.lo), nextfloat(x.hi))
widened(x::EmptyInterval) = x

# unsafe method, only for use with checked input
signed_infinity(x::T) where {T<:AbstractFloat} = sign(x) * T(Inf) |>
    x -> unsafe_interval(prevfloat(x), nextfloat(x))

# common thin intervals
zero(a::I) where {T, I <: ValidInterval{T}} = unsafe_interval(zero(T))
zero(::Type{I}) where {T, I <: ValidInterval{T}} = unsafe_interval(zero(T))
one(a::I) where {T, I <: ValidInterval{T}} = unsafe_interval(one(T))
one(::Type{I}) where {T, I <: ValidInterval{T}} = unsafe_interval(one(T))
#eps(a::Interval) = unsafe_interval(max(eps(a.lo), eps(a.hi)))
eps(::Type{ValidInterval{T}}) where T = unsafe_interval(eps(T))

copysign(::ValidInterval{T}, ::ValidInterval{T}) where T = emptyinterval(T)
copysign(a::Interval{T}, b::Interval{T}) where T = abs(a) * sign(b)

"""
    valtype(::AbstractInterval{T}) where T = T

Returns the type of the bounds of the interval.

### Example

```julia
julia> valtype(Interval(1.0, 2.0))
Float64
julia> valtype(emptyinterval(Float32))
Float32
```
"""
valtype(::AbstractInterval{T}) where T = T

"""
Computes the integer hash code for an `Interval` using the method for composite types used in `AutoHashEquals.jl`
"""
hash(x::Interval, h::UInt) = hash(x.hi, hash(x.lo, hash(:Interval, h)))
hash(::EmptyInterval, h::UInt) = hash(:EmptyInterval, h)
hash(::NotAnInterval, h::UInt) = hash(:NotAnInterval, h)
