Skip to content

Commit

Permalink
Clean up mod1
Browse files Browse the repository at this point in the history
Implement fld1 and fldmod1.
Add test cases.
Deprecate rem1.
Simplify (the only) use case in Base.
Update documentation.
  • Loading branch information
eschnett committed Dec 3, 2015
1 parent 9eb74d4 commit 8505211
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 15 deletions.
4 changes: 1 addition & 3 deletions base/abstractarraymath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,7 @@ function repeat{T}(A::Array{T};
# "Project" outer repetitions into inner repetitions
indices_in[t] = mod1(indices_out[t], inner_size_out[t])
# Find inner repetitions using flooring division
if inner[t] != 1
indices_in[t] = fld1(indices_in[t], inner[t])
end
indices_in[t] = fld1(indices_in[t], inner[t])
end
index_in = sub2ind(size_in, indices_in...)
R[index_out] = A[index_in]
Expand Down
9 changes: 9 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,15 @@ end
@deprecate chol(A::Number, ::Type{Val{:L}}) ctranspose(chol(A))
@deprecate chol(A::AbstractMatrix, ::Type{Val{:L}}) ctranspose(chol(A))

# Number updates

# rem1 is inconsistent for x==0: The result should both have the same
# sign as x, and should be non-zero.
function rem1{T<:Real}(x::T, y::T)
depwarn("`rem1(x,y)` is discontinued, as it cannot be defined consistently for `x==0`. Rewrite the expression using `mod1` instead.", :rem1)
rem(x-1,y)+1
end

# Filesystem module updates

@deprecate_binding FS Filesystem
Expand Down
34 changes: 28 additions & 6 deletions base/docs/helpdb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3265,7 +3265,7 @@ tril!(M, k)
doc"""
divrem(x, y)
The quotient and remainder from Euclidean division. Equivalent to `(x÷y, x%y)`.
The quotient and remainder from Euclidean division. Equivalent to `div(x,y), rem(x,y))` or `(x÷y, x%y)`.
"""
divrem

Expand Down Expand Up @@ -5266,6 +5266,8 @@ doc"""
%(x, y)
Remainder from Euclidean division, returning a value of the same sign as `x`, and smaller in magnitude than `y`. This value is always exact.
x == div(x,y)*y + rem(x,y)
"""
rem

Expand Down Expand Up @@ -5666,9 +5668,9 @@ The distance between `x` and the next larger representable floating-point value
eps(::AbstractFloat)

doc"""
rem1(x,m)
rem1(x, m)
Remainder after division, returning in the range (0,m\]
(Deprecated.) Remainder after division, returning in the range `(0,m\]`
"""
rem1

Expand Down Expand Up @@ -8304,7 +8306,9 @@ procs(::SharedArray)
doc"""
mod(x, y)
Modulus after division, returning in the range \[0,`y`), if `y` is positive, or (`y`,0\] if `y` is negative.
Modulus after flooring division, returning in the range \[0,`y`), if `y` is positive, or (`y`,0\] if `y` is negative.
x == fld(x,m)*m + mod(x,m)
"""
mod

Expand Down Expand Up @@ -8461,12 +8465,30 @@ Matrix inverse
inv

doc"""
mod1(x,m)
fld1(x, m)
Flooring division, returning a value consistent with `mod1(x,m)`
x == fld(x,m)*m + mod(x,m)
x == (fld1(x,m)-1)*m + mod1(x,m)
"""
fld1

doc"""
mod1(x, m)
Modulus after division, returning in the range (0,m\]
Modulus after flooring division, returning a value in the range `(0,m\]`
"""
mod1

doc"""
fldmod1(x, m)
Return `(fld1(x,m), mod1(x,m))`
"""
fldmod1

doc"""
@assert cond [text]
Expand Down
2 changes: 2 additions & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,9 @@ export
factor,
factorial,
fld,
fld1,
fldmod,
fldmod1,
flipsign,
float,
tryparse,
Expand Down
11 changes: 8 additions & 3 deletions base/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,15 @@ const % = rem
.%(x::Real, y::Real) = x%y
const ÷ = div

# mod returns in [0,y) whereas mod1 returns in (0,y]
# mod returns in [0,y) or (y,0] (for negative y),
# whereas mod1 returns in (0,y] or [y,0)
mod1{T<:Real}(x::T, y::T) = (m=mod(x,y); ifelse(m==0, y, m))
rem1{T<:Real}(x::T, y::T) = rem(x-1,y)+1
fld1{T<:Real}(x::T, y::T) = fld(x-1,y)+1
fld1{T<:Real}(x::T, y::T) = (m=mod(x,y); fld(x-m,y))
fldmod1{T<:Real}(x::T, y::T) = (fld1(x,y), mod1(x,y))
# efficient version for integers
mod1{T<:Integer}(x::T, y::T) = mod(x+y-T(1),y)+T(1)
fld1{T<:Integer}(x::T, y::T) = fld(x+y-T(1),y)
fldmod1{T<:Integer}(x::T, y::T) = (fld1(x,y), mod1(x,y))

# transpose
transpose(x) = x
Expand Down
32 changes: 29 additions & 3 deletions doc/stdlib/math.rst
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,11 @@ Mathematical Operators

.. Docstring generated from Julia source
Modulus after division, returning in the range [0,``y``\ ), if ``y`` is positive, or (``y``\ ,0] if ``y`` is negative.
Modulus after flooring division, returning in the range [0,``y``\ ), if ``y`` is positive, or (``y``\ ,0] if ``y`` is negative.

.. code-block:: julia
x == fld(x,m)*m + mod(x,m)
.. function:: mod2pi(x)

Expand All @@ -152,23 +156,45 @@ Mathematical Operators
Remainder from Euclidean division, returning a value of the same sign as ``x``\ , and smaller in magnitude than ``y``\ . This value is always exact.

.. code-block:: julia
x == div(x,y)*y + rem(x,y)
.. function:: divrem(x, y)

.. Docstring generated from Julia source
The quotient and remainder from Euclidean division. Equivalent to ``(x÷y, x%y)``\ .
The quotient and remainder from Euclidean division. Equivalent to ``div(x,y), rem(x,y))`` or ``(x÷y, x%y)``\ .

.. function:: fldmod(x, y)

.. Docstring generated from Julia source
The floored quotient and modulus after division. Equivalent to ``(fld(x,y), mod(x,y))``\ .

.. function:: fld1(x,m)

.. Docstring generated from Julia source
Flooring division, returning a value consistent with mod1(x,m)

.. code-block:: julia
x == fld(x,m)*m + mod(x,m)
x == (fld1(x,m)-1)*m + mod1(x,m)
.. function:: mod1(x,m)

.. Docstring generated from Julia source
Modulus after division, returning in the range (0,m]
Modulus after flooring division, returning a value in the range (0,m]

.. function:: fldmod1(x,m)

.. Docstring generated from Julia source
Return (fld1(x,m), mod1(x,m))

.. function:: rem1(x,m)

Expand Down
3 changes: 3 additions & 0 deletions test/numbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2530,6 +2530,9 @@ end
# test second branch, after all small primes in list have been searched
@test factor(10009 * Int128(1000000000000037)) == Dict(10009=>1,1000000000000037=>1)

@test all(x -> (m=mod1(x,3); 0<m<=3), -5:+5)
@test all(x -> x == (fld1(x,3)-1)*3 + mod1(x,3), -5:+5)
@test all(x -> fldmod1(x,3) == (fld1(x,3), mod1(x,3)), -5:+5)
#Issue #5570
@test map(x -> Int(mod1(UInt(x),UInt(5))), 0:15) == [5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]

Expand Down

0 comments on commit 8505211

Please sign in to comment.