Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sorting API refactor using keywords #3665

Merged
merged 7 commits into from
Jul 11, 2013
Prev Previous commit
Next Next commit
sorting: add rev boolean keyword to reverse any sort ordering.
Also added lt, by, order, rev keywords to the searchsorted* funcs.
  • Loading branch information
StefanKarpinski committed Jul 11, 2013
commit 7bab3508c2700fe17497a3d9b59b96cc3fa597e3
2 changes: 1 addition & 1 deletion base/darray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ function defaultdist(dims, procs)
dims = [dims...]
chunks = ones(Int, length(dims))
np = length(procs)
f = sort!(collect(keys(factor(np))), order=Sort.Reverse)
f = sort!(collect(keys(factor(np))), rev=true)
k = 1
while np > 1
# repeatedly allocate largest factor to largest dim
Expand Down
61 changes: 34 additions & 27 deletions base/sort.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,10 @@ lt(o::ReverseOrdering, a, b) = lt(o.fwd,b,a)
lt(o::By, a, b) = isless(o.by(a),o.by(b))
lt(o::Lt, a, b) = o.lt(a,b)

ord(lt::Function, by::Function, order::Ordering) =
(lt === isless) & (by === identity) ? order :
(lt === isless) ? By(by) : Lt(lt)
function ord(lt::Function, by::Function, order::Ordering, rev::Bool)
o = (lt===isless) & (by===identity) ? order : (lt===isless) ? By(by) : Lt(lt)
rev ? ReverseOrdering(o) : o
end

## functions requiring only ordering ##

Expand All @@ -78,8 +79,9 @@ function issorted(itr, order::Ordering)
end
return true
end
issorted(itr; lt::Function=isless, by::Function=identity, order::Ordering=Forward) =
issorted(itr, ord(lt,by,order))
issorted(itr;
lt::Function=isless, by::Function=identity, order::Ordering=Forward, rev::Bool=false) =
issorted(itr, ord(lt,by,order,rev))

function select!(v::AbstractVector, k::Int, lo::Int, hi::Int, o::Ordering)
lo <= k <= hi || error("select index $k is out of range $lo:$hi")
Expand Down Expand Up @@ -142,8 +144,8 @@ end

select!(v::AbstractVector, k, o::Ordering) = select!(v,k,1,length(v),o)
select!(v::AbstractVector, k;
lt::Function=isless, by::Function=identity, order::Ordering=Forward) =
select!(v, k, ord(lt,by,order))
lt::Function=isless, by::Function=identity, order::Ordering=Forward, rev::Bool=false) =
select!(v, k, ord(lt,by,order,rev))

select(v::AbstractVector, k; kws...) = select!(copy(v), k; kws...)

Expand Down Expand Up @@ -203,46 +205,51 @@ function searchsorted(v::AbstractVector, x, lo::Int, hi::Int, o::Ordering)
return lo+1:hi-1
end

for s in {:searchsortedfirst, :searchsortedlast, :searchsorted}
@eval $s(v::AbstractVector, x; order::Ordering=Forward) = $s(v,x,1,length(v),order)
end

function searchsortedlast{T<:Real}(a::Ranges{T}, x::Real; order::Ordering=Forward)
function searchsortedlast{T<:Real}(a::Ranges{T}, x::Real, o::Ordering=Forward)
if step(a) == 0
lt(order, x, first(a)) ? 0 : length(a)
lt(o, x, first(a)) ? 0 : length(a)
else
n = max(min(iround((x-first(a))/step(a))+1,length(a)),1)
lt(order, x, a[n]) ? n-1 : n
lt(o, x, a[n]) ? n-1 : n
end
end

function searchsortedfirst{T<:Real}(a::Ranges{T}, x::Real; order::Ordering=Forward)
function searchsortedfirst{T<:Real}(a::Ranges{T}, x::Real, o::Ordering=Forward)
if step(a) == 0
lt(order, first(a), x) ? length(a)+1 : 1
lt(o, first(a), x) ? length(a)+1 : 1
else
n = max(min(iround((x-first(a))/step(a))+1,length(a)),1)
lt(order, a[n] ,x) ? n+1 : n
lt(o, a[n] ,x) ? n+1 : n
end
end

function searchsortedlast{T<:Integer}(a::Ranges{T}, x::Real; order::Ordering=Forward)
function searchsortedlast{T<:Integer}(a::Ranges{T}, x::Real, o::Ordering=Forward)
if step(a) == 0
lt(order, x, first(a)) ? 0 : length(a)
lt(o, x, first(a)) ? 0 : length(a)
else
max(min(fld(ifloor(x)-first(a),step(a))+1,length(a)),0)
end
end

function searchsortedfirst{T<:Integer}(a::Ranges{T}, x::Real; order::Ordering=Forward)
function searchsortedfirst{T<:Integer}(a::Ranges{T}, x::Real, o::Ordering=Forward)
if step(a) == 0
lt(order, first(a), x) ? length(a)+1 : 1
lt(o, first(a), x) ? length(a)+1 : 1
else
max(min(-fld(ifloor(-x)+first(a),step(a))+1,length(a)+1),1)
end
end

searchsorted{T<:Real}(a::Ranges{T}, x::Real; order::Ordering=Forward) =
searchsortedfirst(a,x,order=order):searchsortedlast(a,x,order=order)
searchsorted{T<:Real}(a::Ranges{T}, x::Real; kws...) =
searchsortedfirst(a,x; kws...):searchsortedlast(a,x; kws...)

for s in {:searchsortedfirst, :searchsortedlast, :searchsorted}
@eval begin
$s(v::AbstractVector, x, o::Ordering) = $s(v,x,1,length(v),o)
$s(v::AbstractVector, x;
lt::Function=isless, by::Function=identity, order::Ordering=Forward, rev::Bool=false) =
$s(v,x,ord(lt,by,order,rev))
end
end

## sorting algorithms ##

Expand Down Expand Up @@ -353,12 +360,12 @@ defalg{T<:Number}(v::AbstractArray{T}) = DEFAULT_UNSTABLE

sort!(v::AbstractVector, alg::Algorithm, order::Ordering) = sort!(v,1,length(v),alg,order)
sort!(v::AbstractVector; alg::Algorithm=defalg(v),
lt::Function=isless, by::Function=identity, order::Ordering=Forward) =
sort!(v, alg, ord(lt,by,order))
lt::Function=isless, by::Function=identity, order::Ordering=Forward, rev::Bool=false) =
sort!(v, alg, ord(lt,by,order,rev))

sortperm(v::AbstractVector; alg::Algorithm=defalg(v),
lt::Function=isless, by::Function=identity, order::Ordering=Forward) =
sort!([1:length(v)], alg, Perm(ord(lt,by,order),v))
lt::Function=isless, by::Function=identity, order::Ordering=Forward, rev::Bool=false) =
sort!([1:length(v)], alg, Perm(ord(lt,by,order,rev),v))

sort(v::AbstractVector; kws...) = sort!(copy(v); kws...)

Expand Down
4 changes: 2 additions & 2 deletions test/arrayops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -430,11 +430,11 @@ begin
@test isless(asc[:,1],asc[:,2])
@test isless(asc[:,2],asc[:,3])

asr = sortrows(a, order=Sort.Reverse)
asr = sortrows(a, rev=true)
@test isless(asr[2,:],asr[1,:])
@test isless(asr[3,:],asr[2,:])

asc = sortcols(a, order=Sort.Reverse)
asc = sortcols(a, rev=true)
@test isless(asc[:,2],asc[:,1])
@test isless(asc[:,3],asc[:,2])

Expand Down
60 changes: 30 additions & 30 deletions test/sorting.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@test sort([2,3,1]) == [1,2,3]
@test sort([2,3,1], order=Sort.Reverse) == [3,2,1]
@test sort([2,3,1], rev=true) == [3,2,1]
@test sortperm([2,3,1]) == [3,1,2]
@test !issorted([2,3,1])
@test issorted([1,2,3])
Expand Down Expand Up @@ -30,41 +30,41 @@ rg_r = 57:-1:49; rgv_r = [rg_r]
for i = 47:59
@test searchsortedfirst(rg, i) == searchsortedfirst(rgv, i)
@test searchsortedlast(rg, i) == searchsortedlast(rgv, i)
@test searchsortedfirst(rg_r, i, order=Sort.Reverse) ==
searchsortedfirst(rgv_r, i, order=Sort.Reverse)
@test searchsortedlast(rg_r, i, order=Sort.Reverse) ==
searchsortedlast(rgv_r, i, order=Sort.Reverse)
@test searchsortedfirst(rg_r, i, rev=true) ==
searchsortedfirst(rgv_r, i, rev=true)
@test searchsortedlast(rg_r, i, rev=true) ==
searchsortedlast(rgv_r, i, rev=true)
end
rg = 1:2:17; rgv = [rg]
rg_r = 17:-2:1; rgv_r = [rg_r]
for i = -1:19
@test searchsortedfirst(rg, i) == searchsortedfirst(rgv, i)
@test searchsortedlast(rg, i) == searchsortedlast(rgv, i)
@test searchsortedfirst(rg_r, i, order=Sort.Reverse) ==
searchsortedfirst(rgv_r, i, order=Sort.Reverse)
@test searchsortedlast(rg_r, i, order=Sort.Reverse) ==
searchsortedlast(rgv_r, i, order=Sort.Reverse)
@test searchsortedfirst(rg_r, i, rev=true) ==
searchsortedfirst(rgv_r, i, rev=true)
@test searchsortedlast(rg_r, i, rev=true) ==
searchsortedlast(rgv_r, i, rev=true)
end
rg = -3:0.5:2; rgv = [rg]
rg_r = 2:-0.5:-3; rgv_r = [rg_r]
for i = -5:.5:4
@test searchsortedfirst(rg, i) == searchsortedfirst(rgv, i)
@test searchsortedlast(rg, i) == searchsortedlast(rgv, i)
@test searchsortedfirst(rg_r, i, order=Sort.Reverse) ==
searchsortedfirst(rgv_r, i, order=Sort.Reverse)
@test searchsortedlast(rg_r, i, order=Sort.Reverse) ==
searchsortedlast(rgv_r, i, order=Sort.Reverse)
@test searchsortedfirst(rg_r, i, rev=true) ==
searchsortedfirst(rgv_r, i, rev=true)
@test searchsortedlast(rg_r, i, rev=true) ==
searchsortedlast(rgv_r, i, rev=true)
end

rg = 3+0*(1:5); rgv = [rg]
rg_r = rg; rgv_r = [rg_r]
for i = 2:4
@test searchsortedfirst(rg, i) == searchsortedfirst(rgv, i)
@test searchsortedlast(rg, i) == searchsortedlast(rgv, i)
@test searchsortedfirst(rg_r, i, order=Sort.Reverse) ==
searchsortedfirst(rgv_r, i, order=Sort.Reverse)
@test searchsortedlast(rg_r, i, order=Sort.Reverse) ==
searchsortedlast(rgv_r, i, order=Sort.Reverse)
@test searchsortedfirst(rg_r, i, rev=true) ==
searchsortedfirst(rgv_r, i, rev=true)
@test searchsortedlast(rg_r, i, rev=true) ==
searchsortedlast(rgv_r, i, rev=true)
end

rg = 0.0:0.01:1.0
Expand All @@ -80,13 +80,13 @@ end

rg_r = reverse(rg)
for i = 1:100
@test searchsortedfirst(rg_r, rg_r[i], order=Sort.Reverse) == i
@test searchsortedfirst(rg_r, prevfloat(rg_r[i]), order=Sort.Reverse) == i+1
@test searchsortedfirst(rg_r, nextfloat(rg_r[i]), order=Sort.Reverse) == i
@test searchsortedfirst(rg_r, rg_r[i], rev=true) == i
@test searchsortedfirst(rg_r, prevfloat(rg_r[i]), rev=true) == i+1
@test searchsortedfirst(rg_r, nextfloat(rg_r[i]), rev=true) == i

@test searchsortedlast(rg_r, rg_r[i], order=Sort.Reverse) == i
@test searchsortedlast(rg_r, prevfloat(rg_r[i]), order=Sort.Reverse) == i
@test searchsortedlast(rg_r, nextfloat(rg_r[i]), order=Sort.Reverse) == i-1
@test searchsortedlast(rg_r, rg_r[i], rev=true) == i
@test searchsortedlast(rg_r, prevfloat(rg_r[i]), rev=true) == i
@test searchsortedlast(rg_r, nextfloat(rg_r[i]), rev=true) == i-1
end

a = rand(1:10000, 1000)
Expand All @@ -99,11 +99,11 @@ for alg in [InsertionSort, MergeSort, TimSort]
@test issorted(b)
@test a[ix] == b

b = sort(a, alg=alg, order=Sort.Reverse)
@test issorted(b, order=Sort.Reverse)
ix = sortperm(a, alg=alg, order=Sort.Reverse)
b = sort(a, alg=alg, rev=true)
@test issorted(b, rev=true)
ix = sortperm(a, alg=alg, rev=true)
b = a[ix]
@test issorted(b, order=Sort.Reverse)
@test issorted(b, rev=true)
@test a[ix] == b

b = sort(a, alg=alg, by=x->1/x)
Expand All @@ -129,12 +129,12 @@ end

b = sort(a, alg=QuickSort)
@test issorted(b)
b = sort(a, alg=QuickSort, order=Sort.Reverse)
@test issorted(b, order=Sort.Reverse)
b = sort(a, alg=QuickSort, rev=true)
@test issorted(b, rev=true)
b = sort(a, alg=QuickSort, by=x->1/x)
@test issorted(b, by=x->1/x)

@test select([3,6,30,1,9], 2, order=Sort.Reverse) == 9
@test select([3,6,30,1,9], 2, rev=true) == 9
@test select([3,6,30,1,9], 2, by=x->1/x) == 9

## more advanced sorting tests ##
Expand Down