Skip to content

Commit 6b3bb1f

Browse files
kmsquirefredrikekre
authored andcommitted
Check index vector length in partialsortperm!(); clarify documentation, fixes #33184(#33196)
1 parent 1b0510d commit 6b3bb1f

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

base/sort.jl

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -789,16 +789,59 @@ partialsortperm(v::AbstractVector, k::Union{Integer,OrdinalRange}; kwargs...) =
789789
"""
790790
partialsortperm!(ix, v, k; by=<transform>, lt=<comparison>, rev=false, initialized=false)
791791
792-
Like [`partialsortperm`](@ref), but accepts a preallocated index vector `ix`. If `initialized` is `false`
793-
(the default), `ix` is initialized to contain the values `1:length(ix)`.
794-
"""
792+
Like [`partialsortperm`](@ref), but accepts a preallocated index vector `ix` the same size as
793+
`v`, which is used to store (a permutation of) the indices of `v`.
794+
795+
If the index vector `ix` is initialized with the indices of `v` (or a permutation thereof), `initialized` should be set to
796+
`true`.
797+
798+
If `initialized` is `false` (the default), then `ix` is initialized to contain the indices of `v`.
799+
800+
If `initialized` is `true`, but `ix` does not contain (a permutation of) the indices of `v`, the behavior of
801+
`partialsortperm!` is undefined.
802+
803+
(Typically, the indices of `v` will be `1:length(v)`, although if `v` has an alternative array type
804+
with non-one-based indices, such as an `OffsetArray`, `ix` must also be an `OffsetArray` with the same
805+
indices, and must contain as values (a permutation of) these same indices.)
806+
807+
Upon return, `ix` is guaranteed to have the indices `k` in their sorted positions, such that
808+
809+
```julia
810+
partialsortperm!(ix, v, k);
811+
v[ix[k]] == partialsort(v, k)
812+
```
813+
814+
The return value is the `k`th element of `ix` if `k` is an integer, or view into `ix` if `k` is
815+
a range.
816+
817+
# Examples
818+
```jldoctest
819+
julia> v = [3, 1, 2, 1];
820+
821+
julia> ix = Vector{Int}(undef, 4);
822+
823+
julia> partialsortperm!(ix, v, 1)
824+
2
825+
826+
julia> ix = [1:4;];
827+
828+
julia> partialsortperm!(ix, v, 2:3, initialized=true)
829+
2-element view(::Array{Int64,1}, 2:3) with eltype Int64:
830+
4
831+
3
832+
```
833+
"""
795834
function partialsortperm!(ix::AbstractVector{<:Integer}, v::AbstractVector,
796835
k::Union{Int, OrdinalRange};
797836
lt::Function=isless,
798837
by::Function=identity,
799838
rev::Union{Bool,Nothing}=nothing,
800839
order::Ordering=Forward,
801840
initialized::Bool=false)
841+
if axes(ix,1) != axes(v,1)
842+
throw(ArgumentError("The index vector is used as a workspace and must have the " *
843+
"same length/indices as the source vector, $(axes(ix,1)) != $(axes(v,1))"))
844+
end
802845
if !initialized
803846
@inbounds for i = axes(ix,1)
804847
ix[i] = i
@@ -897,7 +940,7 @@ function sortperm!(x::AbstractVector{<:Integer}, v::AbstractVector;
897940
order::Ordering=Forward,
898941
initialized::Bool=false)
899942
if axes(x,1) != axes(v,1)
900-
throw(ArgumentError("index vector must have the same indices as the source vector, $(axes(x,1)) != $(axes(v,1))"))
943+
throw(ArgumentError("index vector must have the same length/indices as the source vector, $(axes(x,1)) != $(axes(v,1))"))
901944
end
902945
if !initialized
903946
@inbounds for i = axes(v,1)

test/sorting.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ let a=[1:10;]
3333
@test partialsortperm(a, r, rev=true) == (11 .- [r;])
3434
end
3535
end
36+
@test_throws ArgumentError partialsortperm!([1,2], [2,3,1], 1:2)
3637
@test sum(randperm(6)) == 21
3738

3839
@testset "searchsorted" begin

0 commit comments

Comments
 (0)