diff --git a/golang/main.go b/golang/main.go index ea50220..42689e2 100644 --- a/golang/main.go +++ b/golang/main.go @@ -2,12 +2,12 @@ package main import ( "fmt" + "io" "math/rand" + "os" "time" ) -// var MAXGOROUTINES = 10000 - func Cqsort(s []int, MAXGOROUTINES int) { if len(s) <= 1 { return @@ -77,34 +77,42 @@ func pickPivot(s []int) (pivotIdx int, pivot int) { return } -func Qsort(s []int) { - if len(s) <= 1 { - return - } - pivotIdx := partition(s) - Qsort(s[:pivotIdx+1]) - Qsort(s[pivotIdx+1:]) - return -} - func main() { - sortSize := 50000000 - // MAXGOROUTINES := 1 - unsorted := make([]int, 0, sortSize) + file, err := os.Open("data/perm50e6.txt") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + var perline int + var nums1 []int + var nums2 []int + fmt.Println("Reading File:...") + for { + _, err := fmt.Fscanf(file, "%d\n", &perline) // give a patter to scan + + if err != nil { + + if err == io.EOF { + break // stop reading the file + } + fmt.Println(err) + os.Exit(1) + } + nums1 = append(nums1, perline) + nums2 = append(nums2, perline) + } + fmt.Println("Sorting!") - // MAXGOROUTINES = 100000 start := time.Now() - unsorted = rand.Perm(sortSize) - Cqsort(unsorted, 8) + Cqsort(nums1, 16) duration := time.Since(start) fmt.Println("goroutines", duration) - // MAXGOROUTINES = 1 start = time.Now() - // unsorted = rand.Perm(sortSize) - Cqsort(unsorted, 1) + Cqsort(nums2, 1) duration = time.Since(start) fmt.Println(duration) diff --git a/rust/src/main.rs b/rust/src/main.rs index db8d624..bf77eb8 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -1,11 +1,18 @@ use std::fs; fn main() { - let input = fs::read_to_string("../data/perm50e3.txt") + let input = fs::read_to_string("../data/perm50e6.txt") .expect("Could not read file") .lines() .map(|s| s.parse::().unwrap()) .collect::>(); - println!("{}", input.len()); + // println!("{}", input.len()); + // let input = vec![100, 32, 57, 10]; +} + +fn Cqsort(s: &Vec) { + if s.len() <= 1 { + return; + } } diff --git a/rust/src/original.rs b/rust/src/original.rs new file mode 100644 index 0000000..6eafc20 --- /dev/null +++ b/rust/src/original.rs @@ -0,0 +1,156 @@ +use rayon::join; + +fn partition(d: &mut [T], is_less: &F) -> usize +where + F: Fn(&T, &T) -> bool, +{ + d.swap(0, d.len() / 2); + let mut mid = 0; + for i in 1..d.len() { + if is_less(&d[i], &d[0]) { + mid += 1; + d.swap(i, mid); + } + } + d.swap(0, mid); + mid +} + +fn insert_sort(d: &mut [T], is_less: &F) +where + F: Fn(&T, &T) -> bool, +{ + for i in 1..d.len() { + let mut n = i; + while n > 0 && is_less(&d[n], &d[n - 1]) { + d.swap(n, n - 1); + n -= 1; + } + } +} + +fn quick_sort(d: &mut [T], is_less: &F) +where + F: Fn(&T, &T) -> bool, +{ + if d.len() > 30 { + let mut mid = partition(d, is_less); + if mid < d.len() / 2 { + mid += 1; + } + let (left, right) = d.split_at_mut(mid); + quick_sort(left, is_less); + quick_sort(right, is_less); + } else { + insert_sort(d, is_less); + } +} + +fn par_quick_sort(d: &mut [T], is_less: &F) +where + F: Fn(&T, &T) -> bool + Send + Sync, + T: Send, +{ + if d.len() > 30 { + let mut mid = partition(d, is_less); + if mid < d.len() / 2 { + mid += 1; + } + let (left, right) = d.split_at_mut(mid); + + if right.len() > 100_000 { + join( + || par_quick_sort(left, is_less), + || par_quick_sort(right, is_less), + ); + } else { + quick_sort(left, is_less); + quick_sort(right, is_less); + } + } else { + insert_sort(d, is_less); + } +} + +pub trait QSort { + fn qsort(&mut self); + + fn is_sorted(&self) -> bool; +} + +impl QSort for [T] +where + T: Ord, +{ + fn qsort(&mut self) { + quick_sort(self, &|a: &T, b: &T| a.lt(b)); + } + + fn is_sorted(&self) -> bool { + self.windows(2).all(|w| w[0] <= w[1]) + } +} + +pub trait ParQSort { + fn par_qsort(&mut self); +} + +impl ParQSort for [T] +where + T: Ord + Send, +{ + fn par_qsort(&mut self) { + par_quick_sort(self, &|a: &T, b: &T| a.lt(b)); + } +} + +use rand::distributions::{Distribution, Uniform}; +use rand::thread_rng; +use rayon::prelude::*; +use std::time::Instant; + +fn main() { + let len = 50_000_000; + let orig: Vec = Uniform::from(0..1_000_000_000) + .sample_iter(&mut thread_rng()) + .take(len) + .collect(); + + macro_rules! test_sort { + ($name:expr, $sort:ident) => { + println!( + "Sorting {} million numbers with {} in Rust ...", + len / 1_000_000, + $name + ); + let mut data = orig.clone(); + let start = Instant::now(); + data.$sort(); + println!("Time: {:.2?}", start.elapsed()); + assert!(data.is_sorted()); + } + } + + test_sort!("naive quicksort", qsort); + test_sort!("stdlib quicksort", sort_unstable); + test_sort!("naive parallel quicksort", par_qsort); + test_sort!("Rayon quicksort", par_sort_unstable); +} + +#[cfg(test)] +mod test { + use super::*; + use quickcheck::quickcheck; + + quickcheck! { + fn test_all(d: Vec) -> bool { + let mut d = d; + + let mut expected = d.clone(); + expected.sort_unstable(); + d.par_qsort(); + + expected == d + } + } +} \ No newline at end of file diff --git a/rust/src/test.scm.txt b/rust/src/test.scm.txt new file mode 100644 index 0000000..c1fad15 --- /dev/null +++ b/rust/src/test.scm.txt @@ -0,0 +1,8 @@ +(define mycount + (lambda (x lst) + (cond ((null? lst) 0) + ((= x (car lst)) (+ 1 (mycount x (cdr lst)))) + (else (mycount x (cdr lst)))))) + +;(mycount 5 '((5 2) (2 (4 2) 6) 2)) +(mycount 3 '(1 2 3 4 3 2 3)) \ No newline at end of file