-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into resolve-ambiguities-without-autoformat
Required manual merge of runtests, as the newly included BufferedVectors' tests were added there, but must now be in the SentinelArraysTests module.
- Loading branch information
Showing
6 changed files
with
165 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
name = "SentinelArrays" | ||
uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c" | ||
authors = ["Jacob Quinn <[email protected]>"] | ||
version = "1.3.18" | ||
version = "1.4.0" | ||
|
||
[deps] | ||
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
module BufferedVectors | ||
|
||
export BufferedVector, skip_element!, shiftleft!, unsafe_push! | ||
mutable struct BufferedVector{T} <: AbstractArray{T,1} | ||
elements::Vector{T} | ||
occupied::Int | ||
end | ||
BufferedVector{T}() where {T} = BufferedVector(T[], 0) | ||
BufferedVector(v::Vector{T}) where {T} = BufferedVector{T}(v, length(v)) | ||
|
||
Base.length(x::BufferedVector) = x.occupied | ||
Base.size(x::BufferedVector) = (x.occupied,) | ||
Base.@propagate_inbounds function Base.last(x::BufferedVector) | ||
return x.elements[x.occupied] | ||
end | ||
@inline function Base.first(x::BufferedVector) | ||
@boundscheck((x.occupied > 0) || Base.throw_boundserror(x, 1)) | ||
return @inbounds(x.elements[1]) | ||
end | ||
@inline function Base.getindex(x::BufferedVector, i::Int) | ||
@boundscheck((x.occupied >= i && i > 0) || Base.throw_boundserror(x, i)) | ||
return @inbounds(x.elements[i]) | ||
end | ||
Base.ndims(x::BufferedVector) = 1 | ||
Base.empty!(x::BufferedVector) = (x.occupied = 0; x) | ||
Base.isempty(x::BufferedVector) = x.occupied == 0 | ||
Base.IndexStyle(::BufferedVector) = Base.IndexLinear() | ||
Base.IteratorSize(::BufferedVector) = Base.HasLength() | ||
Base.IteratorEltype(::BufferedVector) = Base.HasEltype() | ||
Base.collect(x::BufferedVector{T}) where {T} = length(x) > 0 ? @inbounds(x.elements[1:length(x)]) : T[] | ||
Base.eltype(::BufferedVector{T}) where T = T | ||
@inline Base.push!(buffer::T, x::S) where {T,S} = push!(buffer, convert(T, x)) | ||
@inline function Base.push!(buffer::BufferedVector{T}, x::T) where {T} | ||
if length(buffer.elements) == buffer.occupied | ||
Base._growend!(buffer.elements, _grow_by(T)) | ||
end | ||
buffer.occupied += 1 | ||
@inbounds buffer.elements[buffer.occupied] = x | ||
end | ||
_grow_by(::Type) = 16 | ||
_grow_by(::Type{T}) where {T<:Union{Bool,UInt8}} = 64 | ||
|
||
@inline unsafe_push!(buffer::BufferedVector{T}, x::S) where {T,S} = unsafe_push!(buffer, convert(T, x)) | ||
@inline function unsafe_push!(buffer::BufferedVector{T}, x::T) where {T} | ||
buffer.occupied += 1 | ||
@inbounds buffer.elements[buffer.occupied] = x | ||
end | ||
Base.ensureroom(x::BufferedVector, n) = ((length(x.elements) < n) && Base._growend!(x.elements, n - length(x.elements)); return nothing) | ||
skip_element!(x::BufferedVector) = x.occupied += 1 | ||
function shiftleft!(x::BufferedVector, n) | ||
n < 0 && throw(ArgumentError("n must be >= 0")) | ||
n == 0 && return | ||
len = length(x) | ||
if n >= len | ||
empty!(x) | ||
return nothing | ||
end | ||
unsafe_copyto!(x.elements, 1, x.elements, 1 + n, len - n + 1) | ||
x.occupied -= n | ||
return nothing | ||
end | ||
|
||
end # module |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
using Test | ||
using SentinelArrays | ||
using SentinelArrays: BufferedVectors | ||
|
||
|
||
@noinline unsafe(bv, i) = @inbounds bv[i] | ||
|
||
@testset "BufferedVectors" begin | ||
bv = BufferedVector{Int}() | ||
@test eltype(bv) == Int | ||
@test bv == Int[] | ||
@test bv.elements == Int[] | ||
@test bv.occupied == 0 | ||
@test length(bv) == 0 | ||
@test length(bv.elements) == 0 | ||
@test isempty(bv) | ||
@test_throws BoundsError bv[1] | ||
@test_throws BoundsError first(bv) | ||
@test_throws BoundsError last(bv) | ||
@test collect(bv) == Int[] | ||
|
||
Base.ensureroom(bv, 2) | ||
@test length(bv.elements) == 2 | ||
@test bv.occupied == 0 | ||
@test length(bv) == 0 | ||
@test_throws BoundsError first(bv) | ||
|
||
bv = BufferedVector{Int}([1,2,3], 3) | ||
@test bv == [1,2,3] | ||
@test bv.elements[1:3] == [1,2,3] | ||
@test bv.occupied == 3 | ||
@test length(bv) == 3 | ||
@test size(bv) == (3,) | ||
@test collect(bv) == [1,2,3] | ||
@test first(bv) == 1 | ||
@test bv[1] == 1 | ||
@test bv[2] == 2 | ||
@test bv[3] == 3 | ||
@test last(bv) == 3 | ||
@test_throws BoundsError bv[0] | ||
@test_throws BoundsError bv[4] | ||
@test !isempty(bv) | ||
|
||
empty!(bv) | ||
@test bv == Int[] | ||
@test isempty(bv) | ||
|
||
push!(bv, 1) | ||
@test bv == [1] | ||
@assert length(bv) == 1 | ||
skip_element!(bv) | ||
@test length(bv) == 2 | ||
|
||
bv = BufferedVector{Int}() | ||
push!(bv, 1) | ||
@test length(bv.elements) == BufferedVectors._grow_by(Int) | ||
@assert BufferedVectors._grow_by(Int) > 0 | ||
@test_throws BoundsError bv[2] | ||
unsafe_push!(bv, 42) | ||
@test bv == [1, 42] | ||
|
||
code = """ | ||
using SentinelArrays | ||
using Test | ||
bv = BufferedVector{Int}(Int[1, 2], 0) | ||
# `unsafe` is actually safe here, it's just accessing undef values | ||
@noinline unsafe(bv, i) = @inbounds bv[i] | ||
@test unsafe(bv, 2) == bv.elements[2] | ||
""" | ||
cmd = `$(Base.julia_cmd()) --startup-file=no --project=. --check-bounds=auto -e $code` | ||
@test success(pipeline(cmd; stdout=stdout, stderr=stderr)) | ||
|
||
bv = BufferedVector{Int32}() | ||
push!(bv, Int32(1)) | ||
@test length(bv.elements) == BufferedVectors._grow_by(Int32) | ||
@assert BufferedVectors._grow_by(Int32) > 0 | ||
|
||
bv = BufferedVector{Int}([1,2,3], 3) | ||
shiftleft!(bv, 1) | ||
@test bv == [2,3] | ||
|
||
bv = BufferedVector{Int}([1,2,3], 3) | ||
shiftleft!(bv, 2) | ||
@test bv == [3] | ||
|
||
bv = BufferedVector{Int}([1,2,3], 3) | ||
shiftleft!(bv, 3) | ||
@test bv == [] | ||
|
||
bv = BufferedVector{Int}([1,2,3], 3) | ||
shiftleft!(bv, 4) | ||
@test bv == [] | ||
|
||
@test_throws ArgumentError shiftleft!(bv, -1) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
using ReTest | ||
susing ReTest | ||
|
||
using SentinelArrays | ||
|
||
include("SentinelArrayTests.jl") | ||
|
||
retest(SentinelArrays, SentinelArrayTests) | ||
retest(SentinelArrays, SentinelArrayTests) |