diff --git a/src/IntervalArithmetic.jl b/src/IntervalArithmetic.jl index b8d18f24c..d82f57cb3 100644 --- a/src/IntervalArithmetic.jl +++ b/src/IntervalArithmetic.jl @@ -29,7 +29,7 @@ import Base: convert, promote_rule, eltype, size, BigFloat, float, widen, big, ∩, ∪, ⊆, ⊇, ∈, eps, - floor, ceil, trunc, sign, round, + floor, ceil, trunc, sign, round, copysign, flipsign, signbit, expm1, log1p, precision, isfinite, isnan, isinf, iszero, diff --git a/src/intervals/arithmetic.jl b/src/intervals/arithmetic.jl index bdacb7f0b..4123f57ee 100644 --- a/src/intervals/arithmetic.jl +++ b/src/intervals/arithmetic.jl @@ -354,6 +354,43 @@ function sign(a::Interval) return Interval(sign(a.lo), sign(a.hi)) end +""" + signbit(x::Interval) + +Returns an interval containing `true` (`1`) if the value of the sign of any element in `x` is negative, containing `false` (`0`) +if any element in `x` is non-negative, and an empy interval if `x` is empty. + +# Examples +```jldoctest +julia> signbit(@interval(-4)) +[1, 1] + +julia> signbit(@interval(5)) +[0, 0] + +julia> signbit(@interval(-4,5)) +[0, 1] +``` +""" +function signbit(a::Interval) + isempty(a) && return emptyinterval(a) + return Interval(signbit(a.hi), signbit(a.lo)) +end + +for Typ in (:Interval, :Real, :Float64, :Float32, :Signed, :Unsigned) + @eval begin + copysign(a::$Typ, b::Interval) = abs(a)*(1-2signbit(b)) + flipsign(a::$Typ, b::Interval) = a*(1-2signbit(b)) + end +end + +for Typ in (:Real, :Float64, :Float32, :Signed, :Unsigned) + @eval begin + copysign(a::Interval, b::$Typ) = abs(a)*(1-2signbit(b)) + flipsign(a::Interval, b::$Typ) = a*(1-2signbit(b)) + end +end + # RoundTiesToEven is an alias of `RoundNearest` const RoundTiesToEven = RoundNearest # RoundTiesToAway is an alias of `RoundNearestTiesAway` diff --git a/test/interval_tests/numeric.jl b/test/interval_tests/numeric.jl index aafe9799f..46bc888b0 100644 --- a/test/interval_tests/numeric.jl +++ b/test/interval_tests/numeric.jl @@ -192,6 +192,39 @@ end @test ceil(@interval(0.1, 1.1)) == Interval(1, 2) @test round(@interval(0.1, 1.1), RoundUp) == Interval(1, 2) @test sign(@interval(0.1, 1.1)) == Interval(1.0) + @test signbit(@interval(-4)) == @interval(1,1) + @test signbit(@interval(5)) == @interval(0,0) + @test signbit(@interval(-4,5)) == @interval(0,1) + @test copysign(@interval(1,2), @interval(-1,1)) == @interval(-2,2) + @test copysign(3, @interval(-1,1)) == @interval(-3,3) + @test copysign(3.0, @interval(-1,1)) == @interval(-3,3) + @test copysign(3f0, @interval(-1,1)) == @interval(-3,3) + @test copysign(3, @interval(0,1)) == @interval(3) == @interval(copysign(3,0),copysign(3,1)) + @test copysign(3, @interval(-1,0)) == @interval(-3,3) == @interval(copysign(3,-1),copysign(3,0)) + @test copysign(UInt64(3), @interval(-1,1)) == @interval(-3,3) + @test copysign(BigFloat(3), @interval(-1,1)) == @interval(-3,3) + @test copysign(@interval(0,1), -1) == @interval(-1,0) + @test copysign(@interval(0,1), -1.0) == @interval(-1,0) + @test copysign(@interval(0,1), -1f0) == @interval(-1,0) + @test copysign(@interval(0,1), -BigFloat(1)) == @interval(-1,0) + @test copysign(@interval(0,1), UInt64(1)) == @interval(0,1) + @test copysign(@interval(-1),@interval(-1)) == @interval(-1) + @test copysign(@interval(-2,2), 2) == @interval(0,2) + @test flipsign(@interval(1,2), @interval(-1,1)) == @interval(-2,2) + @test flipsign(@interval(1,2), @interval(1,2)) == @interval(1,2) + @test flipsign(3, @interval(-1,1)) == @interval(-3,3) + @test flipsign(3.0, @interval(-1,1)) == @interval(-3,3) + @test flipsign(3f0, @interval(-1,1)) == @interval(-3,3) + @test flipsign(3, @interval(0,1)) == @interval(3,3) == @interval(flipsign(3,0),flipsign(3,1)) + @test flipsign(3, @interval(-1,0)) == @interval(-3,3) == @interval(flipsign(3,-1),flipsign(3,0)) + @test flipsign(UInt64(3), @interval(-1,1)) == @interval(-3,3) + @test flipsign(BigFloat(3), @interval(-1,1)) == @interval(-3,3) + @test flipsign(@interval(0,1), -1) == @interval(-1,0) + @test flipsign(@interval(0,1), -1.0) == @interval(-1,0) + @test flipsign(@interval(0,1), -1f0) == @interval(-1,0) + @test flipsign(@interval(0,1), -BigFloat(1)) == @interval(-1,0) + @test flipsign(@interval(0,1), UInt64(1)) == @interval(0,1) + @test flipsign(@interval(-1),@interval(-1)) == @interval(1) @test trunc(@interval(0.1, 1.1)) == Interval(0.0, 1.0) @test round(@interval(0.1, 1.1), RoundToZero) == Interval(0.0, 1.0) @test round(@interval(0.1, 1.1)) == Interval(0.0, 1.0)