Skip to content

Commit

Permalink
Implement trait-like supported type for interval bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
Kolaru committed Sep 29, 2018
1 parent c801e5e commit 09aa126
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 14 deletions.
28 changes: 17 additions & 11 deletions src/intervals/intervals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ const IASupportedType = Union{Integer, Rational, Irrational, Float16, Float32,

abstract type AbstractInterval{T} <: Real end

struct Interval{T<:IASupportedType} <: AbstractInterval{T}
struct Interval{T<:Real} <: AbstractInterval{T}
lo :: T
hi :: T

function Interval{T}(a::Real, b::Real) where {T<:IASupportedType}
function Interval{T}(::Type{Val{true}}, a::Real, b::Real) where {T <: Real}
if validity_check

if is_valid_interval(a, b)
Expand All @@ -33,28 +33,34 @@ struct Interval{T<:IASupportedType} <: AbstractInterval{T}
end
end


## Traits functions
canBeIntervalBound(::Type{T}) where {T <: IASupportedType} = true
canBeIntervalBound(T) = false # Default case

## Outer constructors
function Interval{T}(::Type{Val{false}}, ::Real, ::Real) where {T <: Real}
throw(ArgumentError("Type $T is not suitable to construct an interval. If it is a custom type and should be accepted, make sure to define `canBeIntervalBound($T) = true`"))
end

Interval(a::T, b::T) where T<:Real = Interval{T}(a, b)
Interval(a::T) where T<:Real = Interval(a, a)
Interval{T}(a::Real, b::Real) where {T <: Real} = Interval{T}(Val{canBeIntervalBound(T)}, a, b)
Interval(a::T, b::T) where {T <: Real} = Interval{T}(Val{canBeIntervalBound(T)}, a, b)
Interval(a::T) where {T <: Real} = Interval(a, a)
Interval(a::Tuple) = Interval(a...)
Interval(a::T, b::S) where {T<:Real, S<:Real} = Interval(promote(a,b)...)
Interval(a::T, b::S) where {T <: Real, S <: Real} = Interval(promote(a,b)...)

## Concrete constructors for Interval, to effectively deal only with Float64,
# BigFloat or Rational{Integer} intervals.
Interval(a::T, b::T) where T<:Integer = Interval(float(a), float(b))
Interval(a::T, b::T) where T<:Irrational = Interval(float(a), float(b))
Interval(a::T, b::T) where {T <: Integer} = Interval(float(a), float(b))
Interval(a::T, b::T) where {T <: Irrational} = Interval(float(a), float(b))

eltype(x::Interval{T}) where T<:Real = T
eltype(x::Interval{T}) where {T <: Real} = T

Interval(x::Interval) = x
Interval(x::Complex) = Interval(real(x)) + im*Interval(imag(x))

Interval{T}(x) where T = Interval(convert(T, x))
Interval{T}(x) where {T} = Interval(convert(T, x))

Interval{T}(x::Interval) where T = atomic(Interval{T}, x)
Interval{T}(x::Interval) where {T} = atomic(Interval{T}, x)

size(x::Interval) = (1,)

Expand Down
6 changes: 3 additions & 3 deletions test/interval_tests/construction.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ const eeuler = Base.MathConstants.e
@test_throws ArgumentError interval(Inf, Inf)

# Disallowed creation of interval witha a or b an interval
@test_throws TypeError Interval(1, 1..2)
@test_throws TypeError Interval(1..2, 1)
@test_throws TypeError Interval(1..2, 1..2)
@test_throws ArgumentError Interval(1, 1..2)
@test_throws ArgumentError Interval(1..2, 1)
@test_throws ArgumentError Interval(1..2, 1..2)

# Conversion to Interval without type
@test convert(Interval, 1) == Interval(1.0)
Expand Down

0 comments on commit 09aa126

Please sign in to comment.