Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

172 lines (155 sloc) 4.23 kb
// based on:
// http://shootout.alioth.debian.org/
// u64q/program.php?test=mandelbrot&lang=python3&id=2
//
// takes 3 optional args:
// square image size, defaults to 80_u
// yield frequency, defaults to 10_u (yield every 10 spawns)
// output path, default is "" (no output), "-" means stdout
//
// in the shootout, they use 16000 as image size
// yield frequency doesn't seem to have much effect
//
// writes pbm image to output path
use std;
import io::writer_util;
import std::map::hashmap;
type cmplx = {re: f64, im: f64};
type line = {i: uint, b: ~[u8]};
impl arith for cmplx {
fn *(x: cmplx) -> cmplx {
{re: self.re*x.re - self.im*x.im, im: self.re*x.im + self.im*x.re}
}
fn +(x: cmplx) -> cmplx {
{re: self.re + x.re, im: self.im + x.im}
}
}
pure fn cabs(x: cmplx) -> f64
{
x.re*x.re + x.im*x.im
}
fn mb(x: cmplx) -> bool
{
let mut z = {re: 0f64, im: 0f64};
let mut i = 0;
let mut in = true;
while i < 50 {
z = z*z + x;
if cabs(z) >= 4f64 {
in = false;
break;
}
i += 1;
}
in
}
fn fillbyte(x: cmplx, incr: f64) -> u8 {
let mut rv = 0_u8;
let mut i = 0_u8;
while i < 8_u8 {
let z = {re: x.re + (i as f64)*incr, im: x.im};
if mb(z) {
rv += 1_u8 << (7_u8 - i);
}
i += 1_u8;
}
rv
}
fn chanmb(i: uint, size: uint, ch: comm::chan<line>) -> ()
{
let mut crv = ~[];
let incr = 2f64/(size as f64);
let y = incr*(i as f64) - 1f64;
let xincr = 8f64*incr;
for uint::range(0_u, size/8_u) |j| {
let x = {re: xincr*(j as f64) - 1.5f64, im: y};
vec::push(crv, fillbyte(x, incr));
};
comm::send(ch, {i:i, b:crv});
}
type devnull = {dn: int};
impl of io::writer for devnull {
fn write(_b: &[const u8]) {}
fn seek(_i: int, _s: io::seek_style) {}
fn tell() -> uint {0_u}
fn flush() -> int {0}
}
fn writer(path: str, writech: comm::chan<comm::chan<line>>, size: uint)
{
let p: comm::port<line> = comm::port();
let ch = comm::chan(p);
comm::send(writech, ch);
let cout: io::writer = alt path {
"" {
{dn: 0} as io::writer
}
"-" {
io::stdout()
}
_ {
result::get(
io::file_writer(path,
~[io::create, io::truncate]))
}
};
cout.write_line("P4");
cout.write_line(#fmt("%u %u", size, size));
let lines = std::map::uint_hash();
let mut done = 0_u;
let mut i = 0_u;
while i < size {
let aline = comm::recv(p);
if aline.i == done {
#debug("W %u", aline.i);
cout.write(aline.b);
done += 1_u;
let mut prev = done;
while prev <= i {
if lines.contains_key(prev) {
#debug("WS %u", prev);
// FIXME (#2280): this temporary shouldn't be
// necessary, but seems to be, for borrowing.
let v : ~[u8] = lines.get(prev);
cout.write(v);
done += 1_u;
lines.remove(prev);
prev += 1_u;
}
else {
break
}
};
}
else {
#debug("S %u", aline.i);
lines.insert(aline.i, aline.b);
};
i += 1_u;
}
}
fn main(args: ~[str]) {
let args = if os::getenv("RUST_BENCH").is_some() {
~["", "4000", "10"]
} else {
args
};
let path = if vec::len(args) < 4_u { "" }
else { args[3] };
let yieldevery = if vec::len(args) < 3_u { 10_u }
else { uint::from_str(args[2]).get() };
let size = if vec::len(args) < 2_u { 80_u }
else { uint::from_str(args[1]).get() };
let writep = comm::port();
let writech = comm::chan(writep);
do task::spawn {
writer(path, writech, size);
};
let ch = comm::recv(writep);
for uint::range(0_u, size) |j| {
task::spawn(|| chanmb(j, size, ch) );
if j % yieldevery == 0_u {
#debug("Y %u", j);
task::yield();
};
};
}
Jump to Line
Something went wrong with that request. Please try again.