diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs index e17324ee596..5302bd1dd63 100644 --- a/src/test/bench/shootout-mandelbrot.rs +++ b/src/test/bench/shootout-mandelbrot.rs @@ -7,6 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(macro_rules)] // ignore-pretty very bad with line comments @@ -18,27 +19,56 @@ use sync::Future; static ITER: int = 50; static LIMIT: f64 = 2.0; -fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec) { - for chunk_init_r in vec_init_r.chunks(8) { - let mut cur_byte = 0xff; - let mut cur_bitmask = 0x80; - for &init_r in chunk_init_r.iter() { - let mut cur_r = init_r; - let mut cur_i = init_i; - for _ in range(0, ITER) { - let r = cur_r; - let i = cur_i; - cur_r = r * r - i * i + init_r; - cur_i = 2.0 * r * i + init_i; +macro_rules! core_loop( + ($pow:expr ~ $mask:expr: $ctx:ident, $b:ident) => ( + { + let r = $ctx.r; + let i = $ctx.i; - if r * r + i * i > LIMIT * LIMIT { - cur_byte &= !cur_bitmask; - break; - } + $ctx.r = r * r - i * i + $ctx.init_r; + $ctx.i = 2.0 * r * i + $ctx.init_i; + + if r * r + i * i > LIMIT * LIMIT { + $b |= $pow; + if $b == $mask { break; } } - cur_bitmask >>= 1; } - res.push(cur_byte); + ); +) + +#[inline(always)] +fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec) { + struct Context { r: f64, i: f64, init_i: f64, init_r: f64 } + impl Context { + #[inline(always)] + fn new(i: f64, r: f64) -> Context { + Context { r: r, i: i, init_r: r, init_i: i } + } + } + + let mut cur_byte; + let mut i; + let mut bit_1; + let mut bit_2; + let mut b; + for chunk_init_r in vec_init_r.chunks(8) { + cur_byte = 0xff; + i = 0; + + while i < 8 { + bit_1 = Context::new(init_i, chunk_init_r[i]); + bit_2 = Context::new(init_i, chunk_init_r[i + 1]); + + b = 0; + for _ in range(0, ITER) { + core_loop!(2 ~ 3: bit_1, b); + core_loop!(1 ~ 3: bit_2, b); + } + + cur_byte = (cur_byte << 2) + b; + i += 2; + } + res.push(cur_byte^-1); } } @@ -46,13 +76,15 @@ fn mandelbrot(w: uint, mut out: W) -> io::IoResult<()> { // Ensure w and h are multiples of 8. let w = (w + 7) / 8 * 8; let h = w; - let chunk_size = h / 8; + let inverse_w_doubled = 2.0 / w as f64; + let inverse_h_doubled = 2.0 / h as f64; + let chunk_size = h / 16; - let data: Vec>> = range(0u, 8).map(|i| Future::spawn(proc () { - let vec_init_r = Vec::from_fn(w, |x| 2.0 * (x as f64) / (w as f64) - 1.5); + let data: Vec>> = range(0u, 16).map(|i| Future::spawn(proc () { + let vec_init_r = Vec::from_fn(w, |x| (x as f64) * inverse_w_doubled - 1.5); let mut res: Vec = Vec::with_capacity((chunk_size * w) / 8); for y in range(i * chunk_size, (i + 1) * chunk_size) { - let init_i = 2.0 * (y as f64) / (h as f64) - 1.0; + let init_i = (y as f64) * inverse_h_doubled - 1.0; write_line(init_i, vec_init_r.as_slice(), &mut res); } res