@@ -2,7 +2,7 @@ module IntervalSets
22
33using Base: @pure
44import Base: eltype, convert, show, in, length, isempty, isequal, issubset, == , hash,
5- union, intersect, minimum, maximum, extrema, range, clamp, float, ⊇ , ⊊ , ⊋
5+ union, intersect, minimum, maximum, extrema, range, clamp, mod, float, ⊇ , ⊊ , ⊋
66
77using Statistics
88import Statistics: mean
@@ -229,6 +229,46 @@ Clamp the scalar `t` such that the result is in the interval `i`.
229229clamp (t, i:: TypedEndpointsInterval{:closed,:closed} ) =
230230 clamp (t, leftendpoint (i), rightendpoint (i))
231231
232+ """
233+ mod(x, i::AbstractInterval)
234+
235+ Find `y` in the `i` interval such that ``x ≡ y (mod w)``, where `w = width(i)`.
236+
237+ # Examples
238+
239+ ```jldoctest
240+ julia> I = 2.5..4.5;
241+
242+ julia> mod(3.0, I)
243+ 3.0
244+
245+ julia> mod(5.0, I)
246+ 3.0
247+
248+ julia> mod(2.5, I)
249+ 2.5
250+
251+ julia> mod(4.5, I) # (a in I) does not imply (a == mod(a, I)) for closed intervals
252+ 2.5
253+
254+ julia> mod(4.5, Interval{:open, :closed}(2.5, 4.5))
255+ 4.5
256+ ```
257+ """
258+ mod (x, i:: TypedEndpointsInterval{:closed,:closed} ) = mod (x - leftendpoint (i), width (i)) + leftendpoint (i)
259+
260+ function mod (x, i:: AbstractInterval )
261+ res = mod (x - leftendpoint (i), width (i)) + leftendpoint (i)
262+ if res == rightendpoint (i) && isrightopen (i)
263+ isleftclosed (i) && return oftype (res, leftendpoint (i))
264+ elseif res == leftendpoint (i) && isleftopen (i)
265+ isrightclosed (i) && return oftype (res, rightendpoint (i))
266+ else
267+ return res
268+ end
269+ throw (DomainError (x, " mod() result is an endpoint of the open interval $i " ))
270+ end
271+
232272include (" interval.jl" )
233273include (" findall.jl" )
234274
0 commit comments