diff --git a/docs/make.jl b/docs/make.jl index 64f12dc4..48c7be6e 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -19,6 +19,7 @@ makedocs(; pages = [ "Home" => "index.md", "Overview" => "intro.md", + "Philosophy" => "philosophy.md", "Manual" => [ "Constructing intervals" => "manual/construction.md", "Usage" => "manual/usage.md", diff --git a/docs/src/manual/usage.md b/docs/src/manual/usage.md index 332161df..fa794066 100644 --- a/docs/src/manual/usage.md +++ b/docs/src/manual/usage.md @@ -91,37 +91,40 @@ sin(Y) -## Comparisons and set operations +## Comparisons -All comparisons and set operations for `Real` have been purposely disallowed to prevent silent errors. For instance, `x == y` does not implies `x - y == 0` for non-singleton intervals. +If the result of a comparison can be established with guarantee, +it will be return, otherwise, an error is thrown. ```@repl usage interval(1) < interval(2) -precedes(interval(1), interval(2)) +interval(1, 5) < interval(7, 9) +interval(1, 5) < interval(4.99, 9) +interval(1.23) == interval(1.23) +interval(1.23) == interval(4.99, 9) +interval(1.23) == interval(1.2, 1.3) +``` + +In particular, `if ... else ... end` statements used for floating-points will often break with intervals. + +See [Philosophy](@ref) for more details and why this choice was made. + + +## Set operations + +Set operations are all disallowed and error on intervals to avoid ambiguities. +To perform set operations on intervals, use the `*_interval` equivalent explicitly, +e.g. `issubset_interval` instead of `issubset`. + + +```@repl usage issubset(interval(1, 2), interval(2)) issubset_interval(interval(1, 2), interval(2)) intersect(interval(1, 2), interval(2)) intersect_interval(interval(1, 2), interval(2)) ``` -In particular, `if ... else ... end` statements used for floating-points will generally break with intervals. - -One can refer to the following: -- `<`: cannot be used with intervals. See instead [`isstrictless`](@ref) or [`strictprecedes`](@ref). -- `==`: allowed if the arguments are singleton intervals, or if at least one argument is not an interval (equivalent to [`isthin`](@ref)). Otherwise, see [`isequal_interval`](@ref). -- `iszero`, `isone`: allowed (equivalent to [`isthinzero`](@ref) and [`isthinone`](@ref) respectively). -- `isinteger`: cannot be used with intervals. See instead [`isthininteger`](ref). -- `isfinite`: cannot be used with intervals. See instead [`isbounded`](@ref). -- `isnan`: cannot be used with intervals. See instead [`isnai`](@ref). -- `in`: allowed if at least one argument is not an interval and the interval argument is a singleton. Otherwise, see [`in_interval`](@ref). -- `issubset`: cannot be used with intervals. See instead [`issubset_interval`](@ref). -- `isdisjoint`: cannot be used with intervals. See instead [`isdisjoint_interval`](@ref). -- `issetequal`: cannot be used with intervals. -- `isempty`: cannot be used with intervals. See instead [`isempty_interval`](@ref). -- `union`: cannot be used with intervals. See instead [`hull`](@ref). -- `intersect`: cannot be used with intervals. See instead [`intersect_interval`](@ref). -- `setdiff`: cannot be used with intervals. See instead [`interiordiff`](@ref). - +See [Philosophy](@ref) for more details and why this choice was made. ## Piecewise functions diff --git a/docs/src/philosophy.md b/docs/src/philosophy.md new file mode 100644 index 00000000..70db376f --- /dev/null +++ b/docs/src/philosophy.md @@ -0,0 +1,148 @@ +# Philosophy + +The goal of the `Interval` type is to be directly used to replace floating point +number in arbitrary julia code, such that in any calculation, +the resulting intervals are guaranteed to bound the true image of the starting +intervals. + +So, essentially, we would like `Interval` to act as numbers and +the julia ecosystem has evolved to use `Real` as the default supertype +for numerical types that are not complex. +Therefore, to ensure the widest compatiblity, +our `Interval` type must be a subtype of `Real`. + +Then, for any function `f(x::Real)`, +we want the following to hold for all real `x` in the interval `X` +(note that it holds for **all** real numbers in `X`, +even those that can not be represented as floating point numbers): +```math +f(x) \in f(X), \qquad \forall x \in X. +``` + +At first glance, this is reasonable: +all arithmetic operations are well-defined for both real numbers and intervals, +therefore we can use multiple dispatch to define the interval behavior of +operations such has `+`, `/`, `sin` or `log`. +Then a code written for `Real`s can be used as is with `Interval`s. + +However, being a `Real` means way more than just being compatible with +arithmetic operations. +`Real`s are also expected to + +1. Be compatible with any other `Number` through promotion. +2. Support comparison operations, such as `==` or `<`. +3. Act as a container of a single element, + e.g. `collect(x)` returns a 0-dimensional array containing `x`. + +Each of those points lead to specific design choice for `IntervalArithmetic.jl`, +choices that we detail below. + + +## Compatibility with other `Number`s + +In julia it is expected that `1 + 2.2` silently promoted the integer `1` +to a `Float64` to be able to perform the addition. +Following this logic, it means that `0.1 + interval(2.2, 2.3)` should +silently promote `0.1` to an interval. + +However, in this case we can not guarantee that `0.1` is known exactly, +because we do not know how it was produced in the first place. +Following the julia convention is thus in contradiction with providing +guaranteed result. + +In this case, we choose to be mostly silent, +the information that a non-interval of unknown origin is recorded in the `NG` flag, +but the calculation is not interrupted, and no warning is printed. + +For convenience, we provide the [`ExactReal`](@ref) and [`@exact`](@ref) macro +to allow to explicitly mark a number as being exact, +and not produce the `NG` flag when mixed with intervals. + + +## Comparison operators + +We can extend our above definition of the desired behavior for two real numbers +`x` and `y`, and their respective intervals `X` and `Y`. +With this, we want to have, for any function`f`, +for all `x` in `X` and all `y` in `Y`, +``math +f(x, y) \in f(X, Y), \qquad \forall x \in X, y \in Y. +`` + +With this in mind, an operation such as `==` can easily be defined for intervals + +1. If the intervals are disjoints (`X ∩ Y === ∅`), then `X == Y` is `[false]`. +2. If the intervals both contain a single element, + and that element is the same for both, + `X == Y` is `[true]`. +3. Otherwise, we can not conclude anything, and `X == Y` must be `[false, true]`. + +Not that we use intervals in all case, because, according to our definition, +the true result must be contained in the returned interval. +However, this is not convenient, as any `if` statement would error when used +with an interval. +Instead, we have opted to return respectively `false` and `true` +for cases 1 and 2, and to immediately error otherwise. + +In this way, we can return a more informative error, +but we only do it when the result is ambiguous. + +This has a clear cost, however, in that some expected behaviors do not hold. +For example, an `Interval` is not equal to itself. + +```julia> X = interval(1, 2) +[1.0, 2.0]_com + +julia> X == X +ERROR: ArgumentError: `==` is purposely not supported when the intervals are overlapping. See instead `isequal_interval` +Stacktrace: + [1] ==(x::Interval{Float64}, y::Interval{Float64}) + @ IntervalArithmetic C:\Users\Kolaru\.julia\packages\IntervalArithmetic\XjBhk\src\intervals\real_interface.jl:86 + [2] top-level scope + @ REPL[6]:1. +``` + + +## Intervals as sets + +We have taken the perspective to always let `Interval`s act as if they were numbers. + +But they are also sets of numbers, +and it would be nice to use all set operations defined in julia on them. + +However, `Real` are also sets. For example, the following is valid + +```julia +julia> 3 in 3 +true +``` + +Then what should `3 in interval(2, 6)` do? + +For interval as a set, it is clearly `true`. +But for intervals as a subtype of `Real` this is equivalent to +```julia +3 == interval(2, 6) +``` +which must either be false (they are not the same things), +or error as the result can not be established. + +To be safe, we decided to go one step further and disable +**all** set operations from julia `Base` on intervals. +These operations can instead be performed with the specific `*_interval` function, +for example `in_interval` as a replacement for `in`, +except for `setdiff`. +We can not meaningfully define the set difference of two intervals, +because our intervals are always closed, +while the result of `setdiff` can be open. + + +# Summary + +| | Functions | Behavior | Note | +| :---- | :---- | :---- | :---- | +| Arithmetic operations | `+`, `-`, `*`, `/`, `^` | Interval extension | Produce the `NG` flag when mixed with non-interval | +| Other numeric function | `sin`, `exp`, `sqrt`, etc. | Interval extension | | +| 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 | \ No newline at end of file diff --git a/src/intervals/interval_operations/boolean.jl b/src/intervals/interval_operations/boolean.jl index 676447ee..4e49ae57 100644 --- a/src/intervals/interval_operations/boolean.jl +++ b/src/intervals/interval_operations/boolean.jl @@ -35,6 +35,15 @@ isequal_interval(x, y, z, w...) = isequal_interval(x, y) & isequal_interval(y, z isequal_interval(x) = Base.Fix2(isequal_interval, x) +""" + issetequal_interval(x, y) + +Return whether the two interval are identical when considered as sets. + +Alias of the [`isequal_interval`](@ref) function. +""" +const issetequal_interval = isequal_interval + """ issubset_interval(x, y) diff --git a/src/intervals/interval_operations/cancellative.jl b/src/intervals/interval_operations/cancellative.jl index 3b2e71e4..eeae2e1a 100644 --- a/src/intervals/interval_operations/cancellative.jl +++ b/src/intervals/interval_operations/cancellative.jl @@ -3,11 +3,16 @@ # IEEE Standard 1788-2015 and required for set-based flavor in Section 10.5.6 """ - cancelminus(x, y) + cancelminus(x, y ; dec = :default) Compute the unique interval `z` such that `y + z == x`. -The result is decorated by at most `trv` (Section 11.7.1). +The keywork `dec` argument controls the decoration of the result, +it `dec` can be either the decoration of the output, +or a symbol: + - `:default`: if at least one of the input intervals is `ill`, + then the result is `ill`, otherwise it is `trv` (Section 11.7.1). + - `:auto`: the ouptut has the minimal decoration of the inputs. Implement the `cancelMinus` function of the IEEE Standard 1788-2015 (Section 9.2). """ @@ -36,23 +41,27 @@ function cancelminus(x::BareInterval{T}, y::BareInterval{T}) where {T<:NumTypes} end cancelminus(x::BareInterval, y::BareInterval) = cancelminus(promote(x, y)...) -function cancelminus(x::Interval, y::Interval) +function cancelminus(x::Interval, y::Interval ; dec = :default) r = cancelminus(bareinterval(x), bareinterval(y)) - d = min(decoration(x), decoration(y), decoration(r), trv) t = isguaranteed(x) & isguaranteed(y) - return _unsafe_interval(r, d, t) + return _unsafe_interval(r, set_decoration(dec, x, y, r), t) end """ - cancelplus(x, y) + cancelplus(x, y ; dec = :default) Compute the unique interval `z` such that `y - z == x`; this is semantically equivalent to `cancelminus(x, -y)`. -The result is decorated by at most `trv` (Section 11.7.1). +The keywork `dec` argument controls the decoration of the result, +it `dec` can be either the decoration of the output, +or a symbol: + - `:default`: if at least one of the input intervals is `ill`, + then the result is `ill`, otherwise it is `trv` (Section 11.7.1). + - `:auto`: the ouptut has the minimal decoration of the inputs. Implement the `cancelPlus` function of the IEEE Standard 1788-2015 (Section 9.2). """ cancelplus(x::BareInterval, y::BareInterval) = cancelminus(x, -y) -cancelplus(x::Interval, y::Interval) = cancelminus(x, -y) +cancelplus(x::Interval, y::Interval ; dec = :default) = cancelminus(x, -y ; dec) diff --git a/src/intervals/interval_operations/set_operations.jl b/src/intervals/interval_operations/set_operations.jl index 8da27cb8..d8be7494 100644 --- a/src/intervals/interval_operations/set_operations.jl +++ b/src/intervals/interval_operations/set_operations.jl @@ -2,14 +2,31 @@ # of the IEEE Std 1788-2015 and required for set-based flavor in Section 10.5.7 # Some other (non required) related functions are also present +function set_decoration(dec, xs...) + if dec == :default + return min(trv, decoration.(xs)...) + elseif dec == :auto + return min(decoration.(xs)...) + end + throw(ArgumentError("unknown decoration option $dec. Valid options are :default or :auto, or a decoration.")) +end + +set_decoration(dec::Decoration, xs...) = dec + + """ - intersect_interval(x, y) + intersect_interval(x, y ; dec = :default) Returns the intersection of the intervals `x` and `y`, considered as (extended) sets of real numbers. That is, the set that contains the points common in `x` and `y`. -The result is decorated by at most `trv` (Section 11.7.1). +The keywork `dec` argument controls the decoration of the result, +it `dec` can be either the decoration of the output, +or a symbol: + - `:default`: if at least one of the input intervals is `ill`, + then the result is `ill`, otherwise it is `trv` (Section 11.7.1). + - `:auto`: the ouptut has the minimal decoration of the inputs. Implement the `intersection` function of the IEEE Standard 1788-2015 (Section 9.3). """ @@ -24,27 +41,31 @@ function intersect_interval(x::BareInterval{T}, y::BareInterval{T}) where {T<:Nu end intersect_interval(x::BareInterval, y::BareInterval) = intersect_interval(promote(x, y)...) -function intersect_interval(x::Interval{T}, y::Interval{S}) where {T<:NumTypes,S<:NumTypes} +function intersect_interval(x::Interval{T}, y::Interval{S} ; dec = :default) where {T<:NumTypes,S<:NumTypes} isnai(x) | isnai(y) && return nai(promote_type(T, S)) r = intersect_interval(bareinterval(x), bareinterval(y)) - d = min(decoration(x), decoration(y), trv) t = isguaranteed(x) & isguaranteed(y) - return _unsafe_interval(r, d, t) + return _unsafe_interval(r, set_decoration(dec, x, y), t) end -intersect_interval(x, y, z, w...) = reduce(intersect_interval, (x, y, z, w...)) -intersect_interval(x::Complex, y::Complex) = complex(intersect_interval(real(x), real(y)), intersect_interval(imag(x), imag(y))) -intersect_interval(x::Real, y::Complex) = complex(intersect_interval(x, real(y)), intersect_interval(zero(x), imag(y))) -intersect_interval(x::Complex, y::Real) = complex(intersect_interval(real(x), y), intersect_interval(imag(x), zero(y))) +intersect_interval(x, y, z, w... ; dec = :default) = reduce((a, b) -> intersect_interval(a, b ; dec), (x, y, z, w...)) +intersect_interval(x::Complex, y::Complex ; dec = :default) = complex(intersect_interval(real(x), real(y) ; dec), intersect_interval(imag(x), imag(y) ; dec)) +intersect_interval(x::Real, y::Complex ; dec = :default) = complex(intersect_interval(x, real(y) ; dec), intersect_interval(zero(x), imag(y) ; dec)) +intersect_interval(x::Complex, y::Real ; dec = :default) = complex(intersect_interval(real(x), y ; dec), intersect_interval(imag(x), zero(y) ; dec)) """ - hull(x, y) + hull(x, y ; dec = :default) Return the interval hull of the intervals `x` and `y`, considered as (extended) sets of real numbers, i.e. the smallest interval that contains all of `x` and `y`. -The result is decorated by at most `trv` (Section 11.7.1). +The keywork `dec` argument controls the decoration of the result, +it `dec` can be either the decoration of the output, +or a symbol: + - `:default`: if at least one of the input intervals is `ill`, + then the result is `ill`, otherwise it is `trv` (Section 11.7.1). + - `:auto`: the ouptut has the minimal decoration of the inputs. Implement the `convexHull` function of the IEEE Standard 1788-2015 (Section 9.3). """ @@ -54,40 +75,55 @@ function hull(x::BareInterval{T}, y::BareInterval{T}) where {T<:NumTypes} end hull(x::BareInterval, y::BareInterval) = hull(promote(x, y)...) -function hull(x::Interval{T}, y::Interval{S}) where {T<:NumTypes,S<:NumTypes} +function hull(x::Interval{T}, y::Interval{S} ; dec = :default) where {T<:NumTypes,S<:NumTypes} isnai(x) | isnai(y) && return nai(promote_type(T, S)) r = hull(bareinterval(x), bareinterval(y)) - d = min(decoration(x), decoration(y), trv) t = isguaranteed(x) & isguaranteed(y) - return _unsafe_interval(r, d, t) + return _unsafe_interval(r, set_decoration(dec, x, y), t) end -hull(x, y, z, w...) = reduce(hull, (x, y, z, w...)) -hull(x::Complex, y::Complex) = complex(hull(real(x), real(y)), hull(imag(x), imag(y))) -hull(x::Real, y::Complex) = complex(hull(x, real(y)), hull(zero(x), imag(y))) -hull(x::Complex, y::Real) = complex(hull(real(x), y), hull(imag(x), zero(y))) +hull(x, y, z, w... ; dec = :default) = reduce((a, b) -> hull(a, b ; dec), (x, y, z, w...)) +hull(x::Complex, y::Complex ; dec = :default) = complex(hull(real(x), real(y) ; dec), hull(imag(x), imag(y) ; dec)) +hull(x::Real, y::Complex ; dec = :default) = complex(hull(x, real(y) ; dec), hull(zero(x), imag(y) ; dec)) +hull(x::Complex, y::Real ; dec = :default) = complex(hull(real(x), y ; dec), hull(imag(x), zero(y) ; dec)) """ - interiordiff(x, y) + union_interval(x, y, z...) + +Return the union of the intervals. + +Alias of the [`hull`](@ref) function. +""" +const union_interval = hull + +""" + interiordiff(x, y ; dec = :default) Remove the interior of `y` from `x`. If `x` and `y` are vectors, then they are treated as multi-dimensional intervals. + +The keywork `dec` argument controls the decoration of the result, +it `dec` can be either the decoration of the output, +or a symbol: + - `:default`: if at least one of the input intervals is `ill`, + then the result is `ill`, otherwise it is `trv` (Section 11.7.1). + - `:auto`: the ouptut has the minimal decoration of the inputs. """ interiordiff(x::BareInterval, y::BareInterval) = interiordiff!(Vector{promote_type(typeof(x), typeof(y))}(undef, 0), x, y) -interiordiff(x::Interval, y::Interval) = - interiordiff!(Vector{promote_type(typeof(x), typeof(y))}(undef, 0), x, y) +interiordiff(x::Interval, y::Interval ; dec = :default) = + interiordiff!(Vector{promote_type(typeof(x), typeof(y))}(undef, 0), x, y ; dec) -interiordiff(x::AbstractVector, y::AbstractVector) = - interiordiff!(Vector{promote_type(typeof(x), typeof(y))}(undef, 0), x, y) +interiordiff(x::AbstractVector, y::AbstractVector ; dec = :default) = + interiordiff!(Vector{promote_type(typeof(x), typeof(y))}(undef, 0), x, y ; dec) """ - interiordiff(x, y) + interiordiff!(x, y) In-place version of [`interiordiff`](@ref). """ -function interiordiff!(v::AbstractVector, x::BareInterval{T}, y::BareInterval{T}) where {T<:NumTypes} +function interiordiff!(v::AbstractVector, x::BareInterval{T}, y::BareInterval{T} ; dec = nothing) where {T<:NumTypes} if isinterior(x, y) empty!(v) elseif isdisjoint_interval(x, y) @@ -109,43 +145,38 @@ function interiordiff!(v::AbstractVector, x::BareInterval{T}, y::BareInterval{T} end return v end -interiordiff!(v::AbstractVector, x::BareInterval, y::BareInterval) = interiordiff!(v, promote(x, y)...) +interiordiff!(v::AbstractVector, x::BareInterval, y::BareInterval ; dec = nothing) = interiordiff!(v, promote(x, y)...) -function interiordiff!(v::AbstractVector, x::Interval{T}, y::Interval{T}) where {T<:NumTypes} +function interiordiff!(v::AbstractVector, x::Interval{T}, y::Interval{T} ; dec = :default) where {T<:NumTypes} if isinterior(x, y) empty!(v) elseif isdisjoint_interval(x, y) resize!(v, 1) @inbounds v[begin] = x else - d = min(decoration(x), decoration(y)) t = isguaranteed(x) & isguaranteed(y) inter = intersect_interval(x, y) if issubset_interval(y, x) resize!(v, 2) r1 = _unsafe_bareinterval(T, inf(x), inf(inter)) - d1 = min(d, decoration(r1), trv) - @inbounds v[begin] = _unsafe_interval(r1, d1, t) + @inbounds v[begin] = _unsafe_interval(r1, set_decoration(dec, x, y, r1), t) r2 = _unsafe_bareinterval(T, sup(inter), sup(x)) - d2 = min(d, decoration(r2), trv) - @inbounds v[end] = _unsafe_interval(r2, d2, t) + @inbounds v[end] = _unsafe_interval(r2, set_decoration(dec, x, y, r2), t) elseif isweakless(x, inter) resize!(v, 1) r1 = _unsafe_bareinterval(T, inf(x), inf(inter)) - d1 = min(d, decoration(r1), trv) - @inbounds v[begin] = _unsafe_interval(r1, d1, t) + @inbounds v[begin] = _unsafe_interval(r1, set_decoration(dec, x, y, r1), t) else resize!(v, 1) r2 = _unsafe_bareinterval(T, sup(inter), sup(x)) - d2 = min(d, decoration(r2), trv) - @inbounds v[begin] = _unsafe_interval(r2, d2, t) + @inbounds v[begin] = _unsafe_interval(r2, set_decoration(dec, x, y, r2), t) end end return v end -interiordiff!(v::AbstractVector, x::Interval, y::Interval) = interiordiff!(v, promote(x, y)...) +interiordiff!(v::AbstractVector, x::Interval, y::Interval ; dec = :default) = interiordiff!(v, promote(x, y)... ; dec) -function interiordiff!(v::AbstractVector{<:AbstractVector}, x::AbstractVector, y::AbstractVector) +function interiordiff!(v::AbstractVector{<:AbstractVector}, x::AbstractVector, y::AbstractVector ; dec = :default) # start from the total overlap (in all directions); expand each direction in turn N = length(x) @@ -162,7 +193,7 @@ function interiordiff!(v::AbstractVector{<:AbstractVector}, x::AbstractVector, y x_bis = copy(x) @inbounds for i ∈ eachindex(x, y) - h₁, h₂, inter = _interiordiff(x[i], y[i]) + h₁, h₂, inter = _interiordiff(x[i], y[i] ; dec) u₁ = similar(eltype(v), N) u₂ = similar(eltype(v), N) @inbounds for j ∈ eachindex(u₁) @@ -181,7 +212,7 @@ function interiordiff!(v::AbstractVector{<:AbstractVector}, x::AbstractVector, y return v end -function _interiordiff(x::BareInterval{T}, y::BareInterval{T}) where {T<:NumTypes} +function _interiordiff(x::BareInterval{T}, y::BareInterval{T} ; dec = nothing) where {T<:NumTypes} isdisjoint_interval(x, y) && return (x, emptyinterval(BareInterval{T}), emptyinterval(BareInterval{T})) inter = intersect_interval(x, y) @@ -193,11 +224,11 @@ function _interiordiff(x::BareInterval{T}, y::BareInterval{T}) where {T<:NumType return (_unsafe_bareinterval(T, inf(x), inf(y)), _unsafe_bareinterval(T, sup(y), sup(x)), inter) end -_interiordiff(x::BareInterval, y::BareInterval) = _interiordiff(promote(x, y)...) +_interiordiff(x::BareInterval, y::BareInterval ; dec = nothing) = _interiordiff(promote(x, y)... ; dec) -function _interiordiff(x::Interval, y::Interval) +function _interiordiff(x::Interval, y::Interval ; dec = :default) h₁, h₂, inter = _interiordiff(bareinterval(x), bareinterval(y)) - d = min(decoration(x), decoration(y), trv) + d = set_decoration(dec, x, y) t = isguaranteed(x) & isguaranteed(y) return (_unsafe_interval(h₁, d, t), _unsafe_interval(h₂, d, t), _unsafe_interval(inter, d, t)) end diff --git a/src/intervals/intervals.jl b/src/intervals/intervals.jl index 37453108..3e645d03 100644 --- a/src/intervals/intervals.jl +++ b/src/intervals/intervals.jl @@ -31,7 +31,7 @@ include("interval_operations/constants.jl") include("interval_operations/extended_div.jl") export extended_div include("interval_operations/boolean.jl") - export isequal_interval, issubset_interval, isstrictsubset, isinterior, + export isequal_interval, issetequal_interval, issubset_interval, isstrictsubset, isinterior, isdisjoint_interval, isweakless, isstrictless, precedes, strictprecedes, in_interval, isempty_interval, isentire_interval, isnai, isbounded, isunbounded, iscommon, isatomic, isthin, isthinzero, isthinone, @@ -42,6 +42,6 @@ include("interval_operations/overlap.jl") include("interval_operations/numeric.jl") export inf, sup, bounds, mid, diam, radius, midradius, mag, mig, dist include("interval_operations/set_operations.jl") - export intersect_interval, hull, interiordiff + export intersect_interval, hull, interiordiff, union_interval include("interval_operations/bisect.jl") export bisect, mince, mince!