@@ -11,7 +11,7 @@ using .Base: copymutable, LinearIndices, length, (:), iterate, OneTo,
11
11
AbstractMatrix, AbstractUnitRange, isless, identity, eltype, > , < , <= , >= , | , + , - , * , ! ,
12
12
extrema, sub_with_overflow, add_with_overflow, oneunit, div, getindex, setindex!,
13
13
length, resize!, fill, Missing, require_one_based_indexing, keytype, UnitRange,
14
- min, max, reinterpret, signed, unsigned, Signed, Unsigned, typemin, xor, Type, BitSigned
14
+ min, max, reinterpret, signed, unsigned, Signed, Unsigned, typemin, xor, Type, BitSigned, Val
15
15
16
16
using . Base: >>> , != =
17
17
@@ -1091,14 +1091,16 @@ end
1091
1091
# # sortperm: the permutation to sort an array ##
1092
1092
1093
1093
"""
1094
- sortperm(v ; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
1094
+ sortperm(A ; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, [dims::Integer] )
1095
1095
1096
- Return a permutation vector `I` that puts `v[I]` in sorted order. The order is specified
1096
+ Return a permutation vector or array `I` that puts `A[I]` in sorted order along the given dimension.
1097
+ If `A` has more than one dimension, then the `dims` keyword argument must be specified. The order is specified
1097
1098
using the same keywords as [`sort!`](@ref). The permutation is guaranteed to be stable even
1098
1099
if the sorting algorithm is unstable, meaning that indices of equal elements appear in
1099
1100
ascending order.
1100
1101
1101
1102
See also [`sortperm!`](@ref), [`partialsortperm`](@ref), [`invperm`](@ref), [`indexin`](@ref).
1103
+ To sort slices of an array, refer to [`sortslices`](@ref).
1102
1104
1103
1105
# Examples
1104
1106
```jldoctest
@@ -1115,37 +1117,53 @@ julia> v[p]
1115
1117
1
1116
1118
2
1117
1119
3
1120
+
1121
+ julia> A = [8 7; 5 6]
1122
+ 2×2 Matrix{Int64}:
1123
+ 8 7
1124
+ 5 6
1125
+
1126
+ julia> sortperm(A, dims = 1)
1127
+ 2×2 Matrix{Int64}:
1128
+ 2 4
1129
+ 1 3
1130
+
1131
+ julia> sortperm(A, dims = 2)
1132
+ 2×2 Matrix{Int64}:
1133
+ 3 1
1134
+ 2 4
1118
1135
```
1119
1136
"""
1120
- function sortperm (v :: AbstractVector ;
1137
+ function sortperm (A :: AbstractArray ;
1121
1138
alg:: Algorithm = DEFAULT_UNSTABLE,
1122
1139
lt= isless,
1123
1140
by= identity,
1124
1141
rev:: Union{Bool,Nothing} = nothing ,
1125
1142
order:: Ordering = Forward,
1126
- workspace:: Union{AbstractVector{<:Integer}, Nothing} = nothing )
1143
+ workspace:: Union{AbstractVector{<:Integer}, Nothing} = nothing ,
1144
+ dims... ) # to optionally specify dims argument
1127
1145
ordr = ord (lt,by,rev,order)
1128
- if ordr === Forward && isa (v ,Vector) && eltype (v )<: Integer
1129
- n = length (v )
1146
+ if ordr === Forward && isa (A ,Vector) && eltype (A )<: Integer
1147
+ n = length (A )
1130
1148
if n > 1
1131
- min, max = extrema (v )
1149
+ min, max = extrema (A )
1132
1150
(diff, o1) = sub_with_overflow (max, min)
1133
1151
(rangelen, o2) = add_with_overflow (diff, oneunit (diff))
1134
1152
if ! o1 && ! o2 && rangelen < div (n,2 )
1135
- return sortperm_int_range (v , rangelen, min)
1153
+ return sortperm_int_range (A , rangelen, min)
1136
1154
end
1137
1155
end
1138
1156
end
1139
- p = copymutable (eachindex (v ))
1140
- sort! (p, alg, Perm (ordr,v) , workspace)
1157
+ ix = copymutable (LinearIndices (A ))
1158
+ sort! (ix; alg, order = Perm (ordr, vec (A)) , workspace, dims ... )
1141
1159
end
1142
1160
1143
1161
1144
1162
"""
1145
- sortperm!(ix, v ; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, initialized::Bool=false)
1163
+ sortperm!(ix, A ; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, initialized::Bool=false, [dims::Integer] )
1146
1164
1147
- Like [`sortperm`](@ref), but accepts a preallocated index vector `ix`. If `initialized` is `false`
1148
- (the default), `ix` is initialized to contain the values `1:length(v )`.
1165
+ Like [`sortperm`](@ref), but accepts a preallocated index vector or array `ix` with the same `axes` as `A `. If `initialized` is `false`
1166
+ (the default), `ix` is initialized to contain the values `LinearIndices(A )`.
1149
1167
1150
1168
# Examples
1151
1169
```jldoctest
@@ -1162,25 +1180,36 @@ julia> v[p]
1162
1180
1
1163
1181
2
1164
1182
3
1183
+
1184
+ julia> A = [8 7; 5 6]; p = zeros(Int,2, 2);
1185
+
1186
+ julia> sortperm!(p, A; dims=1); p
1187
+ 2×2 Matrix{Int64}:
1188
+ 2 4
1189
+ 1 3
1190
+
1191
+ julia> sortperm!(p, A; dims=2); p
1192
+ 2×2 Matrix{Int64}:
1193
+ 3 1
1194
+ 2 4
1165
1195
```
1166
1196
"""
1167
- function sortperm! (x :: AbstractVector {T} , v :: AbstractVector ;
1197
+ function sortperm! (ix :: AbstractArray {T} , A :: AbstractArray ;
1168
1198
alg:: Algorithm = DEFAULT_UNSTABLE,
1169
1199
lt= isless,
1170
1200
by= identity,
1171
1201
rev:: Union{Bool,Nothing} = nothing ,
1172
1202
order:: Ordering = Forward,
1173
1203
initialized:: Bool = false ,
1174
- workspace:: Union{AbstractVector{T}, Nothing} = nothing ) where T <: Integer
1175
- if axes (x,1 ) != axes (v,1 )
1176
- throw (ArgumentError (" index vector must have the same length/indices as the source vector, $(axes (x,1 )) != $(axes (v,1 )) " ))
1177
- end
1204
+ workspace:: Union{AbstractVector{T}, Nothing} = nothing ,
1205
+ dims... ) where T <: Integer # to optionally specify dims argument
1206
+ (typeof (A) <: AbstractVector ) == (:dims in keys (dims)) && throw (ArgumentError (" Dims argument incorrect for type $(typeof (A)) " ))
1207
+ axes (ix) == axes (A) || throw (ArgumentError (" index array must have the same size/axes as the source array, $(axes (ix)) != $(axes (A)) " ))
1208
+
1178
1209
if ! initialized
1179
- @inbounds for i in eachindex (v)
1180
- x[i] = i
1181
- end
1210
+ ix .= LinearIndices (A)
1182
1211
end
1183
- sort! (x, alg, Perm (ord (lt,by,rev,order),v) , workspace)
1212
+ sort! (ix; alg, order = Perm (ord (lt, by, rev, order), vec (A)) , workspace, dims ... )
1184
1213
end
1185
1214
1186
1215
# sortperm for vectors of few unique integers
@@ -1307,16 +1336,20 @@ function sort!(A::AbstractArray{T};
1307
1336
rev:: Union{Bool,Nothing} = nothing ,
1308
1337
order:: Ordering = Forward,
1309
1338
workspace:: Union{AbstractVector{T}, Nothing} = similar (A, size (A, dims))) where T
1310
- ordr = ord (lt, by, rev, order)
1339
+ _sort! (A, Val (dims), alg, ord (lt, by, rev, order), workspace)
1340
+ end
1341
+ function _sort! (A:: AbstractArray{T} , :: Val{K} ,
1342
+ alg:: Algorithm ,
1343
+ order:: Ordering ,
1344
+ workspace:: Union{AbstractVector{T}, Nothing} ) where {K,T}
1311
1345
nd = ndims (A)
1312
- k = dims
1313
1346
1314
- 1 <= k <= nd || throw (ArgumentError (" dimension out of range" ))
1347
+ 1 <= K <= nd || throw (ArgumentError (" dimension out of range" ))
1315
1348
1316
- remdims = ntuple (i -> i == k ? 1 : axes (A, i), nd)
1349
+ remdims = ntuple (i -> i == K ? 1 : axes (A, i), nd)
1317
1350
for idx in CartesianIndices (remdims)
1318
- Av = view (A, ntuple (i -> i == k ? Colon () : idx[i], nd)... )
1319
- sort! (Av, alg, ordr , workspace)
1351
+ Av = view (A, ntuple (i -> i == K ? Colon () : idx[i], nd)... )
1352
+ sort! (Av, alg, order , workspace)
1320
1353
end
1321
1354
A
1322
1355
end
0 commit comments