1
1
## standard sort comparisons ##
3
_jl_fp_pos_lt(x::Float32, y::Float32) = slt_int(unbox(Float32,x),unbox(Float32,y))
4
_jl_fp_pos_lt(x::Float64, y::Float64) = slt_int(unbox(Float64,x),unbox(Float64,y))
5
_jl_fp_pos_le(x::Float32, y::Float32) = sle_int(unbox(Float32,x),unbox(Float32,y))
6
_jl_fp_pos_le(x::Float64, y::Float64) = sle_int(unbox(Float64,x),unbox(Float64,y))
8
_jl_fp_neg_lt(x::Float32, y::Float32) = slt_int(unbox(Float32,y),unbox(Float32,x))
9
_jl_fp_neg_lt(x::Float64, y::Float64) = slt_int(unbox(Float64,y),unbox(Float64,x))
10
_jl_fp_neg_le(x::Float32, y::Float32) = sle_int(unbox(Float32,y),unbox(Float32,x))
11
_jl_fp_neg_le(x::Float64, y::Float64) = sle_int(unbox(Float64,y),unbox(Float64,x))
15
search_sorted_first_r,
16
search_sorted_first_by,
19
search_sorted_last_by,
48
insertionsort_perm_r!,
49
insertionsort_perm_by,
50
insertionsort_perm_by!,
82
import Base.sort, Base.issorted, Base.sort, Base.sort!, Base.sortperm, Base.slt_int,
83
Base.unbox, Base.sle_int, Base.length
85
fp_pos_lt(x::Float32, y::Float32) = slt_int(unbox(Float32,x),unbox(Float32,y))
86
fp_pos_lt(x::Float64, y::Float64) = slt_int(unbox(Float64,x),unbox(Float64,y))
87
fp_pos_le(x::Float32, y::Float32) = sle_int(unbox(Float32,x),unbox(Float32,y))
88
fp_pos_le(x::Float64, y::Float64) = sle_int(unbox(Float64,x),unbox(Float64,y))
90
fp_neg_lt(x::Float32, y::Float32) = slt_int(unbox(Float32,y),unbox(Float32,x))
91
fp_neg_lt(x::Float64, y::Float64) = slt_int(unbox(Float64,y),unbox(Float64,x))
92
fp_neg_le(x::Float32, y::Float32) = sle_int(unbox(Float32,y),unbox(Float32,x))
93
fp_neg_le(x::Float64, y::Float64) = sle_int(unbox(Float64,y),unbox(Float64,x))
13
95
## internal sorting functionality ##
15
macro _jl_sort_functions(suffix, lt, args...)
16
insertionsort = esc(symbol("_jl_insertionsort$suffix"))
17
quicksort = esc(symbol("_jl_quicksort$suffix"))
18
mergesort = esc(symbol("_jl_mergesort$suffix"))
19
pivot_middle = esc(symbol("_jl_pivot_middle$suffix"))
99
for (suffix, lt, args) in (("", (a,b)->:(isless($a,$b)), ()),
100
("_r", (a,b)->:(isless($b,$a)), ()),
101
("", (a,b)->:(lt($a,$b)), (:(lt::Function),)),
102
("_by", (a,b)->:(isless(by($a),by($b))), (:(by::Function),)),
103
## special sorting for floating-point arrays ##
104
("_fp_pos", (a,b)->:(fp_pos_lt($a,$b)), ()),
105
("_fp_neg", (a,b)->:(fp_neg_lt($a,$b)), ()))
106
insertionsort = symbol("insertionsort$(suffix)")
107
insertionsort! = symbol("insertionsort$(suffix)!")
108
insertionsort_perm = symbol("insertionsort_perm$(suffix)")
109
insertionsort_perm! = symbol("insertionsort_perm$(suffix)!")
110
quicksort = symbol("quicksort$(suffix)")
111
quicksort! = symbol("quicksort$(suffix)!")
112
quicksort_perm = symbol("quicksort_perm$(suffix)")
113
quicksort_perm! = symbol("quicksort_perm$(suffix)!")
114
mergesort = symbol("mergesort$(suffix)")
115
mergesort! = symbol("mergesort$(suffix)!")
116
mergesort_perm = symbol("mergesort_perm$(suffix)")
117
mergesort_perm! = symbol("mergesort_perm$(suffix)!")
118
pivot_middle = symbol("pivot_middle$(suffix)")
119
issorted = symbol("issorted$(suffix)")
120
quickselect = symbol("quickselect$(suffix)")
121
select = symbol("select$(suffix)")
122
select! = symbol("select$(suffix)!")
123
search_sorted = symbol("search_sorted$(suffix)")
124
search_sorted_first = symbol("search_sorted_first$(suffix)")
125
search_sorted_last = symbol("search_sorted_last$(suffix)")
126
sortperm = symbol("sortperm$(suffix)")
127
sortperm! = symbol("sortperm$(suffix)!")
23
130
# sorting should be stable
24
131
# Thus, if a permutation is required, or records are being sorted
67
($pivot_middle)(a,b,c) = $(lt(:a,:b)) ? ($(lt(:b,:c)) ? b : c) : ($(lt(:a,:c)) ? a : c)
177
($insertionsort_perm!){T}($(args...), a::AbstractVector{T}, p::AbstractVector{Int}) =
178
($insertionsort_perm!)($(args...), a, p, 1, length(a))
179
($insertionsort_perm!){T}($(args...), a::AbstractVector{T}) =
180
($insertionsort_perm!)($(args...), a, [1:length(a)])
181
($insertionsort_perm){T}($(args...), a::AbstractVector{T}, args2...) =
182
($insertionsort_perm!)($(args...), copy(a), [1:length(a)], args2...)
185
($pivot_middle)($(args...),a,b,c) = $(lt(:a,:b)) ? ($(lt(:b,:c)) ? b : c) : ($(lt(:a,:c)) ? a : c)
69
187
# very fast but unstable
70
function ($quicksort)($(args...), a::AbstractVector, lo::Int, hi::Int)
188
function ($quicksort!)($(args...), a::AbstractVector, lo::Int, hi::Int)
73
return $(expr(:call, insertionsort, args..., :a, :lo, :hi))
191
return $(expr(:call, insertionsort!, args..., :a, :lo, :hi))
76
# pivot = (a[lo]+a[hi])/2 # 1.14x
77
pivot = a[(lo+hi)>>>1] # 1.15x
78
# pivot = (a[lo]+a[hi]+a[(lo+hi)>>>1])/3 # 1.16x
79
# pivot = _jl_pivot_middle(a[lo], a[hi], a[(lo+hi)>>>1]) # 1.23x
80
# pivot = a[randival(lo,hi)] # 1.28x
194
# pivot = (a[lo]+a[hi])/2 # 1.14x
195
pivot = a[(lo+hi)>>>1] # 1.15x
196
# pivot = (a[lo]+a[hi]+a[(lo+hi)>>>1])/3 # 1.16x
197
# pivot = pivot_middle($(args...), a[lo], a[hi], a[(lo+hi)>>>1]) # 1.23x
198
# pivot = a[randival(lo,hi)] # 1.28x
82
200
while $(lt(:(a[i]), :pivot)); i += 1; end
83
201
while $(lt(:pivot, :(a[j]))); j -= 1; end
91
$(expr(:call, quicksort, args..., :a, :lo, :j))
209
$(expr(:call, quicksort!, args..., :a, :lo, :j))
216
($quicksort!)($(args...), a::AbstractVector) = ($quicksort!)($(args...), a, 1, length(a))
217
($quicksort)($(args...), a::AbstractVector) = ($quicksort!)($(args...), copy(a), 1, length(a))
98
219
# less fast & not in-place, but stable
99
function ($mergesort)($(args...), a::AbstractVector, lo::Int, hi::Int, b::AbstractVector)
220
function ($mergesort!)($(args...), a::AbstractVector, lo::Int, hi::Int, b::AbstractVector)
102
return ($insertionsort)($(args...), a, lo, hi)
223
return ($insertionsort!)($(args...), a, lo, hi)
106
($mergesort)($(args...), a, lo, m, b)
107
($mergesort)($(args...), a, m+1, hi, b)
227
($mergesort!)($(args...), a, lo, m, b)
228
($mergesort!)($(args...), a, m+1, hi, b)
260
($mergesort!){T}($(args...), a::AbstractVector{T}) = ($mergesort!)($(args...), a, 1, length(a), Array(T,length(a)))
261
($mergesort){T}($(args...), a::AbstractVector{T}) =
262
($mergesort!)($(args...), copy(a), 1, length(a), Array(T,length(a)))
139
264
# permutes auxilliary arrays mirroring the sort
140
function ($mergesort)($(args...),
141
a::AbstractVector, p::AbstractVector{Int}, lo::Int, hi::Int,
142
b::AbstractVector, pb::AbstractVector{Int})
265
function ($mergesort_perm!)($(args...),
266
a::AbstractVector, p::AbstractVector{Int}, lo::Int, hi::Int,
267
b::AbstractVector, pb::AbstractVector{Int})
145
return ($insertionsort)($(args...), a, p, lo, hi)
270
return ($insertionsort_perm!)($(args...), a, p, lo, hi)
149
($mergesort)($(args...), a, p, lo, m, b, pb)
150
($mergesort)($(args...), a, p, m+1, hi, b, pb)
274
($mergesort_perm!)($(args...), a, p, lo, m, b, pb)
275
($mergesort_perm!)($(args...), a, p, m+1, hi, b, pb)
186
end; end # quote / macro
188
@_jl_sort_functions "" :(isless($a,$b))
189
@_jl_sort_functions "_r" :(isless($b,$a))
190
@_jl_sort_functions "_lt" :(lt($a,$b)) lt::Function
191
@_jl_sort_functions "_by" :(isless(by($a),by($b))) by::Function
311
($mergesort_perm!){T}($(args...), a::AbstractVector{T}, p::AbstractVector{Int}) =
312
($mergesort_perm!)($(args...), a, p, 1, length(a), Array(T,length(a)), Array(Int,length(a)))
313
($mergesort_perm!){T}($(args...), a::AbstractVector{T}) =
314
($mergesort_perm!)($(args...), a, [1:length(a)])
315
($mergesort_perm){T}($(args...), a::AbstractVector{T}, args2...) =
316
($mergesort_perm!)($(args...), copy(a), [1:length(a)], args2...)
319
function ($issorted)($(args...), v::AbstractVector)
320
for i = 1:length(v)-1
321
if $(lt(:(v[i+1]), :(v[i])))
328
function ($quickselect)($(args...), a::AbstractArray, k::Int, lo::Int, hi::Int)
329
if k < lo || k > hi; error("k is out of bounds"); end
333
if lo == hi; return a[lo]; end
336
pivot = ($pivot_middle)($(args...), a[lo], a[hi], a[(lo+hi)>>>1])
338
while $(lt(:(a[i]), :(pivot))); i += 1; end
339
while $(lt(:(pivot), :(a[j]))); j -= 1; end
340
#if isequal(a[i], a[j])
341
if !$(lt(:(a[i]), :(a[j]))) && !$(lt(:(a[j]), :(a[i])))
344
a[i], a[j] = a[j], a[i]
349
len = pivot_ind - lo + 1
363
($select!)($(args...), a::AbstractArray, k::Int) = ($quickselect)($(args...), a, k, 1, length(a))
364
($select)($(args...), a::AbstractArray, k::Int) = ($quickselect)($(args...), copy(a), k, 1, length(a))
366
($search_sorted)($(args...), a::Vector, x) = ($search_sorted_first)($(args...), a, x, 1, length(a))
368
($search_sorted_last)($(args...), a::Vector, x) = ($search_sorted_last)($(args...), a, x, 1, length(a))
370
function ($search_sorted_last)($(args...), a::Vector, x, lo::Int, hi::Int)
371
## Index of the last value of vector a that is less than or equal to x.
372
## Returns 0 if x is less than all values of a.
374
## Good reference: http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary
379
if $(lt(:(x), :(a[i])))
388
($search_sorted_first)($(args...), a::Vector, x) = ($search_sorted_first)($(args...), a, x, 1, length(a))
390
function ($search_sorted_first)($(args...), a::Vector, x, lo::Int, hi::Int)
391
## Index of the first value of vector a that is greater than or equal to x.
392
## Returns length(a) + 1 if x is greater than all values in a.
394
## Good reference: http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary
399
if $(lt(:(a[i]), :(x)))
408
($sortperm){T}($(args...), a::AbstractVector{T}, args2...) = ($mergesort_perm)($(args...), a, args2...)
409
($sortperm!){T}($(args...), a::AbstractVector{T}, args2...) = ($mergesort_perm!)($(args...), a, args2...)
411
end; end # @eval / for
413
search_sorted_last_r(a::Ranges, x::Real) = search_sorted_last(a, x)
414
search_sorted_first_r(a::Ranges, x::Real) = search_sorted_first(a, x)
415
search_sorted_r(a::Ranges, x::Real) = search_sorted(a, x)
416
search_sorted(a::Ranges, x::Real) = search_sorted_first(a, x)
418
search_sorted_last(a::Ranges, x::Real) =
419
max(min(int(fld(x - a[1], step(a))) + 1, length(a)), 0)
421
function search_sorted_first(a::Ranges, x::Real)
424
max(min(int(fld(n, s)) + (rem(n, s) != 0), length(a)), 0) + 1
193
427
## external sorting functions ##
195
sort!{T<:Real}(a::AbstractVector{T}) = _jl_quicksort(a, 1, length(a))
196
sortr!{T<:Real}(a::AbstractVector{T}) = _jl_quicksort_r(a, 1, length(a))
197
sort!{T}(a::AbstractVector{T}) = _jl_mergesort(a, 1, length(a), Array(T,length(a)))
198
sortr!{T}(a::AbstractVector{T}) = _jl_mergesort_r(a, 1, length(a), Array(T,length(a)))
429
sort!{T<:Real}(a::AbstractVector{T}) = quicksort!(a, 1, length(a))
430
sortr!{T<:Real}(a::AbstractVector{T}) = quicksort_r!(a, 1, length(a))
431
sort!{T}(a::AbstractVector{T}) = mergesort!(a, 1, length(a), Array(T,length(a)))
432
sortr!{T}(a::AbstractVector{T}) = mergesort_r!(a, 1, length(a), Array(T,length(a)))
200
434
sort!{T}(lt::Function, a::AbstractVector{T}) =
201
_jl_mergesort_lt(lt, a, 1, length(a), Array(T,length(a)))
435
mergesort!(lt, a, 1, length(a), Array(T,length(a)))
202
436
sort_by!{T}(by::Function, a::AbstractVector{T}) =
203
_jl_mergesort_by(by, a, 1, length(a), Array(T,length(a)))
205
## special sorting for floating-point arrays ##
207
@_jl_sort_functions "_fp_pos" :(_jl_fp_pos_lt($a,$b))
208
@_jl_sort_functions "_fp_neg" :(_jl_fp_neg_lt($a,$b))
437
mergesort_by!(by, a, 1, length(a), Array(T,length(a)))
210
439
# push NaNs to the end of a, returning # of non-NaNs
211
function _jl_nans_to_end{T<:FloatingPoint}(a::AbstractVector{T})
440
function nans_to_end{T<:FloatingPoint}(a::AbstractVector{T})
252
_jl_quicksort_fp_neg(a, 1, j)
253
_jl_quicksort_fp_pos(a, i, n)
257
# TODO: something sensible should happen when each_col et. al. are used with a
258
# pure function argument
259
function each_col!(f::Function, a::AbstractMatrix)
267
function each_row!(f::Function, a::AbstractMatrix)
270
f(sub(a, i:m:numel(a)))
275
function each_vec!(f::Function, a::AbstractMatrix, dim::Integer)
276
if dim == 1; return each_col!(f,a); end
277
if dim == 2; return each_row!(f,a); end
278
error("invalid matrix dimensions: $dim")
281
each_col(f::Function, a::AbstractMatrix) = each_col!(f,copy(a))
282
each_row(f::Function, a::AbstractMatrix) = each_row!(f,copy(a))
283
each_vec(f::Function, a::AbstractMatrix, d::Integer) = each_vec!(f,copy(a),d)
481
quicksort_fp_neg!(a, 1, j)
482
quicksort_fp_pos!(a, i, n)
285
487
## other sorting functions defined in terms of sort! ##
335
sortperm{T}(a::AbstractVector{T}) =
336
_jl_mergesort(copy(a), [1:length(a)], 1, length(a),
337
Array(T, length(a)), Array(Int, length(a)))
339
function issorted(v::AbstractVector)
340
for i = 1:length(v)-1
341
if isless(v[i+1], v[i])
348
function _jl_quickselect(a::AbstractArray, k::Int, lo::Int, hi::Int)
349
if k < lo || k > hi; error("k is out of bounds"); end
353
if lo == hi; return a[lo]; end
356
pivot = _jl_pivot_middle(a[lo], a[hi], a[(lo+hi)>>>1])
358
while isless(a[i], pivot); i += 1; end
359
while isless(pivot, a[j]); j -= 1; end
360
if isequal(a[i], a[j])
363
a[i], a[j] = a[j], a[i]
368
length = pivot_ind - lo + 1
382
select(a::AbstractArray, k::Int) = _jl_quickselect(copy(a), k, 1, length(a))
383
select!(a::AbstractArray, k::Int) = _jl_quickselect(a, k, 1, length(a))
385
search_sorted(a::Vector, x) = search_sorted(a, x, 1, length(a))
387
function search_sorted(a::Vector, x, lo::Int, hi::Int)
399
return isless(a[lo],x) ? hi : lo
402
search_sorted_last(a::Vector, x) = search_sorted_last(a, x, 0, length(a)+1)
404
function search_sorted_last(a::Vector, x, lo::Int, hi::Int)
405
## Index of the last value of vector a that is less than or equal to x.
406
## Returns 0 if x is less than all values of a.
408
## Good reference: http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary
420
search_sorted_first(a::Vector, x) = search_sorted_first(a, x, 0, length(a)+1)
422
function search_sorted_first(a::Vector, x, lo::Int, hi::Int)
423
## Index of the first value of vector a that is greater than or equal to x.
424
## Returns length(a) + 1 if x is greater than all values in a.
426
## Good reference: http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary
438
557
order(a::AbstractVector) = sortperm(a)[2]