Skip to content

Commit

Permalink
Make append! and push! definitions more generic (#32065)
Browse files Browse the repository at this point in the history
Some methods for append! and push! for Array actually work for any AbstractArray
since they only use resize!, setindex! and push!. Broaden the signatures
so that custom array types do not need to copy definitions from Base.

BitArray uses special methods, one of which was apparently not covered by tests.
  • Loading branch information
nalimilan authored and JeffBezanson committed May 21, 2019
1 parent b21d39d commit 62a0a3f
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 4 deletions.
8 changes: 4 additions & 4 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -896,14 +896,14 @@ function append!(a::Vector, items::AbstractVector)
return a
end

append!(a::Vector, iter) = _append!(a, IteratorSize(iter), iter)
push!(a::Vector, iter...) = append!(a, iter)
append!(a::AbstractVector, iter) = _append!(a, IteratorSize(iter), iter)
push!(a::AbstractVector, iter...) = append!(a, iter)

function _append!(a, ::Union{HasLength,HasShape}, iter)
require_one_based_indexing(a)
n = length(a)
i = lastindex(a)
resize!(a, n+length(iter))
@inbounds for (i,item) in zip(n+1:length(a), iter)
@inbounds for (i, item) in zip(i+1:lastindex(a), iter)
a[i] = item
end
a
Expand Down
9 changes: 9 additions & 0 deletions test/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -553,9 +553,18 @@ timesofar("indexing")
b2 = bitrand(m2)
i1 = Array(b1)
i2 = Array(b2)
# Append from array
@test isequal(Array(append!(b1, b2)), append!(i1, i2))
@test isequal(Array(append!(b1, i2)), append!(i1, b2))
@test bitcheck(b1)
# Append from HasLength iterator
@test isequal(Array(append!(b1, (v for v in b2))), append!(i1, i2))
@test isequal(Array(append!(b1, (v for v in i2))), append!(i1, b2))
@test bitcheck(b1)
# Append from SizeUnknown iterator
@test isequal(Array(append!(b1, (v for v in b2 if true))), append!(i1, i2))
@test isequal(Array(append!(b1, (v for v in i2 if true))), append!(i1, b2))
@test bitcheck(b1)
end

for m1 = 0:v1, m2 = [0, 1, 63, 64, 65, 127, 128, 129]
Expand Down
28 changes: 28 additions & 0 deletions test/offsetarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,34 @@ a = OffsetArray(a0, (-1,2,3,4,5))
@test_throws ArgumentError dropdims(a, dims=4)
@test_throws ArgumentError dropdims(a, dims=6)

# push!
v = OffsetArray(rand(4), (-3,))
v2 = copy(v)
@test push!(v2, 1) === v2
@test v2[axes(v, 1)] == v
@test v2[end] == 1
v2 = copy(v)
@test push!(v2, 2, 1) === v2
@test v2[axes(v, 1)] == v
@test v2[end-1] == 2
@test v2[end] == 1

# append! from array
v2 = copy(v)
@test append!(v2, [2, 1]) === v2
@test v2[axes(v, 1)] == v
@test v2[lastindex(v)+1:end] == [2, 1]
# append! from HasLength iterator
v2 = copy(v)
@test append!(v2, (v for v in [2, 1])) === v2
@test v2[axes(v, 1)] == v
@test v2[lastindex(v)+1:end] == [2, 1]
# append! from SizeUnknown iterator
v2 = copy(v)
@test append!(v2, (v for v in [2, 1] if true)) === v2
@test v2[axes(v, 1)] == v
@test v2[lastindex(v)+1:end] == [2, 1]

# other functions
v = OffsetArray(v0, (-3,))
@test lastindex(v) == 1
Expand Down
8 changes: 8 additions & 0 deletions test/testhelpers/OffsetArrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ end
@inbounds deleteat!(parent(A), first_idx:last_idx)
end

function Base.push!(a::OffsetArray{T,1}, item) where T
# convert first so we don't grow the array if the assignment won't work
itemT = convert(T, item)
resize!(a, length(a)+1)
a[end] = itemT
return a
end

# Computing a shifted index (subtracting the offset)
offset(offsets::NTuple{N,Int}, inds::NTuple{N,Int}) where {N} = _offset((), offsets, inds)
_offset(out, ::Tuple{}, ::Tuple{}) = out
Expand Down

0 comments on commit 62a0a3f

Please sign in to comment.