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

for f in (:exp, :expm1)
    @eval begin
        ($f)(a::Interval{T}) where T = @round( ($f)(a.lo), ($f)(a.hi) )
        ($f)(x::EmptyInterval) = x
    end
end

ln_interval(::Type{T}, ::Val{N}) where {T, N} = log(unsafe_atomic(T, N))
ln2_interval(::Type{T}) where T = ln_interval(T, Val(2))
ln10_interval(::Type{T}) where T = ln_interval(T, Val(10))

# no CRlibm version
exp2(x::Interval{T}) where T = exp(ln2_interval(T) * x)
exp10(x::Interval{T}) where T = exp(ln10_interval(T) * x)

for f in (:exp2, :exp10)
  # add BigFloat functions with rounding:
    @eval ($f)(a::Interval{BigFloat}) = @round( ($f)(a.lo), ($f)(a.hi) )
    @eval ($f)(x::EmptyInterval) = x
end

for f in (:log, :log2, :log10)
    @eval ($(Symbol(f, "_inner")))(x::EmptyInterval) = x
    @eval ($(Symbol(f, "_inner")))(a::Interval) =
        a == zero(a) ? emptyinterval(a) : @round(($f)(a.lo), ($f)(a.hi))
    @eval function ($f)(a::Interval{T}) where T
            domain = nonnegatives(T)
            return ($(Symbol(f, "_inner")))(a ∩ domain)
        end
    @eval ($f)(x::EmptyInterval) = x
end

log1p_inner(a::Interval{T}) where T =
    a == -one(a) ? emptyinterval(T) : @round( log1p(a.lo), log1p(a.hi) )
log1p_inner(x::EmptyInterval) = x

function log1p(a::Interval{T}) where T
    domain = unsafe_interval(-one(T), T(Inf))
    return log1p_inner(a ∩ domain)
end
log1p(x::EmptyInterval) = x
