Skip to content
1 change: 1 addition & 0 deletions src/IntervalArithmetic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import Base:
in, zero, one, eps, typemin, typemax, abs, abs2, real, min, max,
sqrt, exp, log, sin, cos, tan, cot, inv, cbrt, csc, hypot, sec,
exp2, exp10, log2, log10,
mod,
asin, acos, atan,
sinh, cosh, tanh, coth, csch, sech, asinh, acosh, atanh, sinpi, cospi,
union, intersect, isempty,
Expand Down
10 changes: 10 additions & 0 deletions src/intervals/functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -373,3 +373,13 @@ function nthroot(a::Interval{T}, n::Integer) where T
b = nthroot(bigequiv(a), n)
return convert(Interval{T}, b)
end

"""
Calculate `x mod y` where `x` is an interval and `y` is a positive divisor.
"""
function mod(x::Interval, y::Real)
@assert y > 0 "modulo is currently implemented only for a positive divisor."
division = x / y
fl = floor(division)
fl.lo < fl.hi ? 0..y : y * (division - fl)
end
25 changes: 25 additions & 0 deletions test/interval_tests/numeric.jl
Original file line number Diff line number Diff line change
Expand Up @@ -434,3 +434,28 @@ end
@test nthroot(Interval{BigFloat}(-81, -16), -4) == ∅
@test nthroot(Interval{BigFloat}(-81, -16), 1) == Interval{BigFloat}(-81, -16)
end

# approximation used for testing (not to rely on ≈ for intervals)
# ⪆(x, y) = (x ≈ y) && (y ⊆ x)
⪆(x::Interval, y::Interval) = x.lo ≈ y.lo && x.hi ≈ y.hi && y ⊆ x

@testset "`mod`" begin
r = 0.0625
x = r..(1+r)
@test mod(x, 1) == mod(x, 1.0) == 0..1
@test mod(x, 2) == mod(x, 2.0) ⪆ x
@test mod(x, 2.5) ⪆ x
@test mod(x, 0.5) == 0..0.5

x = (-1+r) .. -r
@test mod(x, 1) == mod(x, 1.0) ⪆ 1+x
@test mod(x, 2) == mod(x, 2.0) ⪆ 2+x
@test mod(x, 2.5) ⪆ 2.5+x
@test mod(x, 0.5) == 0..0.5

x = -r .. 1-r
@test mod(x, 1) == mod(x, 1.0) == 0..1
@test mod(x, 2) == mod(x, 2.0) == 0..2
@test mod(x, 2.5) == 0..2.5
@test mod(x, 0.5) == 0..0.5
end