Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed bugs towards ITF1788 compliance #49

Merged
merged 11 commits into from
Feb 4, 2022
4 changes: 3 additions & 1 deletion src/IntervalContractors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export plus_rev, minus_rev, inv_rev,
asin_rev, acos_rev, atan_rev,
sinh_rev, cosh_rev, tanh_rev,
asinh_rev, acosh_rev, atanh_rev,
mul_rev_IEEE1788
mul_rev_IEEE1788, mul_rev_to_pair,
pow_rev1, pow_rev2

using IntervalArithmetic

Expand All @@ -32,6 +33,7 @@ include("inverse_trig.jl")
include("hyperbolic.jl")
include("inverse_hyperbolic.jl")
include("extrema.jl")
include("decorated.jl")

"""
Dictionary mapping functions to their reverse functions.
Expand Down
28 changes: 21 additions & 7 deletions src/arithmetic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,12 @@ inv_rev(a,b) = inv_rev(promote(a,b)...)
"""
Reverse power
"""
function power_rev(a::Interval, b::Interval, n::Integer) # a = b^n, log(a) = n.log(b), b = a^(1/n)
function power_rev(a::Interval{T}, b::Interval{T}, n::Integer) where T # a = b^n, log(a) = n.log(b), b = a^(1/n)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there are various "powRev" functions specified in the standard (cf. Sect 10.5.4 and Table 10.1), it's important to have very descriptive docstrings, in this case, of the specific function in the standard, or the differences with that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this comment applies to other functions...


if iszero(n)
1 ∈ a && return (a, entireinterval(T) ∩ b, n)
return (a, emptyinterval(T), n)
end

if n == 2 # a = b^2
root = √a
Expand All @@ -117,6 +122,7 @@ function power_rev(a::Interval, b::Interval, n::Integer) # a = b^n, log(a) = n
return (a, b, n)
end

power_rev(a::Interval{T}, n::Integer) where T = power_rev(a, entireinterval(T), n)

function power_rev(a::Interval, b::Interval, c::Interval) # a = b^c

Expand Down Expand Up @@ -162,8 +168,6 @@ function sqr_rev(c, x) # c = x^2; refine x
return (c, hull(x1, x2))
end

sqr_rev(c) = sqr_rev(c, -∞..∞)

"""
Reverse abs
"""
Expand Down Expand Up @@ -201,14 +205,24 @@ According to the IEEE-1788 standard:
When `∘` is commutative, these agree and we write `∘_rev(b, c, x)`.
"""

function mul_rev_IEEE1788(b, c, x) # c = b*x
return x ∩ (c / b)
end
mul_rev_IEEE1788(b, c, x) = mul_rev(c, x, b)[2]

function pow_rev1(b, c, x) # c = x^b
return x ∩ c^(1/b) # replace by 1//b
end

function pow_rev2(a, c, x) # c = a^x
return x ∩ (log(c) / lob(a))
return x ∩ (log(c) / log(a))
end

mul_rev_to_pair(b::Interval, c::Interval) = extended_div(c, b)

function mul_rev_to_pair(b::DecoratedInterval{T}, c::DecoratedInterval{T}) where T
(isnai(b) || isnai(c)) && return (nai(T), nai(T))

0 ∉ b && return (c/b, DecoratedInterval(emptyinterval(T), trv))

x1, x2 = extended_div(interval(c), interval(b))
return (DecoratedInterval(x1, trv), DecoratedInterval(x2, trv))
end

35 changes: 35 additions & 0 deletions src/decorated.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
entiredecorated(T) = DecoratedInterval(entireinterval(T))

for op in (:sqr_rev, :abs_rev, :sin_rev, :cos_rev, :tan_rev, :cosh_rev, :sinh_rev, :tanh_rev)
lbenet marked this conversation as resolved.
Show resolved Hide resolved
@eval begin
function $op(a::DecoratedInterval{T}, x::DecoratedInterval{T}) where T
( isnai(a) || isnai(x) ) && return nai(T)
bare = $op(interval(a), interval(x))
return (DecoratedInterval(bare[1], trv), DecoratedInterval(bare[2], trv))
end
end
@eval $op(a::Interval{T}) where T = $op(a, entireinterval(T))
@eval $op(a::DecoratedInterval{T}) where T = $op(a, entiredecorated(T))
end

function power_rev(a::DecoratedInterval{T}, x::DecoratedInterval{T}, n::Integer) where T
( isnai(a) || isnai(x) ) && return nai(T)
bare = power_rev(interval(a), interval(x), n)
return (DecoratedInterval(bare[1], trv), DecoratedInterval(bare[2], trv), n)
end

power_rev(a::DecoratedInterval{T}, n::Integer) where T = power_rev(a, entiredecorated(T), n)

for op in (:mul_rev_IEEE1788, :pow_rev1, :pow_rev2)
@eval begin
function $op(b::DecoratedInterval{T}, c::DecoratedInterval{T}, x::DecoratedInterval{T}) where T
(isnai(b) || isnai(c) || isnai(x) ) && return nai(T)
bare = $op(interval(b), interval(c), interval(x))
return DecoratedInterval(bare, trv)
end
end

@eval $op(a::Interval{T}, b::Interval{T}) where T = $op(a, b, entireinterval(T))
@eval $op(a::DecoratedInterval{T}, b::DecoratedInterval{T}) where T = $op(a, b, entiredecorated(T))

end
2 changes: 1 addition & 1 deletion src/hyperbolic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Reverse function for `cosh`.
"""
function cosh_rev(y::Interval,x::Interval)
y_new = y ∩ Interval(1.,∞)
x = x ∩ acosh(y)
x = (x ∩ acosh(y)) ∪ (x ∩ -acosh(y))

return y_new, x
end
Expand Down
11 changes: 0 additions & 11 deletions test/Non1788tests/hyperbolic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,6 @@ isapprox(x::Interval,y::Interval) = isapprox(x.lo,y.lo,atol=1E-4) && isapprox(x.
@test isapprox(sinh_rev(Interval(-1.0, 25.0), -∞..∞)[2], Interval(-0.881374, 3.91243))
end

@testset "cosh_rev_test" begin
@test isapprox(cosh_rev(∅, -∞..∞)[2], ∅)
@test isapprox(cosh_rev(Interval(-10.0, -1.0), -∞..∞)[2], ∅)
@test isapprox(cosh_rev(Interval(0.0, Inf), -∞..∞)[2], Interval(0.0, ∞))
@test isapprox(cosh_rev(Interval(0.0, 1.0), -∞..∞)[2], Interval(0, 0))
@test isapprox(cosh_rev(Interval(-0.5, 1.0), -∞..∞)[2], Interval(0, 0))
@test isapprox(cosh_rev(Interval(-1000.0, 1.0), -∞..∞)[2], Interval(0, 0))
@test isapprox(cosh_rev(Interval(0.0, 25.0), -∞..∞)[2], Interval(0, 3.91163))
@test isapprox(cosh_rev(Interval(-1.0, 25.0), -∞..∞)[2], Interval(0, 3.91163))
end

@testset "tanh_rev_test" begin
@test tanh_rev(∅, -∞..∞)[2] == ∅
@test tanh_rev(Interval(-10.0, -1.0), -∞..∞)[2] == ∅
Expand Down
Loading