The Computer Language
Benchmarks Game

mandelbrot Rust #4 program

source code

// The Computer Language Benchmarks Game
// http://benchmarksgame.alioth.debian.org/
//
// contributed by Matt Watson
// contributed by TeXitoi
// contributed by Cristi Cobzarenco

extern crate rayon;

use std::io::Write;
use std::ops::{Add, Mul, Sub};
use rayon::prelude::*;

const MAX_ITER: usize = 50;
const VLEN: usize = 8;
const ZEROS: Vecf64 = Vecf64([0.; VLEN]);

macro_rules! for_vec {
    ( in_each [ $( $val:tt ),* ] do $from:ident $op:tt $other:ident ) => {
        $( $from.0[$val] $op $other.0[$val]; )*
    };
    ( $from:ident $op:tt $other:ident ) => {
        for_vec!(in_each [0, 1, 2, 3, 4, 5, 6, 7] do $from $op $other);
    };
}

#[derive(Clone, Copy)]
pub struct Vecf64([f64; VLEN]);
impl Mul for Vecf64 {
    type Output = Vecf64;
    fn mul(mut self, other: Vecf64) -> Vecf64 {
        for_vec!(self *= other);
        self
    }
}
impl Add for Vecf64 {
    type Output = Vecf64;
    fn add(mut self, other: Vecf64) -> Vecf64 {
        for_vec!(self += other);
        self
    }
}
impl Sub for Vecf64 {
    type Output = Vecf64;
    fn sub(mut self, other: Vecf64) -> Vecf64 {
        for_vec!(self -= other);
        self
    }
}

pub struct Mandelbrot8 {
    zr: Vecf64,
    zi: Vecf64,
    tr: Vecf64,
    ti: Vecf64,

    cr: Vecf64,
    ci: Vecf64,
    ci2: Vecf64,
}

impl Mandelbrot8 {
    pub fn new(ci: Vecf64) -> Self {
        Mandelbrot8 {
            zr: ZEROS,
            zi: ZEROS,
            tr: ZEROS,
            ti: ZEROS,

            cr: ZEROS,
            ci: ci,
            ci2: ci * ci,
        }
    }

    pub fn run(&mut self, cr: Vecf64, cr2: Vecf64) -> u8 {
        self.zr = cr;
        self.zi = self.ci;
        self.tr = cr2;
        self.ti = self.ci2;
        self.cr = cr;

        self.advance(4);
        for _ in 0..MAX_ITER / 5 - 1 {
            if self.all_diverged() {
                return 0;
            }
            self.advance(5);
        }
        self.to_byte()
    }

    fn advance(&mut self, iterations: usize) {
        for _ in 0..iterations {
            self.zi = (self.zr + self.zr) * self.zi + self.ci;
            self.zr = self.tr - self.ti + self.cr;
            self.tr = self.zr * self.zr;
            self.ti = self.zi * self.zi;
        }
    }

    fn all_diverged(&self) -> bool {
        (self.tr + self.ti).0.iter().all(|&t| t > 4.)
    }

    fn to_byte(&self) -> u8 {
        (self.tr + self.ti)
            .0
            .iter()
            .enumerate()
            .map(|(i, &t)| if t <= 4. { 0x80 >> i } else { 0 })
            .fold(0, |accu, b| accu | b)
    }
}


fn main() {
    let size = std::env::args().nth(1).and_then(|n| n.parse().ok()).unwrap_or(200);
    let size = size / VLEN * VLEN;
    let inv = 2. / size as f64;
    let mut xloc = vec![(ZEROS, ZEROS); size / VLEN];
    for i in 0..size {
        let x = i as f64 * inv - 1.5;
        (xloc[i / VLEN].0).0[i % VLEN] = x;
        (xloc[i / VLEN].1).0[i % VLEN] = x * x;
    }

    let mut output = vec![0u8; size * size / VLEN];
    output.par_chunks_mut(size / VLEN)
        .weight_max()
        .enumerate()
        .for_each(|(y, chunk)| {
            let mut m = Mandelbrot8::new(Vecf64([y as f64 * inv - 1.; VLEN]));
            for (&(x, x2), c) in xloc.iter().zip(chunk) {
                *c = m.run(x, x2);
            }
        });

    println!("P4\n{} {}", size, size);
    let stdout_unlocked = std::io::stdout();
    let mut stdout = stdout_unlocked.lock();
    stdout.write_all(&output).unwrap();
}
    

notes, command-line, and program output

NOTES:
64-bit Ubuntu quad core
rustc 1.20.0 (f3d6973f4 2017-08-27)


Thu, 31 Aug 2017 19:01:41 GMT

MAKE:
/usr/local/src/rust-1.20.0/bin/rustc -C opt-level=3 -C target-cpu=core2 -C lto -L /usr/local/src/rust-libs mandelbrot.rs -o mandelbrot.rust-4.rust_run
error[E0599]: no method named `weight_max` found for type `rayon::slice::ChunksMut<'_, u8>` in the current scope
   --> mandelbrot.rs:130:10
    |
130 |         .weight_max()
    |          ^^^^^^^^^^

error: aborting due to previous error

/home/dunham/benchmarksgame/nanobench/makefiles/u64q.programs.Makefile:620: recipe for target 'mandelbrot.rust-4.rust_run' failed
make: [mandelbrot.rust-4.rust_run] Error 101 (ignored)

0.27s to complete and log all make actions

COMMAND LINE:
./mandelbrot.rust-4.rust_run 1000

MAKE ERROR