Skip to content

Commit

Permalink
Merge pull request #560 from OlivierHnt/1.0-constructors
Browse files Browse the repository at this point in the history
1.0-dev: rework constructors
  • Loading branch information
Kolaru committed Jun 10, 2023
2 parents 3e2e99e + 5fb804e commit 8b9f4fd
Show file tree
Hide file tree
Showing 53 changed files with 1,740 additions and 1,925 deletions.
7 changes: 2 additions & 5 deletions src/IntervalArithmetic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export ×, dot
import Base:
+, -, *, /, //, fma,
<, >, ==, !=, , ^, <=, >=,
in, zero, one, eps, typemin, typemax, abs, abs2, real, min, max,
in, zero, one, eps, typemin, typemax, abs, abs2, min, max,
sqrt, exp, log, exp2, exp10, log2, log10, inv, cbrt, hypot,
sin, cos, tan, cot, csc, sec, asin, acos, atan, acot, sinpi, cospi,
sinh, cosh, tanh, coth, csch, sech, asinh, acosh, atanh, acoth,
Expand Down Expand Up @@ -50,8 +50,7 @@ import .Broadcast: broadcasted

export
Interval, BooleanInterval,
interval, checked_interval,
@interval, @biginterval, @floatinterval,
interval, ±, .., @I_str,
diam, radius, mid, scaled_mid, mag, mig, hull,
emptyinterval, ∅, ∞, isempty, isinterior, isdisjoint, ,
precedes, strictprecedes, , , , , contains_zero, isthinzero,
Expand All @@ -65,7 +64,6 @@ export
IntervalRounding,
PointwisePolicy,
cancelminus, cancelplus, isbounded, isunbounded,
.., @I_str, ±,
pow, extended_div, nthroot,
setformat, @format

Expand All @@ -87,7 +85,6 @@ export

## Decorations
export
@decorated,
interval, decoration, DecoratedInterval,
com, dac, def, trv, ill

Expand Down
14 changes: 7 additions & 7 deletions src/bisect.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ const where_bisect = 0.49609375
Split the interval `X` at position α; α=0.5 corresponds to the midpoint.
Returns a tuple of the new intervals.
"""
function bisect(X::F, α=where_bisect) where {F<:Interval}
function bisect(X::Interval{T}, α=where_bisect) where {T<:NumTypes}
@assert 0 α 1

m = scaled_mid(X, α)

return (F(inf(X), m), F(m, sup(X)))
return (unsafe_interval(T, inf(X), m), unsafe_interval(T, m, sup(X)))
end

"""
Expand Down Expand Up @@ -43,18 +43,18 @@ end
"""
mince(x::Interval, n)
Splits `x` in `n` intervals of the same diameter, which are returned
Split `x` in `n` intervals of the same diameter, which are returned
as a vector.
"""
function mince(x::F, n) where {F<:Interval}
nodes = range(inf(x), sup(x), length = n+1)
return [F(nodes[i], nodes[i+1]) for i in 1:length(nodes)-1]
function mince(x::Interval{T}, n) where {T<:NumTypes}
nodes = LinRange(inf(x), sup(x), n+1)
return [unsafe_interval(T, nodes[i], nodes[i+1]) for i in 1:n]
end

"""
mince(x::IntervalBox, n)
Splits `x` in `n` intervals in each dimension of the same diameter. These
Split `x` in `n` intervals in each dimension of the same diameter. These
intervals are combined in all possible `IntervalBox`-es, which are returned
as a vector.
"""
Expand Down
14 changes: 7 additions & 7 deletions src/decorations/decorations.jl
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
include("intervals.jl")
include("functions.jl")

isnan(x::Interval) = false # NaI is always decorated
isnan(::Interval) = false # NaI is always decorated

"""`NaI` not-an-interval: [NaN, NaN]."""
nai(::Type{T}) where T = DecoratedInterval(convert(T, NaN), convert(T, NaN), ill)
nai(::Type{F}) where {T, F<:Interval{T}} = nai(T)
nai(::Interval{T}) where T<:Real = nai(T)
nai(::DecoratedInterval{T}) where T<:Real = nai(T)
nai() = nai(Interval{default_bound()})
nai(::Type{Interval{T}}) where {T<:NumTypes} = nai(T)
nai(::Type{T}) where {T<:NumTypes} = DecoratedInterval(convert(T, NaN), convert(T, NaN), ill)
nai(::Type{<:Real}) = nai(default_numtype())
nai() = nai(default_numtype())
nai(::T) where {T} = nai(T)

isnai(x::Interval) = isnan(inf(x)) || isnan(sup(x)) #|| inf(x) > sup(x) || (isinf(inf(x)) && inf(x) == sup(x))
isnai(x::Interval) = isnan(inf(x)) || isnan(sup(x)) # || inf(x) > sup(x) || (isinf(inf(x)) && inf(x) == sup(x))
isnai(x::DecoratedInterval) = isnai(interval(x)) || x.decoration == ill
24 changes: 12 additions & 12 deletions src/decorations/functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ Base.literal_pow(::typeof(^), x::DecoratedInterval{T}, ::Val{p}) where {T,p} = x


# zero, one
zero(a::DecoratedInterval{T}) where T<:Real = DecoratedInterval(zero(T))
zero(::Type{DecoratedInterval{T}}) where T<:Real = DecoratedInterval(zero(T))
one(a::DecoratedInterval{T}) where T<:Real = DecoratedInterval(one(T))
one(::Type{DecoratedInterval{T}}) where T<:Real = DecoratedInterval(one(T))
zero(::DecoratedInterval{T}) where {T<:NumTypes} = DecoratedInterval(zero(T))
zero(::Type{DecoratedInterval{T}}) where {T<:NumTypes} = DecoratedInterval(zero(T))
one(::DecoratedInterval{T}) where {T<:NumTypes} = DecoratedInterval(one(T))
one(::Type{DecoratedInterval{T}}) where {T<:NumTypes} = DecoratedInterval(one(T))

## Bool functions
const bool_functions = (
Expand Down Expand Up @@ -323,18 +323,18 @@ end

# The function is unbounded at the bounded edges of the domain
restricted_functions1 = Dict(
:log => Interval{Float64}(0.0, Inf),
:log2 => Interval{Float64}(0.0, Inf),
:log10 => Interval{Float64}(0.0, Inf),
:atanh => Interval{Float64}(-1.0, 1.0)
:log => unsafe_interval(Float64, 0.0, Inf),
:log2 => unsafe_interval(Float64, 0.0, Inf),
:log10 => unsafe_interval(Float64, 0.0, Inf),
:atanh => unsafe_interval(Float64, -1.0, 1.0)
)

# The function is bounded at the bounded edge(s) of the domain
restricted_functions2 = Dict(
:sqrt => Interval{Float64}(0.0, Inf),
:asin => Interval{Float64}(-1.0, 1.0),
:acos => Interval{Float64}(-1.0, 1.0),
:acosh => Interval{Float64}(1.0, Inf)
:sqrt => unsafe_interval(Float64, 0.0, Inf),
:asin => unsafe_interval(Float64, -1.0, 1.0),
:acos => unsafe_interval(Float64, -1.0, 1.0),
:acosh => unsafe_interval(Float64, 1.0, Inf)
)

# Define functions with restricted domains on DecoratedInterval's:
Expand Down
104 changes: 46 additions & 58 deletions src/decorations/intervals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,87 +5,75 @@
"""
DECORATION
Enumeration constant for the types of interval decorations.
The nomenclature of the follows the IEEE-1788 (2015) standard
(sect 11.2):
- `com -> 4`: common: bounded, non-empty
- `dac -> 3`: defined (nonempty) and continuous
- `def -> 2`: defined (nonempty)
- `trv -> 1`: always true (no information)
- `ill -> 0`: nai ("not an interval")
Enumeration constant for the types of interval decorations. The nomenclature
follows Section 11.2 of the IEEE Standard 1788-2015:
- `com -> 4`: non-empty, continuous and bounded (common)
- `dac -> 3`: non-empty and continuous (defined and continuous)
- `def -> 2`: non-empty (defined)
- `trv -> 1`: always true (trivial)
- `ill -> 0`: not an interval (ill-formed)
"""
@enum DECORATION ill=0 trv=1 def=2 dac=3 com=4
# Note that `isweaklyless`, and hence ``<` and `min`, are automatically defined for enums
# Note that `isweaklyless`, and hence `<` and `min`, are automatically defined for enums

"""
DecoratedInterval
DecoratedInterval{T<:NumTypes}
A *decorated* interval is an interval, together with a *decoration*, i.e.
a flag that records the status of the interval when thought of as the result
of a previously executed sequence of functions acting on an initial interval.
Wraps an `Interval` together with a `DECORATION`, i.e. a flag that records the
status of the interval when thought of as the result of a previously executed
sequence of functions acting on an initial interval.
"""

struct DecoratedInterval{T<:NumTypes}
interval::Interval{T}
decoration::DECORATION
end

DecoratedInterval(I::DecoratedInterval, dec::DECORATION) = DecoratedInterval(I.interval, dec)
DecoratedInterval{T}(x::Interval{T}, d::DECORATION) where {T<:NumTypes} = new{T}(x, d)
end

function DecoratedInterval(a::T, b::S, d::DECORATION) where {T<:Real, S<:Real}
NumType = promote_numtype(T, S)
is_valid_interval(a, b) || return DecoratedInterval(Interval{NumType}(a, b), ill)
return DecoratedInterval(Interval{NumType}(a, b), d)
function DecoratedInterval{T}(x::Interval{T}) where {T<:NumTypes}
d = decoration(x)
d trv && return DecoratedInterval{T}(x, d)
d == ill && return DecoratedInterval{T}(nai(T), d)
return DecoratedInterval{T}(x, d)
end

DecoratedInterval(a::Real, d::DECORATION) = DecoratedInterval(a, a, d)
DecoratedInterval(a::Tuple, d::DECORATION) = DecoratedInterval(a..., d)
DecoratedInterval(x::Interval{T}, d::DECORATION) where {T<:NumTypes} = DecoratedInterval{T}(x, d)

function DecoratedInterval{T}(I::Interval) where {T}
d = decoration(I)
d <= trv && return DecoratedInterval{T}(I, d)
d == ill && return DecoratedInterval{T}(nai(I), d)
return DecoratedInterval{T}(I, d)
end
DecoratedInterval(x::Interval{T}) where {T<:NumTypes} = DecoratedInterval{T}(x)

DecoratedInterval(x::DecoratedInterval, d::DECORATION) = DecoratedInterval(x.interval, d) # do we want this behaviour?

DecoratedInterval(I::Interval{T}) where {T<:NumTypes} = DecoratedInterval{T}(I)
DecoratedInterval(a, b, d::DECORATION) =
DecoratedInterval(unsafe_interval(promote_numtype(numtype(a), numtype(b)), a, b),
ifelse(is_valid_interval(a, b), d, ill))

function DecoratedInterval(a::T, b::S) where {T<:Real, S<:Real}
NumType = promote_numtype(T, S)
is_valid_interval(a, b) || return DecoratedInterval(Interval{NumType}(a, b), ill)
return DecoratedInterval(Interval{NumType}(a, b))
function DecoratedInterval(a, b)
T = promote_numtype(numtype(a), numtype(b))
is_valid_interval(a, b) || return DecoratedInterval(unsafe_interval(T, a, b), ill)
return DecoratedInterval(unsafe_interval(T, a, b))
end

DecoratedInterval(a::Real) = DecoratedInterval(a, a)
DecoratedInterval(a, d::DECORATION) = DecoratedInterval(a, a, d)

DecoratedInterval(a) = DecoratedInterval(a, a)

DecoratedInterval(a::Tuple, d::DECORATION) = DecoratedInterval(a..., d)

DecoratedInterval(a::Tuple) = DecoratedInterval(a...)

#

interval(x::DecoratedInterval) = x.interval
decoration(x::DecoratedInterval) = x.decoration

# Automatic decorations for an Interval
function decoration(I::Interval)
isnai(I) && return ill # nai()
isempty(I) && return trv # emptyinterval
isunbounded(I) && return dac # unbounded
com # common
function decoration(x::Interval)
isnai(x) && return ill # nai()
isempty(x) && return trv # emptyinterval
isunbounded(x) && return dac # unbounded
return com # common
end

big(x::DecoratedInterval) = DecoratedInterval(big(interval(x)), decoration(x))
#

macro decorated(ex...)
if !(ex[1] isa String)
if length(ex) == 1
x = :(@interval($(esc(ex[1]))))
lo = :(inf($x))
hi = :(sup($x))
else
lo, hi = ex
end

return :(DecoratedInterval($lo, $hi))
else
s = ex[1]
parse(DecoratedInterval{Float64}, s)
end
end
float(x::DecoratedInterval) = DecoratedInterval(float(interval(x)), decoration(x))
big(x::DecoratedInterval) = DecoratedInterval(big(interval(x)), decoration(x))
42 changes: 23 additions & 19 deletions src/intervals/arithmetic/absmax.jl
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
# This file is part of the IntervalArithmetic.jl package; MIT licensed
# This file contains the functions described as "Absmax functions" in Section
# 9.1 of the IEEE Standard 1788-2015 and required for set-based flavor in
# Section 10.5.3

#= This file contains the functions described as "Absmax functions"
in the IEEE Std 1788-2015 (sections 9.1) and required for set-based flavor
in section 10.5.3.
=#
"""
abs(a::Interval)
Implement the `abs` function of the IEEE Std 1788-2015 (Table 9.1).
Implement the `abs` function of the IEEE Standard 1788-2015 (Table 9.1).
"""
function abs(a::F) where {F<:Interval}
isempty(a) && return emptyinterval(F)
return F(mig(a), mag(a))
function abs(a::Interval{T}) where {T<:NumTypes}
isempty(a) && return a
return unsafe_interval(T, mig(a), mag(a))
end

abs2(a::Interval) = sqr(a)

"""
min(a::Interval)
min(a::Interval, b::Interval)
Implement the `min` function of the IEEE Std 1788-2015 (Table 9.1).
Implement the `min` function of the IEEE Standard 1788-2015 (Table 9.1).
"""
function min(a::F, b::F) where {F<:Interval}
(isempty(a) || isempty(b)) && return emptyinterval(F)
return F(min(inf(a), inf(b)), min(sup(a), sup(b)))
function min(a::Interval{T}, b::Interval{T}) where {T<:NumTypes}
isempty(a) && return a
isempty(b) && return b
return unsafe_interval(T, min(inf(a), inf(b)), min(sup(a), sup(b)))
end

min(a::Interval, b::Interval) = min(promote(a, b)...)

"""
max(a::Interval)
max(a::Interval, b::Interval)
Implement the `max` function of the IEEE Std 1788-2015 (Table 9.1).
Implement the `max` function of the IEEE Standard 1788-2015 (Table 9.1).
"""
function max(a::F, b::F) where {F<:Interval}
(isempty(a) || isempty(b)) && return emptyinterval(F)
return F(max(inf(a), inf(b)), max(sup(a), sup(b)))
function max(a::Interval{T}, b::Interval{T}) where {T<:NumTypes}
isempty(a) && return a
isempty(b) && return b
return unsafe_interval(T, max(inf(a), inf(b)), max(sup(a), sup(b)))
end

max(a::Interval, b::Interval) = max(promote(a, b)...)
Loading

0 comments on commit 8b9f4fd

Please sign in to comment.