Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/libcore/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,12 @@ impl<'a,T> MutableSlice<'a, T> for &'a mut [T] {
let mut i: uint = 0;
let ln = self.len();
while i < ln / 2 {
self.swap(i, ln - i - 1);
// Unsafe swap to avoid the bounds check in safe swap.
unsafe {
let pa: *mut T = self.unsafe_mut_ref(i);
let pb: *mut T = self.unsafe_mut_ref(ln - i - 1);
ptr::swap(pa, pb);
}
i += 1;
}
}
Expand Down
179 changes: 131 additions & 48 deletions src/test/bench/shootout-fannkuch-redux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,68 +38,151 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

use std::cmp::max;
use std::{cmp, iter, mem};
use std::sync::Future;

fn fact(n: uint) -> uint {
range(1, n + 1).fold(1, |accu, i| accu * i)
fn rotate(x: &mut [i32]) {
let mut prev = x[0];
for place in x.mut_iter().rev() {
prev = mem::replace(place, prev)
}
}

fn fannkuch(n: uint, i: uint) -> (int, int) {
let mut perm = Vec::from_fn(n, |e| ((n + e - i) % n + 1) as i32);
let mut tperm = perm.clone();
let mut count = Vec::from_elem(n, 0u);
let mut perm_count = 0i;
let mut checksum = 0;
fn next_permutation(perm: &mut [i32], count: &mut [i32]) {
for i in range(1, perm.len()) {
rotate(perm.mut_slice_to(i + 1));
let count_i = &mut count[i];
if *count_i >= i as i32 {
*count_i = 0;
} else {
*count_i += 1;
break
}
}
}

struct P {
p: [i32, .. 16],
}

struct Perm {
cnt: [i32, .. 16],
fact: [u32, .. 16],
n: u32,
permcount: u32,
perm: P,
}

impl Perm {
fn new(n: u32) -> Perm {
let mut fact = [1, .. 16];
for i in range(1, n as uint + 1) {
fact[i] = fact[i - 1] * i as u32;
}
Perm {
cnt: [0, .. 16],
fact: fact,
n: n,
permcount: 0,
perm: P { p: [0, .. 16 ] }
}
}

fn get(&mut self, mut idx: i32) -> P {
let mut pp = [0u8, .. 16];
self.permcount = idx as u32;
for (i, place) in self.perm.p.mut_iter().enumerate() {
*place = i as i32 + 1;
}

for countdown in range(1, fact(n - 1) + 1).rev() {
for i in range(1, n) {
let perm0 = *perm.get(0);
for j in range(0, i) {
*perm.get_mut(j) = *perm.get(j + 1);
for i in range(1, self.n as uint).rev() {
let d = idx / self.fact[i] as i32;
self.cnt[i] = d;
idx %= self.fact[i] as i32;
for (place, val) in pp.mut_iter().zip(self.perm.p.slice_to(i + 1).iter()) {
*place = (*val) as u8
}
*perm.get_mut(i) = perm0;

let count_i = count.get_mut(i);
if *count_i >= i {
*count_i = 0;
} else {
*count_i += 1;
break;

let d = d as uint;
for j in range(0, i + 1) {
self.perm.p[j] = if j + d <= i {pp[j + d]} else {pp[j+d-i-1]} as i32;
}
}

tperm.clone_from(&perm);
let mut flips_count = 0;
loop {
let k = *tperm.get(0);
if k == 1 { break; }
tperm.mut_slice_to(k as uint).reverse();
flips_count += 1;
self.perm
}

fn count(&self) -> u32 { self.permcount }
fn max(&self) -> u32 { self.fact[self.n as uint] }

fn next(&mut self) -> P {
next_permutation(self.perm.p, self.cnt);
self.permcount += 1;

self.perm
}
}


fn reverse(tperm: &mut [i32], mut k: uint) {
tperm.mut_slice_to(k).reverse()
}

fn work(mut perm: Perm, n: uint, max: uint) -> (i32, i32) {
let mut checksum = 0;
let mut maxflips = 0;

let mut p = perm.get(n as i32);

while perm.count() < max as u32 {
let mut flips = 0;

while p.p[0] != 1 {
let k = p.p[0] as uint;
reverse(p.p, k);
flips += 1;
}
perm_count = max(perm_count, flips_count);
checksum += if countdown & 1 == 1 {flips_count} else {-flips_count}

checksum += if perm.count() % 2 == 0 {flips} else {-flips};
maxflips = cmp::max(maxflips, flips);

p = perm.next();
}
(checksum, perm_count)

(checksum, maxflips)
}

fn main() {
let n = std::os::args().as_slice()
.get(1)
.and_then(|arg| from_str(arg.as_slice()))
.unwrap_or(2u);

let (tx, rx) = channel();
for i in range(0, n) {
let tx = tx.clone();
spawn(proc() tx.send(fannkuch(n, i)));
fn fannkuch(n: i32) -> (i32, i32) {
let perm = Perm::new(n as u32);

let N = 4;
let mut futures = vec![];
let k = perm.max() / N;

for (i, j) in range(0, N).zip(iter::count(0, k)) {
let max = cmp::min(j+k, perm.max());

futures.push(Future::spawn(proc() {
work(perm, j as uint, max as uint)
}))
}
drop(tx);

let mut checksum = 0;
let mut perm = 0;
for (cur_cks, cur_perm) in rx.iter() {
checksum += cur_cks;
perm = max(perm, cur_perm);
let mut maxflips = 0;
for fut in futures.mut_iter() {
let (cs, mf) = fut.get();
checksum += cs;
maxflips = cmp::max(maxflips, mf);
}
println!("{}\nPfannkuchen({}) = {}", checksum, n, perm);
(checksum, maxflips)
}

fn main() {
let n = std::os::args().as_slice()
.get(1)
.and_then(|arg| from_str(arg.as_slice()))
.unwrap_or(2i32);

let (checksum, maxflips) = fannkuch(n);
println!("{}\nPfannkuchen({}) = {}", checksum, n, maxflips);
}