Skip to content

Commit 4d6bd15

Browse files
authored
Merge pull request #558 from OlivierHnt/1.0-conversion
1.0-dev: fully disallow conversion between non `Interval` types
2 parents 466606b + 911499d commit 4d6bd15

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+7071
-7079
lines changed

src/bisect.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ const where_bisect = 0.49609375
77
Split the interval `X` at position α; α=0.5 corresponds to the midpoint.
88
Returns a tuple of the new intervals.
99
"""
10-
function bisect(X::Interval, α=where_bisect)
10+
function bisect(X::F, α=where_bisect) where {F<:Interval}
1111
@assert 0 α 1
1212

1313
m = scaled_mid(X, α)
1414

15-
return (Interval(inf(X), m), Interval(m, sup(X)))
15+
return (F(inf(X), m), F(m, sup(X)))
1616
end
1717

1818
"""
@@ -47,9 +47,9 @@ end
4747
Splits `x` in `n` intervals of the same diameter, which are returned
4848
as a vector.
4949
"""
50-
function mince(x::Interval, n)
50+
function mince(x::F, n) where {F<:Interval}
5151
nodes = range(inf(x), sup(x), length = n+1)
52-
return [Interval(nodes[i], nodes[i+1]) for i in 1:length(nodes)-1]
52+
return [F(nodes[i], nodes[i+1]) for i in 1:length(nodes)-1]
5353
end
5454

5555
"""
@@ -74,4 +74,4 @@ as a vector.
7474
end
7575
nodes
7676
end
77-
end
77+
end

src/decorations/functions.jl

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -323,23 +323,22 @@ end
323323

324324
# The function is unbounded at the bounded edges of the domain
325325
restricted_functions1 = Dict(
326-
:log => [0, Inf],
327-
:log2 => [0, Inf],
328-
:log10 => [0, Inf],
329-
:atanh => [-1, 1]
326+
:log => Interval{Float64}(0.0, Inf),
327+
:log2 => Interval{Float64}(0.0, Inf),
328+
:log10 => Interval{Float64}(0.0, Inf),
329+
:atanh => Interval{Float64}(-1.0, 1.0)
330330
)
331331

332332
# The function is bounded at the bounded edge(s) of the domain
333333
restricted_functions2 = Dict(
334-
:sqrt => [0, Inf],
335-
:asin => [-1, 1],
336-
:acos => [-1, 1],
337-
:acosh => [1, Inf]
334+
:sqrt => Interval{Float64}(0.0, Inf),
335+
:asin => Interval{Float64}(-1.0, 1.0),
336+
:acos => Interval{Float64}(-1.0, 1.0),
337+
:acosh => Interval{Float64}(1.0, Inf)
338338
)
339339

340340
# Define functions with restricted domains on DecoratedInterval's:
341341
for (f, domain) in restricted_functions1
342-
domain = Interval(domain...)
343342
@eval function Base.$(f)(xx::DecoratedInterval{T}) where T
344343
x = interval(xx)
345344
r = $(f)(x)
@@ -350,7 +349,6 @@ for (f, domain) in restricted_functions1
350349
end
351350

352351
for (f, domain) in restricted_functions2
353-
domain = Interval(domain...)
354352
@eval function Base.$(f)(xx::DecoratedInterval{T}) where T
355353
x = interval(xx)
356354
r = $(f)(x)

src/decorations/intervals.jl

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@ end
3333

3434
DecoratedInterval(I::DecoratedInterval, dec::DECORATION) = DecoratedInterval(I.interval, dec)
3535

36-
function DecoratedInterval(a::Real, b::Real, d::DECORATION)
37-
is_valid_interval(a, b) || return DecoratedInterval(Interval(a,b), ill)
38-
return DecoratedInterval(Interval(a,b), d)
36+
function DecoratedInterval(a::T, b::S, d::DECORATION) where {T<:Real, S<:Real}
37+
BoundsType = promote_numtype(T, S)
38+
is_valid_interval(a, b) || return DecoratedInterval(Interval{BoundsType}(a, b), ill)
39+
return DecoratedInterval(Interval{BoundsType}(a, b), d)
3940
end
4041

4142
DecoratedInterval(a::Real, d::DECORATION) = DecoratedInterval(a, a, d)
@@ -50,9 +51,10 @@ end
5051

5152
DecoratedInterval(I::Interval) = DecoratedInterval{default_bound()}(I)
5253

53-
function DecoratedInterval(a::Real, b::Real)
54-
is_valid_interval(a, b) || return DecoratedInterval(Interval(a,b), ill)
55-
return DecoratedInterval(Interval(a,b))
54+
function DecoratedInterval(a::T, b::S) where {T<:Real, S<:Real}
55+
BoundsType = promote_numtype(T, S)
56+
is_valid_interval(a, b) || return DecoratedInterval(Interval{BoundsType}(a, b), ill)
57+
return DecoratedInterval(Interval{BoundsType}(a, b))
5658
end
5759

5860
DecoratedInterval(a::Real) = DecoratedInterval(a, a)

src/display.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,12 +212,12 @@ end
212212

213213
# `String` representation of an `Interval`
214214

215-
function basic_representation(a::Interval, format::Symbol)
215+
function basic_representation(a::Interval{T}, format::Symbol) where {T}
216216
isempty(a) && return ""
217217
sigdigits = display_params.sigdigits
218218
if format === :full
219219
# Do not use `inf(a)` to avoid -0.0
220-
return string("Interval(", a.lo, ", ", sup(a), ")")
220+
return string("Interval{", T, "}(", a.lo, ", ", sup(a), ")")
221221
elseif format === :midpoint
222222
m = round_string(mid(a), sigdigits, RoundNearest)
223223
r = round_string(radius(a), sigdigits, RoundUp)
@@ -237,8 +237,8 @@ function basic_representation(a::Interval{Float32}, format::Symbol)
237237
sigdigits = display_params.sigdigits
238238
if format === :full
239239
# Do not use `inf(a)` to avoid -0.0
240-
output = string("Interval(", a.lo, "f0, ", sup(a), "f0)")
241-
return replace(replace(output, "NaNf0" => "NaN32"), "Inff0" => '')
240+
output = string("Interval{Float32}(", a.lo, "f0, ", sup(a), "f0)")
241+
return replace(replace(output, "NaNf0" => "NaN32"), "Inff0" => "Inf32")
242242
elseif format === :midpoint
243243
m = round_string(mid(a), sigdigits, RoundNearest)
244244
r = round_string(radius(a), sigdigits, RoundUp)
@@ -253,11 +253,11 @@ function basic_representation(a::Interval{Float32}, format::Symbol)
253253
end
254254
end
255255

256-
function basic_representation(a::Interval{<:Rational}, format::Symbol)
256+
function basic_representation(a::Interval{T}, format::Symbol) where {T<:Rational}
257257
isempty(a) && return ""
258258
if format === :full
259259
# Do not use `inf(a)` to avoid -0.0
260-
return string("Interval(", a.lo, ", ", sup(a), ")")
260+
return string("Interval{", T, "}(", a.lo, ", ", sup(a), ")")
261261
elseif format === :midpoint
262262
return string(mid(a), " ± ", radius(a))
263263
else # format === :standard

src/intervals/arithmetic/absmax.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Implement the `min` function of the IEEE Std 1788-2015 (Table 9.1).
2323
"""
2424
function min(a::F, b::F) where {F<:Interval}
2525
(isempty(a) || isempty(b)) && return emptyinterval(F)
26-
return F( min(inf(a), inf(b)), min(sup(a), sup(b)))
26+
return F(min(inf(a), inf(b)), min(sup(a), sup(b)))
2727
end
2828

2929
"""
@@ -33,5 +33,5 @@ Implement the `max` function of the IEEE Std 1788-2015 (Table 9.1).
3333
"""
3434
function max(a::F, b::F) where {F<:Interval}
3535
(isempty(a) || isempty(b)) && return emptyinterval(F)
36-
return F( max(inf(a), inf(b)), max(sup(a), sup(b)))
37-
end
36+
return F(max(inf(a), inf(b)), max(sup(a), sup(b)))
37+
end

src/intervals/arithmetic/basic.jl

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ function +(a::F, b::T) where {T, F<:Interval{T}}
1919
isempty(a) && return emptyinterval(F)
2020
return @round(F, inf(a) + b, sup(a) + b)
2121
end
22-
+(a::Interval{T}, b::S) where {T, S<:Real} = a + Interval{T}(b)
23-
+(b::Real, a::Interval) = a + b
22+
+(a::Interval{T}, b::Real) where {T} = a + interval(T, b)
23+
+(a::Real, b::Interval{T}) where {T} = b + a
2424

2525
function +(a::F, b::F) where {F<:Interval}
2626
(isempty(a) || isempty(b)) && return emptyinterval(F)
@@ -50,8 +50,8 @@ function -(b::T, a::F) where {T, F<:Interval{T}}
5050
isempty(a) && return emptyinterval(F)
5151
return @round(F, b - sup(a), b - inf(a))
5252
end
53-
-(a::F, b::Real) where {F<:Interval} = a - F(b)
54-
-(a::Real, b::F) where {F<:Interval} = F(a) - b
53+
-(a::Interval{T}, b::Real) where {T} = a - interval(T, b)
54+
-(a::Real, b::Interval{T}) where {T} = interval(T, a) - b
5555

5656
function -(a::F, b::F) where {F<:Interval}
5757
(isempty(a) || isempty(b)) && return emptyinterval(F)
@@ -77,18 +77,18 @@ Implement the `mul` function of the IEEE Std 1788-2015 (Table 9.1).
7777
7878
Note: the behavior of the multiplication is flavor dependent for some edge cases.
7979
"""
80-
function *(x::T, a::F) where {T<:Real, F<:Interval{T}}
80+
function *(a::F, b::T) where {T<:Real, F<:Interval{T}}
8181
isempty(a) && return emptyinterval(F)
82-
(isthinzero(a) || iszero(x)) && return zero(F)
82+
(isthinzero(a) || iszero(b)) && return zero(F)
8383

84-
if x 0.0
85-
return @round(F, inf(a)*x, sup(a)*x)
84+
if b 0.0
85+
return @round(F, inf(a)*b, sup(a)*b)
8686
else
87-
return @round(F, sup(a)*x, inf(a)*x)
87+
return @round(F, sup(a)*b, inf(a)*b)
8888
end
8989
end
90-
*(x::T, a::F) where {T<:Real, S, F<:Interval{S}} = Interval{S}(x) * a
91-
*(a::F, x::T) where {T<:Real, S, F<:Interval{S}} = x*a
90+
*(a::Interval{T}, b::Real) where {T} = a * interval(T, b)
91+
*(a::Real, b::Interval{T}) where {T} = b * a
9292

9393
function *(a::F, b::F) where {F<:Interval}
9494
(isempty(a) || isempty(b)) && return emptyinterval(F)
@@ -131,18 +131,18 @@ Implement the `div` function of the IEEE Std 1788-2015 (Table 9.1).
131131
132132
Note: the behavior of the division is flavor dependent for some edge cases.
133133
"""
134-
function /(a::F, x::Real) where {F<:Interval}
134+
function /(a::F, b::Real) where {F<:Interval}
135135
isempty(a) && return emptyinterval(T)
136-
iszero(x) && return div_by_thin_zero(a)
136+
iszero(b) && return div_by_thin_zero(a)
137137

138-
if x 0.0
139-
return @round(F, inf(a)/x, sup(a)/x)
138+
if b 0
139+
return @round(F, inf(a)/b, sup(a)/b)
140140
else
141-
return @round(F, sup(a)/x, inf(a)/x)
141+
return @round(F, sup(a)/b, inf(a)/b)
142142
end
143143
end
144144

145-
/(x::Real, a::Interval) = x*inv(a)
145+
/(a::Real, b::Interval) = a * inv(b)
146146

147147
function /(a::F, b::F) where {T, F<:Interval{T}}
148148
(isempty(a) || isempty(b)) && return emptyinterval(F)
@@ -255,10 +255,11 @@ Square root of an interval.
255255
Implement the `sqrt` function of the IEEE Std 1788-2015 (Table 9.1).
256256
"""
257257
function sqrt(a::F) where {F<:Interval}
258-
domain = F(0, Inf)
258+
G = float(F)
259+
domain = G(0, Inf)
259260
a = a domain
260261

261262
isempty(a) && return a
262263

263-
return @round(F, sqrt(inf(a)), sqrt(sup(a))) # `sqrt` is correctly-rounded
264+
return @round(G, sqrt(inf(a)), sqrt(sup(a))) # `sqrt` is correctly-rounded
264265
end

src/intervals/arithmetic/power.jl

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function ^(a::F, n::Integer) where {F<:Interval{BigFloat}}
4040
isempty(a) && return a
4141
iszero(n) && return one(F)
4242
n == 1 && return a
43-
n < 0 && isthinzero(a) && return emptyinterval(F)
43+
(n < 0 && isthinzero(a)) && return emptyinterval(F)
4444

4545
if isodd(n) # odd power
4646
isentire(a) && return a
@@ -98,7 +98,7 @@ function ^(a::F, x::BigFloat) where {F<:Interval{BigFloat}}
9898
a = a domain
9999
(isempty(x) || isempty(a)) && return emptyinterval(F)
100100

101-
xx = F(x)
101+
xx = F(x, x)
102102

103103
lo = @round(F, inf(a)^inf(xx), inf(a)^inf(xx))
104104
lo = (inf(lo) == Inf) ? F(prevfloat(Inf), Inf) : lo
@@ -167,20 +167,10 @@ function ^(a::F, x::Interval) where {F<:Interval{BigFloat}}
167167

168168
(isempty(x) || isempty(a)) && return emptyinterval(F)
169169

170-
lo1 = a^inf(x)
171-
lo2 = a^sup(x)
172-
lo1 = hull(lo1, lo2)
173-
174-
hi1 = a^inf(x)
175-
hi2 = a^sup(x)
176-
hi1 = hull(hi1, hi2)
177-
178-
return hull(lo1, hi1)
170+
return hull(a^inf(x), a^sup(x))
179171
end
180172

181-
function sqr(a::Interval)
182-
return a^2
183-
end
173+
sqr(a::Interval) = a^2
184174

185175
"""
186176
hypot(x::Interval, n::Integer)
@@ -203,13 +193,16 @@ function pow(x::F, n::Integer) where {F<:Interval}
203193
isempty(x) && return x
204194

205195
if iseven(n) && 0 x
196+
xmig = mig(x)
197+
xmag = mag(x)
206198
return hull(zero(x),
207-
Base.power_by_squaring(F(mig(x)), n),
208-
Base.power_by_squaring(F(mag(x)), n)
209-
)
199+
Base.power_by_squaring(F(xmig, xmig), n),
200+
Base.power_by_squaring(F(xmag, xmag), n))
210201
else
211-
return hull( Base.power_by_squaring(F(inf(x)), n),
212-
Base.power_by_squaring(F(sup(x)), n) )
202+
xinf = inf(x)
203+
xsup = sup(x)
204+
return hull(Base.power_by_squaring(F(xinf, xinf), n),
205+
Base.power_by_squaring(F(xsup, xsup), n))
213206
end
214207
end
215208

@@ -262,7 +255,7 @@ for f in (:log, :log2, :log10)
262255
end
263256

264257
function log1p(a::F) where {T, F<:Interval{T}}
265-
domain = Interval{T}(-1, Inf)
258+
domain = F(-1, Inf)
266259
a = a domain
267260

268261
(isempty(a) || sup(a) -one(T)) && return emptyinterval(a)

0 commit comments

Comments
 (0)