The Computer Language
Benchmarks Game

mandelbrot Rust #2 program

source code

// The Computer Language Benchmarks Game
// http://benchmarksgame.alioth.debian.org/
//
// Contributed by Rodrigo Corsi (Rust 1.0.0)

use std::io;
use std::thread;
use std::sync::Arc;

const LIMIT: f64 = 4f64; //2*2
const ITER : u16 = 50; // Benchmark parameter

struct Mandelbrot {
    bytes_per_row: usize,
    initial_r: Vec<f64>,
    initial_i: Vec<f64>
}

impl Mandelbrot {
    fn new(size: usize) -> Mandelbrot {
        let mut initial_r = Vec::with_capacity(size);
        let mut initial_i = Vec::with_capacity(size);

        let inv = 2.0f64 / size as f64;

        for xy in 0..size {
            let i = inv * xy as f64;
            initial_r.push(i-1.5f64);
            initial_i.push(i-1.0f64);
        }

        Mandelbrot {
            bytes_per_row: (size >> 3),
            initial_r: initial_r,
            initial_i: initial_i
        }
    }

    // This func is responsible for rendering a chunk of pixels
    fn render_chunk(&self, start: usize, end: usize) -> Vec<u8> {
        let mut xb: usize;
        let mut res: u8;
        let mut b: u8;
        let mut zr1: f64;
        let mut zr2: f64;
        let mut zi1: f64;
        let mut zi2: f64;
        let mut tr1: f64;
        let mut tr2: f64;
        let mut ti1: f64;
        let mut ti2: f64;
        let mut cr1: f64;
        let mut cr2: f64;
        let mut ci: f64;
        let nums = vec![0,2,4,6];

        let mut field: Vec<u8> = Vec::with_capacity(end-start);

        for y0 in start..end {
            ci = self.initial_i[y0];

            for x in 0..self.bytes_per_row {
                res=0;

                for i in &nums {
                    xb = x<<3;
                    cr1=self.initial_r[xb+i];
                    cr2=self.initial_r[xb+i+1];

                    zr1=cr1;
                    zi1=ci;

                    zr2=cr2;
                    zi2=ci;

                    b = 0;

                    for _ in 0..ITER{
                        tr1 = zr1*zr1;
                        ti1 = zi1*zi1;
                        zi1 = 2f64*zr1*zi1+ci;
                        zr1 = tr1-ti1+cr1;

                        if tr1+ti1>LIMIT {
                            b|=2;
                            if b==3 {
                                break;
                            }
                        }

                        tr2 = zr2*zr2;
                        ti2 = zi2*zi2;
                        zi2 = 2f64*zr2*zi2+ci;
                        zr2 = tr2-ti2+cr2; 

                        if tr2+ti2>LIMIT {
                            b|=1;
                            if b==3 {
                                break;
                            }
                        }
                    }
                    res= (res<<2) | b;
                }
                field.push(res^-1);
            }
        }
        return field;
    }
}

fn run<W: io::Write>(writer: &mut W) -> io::Result<()> {
    let size = std::env::args_os().nth(1)
        .and_then(|s| s.into_string().ok())
        .and_then(|n| n.parse().ok())
        .unwrap_or(200);

    let workers = 16; //std::os::num_cpus()*4;

    let mandelbrot = Mandelbrot::new(size);

    try!(writeln!(writer, "P4\n{} {}", size, size));

    let arc_mandel = Arc::new(mandelbrot);
    let chunk = size / workers;
    
    let last_chunk = if size % workers != 0 {
        chunk + size % workers
    } else {
        chunk
    };

    let messages = (0..workers).map(|w| {
        let mclone = arc_mandel.clone();
        thread::spawn(move || {
            let _chunk = if w+1 == workers {
                last_chunk
            }else{
                chunk
            };

            let start = w * chunk;
            let end = start+_chunk;
            return mclone.render_chunk(start, end);

        })
    }).collect::<Vec<_>>();

    for message in messages.into_iter() {
        try!(writer.write_all(&message.join().unwrap()));
    }

    writer.flush()
}

fn main() {
    run(&mut io::stdout()).unwrap()
}
    

notes, command-line, and program output

NOTES:
32-bit Ubuntu one core
rustc 1.13.0 (2c6933acc 2016-11-07)


Fri, 11 Nov 2016 20:38:11 GMT

MAKE:
/usr/local/src/rust-1.13.0/bin/rustc -C opt-level=3 -C target-cpu=core2  mandelbrot.rs -o mandelbrot.rust-2.rust_run
error[E0080]: constant evaluation error
   --> mandelbrot.rs:105:32
    |
105 |                 field.push(res^-1);
    |                                ^^ unary negation of unsigned integer

error: aborting due to previous error

/home/dunham/benchmarksgame/nanobench/makefiles/u32.programs.Makefile:593: recipe for target 'mandelbrot.rust-2.rust_run' failed
make: [mandelbrot.rust-2.rust_run] Error 101 (ignored)
0.35s to complete and log all make actions

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

MAKE ERROR