Skip to content

Commit

Permalink
Merge pull request JuliaLang#5176 from JuliaLang/kms/delindex
Browse files Browse the repository at this point in the history
Implementation of deleteat! (Fixes JuliaLang#5118)
  • Loading branch information
StefanKarpinski committed Jan 22, 2014
2 parents 514eb69 + fc15701 commit 7b82845
Show file tree
Hide file tree
Showing 7 changed files with 289 additions and 72 deletions.
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ Library improvements

* LU factorization ([#5381] and [#5430])

* New function `deleteat!` deletes a specified index or indices and
returns the updated collection

Deprecated or removed
---------------------

Expand Down
174 changes: 118 additions & 56 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,65 @@ setindex!(A::Array, X::AbstractArray, I::AbstractArray{Bool}) = assign_bool_vect
setindex!(A::Array, x, I::AbstractVector{Bool}) = assign_bool_scalar_1d!(A, x, I)
setindex!(A::Array, x, I::AbstractArray{Bool}) = assign_bool_scalar_1d!(A, x, I)

# efficiently grow an array

function _growat!(a::Vector, i::Integer, delta::Integer)
n = length(a)
if i < div(n,2)
_growat_beg!(a, i, delta)
else
_growat_end!(a, i, delta)
end
return a
end

function _growat_beg!(a::Vector, i::Integer, delta::Integer)
ccall(:jl_array_grow_beg, Void, (Any, Uint), a, delta)
@inbounds for k = 1:i-1
a[k] = a[k+delta]
end
return a
end

function _growat_end!(a::Vector, i::Integer, delta::Integer)
ccall(:jl_array_grow_end, Void, (Any, Uint), a, delta)
n = length(a)
@inbounds for k = n:-1:(i+delta)
a[k] = a[k-delta]
end
return a
end

# efficiently delete part of an array

function _deleteat!(a::Vector, i::Integer, delta::Integer)
n = length(a)
last = i+delta-1
if i-1 < n-last
_deleteat_beg!(a, i, delta)
else
_deleteat_end!(a, i, delta)
end
return a
end

function _deleteat_beg!(a::Vector, i::Integer, delta::Integer)
@inbounds for k = i+delta-1:-1:1+delta
a[k] = a[k-delta]
end
ccall(:jl_array_del_beg, Void, (Any, Uint), a, delta)
return a
end

function _deleteat_end!(a::Vector, i::Integer, delta::Integer)
n = length(a)
@inbounds for k = i:n-delta
a[k] = a[k+delta]
end
ccall(:jl_array_del_end, Void, (Any, Uint), a, delta)
return a
end

## Dequeue functionality ##

const _grow_none_errmsg =
Expand Down Expand Up @@ -512,56 +571,67 @@ function insert!{T}(a::Array{T,1}, i::Integer, item)
n = length(a)
if i > n
ccall(:jl_array_grow_end, Void, (Any, Uint), a, i-n)
elseif i > div(n,2)
ccall(:jl_array_grow_end, Void, (Any, Uint), a, 1)
for k=n+1:-1:i+1
a[k] = a[k-1]
end
else
ccall(:jl_array_grow_beg, Void, (Any, Uint), a, 1)
for k=1:(i-1)
a[k] = a[k+1]
end
_growat!(a, i, 1)
end
a[i] = item
return a
end

const _default_splice = []
function deleteat!(a::Vector, i::Integer)
if !(1 <= i <= length(a))
throw(BoundsError())
end
return _deleteat!(a, i, 1)
end

function splice!(a::Vector, i::Integer, ins::AbstractArray=_default_splice)
function deleteat!{T<:Integer}(a::Vector, r::Range1{T})
n = length(a)
if !(1 <= i <= n)
f = first(r)
l = last(r)
if !(1 <= f && l <= n)
throw(BoundsError())
end
return _deleteat!(a, f, length(r))
end

function deleteat!(a::Vector, inds)
n = length(a)
s = start(inds)
done(inds, s) && return a
(p, s) = next(inds, s)
q = p+1
while !done(inds, s)
(i,s) = next(inds, s)
if !(q <= i <= n)
i < q && error("indices must be unique and sorted")
throw(BoundsError())
end
while q < i
@inbounds a[p] = a[q]
p += 1; q += 1
end
q = i+1
end
while q <= n
@inbounds a[p] = a[q]
p += 1; q += 1
end
ccall(:jl_array_del_end, Void, (Any, Uint), a, n-p+1)
return a
end

const _default_splice = []

function splice!(a::Vector, i::Integer, ins::AbstractArray=_default_splice)
v = a[i]
m = length(ins)
if m == 0
if i < div(n,2)
for k = i:-1:2
a[k] = a[k-1]
end
ccall(:jl_array_del_beg, Void, (Any, Uint), a, 1)
else
for k = i:n-1
a[k] = a[k+1]
end
ccall(:jl_array_del_end, Void, (Any, Uint), a, 1)
end
_deleteat!(a, i, 1)
elseif m == 1
a[i] = ins[1]
else
if i < div(n,2)
ccall(:jl_array_grow_beg, Void, (Any, Uint), a, m-1)
for k = 1:i-1
a[k] = a[k+m-1]
end
else
ccall(:jl_array_grow_end, Void, (Any, Uint), a, m-1)
for k = n+m-1:-1:(i+1+(m-1))
a[k] = a[k-(m-1)]
end
end
_growat!(a, i, m-1)
for k = 1:m
a[i+k-1] = ins[k]
end
Expand All @@ -570,42 +640,34 @@ function splice!(a::Vector, i::Integer, ins::AbstractArray=_default_splice)
end

function splice!{T<:Integer}(a::Vector, r::Range1{T}, ins::AbstractArray=_default_splice)
v = a[r]
m = length(ins)
if m == 0
deleteat!(a, r)
return v
end

n = length(a)
f = first(r)
l = last(r)
if !(1 <= f && l <= n)
throw(BoundsError())
end
d = l-f+1
v = a[r]
m = length(ins)
d = length(r)

if m < d
delta = d - m
if f-1 < n-l
for k = l:-1:1+delta
a[k] = a[k-delta]
end
ccall(:jl_array_del_beg, Void, (Any, Uint), a, delta)
_deleteat_beg!(a, f, delta)
else
for k = f:n-delta
a[k] = a[k+delta]
end
ccall(:jl_array_del_end, Void, (Any, Uint), a, delta)
_deleteat_end!(a, l-delta+1, delta)
end
elseif m > d
delta = m - d
if f-1 < n-l
ccall(:jl_array_grow_beg, Void, (Any, Uint), a, delta)
for k = 1:f-1
a[k] = a[k+delta]
end
_growat_beg!(a, f, delta)
else
ccall(:jl_array_grow_end, Void, (Any, Uint), a, delta)
for k = n+delta:-1:(l+1+delta)
a[k] = a[k-delta]
end
_growat_end!(a, l+1, delta)
end
end

for k = 1:m
a[f+k-1] = ins[k]
end
Expand Down
99 changes: 91 additions & 8 deletions base/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -825,12 +825,7 @@ function insert!(B::BitVector, i::Integer, item)
B[i] = item
end

function splice!(B::BitVector, i::Integer)
n = length(B)
if !(1 <= i <= n)
throw(BoundsError())
end
v = B[i]
function _deleteat!(B::BitVector, i::Integer)

k, j = get_chunks_id(i)

Expand Down Expand Up @@ -861,6 +856,91 @@ function splice!(B::BitVector, i::Integer)

B.len -= 1

return B
end

function deleteat!(B::BitVector, i::Integer)
n = length(B)
if !(1 <= i <= n)
throw(BoundsError())
end

return _deleteat!(B, i)
end

function deleteat!(B::BitVector, r::Range1{Int})
n = length(B)
i_f = first(r)
i_l = last(r)
if !(1 <= i_f && i_l <= n)
throw(BoundsError())
end

Bc = B.chunks
new_l = length(B) - length(r)
delta_k = num_bit_chunks(new_l) - length(Bc)

copy_chunks(Bc, i_f, Bc, i_l+1, n-i_l)

if delta_k < 0
ccall(:jl_array_del_end, Void, (Any, Uint), Bc, -delta_k)
end

B.len = new_l

if new_l > 0
Bc[end] &= @_msk_end new_l
end

return B
end

function deleteat!(B::BitVector, inds)
n = new_l = length(B)
s = start(inds)
done(inds, s) && return B

Bc = B.chunks

(p, s) = next(inds, s)
q = p+1
new_l -= 1
while !done(inds, s)
(i,s) = next(inds, s)
if !(q <= i <= n)
i < q && error("indices must be unique and sorted")
throw(BoundsError())
end
new_l -= 1
if i > q
copy_chunks(Bc, p, Bc, q, i-q)
p += i-q
end
q = i+1
end

q <= n && copy_chunks(Bc, p, Bc, q, n-q+1)

delta_k = num_bit_chunks(new_l) - length(Bc)
delta_k < 0 && ccall(:jl_array_del_end, Void, (Any, Uint), Bc, -delta_k)

B.len = new_l

if new_l > 0
Bc[end] &= @_msk_end new_l
end

return B
end

function splice!(B::BitVector, i::Integer)
n = length(B)
if !(1 <= i <= n)
throw(BoundsError())
end

v = B[i] # TODO: change to a copy if/when subscripting becomes an ArrayView
_deleteat!(B, i)
return v
end
splice!(B::BitVector, i::Integer, ins::BitVector) = splice!(B, int(i):int(i), ins)
Expand All @@ -879,9 +959,12 @@ function splice!(B::BitVector, r::Range1{Int}, ins::BitVector = _default_bit_spl
throw(BoundsError())
end
if (i_f > n)
return append!(B, ins)
append!(B, ins)
return BitVector(0)
end

v = B[r] # TODO: change to a copy if/when subscripting becomes an ArrayView

Bc = B.chunks

lins = length(ins)
Expand All @@ -905,7 +988,7 @@ function splice!(B::BitVector, r::Range1{Int}, ins::BitVector = _default_bit_spl
Bc[end] &= @_msk_end new_l
end

return B
return v
end
splice!(B::BitVector, r::Range1{Int}, ins::AbstractVector{Bool}) = splice!(B, r, bitpack(ins))

Expand Down
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,7 @@ export
contains,
count,
delete!,
deleteat!,
eltype,
empty!,
endof,
Expand Down
10 changes: 10 additions & 0 deletions doc/stdlib/base.rst
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,16 @@ Dequeues

Insert an item at the given index.

.. function:: deleteat!(collection, index)

Remove the item at the given index, and return the modified collection. Subsequent items
are shifted to fill the resulting gap.

.. function:: deleteat!(collection, itr)

Remove the items at the indices given by `itr`, and return the modified collection. Subsequent
items are shifted to fill the resulting gap. `itr` must be sorted and unique.

.. function:: splice!(collection, index, [replacement]) -> item

Remove the item at the given index, and return the removed item. Subsequent items
Expand Down
Loading

0 comments on commit 7b82845

Please sign in to comment.