I tried to implement the bitonicsorter I wrote about in my masters thesis. The result is the following code:
// BitonicSort
//
// http://www.diku.dk/forskning/performance-engineering/Ramon/thesis.pdf
let inline isPow2 x =
match x with
| 0 -> false
| _ -> x &&& (x - 1) = 0
let comparator x y =
match x with
| _ when x < y -> (x,y)
| _ -> (y,x)
let halfCleaner bs =
let n = bs |> Array.length
let m = n/2
match isPow2(n) with
| true -> ()
| false -> failwith "Input array %A, must be n=2^k" bs
Array.mapi(fun i x ->
match i with
| _ when i < m -> fst (comparator x bs.[m+i])
| _ -> snd (comparator x bs.[i-m])) bs
let rec bitonicSorter bs =
let n = bs |> Array.length
let m = n/2
match isPow2(n) with
| true -> ()
| false -> failwith "Input array %A, must be n=2^k" bs
let bs' = halfCleaner bs
let bs1 = bs'.[0 .. (m - 1)]
let bs2 = bs'.[m .. (n - 1)]
match n with
| _ when 2 < n ->
Array.append (bitonicSorter bs1) (bitonicSorter bs2)
| _ -> bs'
let merger ss1 ss2 =
let m1 = ss1 |> Array.length
let m2 = ss2 |> Array.length
let n = m1 + m2
let m = n/2
match (m1 = m2) with
| true -> ()
| false -> failwith "Input arrays (%A,%A), must have the same length" ss1 ss2
match isPow2(n) with
| true -> ()
| false -> failwith "Comibnation of (%A,%A) arrays, must be n=2^k" ss1 ss2
let ss2' = ss2 |> Array.rev
let ss1'' = Array.map2(fun x y -> fst (comparator x y)) ss1 ss2'
let ss2'' = Array.map2(fun x y -> snd (comparator x y)) ss1 ss2'
match n with
| _ when 2 < n -> Array.append (bitonicSorter ss1'') (bitonicSorter ss2'')
| _ -> Array.append ss1'' ss2''
let rec sorter array =
let n = array |> Array.length
let m = n/2
match isPow2(n) with
| true -> ()
| false -> failwith "Input array %A, must be n=2^k" array
let as1 = array.[0 .. (m - 1)]
let as2 = array.[m .. (n - 1)]
match n with
| _ when 2 < n -> merger (sorter as1) (sorter as2)
| _ -> merger as1 as2
let n = 1 <<< 16
let a = Array.init n (fun i -> i % 2)
sorter a
It still lacks of speed, even with the use of the included libraries
Array.Parallel
or Async.Parallel
/
Async.RunSynchronously
(fork/join) but it was fun to write as
usual.
REMARK: It’s much more readable than the code I wrote back in the days …