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
11 changes: 8 additions & 3 deletions docs/src/manual/construction.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,16 @@ interval(2, 1)
interval(NaN)
```

These are all examples of ill-formed intervals, resulting in the decoration `ill`.
These are all examples of ill-formed intervals,
also known as `NaI`, resulting in the decoration `ill`.

!!! danger
The decoration `ill` is an indicator that an error has occured. Therefore, any interval marked by this decoration cannot be trusted and the code needs to be debugged.
Similarly to the floating point `NaN`,
all boolean operations on an ill-formed interval return `false`.

!!! danger
The decoration `ill` is an indicator that an error has occured.
Therefore, when an ill-formed interval is created, a warning is raised.
Any interval marked by this decoration cannot be trusted and the code needs to be debugged.


### More constructors
Expand Down
19 changes: 19 additions & 0 deletions docs/src/philosophy.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,24 @@ because our intervals are always closed,
while the result of `setdiff` can be open.


## `hash`

The function `hash` is the only case where we do not define the value of
a function based on its interval extension.

`hash` return a single hash, and not an interval bounding the image
of the function.

```julia
julia> hash(interval(1, 2))
0xda823f68b9653b1a

julia> hash(1.2) in hash(interval(-10, 10))
false
```

This is justified as `hash` is not a mathematical function,
and julia requires that `hash` returns a `UInt`.

# Summary

Expand All @@ -165,3 +183,4 @@ while the result of `setdiff` can be open.
| Boolean operations | `==`, `<`, `<=`, `iszero`, `isnan`, `isinteger`, `isfinite` | Error if the result can not be guaranteed to be either `true` or `false` | See [`isequal_interval`](@ref) to test equality of intervals, and [`isbounded`](@ref) to test the finiteness of the elements |
| Set operations | `in`, `issubset`, `isdisjoint`, `issetequal`, `isempty`, `union`, `intersect` | Always error | Use the `*_interval` function instead (e.g. [`in_interval`](@ref))
| Exceptions | `≈`, `setdiff` | Always error | No meaningful interval extension |
| Hash | `hash` | Hash the interval as a julia object | |
2 changes: 2 additions & 0 deletions src/display.jl
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ function _str_repr(a::BareInterval{T}, format::Symbol) where {T<:NumTypes}
end

function _str_repr(a::Interval{T}, format::Symbol) where {T<:NumTypes}
isnai(a) && return "NaI"

# `format` is either `:infsup`, `:midpoint` or `:full`
str_interval = _str_basic_repr(a.bareinterval, format) # use `a.bareinterval` to not print a warning if `a` is an NaI
if format === :full && str_interval != "∅"
Expand Down
45 changes: 32 additions & 13 deletions src/intervals/interval_operations/boolean.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# flavor in Section 10.5.9
# Some other (non required) related functions are also present, as well as some
# of the "Recommended operations" (Section 10.6.3)
# The requirement for decorated intervals are described in Chapter 12,
# mostly sections 12.12.9 and 12.13.3.

# used internally, equivalent to `<` but with `(Inf < Inf) == true`
_strictlessprime(x::Real, y::Real) = (x < y) | ((isinf(x) | isinf(y)) & (x == y))
Expand All @@ -12,7 +14,8 @@ _strictlessprime(x::Real, y::Real) = (x < y) | ((isinf(x) | isinf(y)) & (x == y)

Test whether `x` and `y` are identical.

Implement the `equal` function of the IEEE Standard 1788-2015 (Table 9.3).
Implement the `equal` function of the IEEE Standard 1788-2015
(Tables 9.3 and 10.3, and Sections 9.5, 10.5.10 and 12.12.9).
"""
isequal_interval(x::BareInterval, y::BareInterval) = (inf(x) == inf(y)) & (sup(x) == sup(y))

Expand Down Expand Up @@ -49,7 +52,8 @@ const issetequal_interval = isequal_interval

Test whether `x` is contained in `y`.

Implement the `subset` function of the IEEE Standard 1788-2015 (Table 9.3).
Implement the `subset` function of the IEEE Standard 1788-2015
(Tables 9.3 and 10.3, and Sections 9.5, 10.5.10 and 12.12.9).

See also: [`isstrictsubset`](@ref) and [`isinterior`](@ref).
"""
Expand Down Expand Up @@ -100,7 +104,8 @@ isstrictsubset(x) = Base.Fix2(isstrictsubset, x)

Test whether `x` is in the interior of `y`.

Implement the `interior` function of the IEEE Standard 1788-2015 (Table 9.3).
Implement the `interior` function of the IEEE Standard 1788-2015
(Tables 9.3 and 10.3, and Sections 9.5, 10.5.10 and 12.12.9).

See also: [`issubset_interval`](@ref) and [`isstrictsubset`](@ref).
"""
Expand Down Expand Up @@ -129,7 +134,8 @@ isinterior(x, y, z, w...) = isinterior(x, y) & isinterior(y, z, w...)

Test whether the given intervals have no common elements.

Implement the `disjoint` function of the IEEE Standard 1788-2015 (Table 9.3).
Implement the `disjoint` function of the IEEE Standard 1788-2015.
(Tables 9.3 and 10.3, and Sections 9.5, 10.5.10 and 12.12.9).
"""
isdisjoint_interval(x::BareInterval, y::BareInterval) =
isempty_interval(x) | isempty_interval(y) | _strictlessprime(sup(y), inf(x)) | _strictlessprime(sup(x), inf(y))
Expand Down Expand Up @@ -161,7 +167,8 @@ _isdisjoint_interval(x, y, z, w...) = _isdisjoint_interval(x, y) && _isdisjoint_
Test whether `inf(x) ≤ inf(y)` and `sup(x) ≤ sup(y)`, where `<` is replaced by
`≤` for infinite values.

Implement the `less` function of the IEEE Standard 1788-2015 (Table 10.3).
Implement the `less` function of the IEEE Standard 1788-2015
(Table 10.3, and Sections 10.5.10 and 12.12.9).
"""
isweakless(x::BareInterval, y::BareInterval) = (inf(x) ≤ inf(y)) & (sup(x) ≤ sup(y))

Expand All @@ -176,7 +183,8 @@ end
Test whether `inf(x) < inf(y)` and `sup(x) < sup(y)`, where `<` is replaced by
`≤` for infinite values.

Implement the `strictLess` function of the IEEE Standard 1788-2015 (Table 10.3).
Implement the `strictLess` function of the IEEE Standard 1788-2015
(Table 10.3, and Sections 10.5.10 and 12.12.9).
"""
isstrictless(x::BareInterval, y::BareInterval) = # this may be flavor dependent? Should _strictlessprime be < for cset flavor?
_strictlessprime(inf(x), inf(y)) & _strictlessprime(sup(x), sup(y))
Expand All @@ -191,7 +199,8 @@ end

Test whether any element of `x` is lesser or equal to every elements of `y`.

Implement the `precedes` function of the IEEE Standard 1788-2015 (Table 10.3).
Implement the `precedes` function of the IEEE Standard 1788-2015
(Table 10.3, and Sections 10.5.10 and 12.12.9).
"""
precedes(x::BareInterval, y::BareInterval) = sup(x) ≤ inf(y)

Expand All @@ -205,7 +214,8 @@ end

Test whether any element of `x` is strictly lesser than every elements of `y`.

Implement the `strictPrecedes` function of the IEEE Standard 1788-2015 (Table 10.3).
Implement the `strictPrecedes` function of the IEEE Standard 1788-2015
(Table 10.3, and Sections 10.5.10 and 12.12.9).
"""
strictprecedes(x::BareInterval, y::BareInterval) = isempty_interval(x) | isempty_interval(y) | (sup(x) < inf(y))

Expand All @@ -219,7 +229,8 @@ end

Test whether `x` is an element of `y`.

Implement the `isMember` function of the IEEE Standard 1788-2015 (Section 10.6.3).
Implement the `isMember` function of the IEEE Standard 1788-2015
(Sections 10.6.3 and 12.13.3).
"""
function in_interval(x::Number, y::BareInterval)
isinf(x) && return contains_infinity(y)
Expand All @@ -246,7 +257,8 @@ in_interval(x) = Base.Fix2(in_interval, x)

Test whether `x` contains no elements.

Implement the `isEmpty` function of the IEEE Standard 1788-2015 (Section 10.6.3).
Implement the `isEmpty` function of the IEEE Standard 1788-2015
(Sections 10.5.10 and 12.12.9).
"""
isempty_interval(x::BareInterval{T}) where {T<:NumTypes} = (inf(x) == typemax(T)) & (sup(x) == typemin(T))

Expand All @@ -263,7 +275,8 @@ isempty_interval(x::AbstractVector) = any(isempty_interval, x)

Test whether `x` is the entire real line.

Implement the `isEntire` function of the IEEE Standard 1788-2015 (Section 10.6.3).
Implement the `isEntire` function of the IEEE Standard 1788-2015
(Sections 10.5.10 and 12.12.9).
"""
isentire_interval(x::BareInterval{T}) where {T<:NumTypes} = (inf(x) == typemin(T)) & (sup(x) == typemax(T))

Expand All @@ -277,6 +290,8 @@ isentire_interval(x::Complex{<:Interval}) = isentire_interval(real(x)) & isentir
isnai(x)

Test whether `x` is an NaI (Not an Interval).

Implement the `isNaI` function of the IEEE Standard 1788-2015 (Section 12.12.9).
"""
isnai(::BareInterval) = false

Expand Down Expand Up @@ -314,8 +329,11 @@ isunbounded(x::Complex{<:Interval}) = isunbounded(real(x)) | isunbounded(imag(x)

Test whether `x` is not empty and bounded.

Implement the `isCommonInterval` function of the IEEE Standard 1788-2015
(Sections 10.6.3 and 12.13.3).

!!! note
This is does not take into consideration the decoration of the interval.
This does not take into consideration the decoration of the interval.
"""
iscommon(x::BareInterval) = !(isentire_interval(x) | isempty_interval(x) | isunbounded(x))

Expand Down Expand Up @@ -346,7 +364,8 @@ isatomic(x::Complex{<:Interval}) = isatomic(real(x)) & isatomic(imag(x))

Test whether `x` contains only a real.

Implement the `isSingleton` function of the IEEE Standard 1788-2015 (Table 9.3).
Implement the `isSingleton` function of the IEEE Standard 1788-2015
(Sections 10.6.3 and 12.13.3).
"""
isthin(x::BareInterval) = inf(x) == sup(x)

Expand Down
4 changes: 4 additions & 0 deletions test/interval_tests/display.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
setprecision(BigFloat, 256) do
@testset "Ill-formed interval" begin
@test sprint(show, MIME("text/plain"), interval(1, -1)) == "NaI"
end

@testset "BareInterval" begin
a = bareinterval(-floatmin(Float64), 1.3)
large_expo = bareinterval(0, big"1e123456789") # use "small" exponent, cf. JuliaLang/julia#48678
Expand Down
28 changes: 23 additions & 5 deletions test/interval_tests/multidim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -104,25 +104,43 @@ end
[(-1 .. -0.5), (0.5 .. 1)], [(-0.5 .. 0), (0.5 .. 1)],
[(0 .. 0.5), (0.5 .. 1)], [(0.5 .. 1), (0.5 .. 1)]]
@test mapreduce((x, y) -> all(isequal_interval.(x, y)), &, vb2, vv)
@test all(isequal_interval.(hull.(vb2...), ib2))
@test all(enumerate(ib2)) do (i, Ib)
hulled = reduce(hull, [vb2[k][i] for k in eachindex(vb2)])
isequal_interval(hulled, Ib)
end
@test mapreduce((x, y) -> all(isequal_interval.(x, y)), &, mince(ib2, (4, 4)), vb2)
@test mapreduce((x, y) -> all(isequal_interval.(x, y)), &, mince(ib2, (1,4)),
[[(-1 .. 1), (-1 .. -0.5)], [(-1 .. 1), (-0.5 .. 0)], [(-1 .. 1), (0 .. 0.5)], [(-1 .. 1), (0.5 .. 1)]])
@test all(isequal_interval.(hull.(mince(ib2, (1,4))...), ib2))

vb2bis = mince(ib2, (1,4))
@test all(enumerate(ib2)) do (i, Ib)
hulled = reduce(hull, [vb2bis[k][i] for k in eachindex(vb2bis)])
isequal_interval(hulled, Ib)
end

ib3 = fill(-1..1, 3)
vb3 = mince(ib3, 4)
@test length(vb3) == 4^3
@test all(isequal_interval.(hull.(vb3...), ib3))
@test all(enumerate(ib3)) do (i, Ib)
hulled = reduce(hull, [vb3[k][i] for k in eachindex(vb3)])
isequal_interval(hulled, Ib)
end
@test mapreduce((x, y) -> all(isequal_interval.(x, y)), &, mince(ib3, (4,4,4)), vb3)
@test mapreduce((x, y) -> all(isequal_interval.(x, y)), &, mince(ib3, (2,1,1)),
[[(-1 .. 0), (-1 .. 1), (-1 .. 1)], [(0 .. 1), (-1 .. 1), (-1 .. 1)]])
@test all(isequal_interval.(hull.(mince(ib3, (2,1,1))...), ib3))
vb3bis = mince(ib3, (2,1,1))
@test all(enumerate(ib3)) do (i, Ib)
hulled = reduce(hull, [vb3bis[k][i] for k in eachindex(vb3bis)])
isequal_interval(hulled, Ib)
end

ib4 = fill(-1..1, 4)
vb4 = mince(ib4, 4)
@test length(vb4) == 4^4
@test all(isequal_interval.(hull.(vb4...), ib4))
@test all(enumerate(ib4)) do (i, Ib)
hulled = reduce(hull, [vb4[k][i] for k in eachindex(vb4)])
isequal_interval(hulled, Ib)
end
@test mapreduce((x, y) -> all(isequal_interval.(x, y)), &, mince(ib4, (4,4,4,4)), vb4)
@test mapreduce((x, y) -> all(isequal_interval.(x, y)), &, mince(ib4, (1,1,1,1)), (ib4,))
end
Expand Down
Loading