Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

sorting API refactor using keywords #3665

Merged
merged 7 commits into from

4 participants

@StefanKarpinski

Quoting the main commit:

The idea here is that the ordering and algorithm for sorting are two orthogonal parameters that have sensible defaults: neither, both or either can be independently specified. The resulting API is slightly more verbose but also somewhat more self-documenting.

Another sign that this might be on the right track is that this change reduces the LOC of base/sort.jl by 41 lines and reduces the method count of sort, for example, from 12 to 6.

Still needs deprecation methods before merging, but I thought I'd put it out there for feedback.

Note: I really wish that the lt and by ordering variations could be cleanly specified this way too – that would really cut the API down to a nice lean size without sacrificing any functionality. But I can't figure out a good way to do it.

@StefanKarpinski

Ok, I took a crack at using keywords for by and lt as well and I really rather like the resulting API. It eliminates the need for sortby! and sortby – and generalizes naturally to other order-related functions without blowing up the export set or requiring the use of awkward types that really should be implementation details of the sorting code.

It has, however, revealed what seems to be a method dispatch bug. Will file an issue.

StefanKarpinski added some commits
@StefanKarpinski StefanKarpinski sorting: make `order` and `alg` keyword arguments.
The idea here is that the ordering and algorithm for sorting are
two orthogonal parameters that have sensible defaults: neither,
both or either can be independently specified. The resulting API
is slightly more verbose but also somewhat more self-documenting.

Another sign that this might be on the right track is that this
change reduces the LOC of base/sort.jl by 41 lines and reduces the
method count of sort, for example, from 12 to 6.
73ecfd8
@StefanKarpinski StefanKarpinski sorting: move matrix sorts up with other generic sorting functions. 738c230
@StefanKarpinski StefanKarpinski sorting: eliminate a few nans2{left,right} definitions via defaults. e5498d1
@StefanKarpinski StefanKarpinski sorting: keyword arguments for `by` and `lt` as well. 2409b35
@StefanKarpinski StefanKarpinski sorting: make ReverseOrder parametric -- can reverse any ordering. 3326e0c
@StefanKarpinski StefanKarpinski sorting: add `rev` boolean keyword to reverse any sort ordering.
Also added lt, by, order, rev keywords to the searchsorted* funcs.
7bab350
@StefanKarpinski StefanKarpinski sorting: deprecations for the old sorting API af97a6c
@StefanKarpinski StefanKarpinski merged commit f951d7c into master
@StefanKarpinski StefanKarpinski deleted the sk/sort-keywords branch
@StefanKarpinski StefanKarpinski referenced this pull request
Closed

0.2 release notes #2581

@stevengj
Owner

@StefanKarpinski gets the hornéd hat of shame for checking this in without updating the documentation...

@ViralBShah
Owner

I hate to do this.

+1

@StefanKarpinski

I'm always wearing a horned hat of shame.

@GunnarFarneback

This ought to give a deprecation message, I suppose:

julia> sort(>, [1:5])
ERROR: no method sort(Function,Array{Int64,1})
@StefanKarpinski

Yes, thanks – I missed that one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 11, 2013
  1. @StefanKarpinski

    sorting: make `order` and `alg` keyword arguments.

    StefanKarpinski authored
    The idea here is that the ordering and algorithm for sorting are
    two orthogonal parameters that have sensible defaults: neither,
    both or either can be independently specified. The resulting API
    is slightly more verbose but also somewhat more self-documenting.
    
    Another sign that this might be on the right track is that this
    change reduces the LOC of base/sort.jl by 41 lines and reduces the
    method count of sort, for example, from 12 to 6.
  2. @StefanKarpinski
  3. @StefanKarpinski
  4. @StefanKarpinski
  5. @StefanKarpinski
  6. @StefanKarpinski

    sorting: add `rev` boolean keyword to reverse any sort ordering.

    StefanKarpinski authored
    Also added lt, by, order, rev keywords to the searchsorted* funcs.
  7. @StefanKarpinski
This page is out of date. Refresh to see the latest.
View
2  base/darray.jl
@@ -60,7 +60,7 @@ function defaultdist(dims, procs)
dims = [dims...]
chunks = ones(Int, length(dims))
np = length(procs)
- f = sort!(collect(keys(factor(np))), Sort.Reverse)
+ f = sort!(collect(keys(factor(np))), rev=true)
k = 1
while np > 1
# repeatedly allocate largest factor to largest dim
View
68 base/deprecated.jl
@@ -252,7 +252,73 @@ export assign
typealias ComplexPair Complex
export ComplexPair
-## along an axis
+# superseded sorting API
+
+@deprecate select(v::AbstractVector,k::Union(Int,Range1),o::Ordering) select(v,k,order=o)
+@deprecate select(v::AbstractVector,k::Union(Int,Range1),f::Function) select(v,k,lt=f)
+@deprecate select(f::Function,v::AbstractVector,k::Union(Int,Range1)) select(v,k,lt=f)
+
+# @deprecate select!(v::AbstractVector,k::Union(Int,Range1),o::Ordering) select!(v,k,order=o)
+@deprecate select!(v::AbstractVector,k::Union(Int,Range1),f::Function) select!(v,k,lt=f)
+@deprecate select!(f::Function,v::AbstractVector,k::k::Union(Int,Range1)) select!(v,k,lt=f)
+
+@deprecate sort(v::AbstractVector,o::Ordering) sort(v,order=o)
+@deprecate sort(v::AbstractVector,a::Algorithm) sort(v,alg=a)
+@deprecate sort(v::AbstractVector,a::Algorithm,o::Ordering) sort(v,alg=a,order=o)
+@deprecate sort(v::AbstractVector,o::Ordering,a::Algorithm) sort(v,alg=a,order=o)
+@deprecate sort(v::AbstractVector,f::Function) sort(v,lt=f)
+@deprecate sort(v::AbstractVector,a::Algorithm,f::Function) sort(v,alg=a,lt=f)
+@deprecate sort(v::AbstractVector,f::Function,a::Algorithm) sort(v,alg=a,lt=f)
+@deprecate sort(f::Function,v::AbstractVector,a::Algorithm) sort(v,alg=a,lt=f)
+
+@deprecate sort!(v::AbstractVector,o::Ordering) sort!(v,order=o)
+@deprecate sort!(v::AbstractVector,a::Algorithm) sort!(v,alg=a)
+# @deprecate sort!(v::AbstractVector,a::Algorithm,o::Ordering) sort!(v,alg=a,order=o)
+@deprecate sort!(v::AbstractVector,o::Ordering,a::Algorithm) sort!(v,alg=a,order=o)
+@deprecate sort!(v::AbstractVector,f::Function) sort!(v,lt=f)
+@deprecate sort!(v::AbstractVector,a::Algorithm,f::Function) sort!(v,alg=a,lt=f)
+@deprecate sort!(v::AbstractVector,f::Function,a::Algorithm) sort!(v,alg=a,lt=f)
+@deprecate sort!(f::Function,v::AbstractVector,a::Algorithm) sort!(v,alg=a,lt=f)
+
+@deprecate sortperm(v::AbstractVector,o::Ordering) sortperm(v,order=o)
+@deprecate sortperm(v::AbstractVector,a::Algorithm) sortperm(v,alg=a)
+@deprecate sortperm(v::AbstractVector,a::Algorithm,o::Ordering) sortperm(v,alg=a,order=o)
+@deprecate sortperm(v::AbstractVector,o::Ordering,a::Algorithm) sortperm(v,alg=a,order=o)
+@deprecate sortperm(v::AbstractVector,f::Function) sortperm(v,lt=f)
+@deprecate sortperm(v::AbstractVector,a::Algorithm,f::Function) sortperm(v,alg=a,lt=f)
+@deprecate sortperm(v::AbstractVector,f::Function,a::Algorithm) sortperm(v,alg=a,lt=f)
+@deprecate sortperm(f::Function,v::AbstractVector,a::Algorithm) sortperm(v,alg=a,lt=f)
+
+@deprecate sort(v::AbstractVector,d::Integer,o::Ordering) sort(v,d,order=o)
+@deprecate sort(v::AbstractVector,d::Integer,a::Algorithm) sort(v,d,alg=a)
+@deprecate sort(v::AbstractVector,d::Integer,a::Algorithm,o::Ordering) sort(v,d,alg=a,order=o)
+@deprecate sort(v::AbstractVector,d::Integer,o::Ordering,a::Algorithm) sort(v,d,alg=a,order=o)
+
+@deprecate sort!(v::AbstractVector,d::Integer,o::Ordering) sort!(v,d,order=o)
+@deprecate sort!(v::AbstractVector,d::Integer,a::Algorithm) sort!(v,d,alg=a)
+@deprecate sort!(v::AbstractVector,d::Integer,a::Algorithm,o::Ordering) sort!(v,d,alg=a,order=o)
+@deprecate sort!(v::AbstractVector,d::Integer,o::Ordering,a::Algorithm) sort!(v,d,alg=a,order=o)
+
+@deprecate sortby(v::AbstractVector,f::Function) sort(v,by=f)
+@deprecate sortby(v::AbstractVector,a::Algorithm,f::Function) sort(v,alg=a,by=f)
+@deprecate sortby(v::AbstractVector,f::Function,a::Algorithm) sort(v,alg=a,by=f)
+@deprecate sortby(f::Function,v::AbstractVector,a::Algorithm) sort(v,alg=a,by=f)
+
+@deprecate sortby!(v::AbstractVector,f::Function) sortby!(v,by=f)
+@deprecate sortby!(v::AbstractVector,a::Algorithm,f::Function) sort!(v,alg=a,by=f)
+@deprecate sortby!(v::AbstractVector,f::Function,a::Algorithm) sort!(v,alg=a,by=f)
+@deprecate sortby!(f::Function,v::AbstractVector,a::Algorithm) sort!(v,alg=a,by=f)
+
+@deprecate sortrows(v::AbstractMatrix,o::Ordering) sortrows(v,order=o)
+@deprecate sortrows(v::AbstractMatrix,a::Algorithm) sortrows(v,alg=a)
+@deprecate sortrows(v::AbstractMatrix,a::Algorithm,o::Ordering) sortrows(v,alg=a,order=o)
+@deprecate sortrows(v::AbstractMatrix,o::Ordering,a::Algorithm) sortrows(v,alg=a,order=o)
+
+@deprecate sortcols(v::AbstractMatrix,o::Ordering) sortcols(v,order=o)
+@deprecate sortcols(v::AbstractMatrix,a::Algorithm) sortcols(v,alg=a)
+@deprecate sortcols(v::AbstractMatrix,a::Algorithm,o::Ordering) sortcols(v,alg=a,order=o)
+@deprecate sortcols(v::AbstractMatrix,o::Ordering,a::Algorithm) sortcols(v,alg=a,order=o)
+
function amap(f::Function, A::AbstractArray, axis::Integer)
warn_once("amap is deprecated, use mapslices(f, A, dims) instead")
dimsA = size(A)
View
2  base/exports.jl
@@ -547,8 +547,6 @@ export
slicedim,
sort,
sort!,
- sortby,
- sortby!,
sortperm,
sortrows,
sortcols,
View
6 base/pkg/resolve.jl
@@ -911,7 +911,7 @@ function decimate(n::Int, graph::Graph, msgs::Messages)
#println("DECIMATING $n NODES")
fld = msgs.fld
decimated = msgs.decimated
- fldorder = sortperm(fld, Sort.By(secondmax))
+ fldorder = sortperm(fld, by=secondmax)
for p0 in fldorder
if decimated[p0]
continue
@@ -1300,7 +1300,7 @@ function sanity_check(vers::Vector{Version}, deps::Vector{(Version,VersionSet)})
p0, v0 = vdict[v]
return -pndeps[p0][v0]
end
- svers = sortby(vers, vrank)
+ svers = sort(vers, by=vrank)
nv = length(svers)
@@ -1373,7 +1373,7 @@ function sanity_check(vers::Vector{Version}, deps::Vector{(Version,VersionSet)})
end
i += 1
end
- sortby!(insane, x->x[1])
+ sort!(insane, by=x->x[1])
throw(MetadataError(insane))
end
View
2  base/pkg2/resolve.jl
@@ -60,7 +60,7 @@ function sanity_check(deps::Dict{ByteString,Dict{VersionNumber,Available}})
for (p,d) in deps, (vn,_) in d
push!(vers, (p,vn))
end
- sortby!(vers, pvn->(-ndeps[pvn[1]][pvn[2]]))
+ sort!(vers, by=pvn->(-ndeps[pvn[1]][pvn[2]]))
nv = length(vers)
View
2  base/pkg2/resolve/maxsum.jl
@@ -399,7 +399,7 @@ function decimate(n::Int, graph::Graph, msgs::Messages)
#println("DECIMATING $n NODES")
fld = msgs.fld
decimated = msgs.decimated
- fldorder = sortperm(fld, Sort.By(secondmax))
+ fldorder = sortperm(fld, by=secondmax)
for p0 in fldorder
if decimated[p0]
continue
View
2  base/pkg2/types.jl
@@ -39,7 +39,7 @@ Base.contains(s::VersionSet, v::VersionNumber) = any(i->contains(i,v), s.interva
function Base.intersect(A::VersionSet, B::VersionSet)
ivals = vec([ intersect(a,b) for a in A.intervals, b in B.intervals ])
filter!(i->!isempty(i), ivals)
- sortby!(ivals, i->i.lower)
+ sort!(ivals, by=i->i.lower)
VersionSet(ivals)
end
Base.isequal(A::VersionSet, B::VersionSet) = (A.intervals == B.intervals)
View
2  base/reflection.jl
@@ -62,7 +62,7 @@ function _subtypes(m::Module, x::DataType, sts=Set(), visited=Set())
end
sts
end
-subtypes(m::Module, x::DataType) = sortby(string, collect(_subtypes(m, x)))
+subtypes(m::Module, x::DataType) = sort(collect(_subtypes(m, x)), by=string)
subtypes(x::DataType) = subtypes(Main, x)
subtypetree(x::DataType, level=-1) = (level == 0 ? (x, {}) : (x, {subtypetree(y, level-1) for y in subtypes(x)}))
View
268 base/sort.jl
@@ -7,19 +7,20 @@ import
Base.sortperm
export # also exported by Base
- sort,
- sort!,
- sortby,
- sortby!,
- sortperm,
- sortrows,
- sortcols,
+ # order-only:
+ issorted,
select,
select!,
- issorted,
searchsorted,
searchsortedfirst,
searchsortedlast,
+ # order & algorithm:
+ sort,
+ sort!,
+ sortperm,
+ sortrows,
+ sortcols,
+ # algorithms:
InsertionSort,
QuickSort,
MergeSort,
@@ -35,41 +36,50 @@ export # not exported by Base
SMALL_ALGORITHM,
SMALL_THRESHOLD
-# not exported
- # selectby
- # selectby!
- # sortpermby
-
## notions of element ordering ##
abstract Ordering
-type ForwardOrdering <: Ordering end
-type ReverseOrdering <: Ordering end
-immutable By <: Ordering by::Function end
-immutable Lt <: Ordering lt::Function end
+immutable ForwardOrdering <: Ordering end
+immutable ReverseOrdering{Fwd<:Ordering} <: Ordering
+ fwd::Fwd
+end
+immutable By <: Ordering
+ by::Function
+end
+immutable Lt <: Ordering
+ lt::Function
+end
const Forward = ForwardOrdering()
-const Reverse = ReverseOrdering()
+const Reverse = ReverseOrdering(Forward)
lt(o::ForwardOrdering, a, b) = isless(a,b)
-lt(o::ReverseOrdering, a, b) = isless(b,a)
+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)
+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 ##
-function issorted(itr, o::Ordering = Forward)
+function issorted(itr, order::Ordering)
state = start(itr)
done(itr,state) && return true
prev, state = next(itr, state)
while !done(itr, state)
this, state = next(itr, state)
- lt(o, this, prev) && return false
+ lt(order, this, prev) && return false
prev = this
end
return true
end
+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")
@@ -130,22 +140,12 @@ function select!(v::AbstractVector, r::Range1, lo::Int, hi::Int, o::Ordering)
end
end
-select!(v::AbstractVector, k, o::Ordering=Forward) = select!(v, k, 1, length(v), o)
-select (v::AbstractVector, k, o::Ordering=Forward) = select!(copy(v), k, o)
+select!(v::AbstractVector, k::Union(Int,Range1), o::Ordering) = select!(v,k,1,length(v),o)
+select!(v::AbstractVector, k::Union(Int,Range1);
+ lt::Function=isless, by::Function=identity, order::Ordering=Forward, rev::Bool=false) =
+ select!(v, k, ord(lt,by,order,rev))
-for s in {:select!, :select}
- @eval begin
- $s(v::AbstractVector, k::Int, lt::Function) = $s(v, k, Sort.Lt(lt))
- $s(lt::Function, v::AbstractVector, k::Int) = $s(v, k, lt)
- end
-end
-
-for s in {:selectby!, :selectby}
- @eval begin
- $s(v::AbstractVector, k::Int, by::Function) = $s(v, k, Sort.By(by))
- $s(by::Function, v::AbstractVector, k::Int) = $s(v, k, by)
- end
-end
+select(v::AbstractVector, k::Union(Int,Range1); kws...) = select!(copy(v), k; kws...)
# reference on sorted binary search:
# http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary
@@ -195,38 +195,33 @@ function searchsorted(v::AbstractVector, x, lo::Int, hi::Int, o::Ordering)
elseif lt(o, x, v[m])
hi = m
else
- return searchsortedfirst(v, x, max(lo,1), m, o):searchsortedlast(v, x, m, min(hi,length(v)), o)
+ a = searchsortedfirst(v, x, max(lo,1), m, o)
+ b = searchsortedlast(v, x, m, min(hi,length(v)), o)
+ return a:b
end
end
return lo+1:hi-1
end
-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) = $s(v, x, Forward)
- end
-end
-
-function searchsortedlast{T<:Real}(a::Ranges{T},x::Real,o::Ordering)
+function searchsortedlast{T<:Real}(a::Ranges{T}, x::Real, o::Ordering=Forward)
if step(a) == 0
lt(o, x, first(a)) ? 0 : length(a)
else
n = max(min(iround((x-first(a))/step(a))+1,length(a)),1)
- lt(o,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,o::Ordering)
+function searchsortedfirst{T<:Real}(a::Ranges{T}, x::Real, o::Ordering=Forward)
if step(a) == 0
- lt(o, 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(o,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,o::Ordering)
+function searchsortedlast{T<:Integer}(a::Ranges{T}, x::Real, o::Ordering=Forward)
if step(a) == 0
lt(o, x, first(a)) ? 0 : length(a)
else
@@ -234,24 +229,34 @@ function searchsortedlast{T<:Integer}(a::Ranges{T},x::Real,o::Ordering)
end
end
-function searchsortedfirst{T<:Integer}(a::Ranges{T},x::Real,o::Ordering)
+function searchsortedfirst{T<:Integer}(a::Ranges{T}, x::Real, o::Ordering=Forward)
if step(a) == 0
- lt(o, 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) = searchsortedfirst(a,x):searchsortedlast(a,x)
+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 ##
abstract Algorithm
-type InsertionSortAlg <: Algorithm end
-type QuickSortAlg <: Algorithm end
-type MergeSortAlg <: Algorithm end
-type TimSortAlg <: Algorithm end
+immutable InsertionSortAlg <: Algorithm end
+immutable QuickSortAlg <: Algorithm end
+immutable MergeSortAlg <: Algorithm end
+immutable TimSortAlg <: Algorithm end
const InsertionSort = InsertionSortAlg()
const QuickSort = QuickSortAlg()
@@ -263,15 +268,6 @@ const DEFAULT_STABLE = MergeSort
const SMALL_ALGORITHM = InsertionSort
const SMALL_THRESHOLD = 20
-sort!(v::AbstractVector, a::Algorithm, o::Ordering) = sort!(v, 1, length(v), a, o)
-sort (v::AbstractVector, a::Algorithm, o::Ordering) = sort!(copy(v), a, o)
-
-sort!{T<:Number}(v::AbstractVector{T}, o::Ordering) = sort!(v, DEFAULT_UNSTABLE, o)
-sort {T<:Number}(v::AbstractVector{T}, o::Ordering) = sort (v, DEFAULT_UNSTABLE, o)
-
-sort!(v::AbstractVector, o::Ordering) = sort!(v, DEFAULT_STABLE, o)
-sort (v::AbstractVector, o::Ordering) = sort (v, DEFAULT_STABLE, o)
-
function sort!(v::AbstractVector, lo::Int, hi::Int, ::InsertionSortAlg, o::Ordering)
for i = lo+1:hi
j = i
@@ -307,7 +303,7 @@ function sort!(v::AbstractVector, lo::Int, hi::Int, a::QuickSortAlg, o::Ordering
return v
end
-function sort!(v::AbstractVector, lo::Int, hi::Int, a::MergeSortAlg, o::Ordering, t::AbstractVector)
+function sort!(v::AbstractVector, lo::Int, hi::Int, a::MergeSortAlg, o::Ordering, t=similar(v))
if lo < hi
hi-lo <= SMALL_THRESHOLD && return sort!(v, lo, hi, SMALL_ALGORITHM, o)
@@ -342,54 +338,51 @@ function sort!(v::AbstractVector, lo::Int, hi::Int, a::MergeSortAlg, o::Ordering
return v
end
-sort!(v::AbstractVector, lo::Int, hi::Int, a::MergeSortAlg, o::Ordering) = sort!(v, lo, hi, a, o, similar(v))
include("timsort.jl")
## sortperm: the permutation to sort an array ##
immutable Perm{O<:Ordering,V<:AbstractVector} <: Ordering
- ord::O
- vec::V
+ order::O
+ data::V
end
Perm{O<:Ordering,V<:AbstractVector}(o::O,v::V) = Perm{O,V}(o,v)
-lt(p::Perm, a, b) = lt(p.ord, p.vec[a], p.vec[b])
+lt(p::Perm, a, b) = lt(p.order, p.data[a], p.data[b])
-sortperm(v::AbstractVector, a::Algorithm, o::Ordering) = sort!([1:length(v)], a, Perm(o,v))
-sortperm(v::AbstractVector, o::Ordering) = sortperm(v, DEFAULT_STABLE, o)
+## generic sorting methods ##
-##############
+defalg(v::AbstractArray) = DEFAULT_STABLE
+defalg{T<:Number}(v::AbstractArray{T}) = DEFAULT_UNSTABLE
-# generic sorting methods
+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, rev::Bool=false) =
+ sort!(v, alg, ord(lt,by,order,rev))
-for s in {:sort!, :sort, :sortperm}
- @eval begin
- # default to forward sort ordering
- $s(v::AbstractVector, a::Algorithm) = $s(v, a, Forward)
- $s(v::AbstractVector ) = $s(v, Forward)
+sortperm(v::AbstractVector; alg::Algorithm=defalg(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))
- # also allow ordering before algorithm
- $s(v::AbstractVector, o::Ordering, a::Algorithm) = $s(v, a, o)
- end
-end
+sort(v::AbstractVector; kws...) = sort!(copy(v); kws...)
-for s in {:sort!, :sort, :sortperm}
- @eval begin
- $s(v::AbstractVector, a::Algorithm, lt::Function) = $s(v, a, Sort.Lt(lt))
- $s(v::AbstractVector, lt::Function, a::Algorithm) = $s(v, a, lt)
- $s(v::AbstractVector, lt::Function) = $s(v, Sort.Lt(lt))
- $s(lt::Function, v::AbstractVector, args...) = $s(v, lt, args...)
- end
+## sorting multi-dimensional arrays ##
+
+sort(A::AbstractArray, dim::Integer; kws...) = mapslices(a->sort(a; kws...), A, [dim])
+
+function sortrows(A::AbstractMatrix; kws...)
+ c = 1:size(A,2)
+ rows = [ sub(A,i,c) for i=1:size(A,1) ]
+ p = sortperm(rows; kws...)
+ A[p,:]
end
-for (sb,s) in {(:sortby!, :sort!), (:sortby, :sort), (:sortpermby, :sortperm)}
- @eval begin
- $sb(v::AbstractVector, a::Algorithm, by::Function) = $s(v, a, Sort.By(by))
- $sb(v::AbstractVector, by::Function, a::Algorithm) = $s(v, a, Sort.By(by))
- $sb(v::AbstractVector, by::Function) = $s(v, Sort.By(by))
- $sb(by::Function, v::AbstractVector, args...) = $s(v, Sort.By(by), args...)
- end
+function sortcols(A::AbstractMatrix; kws...)
+ r = 1:size(A,1)
+ cols = [ sub(A,r,i) for i=1:size(A,2) ]
+ p = sortperm(cols; kws...)
+ A[:,p]
end
## fast clever sorting for floats ##
@@ -397,28 +390,28 @@ end
module Float
using ..Sort
+import Core.Intrinsics: unbox, slt_int
import ..Sort: sort!, Perm, lt, Reverse
-import Core.Intrinsics.slt_int, Core.Intrinsics.unbox
typealias Floats Union(Float32,Float64)
-typealias Direct Union(ForwardOrdering,ReverseOrdering)
+typealias Direct Union(ForwardOrdering,ReverseOrdering{ForwardOrdering})
-type Left <: Ordering end
-type Right <: Ordering end
+immutable Left <: Ordering end
+immutable Right <: Ordering end
left(::Direct) = Left()
right(::Direct) = Right()
-left{O<:Direct}(o::Perm{O}) = Perm(left(O()),o.vec)
-right{O<:Direct}(o::Perm{O}) = Perm(right(O()),o.vec)
+left(o::Perm) = Perm(left(o.order),o.data)
+right(o::Perm) = Perm(right(o.order),o.data)
lt{T<:Floats}(::Left, x::T, y::T) = slt_int(unbox(T,y),unbox(T,x))
lt{T<:Floats}(::Right, x::T, y::T) = slt_int(unbox(T,x),unbox(T,y))
isnan(o::Direct, x::Floats) = (x!=x)
-isnan{O<:Direct}(o::Perm{O}, i::Int) = isnan(O(),o.vec[i])
+isnan(o::Perm, i::Int) = isnan(o.order,o.data[i])
-function nans2left!(v::AbstractVector, lo::Int, hi::Int, o::Ordering)
+function nans2left!(v::AbstractVector, o::Ordering, lo::Int=1, hi::Int=length(v))
hi < lo && return lo, hi
i = lo
while (i < hi) & isnan(o, v[i])
@@ -439,7 +432,7 @@ function nans2left!(v::AbstractVector, lo::Int, hi::Int, o::Ordering)
end
return i, hi
end
-function nans2right!(v::AbstractVector, lo::Int, hi::Int, o::Ordering)
+function nans2right!(v::AbstractVector, o::Ordering, lo::Int=1, hi::Int=length(v))
hi < lo && return lo, hi
i = hi
while (i > lo) & isnan(o, v[i])
@@ -460,22 +453,20 @@ function nans2right!(v::AbstractVector, lo::Int, hi::Int, o::Ordering)
end
return lo, i
end
-nans2left!(v::AbstractVector, o::Ordering) = nans2left!(v, 1, length(v), o)
-nans2right!(v::AbstractVector, o::Ordering) = nans2right!(v, 1, length(v), o)
-nans2end!(v::AbstractVector, o::ForwardOrdering) = nans2right!(v, o)
-nans2end!(v::AbstractVector, o::ReverseOrdering) = nans2left!(v, o)
-nans2end!{O<:ForwardOrdering}(v::AbstractVector{Int}, o::Perm{O}) = nans2right!(v, o)
-nans2end!{O<:ReverseOrdering}(v::AbstractVector{Int}, o::Perm{O}) = nans2left!(v, o)
+nans2end!(v::AbstractVector, o::ForwardOrdering) = nans2right!(v,o)
+nans2end!(v::AbstractVector, o::ReverseOrdering) = nans2left!(v,o)
+nans2end!{O<:ForwardOrdering}(v::AbstractVector{Int}, o::Perm{O}) = nans2right!(v,o)
+nans2end!{O<:ReverseOrdering}(v::AbstractVector{Int}, o::Perm{O}) = nans2left!(v,o)
issignleft(o::Direct, x::Floats) = lt(o, x, zero(x))
-issignleft{O<:Direct}(o::Perm{O}, i::Int) = issignleft(O(), o.vec[i])
+issignleft(o::Perm, i::Int) = issignleft(o.order, o.data[i])
function fpsort!(v::AbstractVector, a::Algorithm, o::Ordering)
i, j = lo, hi = nans2end!(v,o)
while true
- while i <= j && issignleft(o, v[i]); i += 1; end
- while i <= j && !issignleft(o, v[j]); j -= 1; end
+ while i <= j && issignleft(o,v[i]); i += 1; end
+ while i <= j && !issignleft(o,v[j]); j -= 1; end
if i <= j
v[i], v[j] = v[j], v[i]
i += 1
@@ -488,49 +479,10 @@ function fpsort!(v::AbstractVector, a::Algorithm, o::Ordering)
sort!(v, i, hi, a, right(o))
return v
end
-sort!{T<:Floats}(v::AbstractVector{T}, a::Algorithm, o::Direct) = fpsort!(v, a, o)
-sort!{O<:Direct,T<:Floats}(v::Vector{Int}, a::Algorithm, o::Perm{O,Vector{T}}) = fpsort!(v, a, o)
-
-end # module Sort.Float
-
-# sorting multi-dimensional arrays
-
-sort(A::AbstractArray, dim::Integer, o::Base.Sort.Ordering=Base.Sort.Forward,
- alg::Base.Sort.Algorithm = DEFAULT_STABLE) =
- mapslices(a->sort(a,o), A, [dim])
-
-sort(A::AbstractArray, dim::Integer, alg::Base.Sort.Algorithm) =
- sort(A, dim, Base.Sort.Forward, alg)
-
-sort(A::AbstractArray, dim::Integer, alg::Base.Sort.Algorithm, o::Base.Sort.Ordering) =
- sort(A, dim, o, alg)
-
-function sortrows(A::AbstractMatrix, o::Base.Sort.Ordering=Base.Sort.Forward,
- alg::Base.Sort.Algorithm = DEFAULT_STABLE)
- c = 1:size(A,2)
- rows = [ sub(A,i,c) for i=1:size(A,1) ]
- p = sortperm(rows, o, alg)
- A[p,:]
-end
-
-sortrows(A::AbstractMatrix, alg::Base.Sort.Algorithm) =
- sortrows(A, Base.Sort.Forward, alg)
-sortrows(A::AbstractMatrix, alg::Base.Sort.Algorithm, o::Base.Sort.Ordering) =
- sortrows(A, o, alg)
+sort!{T<:Floats}(v::AbstractVector{T}, a::Algorithm, o::Direct) = fpsort!(v,a,o)
+sort!{O<:Direct,T<:Floats}(v::Vector{Int}, a::Algorithm, o::Perm{O,Vector{T}}) = fpsort!(v,a,o)
-function sortcols(A::AbstractMatrix, o::Base.Sort.Ordering=Base.Sort.Forward,
- alg::Base.Sort.Algorithm = DEFAULT_STABLE)
- r = 1:size(A,1)
- cols = [ sub(A,r,i) for i=1:size(A,2) ]
- p = sortperm(cols, o, alg)
- A[:,p]
-end
-
-sortcols(A::AbstractMatrix, alg::Base.Sort.Algorithm) =
- sortcols(A, Base.Sort.Forward, alg)
-
-sortcols(A::AbstractMatrix, alg::Base.Sort.Algorithm, o::Base.Sort.Ordering) =
- sortcols(A, o, alg)
+end # module Sort.Float
end # module Sort
View
7 examples/bubblesort.jl
@@ -1,8 +1,7 @@
-importall Base
+immutable BubbleSortAlg <: Sort.Algorithm end
+const BubbleSort = BubbleSortAlg()
-type BubbleSort <: Sort.Algorithm end
-
-function sort!(v::AbstractVector, lo::Int, hi::Int, ::BubbleSort, o::Sort.Ordering)
+function Base.sort!(v::AbstractVector, lo::Int, hi::Int, ::BubbleSortAlg, o::Sort.Ordering)
while true
clean = true
for i = lo:hi-1
View
4 test/arrayops.jl
@@ -430,11 +430,11 @@ begin
@test isless(asc[:,1],asc[:,2])
@test isless(asc[:,2],asc[:,3])
- asr = sortrows(a, Sort.Reverse)
+ asr = sortrows(a, rev=true)
@test isless(asr[2,:],asr[1,:])
@test isless(asr[3,:],asr[2,:])
- asc = sortcols(a, Sort.Reverse)
+ asc = sortcols(a, rev=true)
@test isless(asc[:,2],asc[:,1])
@test isless(asc[:,3],asc[:,2])
View
122 test/sorting.jl
@@ -1,5 +1,5 @@
@test sort([2,3,1]) == [1,2,3]
-@test sort([2,3,1],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])
@@ -30,30 +30,30 @@ 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, Sort.Reverse) ==
- searchsortedfirst(rgv_r, i, Sort.Reverse)
- @test searchsortedlast(rg_r, i, Sort.Reverse) ==
- searchsortedlast(rgv_r, i, 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, Sort.Reverse) ==
- searchsortedfirst(rgv_r, i, Sort.Reverse)
- @test searchsortedlast(rg_r, i, Sort.Reverse) ==
- searchsortedlast(rgv_r, i, 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, Sort.Reverse) ==
- searchsortedfirst(rgv_r, i, Sort.Reverse)
- @test searchsortedlast(rg_r, i, Sort.Reverse) ==
- searchsortedlast(rgv_r, i, 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]
@@ -61,56 +61,56 @@ 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, Sort.Reverse) ==
- searchsortedfirst(rgv_r, i, Sort.Reverse)
- @test searchsortedlast(rg_r, i, Sort.Reverse) ==
- searchsortedlast(rgv_r, i, 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
for i = 2:101
- @test searchsortedfirst(rg,rg[i]) == i
- @test searchsortedfirst(rg,prevfloat(rg[i])) == i
- @test searchsortedfirst(rg,nextfloat(rg[i])) == i+1
+ @test searchsortedfirst(rg, rg[i]) == i
+ @test searchsortedfirst(rg, prevfloat(rg[i])) == i
+ @test searchsortedfirst(rg, nextfloat(rg[i])) == i+1
- @test searchsortedlast(rg,rg[i]) == i
- @test searchsortedlast(rg,prevfloat(rg[i])) == i-1
- @test searchsortedlast(rg,nextfloat(rg[i])) == i
+ @test searchsortedlast(rg, rg[i]) == i
+ @test searchsortedlast(rg, prevfloat(rg[i])) == i-1
+ @test searchsortedlast(rg, nextfloat(rg[i])) == i
end
rg_r = reverse(rg)
for i = 1:100
- @test searchsortedfirst(rg_r,rg_r[i],Sort.Reverse) == i
- @test searchsortedfirst(rg_r,prevfloat(rg_r[i]),Sort.Reverse) == i+1
- @test searchsortedfirst(rg_r,nextfloat(rg_r[i]),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],Sort.Reverse) == i
- @test searchsortedlast(rg_r,prevfloat(rg_r[i]),Sort.Reverse) == i
- @test searchsortedlast(rg_r,nextfloat(rg_r[i]),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)
for alg in [InsertionSort, MergeSort, TimSort]
- b = sort(a, alg)
+ b = sort(a, alg=alg)
@test issorted(b)
- ix = sortperm(a, alg)
+ ix = sortperm(a, alg=alg)
b = a[ix]
@test issorted(b)
@test a[ix] == b
- b = sort(a, alg, Sort.Reverse)
- @test issorted(b, Sort.Reverse)
- ix = sortperm(a, alg, 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, Sort.Reverse)
+ @test issorted(b, rev=true)
@test a[ix] == b
- b = sortby(a, alg, x -> -10x)
- @test issorted(b, Sort.By(x -> -10x))
- ix = sortperm(a, alg, Sort.By(x -> -10x))
+ b = sort(a, alg=alg, by=x->1/x)
+ @test issorted(b, by=x->1/x)
+ ix = sortperm(a, alg=alg, by=x->1/x)
b = a[ix]
- @test issorted(b, Sort.By(x -> -10x))
+ @test issorted(b, by=x->1/x)
@test a[ix] == b
c = copy(a)
@@ -120,26 +120,22 @@ for alg in [InsertionSort, MergeSort, TimSort]
ipermute!(c, ix)
@test c == a
- c = sort(a, alg) do x,y
- x > y
- end
+ c = sort(a, alg=alg, lt=(>))
@test b == c
- c = sortby(a, alg) do x
- -10x
- end
+ c = sort(a, alg=alg, by=x->1/x)
@test b == c
end
-b = sort(a, QuickSort)
+b = sort(a, alg=QuickSort)
@test issorted(b)
-b = sort(a, QuickSort, Sort.Reverse)
-@test issorted(b, Sort.Reverse)
-b = sortby(a, QuickSort, x -> -10x)
-@test issorted(b, Sort.By(x -> -10x))
+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, Sort.Reverse) == 9
-@test select([3,6,30,1,9], 2, Sort.By(x -> -x)) == 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 ##
@@ -161,12 +157,12 @@ for n in [0:10, 100, 1000]
for ord in [Sort.Forward, Sort.Reverse]
# insersion sort as a reference
- pi = sortperm(v,InsertionSort,ord)
+ pi = sortperm(v, alg=InsertionSort, order=ord)
@test isperm(pi)
s = v[pi]
- @test issorted(s, ord)
+ @test issorted(s, order=ord)
@test hist(s,r) == h
- @test all([ issorted(pi[s.==i]) for i in r ])
+ @test all(issorted,[pi[s.==i] for i in r])
si = copy(v)
permute!(si, pi)
@test si == s
@@ -174,7 +170,7 @@ for n in [0:10, 100, 1000]
@test si == v
# mergesort
- pm = sortperm(v,MergeSort,ord)
+ pm = sortperm(v, alg=MergeSort, order=ord)
@test pi == pm
sm = copy(v)
permute!(sm, pm)
@@ -183,7 +179,7 @@ for n in [0:10, 100, 1000]
@test sm == v
# timsort
- pt = sortperm(v,TimSort,ord)
+ pt = sortperm(v, alg=TimSort, order=ord)
@test pi == pt
st = copy(v)
permute!(st, pt)
@@ -192,7 +188,7 @@ for n in [0:10, 100, 1000]
@test st == v
# quicksort (unstable)
- pq = sortperm(v,QuickSort,ord)
+ pq = sortperm(v, alg=QuickSort, order=ord)
@test isperm(pi)
@test v[pq] == s
sq = copy(v)
@@ -207,15 +203,15 @@ for n in [0:10, 100, 1000]
for ord in [Sort.Forward, Sort.Reverse],
alg in [InsertionSort, QuickSort, MergeSort, TimSort]
# test float sorting with NaNs
- s = sort(v,alg,ord)
- @test issorted(s, ord)
+ s = sort(v, alg=alg, order=ord)
+ @test issorted(s, order=ord)
@test reinterpret(Uint64,v[isnan(v)]) == reinterpret(Uint64,s[isnan(s)])
# test float permutation with NaNs
- p = sortperm(v,alg,ord)
+ p = sortperm(v, alg=alg, order=ord)
@test isperm(p)
vp = v[p]
- @test isequal(s,vp)
- @test reinterpret(Uint64,s) == reinterpret(Uint64,vp)
+ @test isequal(vp,s)
+ @test reinterpret(Uint64,vp) == reinterpret(Uint64,s)
end
end
Something went wrong with that request. Please try again.