add shared quicksort example

This commit is contained in:
Folkert 2020-08-14 15:44:17 +02:00
parent d8c71c23f4
commit c3b242bad1
2 changed files with 112 additions and 0 deletions

View File

@ -0,0 +1,65 @@
app Quicksort provides [ quicksort ] imports []
quicksort : List Int -> List Int
quicksort = \originalList ->
quicksortHelp : List (Num a), Int, Int -> List (Num a)
quicksortHelp = \list, low, high ->
if low < high then
when partition low high list is
Pair partitionIndex partitioned ->
partitioned
|> quicksortHelp low (partitionIndex - 1)
|> quicksortHelp (partitionIndex + 1) high
else
list
swap : Int, Int, List a -> List a
swap = \i, j, list ->
when Pair (List.get list i) (List.get list j) is
Pair (Ok atI) (Ok atJ) ->
list
|> List.set i atJ
|> List.set j atI
_ ->
[]
partition : Int, Int, List (Num a) -> [ Pair Int (List (Num a)) ]
partition = \low, high, initialList ->
when List.get initialList high is
Ok pivot ->
when partitionHelp (low - 1) low initialList high pivot is
Pair newI newList ->
Pair (newI + 1) (swap (newI + 1) high newList)
Err _ ->
Pair (low - 1) initialList
partitionHelp : Int, Int, List (Num a), Int, (Num a) -> [ Pair Int (List (Num a)) ]
partitionHelp = \i, j, list, high, pivot ->
if j < high then
when List.get list j is
Ok value ->
if value <= pivot then
partitionHelp (i + 1) (j + 1) (swap (i + 1) j list) high pivot
else
partitionHelp i (j + 1) list high pivot
Err _ ->
Pair i list
else
Pair i list
result = quicksortHelp originalList 0 (List.len originalList - 1)
# Absolutely make the `originalList` Shared by using it again here
if List.len (List.set originalList 0 3) > 3 then
result
else
result

View File

@ -0,0 +1,47 @@
use std::time::SystemTime;
#[link(name = "roc_app", kind = "static")]
extern "C" {
#[allow(improper_ctypes)]
#[link_name = "quicksort#1"]
fn quicksort(list: &[i64]) -> Box<[i64]>;
}
const NUM_NUMS: usize = 1_00;
pub fn main() {
let nums = {
let mut nums = Vec::with_capacity(NUM_NUMS + 1);
// give this list refcount 1
nums.push((std::usize::MAX - 1) as i64);
for index in 1..nums.capacity() {
let num = index as i64 % 12345;
nums.push(num);
}
nums
};
println!("Running Roc shared quicksort");
let start_time = SystemTime::now();
let answer = unsafe { quicksort(&nums[1..]) };
let end_time = SystemTime::now();
let duration = end_time.duration_since(start_time).unwrap();
println!(
"Roc quicksort took {:.4} ms to compute this answer: {:?}",
duration.as_secs_f64() * 1000.0,
// truncate the answer, so stdout is not swamped
// NOTE index 0 is the refcount!
&answer[1..20]
);
// the pointer is to the first _element_ of the list,
// but the refcount precedes it. Thus calling free() on
// this pointer would segfault/cause badness. Therefore, we
// leak it for now
Box::leak(answer);
}