Skip to content

Commit af4ea11

Browse files
committed
test: Rewrite mandelbrot benchmark.
1 parent 9902e79 commit af4ea11

File tree

1 file changed

+53
-175
lines changed

1 file changed

+53
-175
lines changed

src/test/bench/shootout-mandelbrot.rs

Lines changed: 53 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -1,182 +1,60 @@
1-
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2-
// file at the top-level directory of this distribution and at
3-
// http://rust-lang.org/COPYRIGHT.
4-
//
5-
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6-
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7-
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8-
// option. This file may not be copied, modified, or distributed
9-
// except according to those terms.
1+
use core::cast::transmute;
2+
use core::from_str::FromStr;
3+
use core::i32::range;
4+
use core::libc::{STDOUT_FILENO, c_int, fdopen, fputc};
105

11-
// based on:
12-
// http://shootout.alioth.debian.org/
13-
// u64q/program.php?test=mandelbrot&lang=python3&id=2
14-
//
15-
// takes 3 optional args:
16-
// square image size, defaults to 80_u
17-
// output path, default is "" (no output), "-" means stdout
18-
// depth (max iterations per pixel), defaults to 50_u
19-
//
20-
// in the shootout, they use 16000 as image size, 50 as depth,
21-
// and write to stdout:
22-
//
23-
// ./shootout_mandelbrot 16000 "-" 50 > /tmp/mandel.pbm
24-
//
25-
// writes pbm image to output path
6+
static ITER: uint = 50;
7+
static LIMIT: f64 = 2.0;
268

27-
use core::io::WriterUtil;
28-
use core::hashmap::HashMap;
29-
30-
struct cmplx {
31-
re: f64,
32-
im: f64
33-
}
34-
35-
impl ops::Mul<cmplx,cmplx> for cmplx {
36-
fn mul(&self, x: &cmplx) -> cmplx {
37-
cmplx {
38-
re: self.re*(*x).re - self.im*(*x).im,
39-
im: self.re*(*x).im + self.im*(*x).re
40-
}
41-
}
42-
}
43-
44-
impl ops::Add<cmplx,cmplx> for cmplx {
45-
fn add(&self, x: &cmplx) -> cmplx {
46-
cmplx {
47-
re: self.re + (*x).re,
48-
im: self.im + (*x).im
49-
}
50-
}
51-
}
52-
53-
struct Line {i: uint, b: ~[u8]}
54-
55-
fn cabs(x: cmplx) -> f64
56-
{
57-
x.re*x.re + x.im*x.im
58-
}
59-
60-
fn mb(x: cmplx, depth: uint) -> bool
61-
{
62-
let mut z = x;
63-
let mut i = 0;
64-
while i < depth {
65-
if cabs(z) >= 4_f64 {
66-
return false;
67-
}
68-
z = z*z + x;
69-
i += 1;
70-
}
71-
true
72-
}
73-
74-
fn fillbyte(x: cmplx, incr: f64, depth: uint) -> u8 {
75-
let mut rv = 0_u8;
76-
let mut i = 0_u8;
77-
while i < 8_u8 {
78-
let z = cmplx {re: x.re + (i as f64)*incr, im: x.im};
79-
if mb(z, depth) {
80-
rv += 1_u8 << (7_u8 - i);
81-
}
82-
i += 1_u8;
83-
}
84-
rv
85-
}
86-
87-
fn chanmb(i: uint, size: uint, depth: uint) -> Line
88-
{
89-
let bsize = size/8_u;
90-
let mut crv = vec::with_capacity(bsize);
91-
let incr = 2_f64/(size as f64);
92-
let y = incr*(i as f64) - 1_f64;
93-
let xincr = 8_f64*incr;
94-
for uint::range(0_u, bsize) |j| {
95-
let x = cmplx {re: xincr*(j as f64) - 1.5_f64, im: y};
96-
crv.push(fillbyte(x, incr, depth));
97-
};
98-
Line {i:i, b:crv}
99-
}
100-
101-
struct Devnull();
102-
103-
impl io::Writer for Devnull {
104-
fn write(&self, _b: &const [u8]) {}
105-
fn seek(&self, _i: int, _s: io::SeekStyle) {}
106-
fn tell(&self) -> uint {0_u}
107-
fn flush(&self) -> int {0}
108-
fn get_type(&self) -> io::WriterType { io::File }
109-
}
110-
111-
fn writer(path: ~str, pport: comm::Port<Line>, size: uint)
112-
{
113-
let cout: @io::Writer = match path {
114-
~"" => {
115-
@Devnull as @io::Writer
116-
}
117-
~"-" => {
118-
io::stdout()
119-
}
120-
_ => {
121-
result::get(
122-
&io::file_writer(&Path(path),
123-
~[io::Create, io::Truncate]))
124-
}
125-
};
126-
cout.write_line("P4");
127-
cout.write_line(fmt!("%u %u", size, size));
128-
let mut lines: HashMap<uint, Line> = HashMap::new();
129-
let mut done = 0_u;
130-
let mut i = 0_u;
131-
while i < size {
132-
let aline = pport.recv();
133-
if aline.i == done {
134-
debug!("W %u", done);
135-
cout.write(aline.b);
136-
done += 1_u;
137-
let mut prev = done;
138-
while prev <= i {
139-
match lines.pop(&prev) {
140-
Some(pl) => {
141-
debug!("WS %u", prev);
142-
cout.write(pl.b);
143-
done += 1_u;
144-
prev += 1_u;
9+
#[fixed_stack_segment]
10+
fn main() {
11+
unsafe {
12+
let w: i32 = FromStr::from_str(os::args()[1]).get(), h = w;
13+
let mut byte_acc: i8 = 0;
14+
let mut bit_num: i32 = 0;
15+
16+
println(fmt!("P4\n%d %d", w as int, h as int));
17+
18+
let mode = "w";
19+
let stdout = fdopen(STDOUT_FILENO as c_int, transmute(&mode[0]));
20+
21+
for range(0, h) |y| {
22+
let y = y as f64;
23+
for range(0, w) |x| {
24+
let mut (Zr, Zi, Tr, Ti) = (0f64, 0f64, 0f64, 0f64);
25+
let Cr = 2.0 * (x as f64) / (w as f64) - 1.5;
26+
let Ci = 2.0 * (y as f64) / (h as f64) - 1.0;
27+
28+
for ITER.times {
29+
if Tr + Ti > LIMIT * LIMIT {
30+
break;
14531
}
146-
None => break
147-
};
148-
};
32+
33+
Zi = 2.0*Zr*Zi + Ci;
34+
Zr = Tr - Ti + Cr;
35+
Tr = Zr * Zr;
36+
Ti = Zi * Zi;
37+
}
38+
39+
byte_acc <<= 1;
40+
if Tr + Ti <= LIMIT * LIMIT {
41+
byte_acc |= 1;
42+
}
43+
44+
bit_num += 1;
45+
46+
if bit_num == 8 {
47+
fputc(byte_acc as c_int, stdout);
48+
byte_acc = 0;
49+
bit_num = 0;
50+
} else if x == w - 1 {
51+
byte_acc <<= 8 - w%8;
52+
fputc(byte_acc as c_int, stdout);
53+
byte_acc = 0;
54+
bit_num = 0;
55+
}
56+
}
14957
}
150-
else {
151-
debug!("S %u", aline.i);
152-
lines.insert(aline.i, aline);
153-
};
154-
i += 1_u;
15558
}
15659
}
15760

158-
fn main() {
159-
let args = os::args();
160-
let args = if os::getenv(~"RUST_BENCH").is_some() {
161-
~[~"", ~"4000", ~"50"]
162-
} else {
163-
args
164-
};
165-
166-
let depth = if vec::len(args) < 4_u { 50_u }
167-
else { uint::from_str(args[3]).get() };
168-
169-
let path = if vec::len(args) < 3_u { ~"" }
170-
else { copy args[2] }; // FIXME: bad for perf
171-
172-
let size = if vec::len(args) < 2_u { 80_u }
173-
else { uint::from_str(args[1]).get() };
174-
175-
let (pport, pchan) = comm::stream();
176-
let pchan = comm::SharedChan::new(pchan);
177-
for uint::range(0_u, size) |j| {
178-
let cchan = pchan.clone();
179-
do task::spawn { cchan.send(chanmb(j, size, depth)) };
180-
};
181-
writer(path, pport, size);
182-
}

0 commit comments

Comments
 (0)