Skip to content

Commit

Permalink
separate set-like and number-like behaviors
Browse files Browse the repository at this point in the history
  • Loading branch information
gwater committed Jul 25, 2018
1 parent 29f33d3 commit 3ced063
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/IntervalArithmetic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import Base: # for IntervalBox
start, next, done, eltype

export
AbstractInterval, Interval,
AbstractInterval, Interval, SetInterval, NumberInterval,
interval,
@interval, @biginterval, @floatinterval, @make_interval,
diam, radius, mid, mag, mig, hull,
Expand Down
8 changes: 4 additions & 4 deletions src/intervals/arithmetic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
## Comparisons

"""
isequal(a,b)
==(a,b)
Checks if the intervals `a` and `b` are equal.
"""
function isequal(a::Interval, b::Interval)
function ==(a::SetInterval, b::SetInterval)
isempty(a) && isempty(b) && return true
a.lo == b.lo && a.hi == b.hi
end
Expand All @@ -20,14 +20,14 @@ function islessprime(a::T, b::T) where T<:Real
end

# Weakly less, \le, <=
function isweaklyless(a::Interval, b::Interval)
function <=(a::SetInterval, b::SetInterval)
isempty(a) && isempty(b) && return true
(isempty(a) || isempty(b)) && return false
(a.lo b.lo) && (a.hi b.hi)
end

# Strict less: <
function isstrictlyless(a::Interval, b::Interval)
function <(a::SetInterval, b::SetInterval)
isempty(a) && isempty(b) && return true
(isempty(a) || isempty(b)) && return false
islessprime(a.lo, b.lo) && islessprime(a.hi, b.hi)
Expand Down
4 changes: 2 additions & 2 deletions src/intervals/conversion.jl
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ else
function atomic(::Type{Interval{T}}, x::S) where {T<:AbstractFloat, S<:Real}
isinf(x) && return wideinterval(T(x))

Interval{T}( T(x, RoundDown), T(x, RoundUp) )
Interval( T(x, RoundDown), T(x, RoundUp) )
# the rounding up could be done as nextfloat of the rounded down one?
# use @round_up and @round_down here?
end
Expand All @@ -120,7 +120,7 @@ atomic(::Type{Interval{Irrational{T}}}, x::Irrational{S}) where {T, S} =
float(atomic(Interval{Float64}, x))

function atomic(::Type{Interval{T}}, x::Interval) where T<:AbstractFloat
Interval{T}( T(x.lo, RoundDown), T(x.hi, RoundUp) )
Interval( T(x.lo, RoundDown), T(x.hi, RoundUp) )
end

# Complex numbers:
Expand Down
25 changes: 14 additions & 11 deletions src/intervals/heuristics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ struct UndecidableError <: Exception
msg
end

function isfinite(x::Interval)
function isfinite(x::NumberInterval)
isbounded(x) && return true
throw(UndecidableError("may represent a finite number (or not)"))
end
isinf(x::Interval) = !isfinite(x)
isinf(x::NumberInterval) = !isfinite(x)

isnan(x::Interval) = isnai(x)

function iszero(x::Interval)
function iszero(x::NumberInterval)
if contains_zero(x)
if isthin(x)
return true
Expand All @@ -22,18 +20,23 @@ function iszero(x::Interval)
return false
end

function ==(a::Interval, b::Interval)
#isequal(a::NumberInterval{T}, b::NumberInterval{S}) where {T, S} =
# SetInterval{T}(a) == SetInterval{S}(b)
isequal(a::NumberInterval, b::NumberInterval) =
SetInterval(a) == SetInterval(b)

function ==(a::NumberInterval, b::NumberInterval)
isthin(a) && isequal(a, b) && return true
isempty(a b) && return false
throw(UndecidableError("may represent equal numbers (or not)"))
end
!=(a::Interval, b::Interval) = !(a == b)
!=(a::NumberInterval, b::NumberInterval) = !(a == b)

function <(a::Interval, b::Interval)
function <(a::NumberInterval, b::NumberInterval)
strictprecedes(a, b) && return true
precedes(b, a) && return false
throw(UndecidableError("cannot compare represented numbers"))
end
>(a::Interval, b::Interval) = b < a
<=(a::Interval, b::Interval) = !(b < a)
#>=(a::Interval, b::Interval) = b <= a
>(a::NumberInterval, b::NumberInterval) = b < a
<=(a::NumberInterval, b::NumberInterval) = !(b < a)
#>=(a::NumberInterval, b::NumberInterval) = b <= a
19 changes: 15 additions & 4 deletions src/intervals/intervals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@ end

abstract type AbstractInterval{T} <: Real end

struct Interval{T<:Real} <: AbstractInterval{T}
abstract type Behavior end
struct SetLike <: Behavior end
struct NumberLike <: Behavior end
const DefaultBehavior = NumberLike

struct Interval{T <: Real, B <: Behavior} <: AbstractInterval{T}
lo :: T
hi :: T

function Interval{T}(a::Real, b::Real) where T<:Real
function Interval{T, B}(a::Real, b::Real) where {T<:Real, B<: Behavior}

if validity_check

Expand All @@ -35,14 +40,20 @@ struct Interval{T<:Real} <: AbstractInterval{T}
end
end

const SetInterval{T} = Interval{T, SetLike}
const NumberInterval{T} = Interval{T, NumberLike}

SetInterval(x::NumberInterval{T}) where T = SetInterval{T}(x.lo, x.hi)
NumberInterval(x::SetInterval{T}) where T = NumberInterval{T}(x.lo, x.hi)

## Outer constructors

Interval(a::T, b::T) where T<:Real = Interval{T}(a, b)
Interval(a::T, b::T) where {T<:Real} = Interval{T, DefaultBehavior}(a, b)
#Interval(::Type{B}, a::T, b::T) where {B <: Behavior, T <: Real} =
# Interval{T, B}(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.
Expand Down
11 changes: 9 additions & 2 deletions src/intervals/special.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
"""`emptyinterval`s are represented as the interval [∞, -∞]; note
that this interval is an exception to the fact that the lower bound is
larger than the upper one."""
emptyinterval(::Type{T}) where T<:Real = Interval{T}(Inf, -Inf)
emptyinterval(x::Interval{T}) where T<:Real = emptyinterval(T)
emptyinterval(::Type{T}) where {T<:Real} =
Interval(convert(T, Inf), convert(T, -Inf))
emptyinterval(x::Interval{T}) where {T<:Real} = emptyinterval(T)
emptyinterval() = emptyinterval(precision(Interval)[1])
const= emptyinterval(Float64)

Expand All @@ -22,6 +23,7 @@ entireinterval(x::Interval{T}) where T<:Real = entireinterval(T)
entireinterval() = entireinterval(precision(Interval)[1])

isentire(x::Interval) = x.lo == -Inf && x.hi == Inf
isinf(x::SetInterval) = isentire(x)
isunbounded(x::Interval) = x.lo == -Inf || x.hi == Inf
isbounded(x::Interval) = !isunbounded(x)

Expand All @@ -33,6 +35,9 @@ nai() = nai(precision(Interval)[1])

isnai(x::Interval) = isnan(x.lo) || isnan(x.hi)

isfinite(x::SetInterval) = isfinite(x.lo) && isfinite(x.hi)
isnan(x::SetInterval) = isnai(x)

"""
isthin(x)
Expand Down Expand Up @@ -72,6 +77,8 @@ This occurs when the interval is empty, or when the upper bound equals the lower
"""
isatomic(x::Interval) = isempty(x) || (x.hi == x.lo) || (x.hi == nextfloat(x.lo))

iszero(x::SetInterval) = iszero(x.lo) && iszero(x.hi)

contains_zero(X::Interval{T}) where {T} = zero(T) X


Expand Down

0 comments on commit 3ced063

Please sign in to comment.