Skip to content

Commit 249040d

Browse files
authored
Merge pull request #525 from petvana/simplified-mod
Simplified version of mod(x::Interval, y::Real)
2 parents 4404658 + 7bef23e commit 249040d

File tree

3 files changed

+60
-0
lines changed

3 files changed

+60
-0
lines changed

src/IntervalArithmetic.jl

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import Base:
2222
in, zero, one, eps, typemin, typemax, abs, abs2, real, min, max,
2323
sqrt, exp, log, sin, cos, tan, cot, inv, cbrt, csc, hypot, sec,
2424
exp2, exp10, log2, log10,
25+
mod,
2526
asin, acos, atan,
2627
sinh, cosh, tanh, coth, csch, sech, asinh, acosh, atanh, sinpi, cospi,
2728
union, intersect, isempty,

src/intervals/functions.jl

+18
Original file line numberDiff line numberDiff line change
@@ -373,3 +373,21 @@ function nthroot(a::Interval{T}, n::Integer) where T
373373
b = nthroot(bigequiv(a), n)
374374
return convert(Interval{T}, b)
375375
end
376+
377+
"""
378+
Calculate `x::Interval mod y::Real` where y != zero(y) and y is not inteval`.
379+
"""
380+
function mod(x::Interval, y::Real)
381+
@assert y != zero(y) """mod(x::Interval, y::Real)
382+
is currently implemented only for a strictly positive or negative divisor y."""
383+
division = x / y
384+
fl = floor(division)
385+
if !isthin(fl)
386+
return y > zero(y) ? Interval(zero(y), y) : Interval(y, zero(y))
387+
else
388+
return y * (division - fl)
389+
end
390+
end
391+
392+
mod(x::Interval, y::Interval) = throw(ArgumentError("mod not defined for interval as divisor `y`"))
393+
mod(x::Real, y::Interval) = throw(ArgumentError("mod not defined for interval as divisor `y`"))

test/interval_tests/numeric.jl

+41
Original file line numberDiff line numberDiff line change
@@ -434,3 +434,44 @@ end
434434
@test nthroot(Interval{BigFloat}(-81, -16), -4) ==
435435
@test nthroot(Interval{BigFloat}(-81, -16), 1) == Interval{BigFloat}(-81, -16)
436436
end
437+
438+
# approximation used for testing (not to rely on ≈ for intervals)
439+
# ⪆(x, y) = (x ≈ y) && (x ⊇ y)
440+
(x::Interval, y::Interval) = x.lo y.lo && x.hi y.hi && x y
441+
442+
@testset "`mod`" begin
443+
r = 0.0625
444+
x = r..(1+r)
445+
@test mod(x, 1) == mod(x, 1.0) == 0..1
446+
@test mod(x, 2) == mod(x, 2.0) x
447+
@test mod(x, 2.5) x
448+
@test mod(x, 0.5) == 0..0.5
449+
@test mod(x, -1) == mod(x, -1.0) == -1..0
450+
@test mod(x, -2) == mod(x, -2.0) -2+x
451+
@test mod(x, -2.5) -2.5+x
452+
@test mod(x, -0.5) == -0.5..0
453+
454+
x = (-1+r) .. -r
455+
@test mod(x, 1) == mod(x, 1.0) 1+x
456+
@test mod(x, 2) == mod(x, 2.0) 2+x
457+
@test mod(x, 2.5) 2.5+x
458+
@test mod(x, 0.5) == 0..0.5
459+
@test mod(x, -1) == mod(x, -1.0) x
460+
@test mod(x, -2) == mod(x, -2.0) x
461+
@test mod(x, -2.5) x
462+
@test mod(x, -0.5) == -0.5..0
463+
464+
x = -r .. 1-r
465+
@test mod(x, 1) == mod(x, 1.0) == 0..1
466+
@test mod(x, 2) == mod(x, 2.0) == 0..2
467+
@test mod(x, 2.5) == 0..2.5
468+
@test mod(x, 0.5) == 0..0.5
469+
@test mod(x, -1) == mod(x, -1.0) == -1..0
470+
@test mod(x, -2) == mod(x, -2.0) == -2..0
471+
@test mod(x, -2.5) == -2.5..0
472+
@test mod(x, -0.5) == -0.5..0
473+
474+
# TODO - implement mod for two intervals
475+
@test_throws ArgumentError mod(1..2, 1.4..1.5)
476+
@test_throws ArgumentError mod(1.0, 1.4..1.5)
477+
end

0 commit comments

Comments
 (0)