Skip to content

Commit e7738ca

Browse files
tedhorstbrson
authored andcommitted
add mandelbrot image generator from shootout
1 parent 8fc624b commit e7738ca

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

src/test/bench/shootout-mandelbrot.rs

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// based on:
2+
// http://shootout.alioth.debian.org/u64q/program.php?test=mandelbrot&lang=python3&id=2
3+
//
4+
// takes 2 optional numeric args: square image size and yield frequency
5+
// in the shootout, they use 16000 as image size
6+
// yield frequency doesn't seem to have much effect
7+
//
8+
// writes pbm image to stdout
9+
10+
use std;
11+
import std::io::writer_util;
12+
13+
type cmplx = {re: f64, im: f64};
14+
type line = {i: uint, b: [u8]};
15+
16+
impl arith for cmplx {
17+
fn *(x: cmplx) -> cmplx {
18+
{re: self.re*x.re - self.im*x.im, im: self.re*x.im + self.im*x.re}
19+
}
20+
21+
fn +(x: cmplx) -> cmplx {
22+
{re: self.re + x.re, im: self.im + x.im}
23+
}
24+
}
25+
26+
pure fn cabs(x: cmplx) -> f64
27+
{
28+
x.re*x.re + x.im*x.im
29+
}
30+
31+
fn mb(x: cmplx) -> bool
32+
{
33+
let z = {re: 0., im: 0.};
34+
let i = 0;
35+
let in = true;
36+
while i < 50 {
37+
z = z*z + x;
38+
if cabs(z) >= 4. {
39+
in = false;
40+
break;
41+
}
42+
i += 1;
43+
}
44+
in
45+
}
46+
47+
fn fillbyte(x: cmplx, incr: f64) -> u8 {
48+
let rv = 0_u8;
49+
let i = 0_u8;
50+
while i < 8_u8 {
51+
let z = {re: x.re + (i as f64)*incr, im: x.im};
52+
if mb(z) {
53+
rv += 1_u8 << (7_u8 - i);
54+
}
55+
i += 1_u8;
56+
}
57+
rv
58+
}
59+
60+
fn chanmb(i: uint, size: uint, ch: comm::chan<line>) -> ()
61+
{
62+
let crv = [];
63+
let incr = 2./(size as f64);
64+
let y = incr*(i as f64) - 1.;
65+
let xincr = 8.*incr;
66+
uint::range(0_u, size/8_u) {
67+
|j|
68+
let x = {re: xincr*(j as f64) - 1.5, im: y};
69+
crv += [fillbyte(x, incr)];
70+
};
71+
comm::send(ch, {i:i, b:crv});
72+
}
73+
74+
fn writer(writech: comm::chan<comm::chan<line>>, size: uint)
75+
{
76+
let p: comm::port<line> = comm::port();
77+
let ch = comm::chan(p);
78+
comm::send(writech, ch);
79+
let cout = std::io::stdout();
80+
cout.write_line("P4");
81+
cout.write_line(#fmt("%u %u", size, size));
82+
let lines = std::map::new_uint_hash();
83+
let done = 0_u;
84+
let i = 0_u;
85+
while i < size {
86+
let aline = comm::recv(p);
87+
if aline.i == done {
88+
#debug("W %u", aline.i);
89+
cout.write(aline.b);
90+
done += 1_u;
91+
let prev = done;
92+
while prev <= i {
93+
if lines.contains_key(prev) {
94+
#debug("WS %u", prev);
95+
cout.write(lines.get(prev));
96+
done += 1_u;
97+
lines.remove(prev);
98+
prev += 1_u;
99+
}
100+
else {
101+
break
102+
}
103+
};
104+
105+
}
106+
else {
107+
#debug("S %u", aline.i);
108+
lines.insert(aline.i, aline.b);
109+
};
110+
i += 1_u;
111+
}
112+
}
113+
114+
fn main(argv: [str])
115+
{
116+
let size = if vec::len(argv) < 2_u {
117+
80u
118+
}
119+
else {
120+
uint::from_str(argv[1])
121+
};
122+
let yieldevery = if vec::len(argv) < 3_u {
123+
10_u
124+
}
125+
else {
126+
uint::from_str(argv[2])
127+
};
128+
let writep = comm::port();
129+
let writech = comm::chan(writep);
130+
task::spawn {
131+
|| writer(writech, size);
132+
};
133+
let ch = comm::recv(writep);
134+
uint::range(0_u, size) {
135+
|j| task::spawn {
136+
|| chanmb(j, size, ch);
137+
};
138+
if j % yieldevery == 0_u {
139+
#debug("Y %u", j);
140+
task::yield();
141+
};
142+
};
143+
}

0 commit comments

Comments
 (0)