let inline swap (data:'a[]) a b =
let t = data.[a]
data.[a] <- data.[b]
data.[b] <- t
/// Sort the values from an array. Put the smallest
/// at index a, biggest at c, and median at b.
let inline median_of_three (data:'a[]) a b c =
if data.[b] < data.[a] then
swap data a b
if data.[c] < data.[b] then
swap data c b
if data.[b] < data.[a] then
swap data a b
let inline partition (data:'a[]) a b =
// After this is called, return the new position
// of the pivot value. After the call, all values before
// the pivot position should be <= to the pivot, and all values
// after should be >= the pivot.
let mutable i = a - 1
let mutable j = b
let pivot = data.[b]
while i < j do
i <- i + 1
while data.[i] < pivot do
i <- i + 1
j <- j - 1
while data.[j] > pivot do
j <- j - 1
if i < j then
swap data i j
// Now, i is >= j. data.[i] is >= pivot.
// data.[j] <= pivot. So, move the pivot
// to the middle where it belongs, and move
// the value at i to the end of the array.
swap data i b
i
let inline sort (data:'a[]) =
let rec loop a b =
if a >= b then ()
elif a + 1 = b then
if data.[a] > data.[b] then swap data a b
else
let c = (a+b)/2
median_of_three data a b c
let p = partition data a b
loop a (p-1)
loop (p+1) b
loop 0 (data.Length - 1)
let
rand = new System.
Random()
let shuffle (data:'a[]) =
let N = data.Length
for i in 0 .. N - 2 do
let j = rand.Next(N-i) + i
swap data i j
let isSorted (data:'a[]) =
for i in 0 .. data.Length - 2 do
if data.[i] > data.[i+1] then
failwith "Not sorted"
let testf data =
printfn "before: %A" data
sort data
printfn "after : %A" data
testf [|2;4;1;0|]
testf [||]
testf [|10 .. -1 .. 1 |]
testf [|1;1;1;1;|]
testf [|1..6|]