Skip to content

Commit

Permalink
Add Compat.repeat() accepting any AbstractArray
Browse files Browse the repository at this point in the history
Compatibility for JuliaLang/julia#14082. Since the new version in
Julia 0.5 calls similar() internally, it is not enough to wrap it
into a compatibility function to backport the fix. This is required
to deprecate rep() from DataArrays.jl, which provides similar
functionality for two custom array types.
  • Loading branch information
nalimilan committed May 25, 2016
1 parent 8ddd0a8 commit 4bc89f2
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ Currently, the `@compat` macro supports the following syntaxes:
Compat provides an unexported `Compat.AsyncCondition` type that is aliased to
`Base.SingleAsyncWork` on Julia 0.3 and 0.4 and `Base.AsyncCondition` on Julia 0.5.

* `repeat` now accepts any `AbstractArray` [#14082](https://github.com/JuliaLang/julia/pull/14082): `Compat.repeat` supports this new API on Julia 0.3 and 0.4, and calls `Base.repeat` on 0.5.

## New types

* [`Nullable` types](http://julia.readthedocs.org/en/latest/manual/types/?highlight=nullable#nullable-types-representing-missing-values) and their associated operations.
Expand Down
45 changes: 45 additions & 0 deletions src/Compat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1157,4 +1157,49 @@ if !isdefined(Base, @compat Symbol("@static"))
export @static
end

# JuliaLang/julia#14082
if VERSION < v"0.5.0-dev+4295"
function repeat(A::AbstractArray;
inner=ntuple(x->1, ndims(A)),
outer=ntuple(x->1, ndims(A)))
ndims_in = ndims(A)
length_inner = length(inner)
length_outer = length(outer)

length_inner >= ndims_in || throw(ArgumentError("number of inner repetitions ($(length(inner))) cannot be less than number of dimensions of input ($(ndims(A)))"))
length_outer >= ndims_in || throw(ArgumentError("number of outer repetitions ($(length(outer))) cannot be less than number of dimensions of input ($(ndims(A)))"))

ndims_out = max(ndims_in, length_inner, length_outer)

inner = vcat(collect(inner), ones(Int,ndims_out-length_inner))
outer = vcat(collect(outer), ones(Int,ndims_out-length_outer))

size_in = size(A)
size_out = ntuple(i->inner[i]*size(A,i)*outer[i],ndims_out)::Dims
inner_size_out = ntuple(i->inner[i]*size(A,i),ndims_out)::Dims

indices_in = Array(Int, ndims_in)
indices_out = Array(Int, ndims_out)

length_out = prod(size_out)
R = similar(A, size_out)

for index_out in 1:length_out
indices_out = ind2sub(size_out, index_out)
for t in 1:ndims_in
# "Project" outer repetitions into inner repetitions
indices_in[t] = mod1(indices_out[t], inner_size_out[t])
# Find inner repetitions using flooring division
indices_in[t] = Base.fld1(indices_in[t], inner[t])
end
index_in = sub2ind(size_in, indices_in...)
R[index_out] = A[index_in]
end

return R
end
else
const repeat = Base.repeat
end

end # module
4 changes: 4 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1164,3 +1164,7 @@ let io = IOBuffer(), s = "hello"
@test string(s, s, s) == "hellohellohello"
@test String == @compat(Union{Compat.UTF8String,Compat.ASCIIString})
end

@test Compat.repeat(1:2, inner=2) == [1, 1, 2, 2]
@test Compat.repeat(1:2, outer=[2]) == [1, 2, 1, 2]
@test Compat.repeat([1,2], inner=(2,)) == [1, 1, 2, 2]

0 comments on commit 4bc89f2

Please sign in to comment.