diff --git a/base/array.jl b/base/array.jl index aafcfc182124b..36b604a2a7050 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1443,12 +1443,19 @@ function _prepend!(a::Vector, ::IteratorSize, iter) end """ - resize!(a::Vector, n::Integer) -> Vector + resize!(a::Vector, n::Integer; first::Bool=false) -> Vector Resize `a` to contain `n` elements. If `n` is smaller than the current collection length, the first `n` elements will be retained. If `n` is larger, the new elements are not guaranteed to be initialized. +If `first` is true, then the new elements are inserted at the start of the collection. In +this case, if `n` is smaller than the current collection length, the last `n` elements will +be retained. + +!!! compat "Julia 1.13" + The `first` argument was added in Julia 1.13. + # Examples ```jldoctest julia> resize!([6, 5, 4, 3, 2, 1], 3) @@ -1472,15 +1479,15 @@ julia> a[1:6] 1 ``` """ -function resize!(a::Vector, nl::Integer) +function resize!(a::Vector, nl::Integer; first::Bool=false) l = length(a) if nl > l - _growend!(a, nl-l) + first ? _growbeg!(a, nl-l) : _growend!(a, nl-l) elseif nl != l if nl < 0 _throw_argerror("new length must be ≥ 0") end - _deleteend!(a, l-nl) + first ? _deletebeg!(a, l-nl) : _deleteend!(a, l-nl) end return a end diff --git a/base/bitarray.jl b/base/bitarray.jl index 93fa48c56e379..1ea48b8630a30 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -811,21 +811,32 @@ function sizehint!(B::BitVector, sz::Integer) return B end -resize!(B::BitVector, n::Integer) = _resize_int!(B, Int(n)) -function _resize_int!(B::BitVector, n::Int) +resize!(B::BitVector, n::Integer; first::Bool=false) = _resize_int!(B, Int(n), first) +function _resize_int!(B::BitVector, n::Int, first::Bool) n0 = length(B) n == n0 && return B n >= 0 || throw(BoundsError(B, n)) if n < n0 - deleteat!(B, n+1:n0) + r = first ? (1:n0-n) : (n+1:n0) + deleteat!(B, r) return B end Bc = B.chunks k0 = length(Bc) k1 = num_bit_chunks(n) if k1 > k0 - _growend!(Bc, k1 - k0) - Bc[end] = UInt64(0) + if first + if (n0 - n) & 63 == 0 + _growbeg!(Bc, k1 - k0) + else + _growend!(Bc, k1 - k0) + Bc[end] = UInt64(0) + copy_chunks!(Bc, 1 + n - n0, Bc, 1, n0) + end + else + _growend!(Bc, k1 - k0) + Bc[end] = UInt64(0) + end end B.len = n return B diff --git a/test/bitarray.jl b/test/bitarray.jl index fd5c1421a256f..7e35557f3748c 100644 --- a/test/bitarray.jl +++ b/test/bitarray.jl @@ -204,6 +204,22 @@ timesofar("promotions") @check_bit_operation resize!(b1, v1 ÷ 2) BitVector gr(b) = (resize!(b, v1)[(v1÷2):end] .= 1; b) @check_bit_operation gr(b1) BitVector + + b1 = bitrand(v1) + @test_throws BoundsError resize!(b1, -1; first=true) + b2 = copy(b1) + @test resize!(b1, v1+100; first=true)[end-v1+1:end] == b2 + @test resize!(b1, v1+200)[end-100-v1+1:end-100] == b2 + + b1 = bitrand(128) + b2 = copy(b1) + @test resize!(b1, 256; first=true)[end-128+1:end] == b2 + b2 = copy(b1) + @test resize!(b1, 300; first=true)[end-256+1:end] == b2 + b2 = copy(b1) + @test resize!(b1, 340; first=true)[end-300+1:end] == b2 + b2 = copy(b1) + @test resize!(b1, 404; first=true)[end-340+1:end] == b2 end @testset "sizeof (issue #7515)" begin diff --git a/test/core.jl b/test/core.jl index ee47eba0d2c7d..15297d0c70992 100644 --- a/test/core.jl +++ b/test/core.jl @@ -6465,6 +6465,15 @@ for U in unboxedunions @test A[1] === initvalue2(F2) @test typeof(A[end]) === F2 + A = U[initvalue2(F2) for i = 1:len] + resize!(A, 1; first=true) + @test length(A) === 1 + @test A[1] === initvalue2(F2) + resize!(A, len; first=true) + @test length(A) === len + @test A[end] === initvalue2(F2) + @test typeof(A[end]) === F2 + # deleteat! F = Base.uniontypes(U)[2] A = U[rand(F(1):F(len)) for i = 1:len] @@ -6653,7 +6662,7 @@ setindex!(A, missing, 2) setindex!(A, 0x03, 3) setindex!(A, missing, 4) setindex!(A, 0x05, 5) -Base._growat!(A, 1, 1) +resize!(A, 6; first=true) @test getindex(A, 1) === missing @test getindex(A, 2) === 0x01 @@ -6663,7 +6672,7 @@ Base._growat!(A, 1, 1) @test getindex(A, 6) === 0x05 # grow_at_beg 2 -Base._growat!(A, 1, 1) +resize!(A, 7; first=true) @test getindex(A, 1) === missing @test getindex(A, 2) === missing @test getindex(A, 3) === 0x01 @@ -6684,7 +6693,7 @@ Base._growat!(A, 2, 1) @test getindex(A, 8) === 0x05 # grow_at_beg 9 -Base._growat!(A, 1, 1) +resize!(A, 9; first=true) @test getindex(A, 1) === missing @test getindex(A, 2) === missing @test getindex(A, 3) === missing @@ -6744,6 +6753,11 @@ Base._growat!(A, 2, 3) @test getindex(A, 9) === missing @test getindex(A, 10) === 0x05 +resize!(A, 2; first=true) +@test getindex(A, 1) === missing +@test getindex(A, 2) === 0x05 +@test length(A) === 2 + # grow_at_beg 3 A = Vector{Union{Missing, UInt8}}(undef, 1048577) setindex!(A, 0x01, 1)