Skip to content

Instantly share code, notes, and snippets.

@huonw
Last active August 29, 2015 14:06
Show Gist options
  • Save huonw/786aac903561c074c46b to your computer and use it in GitHub Desktop.
Save huonw/786aac903561c074c46b to your computer and use it in GitHub Desktop.
Compiling with --cfg idx_reverse --opt-level=3
Samples: 27K of event 'cycles', Event count (approx.): 18709445305
39.57% fannkuchredux fannkuchredux [.] fannkuch::h3c886b0c9fd4152cYda
37.13% fannkuchredux fannkuchredux [.] reverse::h8a92c2595b4c13ffaca
11.71% fannkuchredux fannkuchredux [.] next_permutation::h0b3a5cb57aef64bcdba
7.96% fannkuchredux fannkuchredux [.] rotate::ha766464a328f18a5Kaa
3.40% fannkuchredux fannkuchredux [.] vec::Vec$LT$T$GT$::push_all::h9473677268961327811
0.01% fannkuchredux [kernel.kallsyms] [k] native_write_msr_safe
// The Computer Language Benchmarks Game
// http://benchmarksgame.alioth.debian.org/
//
// contributed by the Rust Project Developers
// Copyright (c) 2014 The Rust Project Developers
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// - Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
//
// - Neither the name of "The Computer Language Benchmarks Game" nor
// the name of "The Computer Language Shootout Benchmarks" nor the
// names of its contributors may be used to endorse or promote
// products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
extern crate test;
use std::cmp::max;
use std::mem;
#[inline(never)]
fn fact(n: uint) -> uint {
range(1, n + 1).fold(1, |accu, i| accu * i)
}
#[inline(never)]
fn rotate(x: &mut [i32]) {
let mut prev = x[0];
for place in x.mut_iter().rev() {
prev = mem::replace(place, prev)
}
}
#[inline(never)]
fn next_permutation(perm: &mut [i32], count: &mut [uint]) {
for i in range(1, perm.len()) {
rotate(perm.mut_slice_to(i + 1));
let count_i = &mut count[i];
if *count_i >= i {
*count_i = 0;
} else {
*count_i += 1;
break
}
}
}
#[inline(never)]
fn reverse(tperm: &mut [i32], mut k: uint) {
if cfg!(idx_reverse) {
let mut i = 0;
k -= 1;
while i < k {
unsafe {
std::ptr::swap(tperm.unsafe_mut_ref(i), tperm.unsafe_mut_ref(k));
}
i += 1;
k -= 1;
}
} else if cfg!(ptr_reverse) {
unsafe {
let mut p = tperm.as_mut_ptr();
let mut q = p.offset(k as int - 1);
while p < q {
use std::ptr;
ptr::swap(p, q);
p = p.offset(1);
q = q.offset(-1);
}
}
} else if cfg!(iter_reverse) {
tperm.mut_slice_to(k).mut_iter().reverse_()
} else {
tperm.mut_slice_to(k).reverse()
}
}
#[inline(never)]
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;
for countdown in range(1, fact(n - 1) + 1).rev() {
next_permutation(perm.as_mut_slice(), count.as_mut_slice());
tperm.clone_from(&perm);
let mut flips_count = 0;
loop {
let k = tperm[0];
if k == 1 { break; }
reverse(tperm.as_mut_slice(), k as uint);
flips_count += 1;
}
perm_count = max(perm_count, flips_count);
checksum += if countdown & 1 == 1 {flips_count} else {-flips_count}
}
(checksum, perm_count)
}
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)));
}
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);
}
println!("{}\nPfannkuchen({}) = {}", checksum, n, perm);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment