Skip to content

Commit 2182389

Browse files
mcabbottmbauman
authored andcommitted
mod(n, range) for integers (#32628)
`mod` now accepts a unit range as the second argument to easily perform offset modular arithmetic to ensure the result is inside the range
1 parent 9daaed6 commit 2182389

File tree

3 files changed

+39
-1
lines changed

3 files changed

+39
-1
lines changed

NEWS.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ Standard library changes
4747
when operating over zero-dimensional arrays ([#32122]).
4848
* `IPAddr` subtypes now behave like scalars when used in broadcasting ([#32133]).
4949
* `clamp` can now handle missing values ([#31066]).
50-
* `empty` now accepts a `NamedTuple` ([#32534])
50+
* `empty` now accepts a `NamedTuple` ([#32534]).
51+
* `mod` now accepts a unit range as the second argument to easily perform offset modular arithmetic to ensure the result is inside the range ([#32628]).
5152

5253
#### Libdl
5354

base/range.jl

+22
Original file line numberDiff line numberDiff line change
@@ -1038,3 +1038,25 @@ function +(r1::StepRangeLen{T,S}, r2::StepRangeLen{T,S}) where {T,S}
10381038
end
10391039

10401040
-(r1::StepRangeLen, r2::StepRangeLen) = +(r1, -r2)
1041+
1042+
# Modular arithmetic on ranges
1043+
1044+
"""
1045+
mod(x::Integer, r::AbstractUnitRange)
1046+
1047+
Find `y` in the range `r` such that ``x ≡ y (mod n)``, where `n = length(r)`,
1048+
i.e. `y = mod(x - first(r), n) + first(r)`.
1049+
1050+
See also: [`mod1`](@ref).
1051+
1052+
# Examples
1053+
```jldoctest
1054+
julia> mod(0, Base.OneTo(3))
1055+
3
1056+
1057+
julia> mod(3, 0:2)
1058+
0
1059+
```
1060+
"""
1061+
mod(i::Integer, r::OneTo) = mod1(i, last(r))
1062+
mod(i::Integer, r::AbstractUnitRange{<:Integer}) = mod(i-first(r), length(r)) + first(r)

test/ranges.jl

+15
Original file line numberDiff line numberDiff line change
@@ -1519,3 +1519,18 @@ end
15191519
@test range(1, step = big(1.0), length=10) == big(1.0):1:10
15201520
@test range(1.0, step = big(1.0), length=10) == big(1.0):1:10
15211521
end
1522+
1523+
@testset "mod with ranges" begin
1524+
for n in -10:10
1525+
@test mod(n, 0:4) == mod(n, 5)
1526+
@test mod(n, 1:5) == mod1(n, 5)
1527+
@test mod(n, 2:6) == 2 + mod(n-2, 5)
1528+
@test mod(n, Base.OneTo(5)) == mod1(n, 5)
1529+
end
1530+
@test mod(Int32(3), 1:5) == 3
1531+
@test mod(big(typemax(Int))+99, 0:4) == mod(big(typemax(Int))+99, 5)
1532+
@test_throws MethodError mod(3.141, 1:5)
1533+
@test_throws MethodError mod(3, UnitRange(1.0,5.0))
1534+
@test_throws MethodError mod(3, 1:2:7)
1535+
@test_throws DivideError mod(3, 1:0)
1536+
end

0 commit comments

Comments
 (0)