diff --git a/base/abstractarraymath.jl b/base/abstractarraymath.jl index 7fc7a868187a3c..a924a083eddd9e 100644 --- a/base/abstractarraymath.jl +++ b/base/abstractarraymath.jl @@ -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] diff --git a/base/deprecated.jl b/base/deprecated.jl index 8bcf077b5c6e38..9879c934bbc320 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -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 diff --git a/base/docs/helpdb.jl b/base/docs/helpdb.jl index 31774c438daf4d..e4ee5eaf2fb78b 100644 --- a/base/docs/helpdb.jl +++ b/base/docs/helpdb.jl @@ -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,m)*m + rem(x,m) """ rem @@ -8305,6 +8307,8 @@ doc""" mod(x, y) Modulus after 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 @@ -8460,13 +8464,31 @@ Matrix inverse """ inv +doc""" + 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] diff --git a/base/exports.jl b/base/exports.jl index 4e224daded8000..e1d999b6369250 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -357,7 +357,9 @@ export factor, factorial, fld, + fld1, fldmod, + fldmod1, flipsign, float, tryparse, diff --git a/base/operators.jl b/base/operators.jl index 10e5a5982abef8..796090e13aee92 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -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 diff --git a/doc/stdlib/math.rst b/doc/stdlib/math.rst index a9bb3d784ac7b9..ff037f0d9192a8 100644 --- a/doc/stdlib/math.rst +++ b/doc/stdlib/math.rst @@ -137,6 +137,10 @@ Mathematical Operators Modulus after 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) .. Docstring generated from Julia source @@ -152,6 +156,10 @@ 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,m)*m + rem(x,m) + .. function:: divrem(x, y) .. Docstring generated from Julia source @@ -164,11 +172,29 @@ Mathematical Operators 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) diff --git a/test/numbers.jl b/test/numbers.jl index db0222a942fac8..ef332a16181f0c 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -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 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]