1
- // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1
+ // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2
2
// file at the top-level directory of this distribution and at
3
3
// http://rust-lang.org/COPYRIGHT.
4
4
//
12
12
// http://shootout.alioth.debian.org/
13
13
// u64q/program.php?test=mandelbrot&lang=python3&id=2
14
14
//
15
- // takes 2 optional args:
15
+ // takes 3 optional args:
16
16
// square image size, defaults to 80_u
17
17
// output path, default is "" (no output), "-" means stdout
18
+ // depth (max iterations per pixel), defaults to 50_u
18
19
//
19
- // in the shootout, they use 16000 as image size
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
20
24
//
21
25
// writes pbm image to output path
22
26
23
- extern mod std;
24
27
use io:: WriterUtil ;
25
- use std :: oldmap :: HashMap ;
28
+ use core :: hashmap :: linear :: LinearMap ;
26
29
27
30
struct cmplx {
28
31
re : f64 ,
@@ -54,44 +57,43 @@ pure fn cabs(x: cmplx) -> f64
54
57
x. re * x. re + x. im * x. im
55
58
}
56
59
57
- fn mb ( x : cmplx ) -> bool
60
+ fn mb ( x : cmplx , depth : uint ) -> bool
58
61
{
59
- let mut z = cmplx { re : 0f64 , im : 0f64 } ;
62
+ let mut z = x ;
60
63
let mut i = 0 ;
61
- let mut in = true ;
62
- while i < 50 {
63
- z = z* z + x;
64
- if cabs ( z) >= 4f64 {
65
- in = false ;
66
- break ;
64
+ while i < depth {
65
+ if cabs ( z) >= 4_f64 {
66
+ return false ;
67
67
}
68
+ z = z* z + x;
68
69
i += 1 ;
69
70
}
70
- in
71
+ true
71
72
}
72
73
73
- fn fillbyte ( x : cmplx , incr : f64 ) -> u8 {
74
+ fn fillbyte ( x : cmplx , incr : f64 , depth : uint ) -> u8 {
74
75
let mut rv = 0_u8 ;
75
76
let mut i = 0_u8 ;
76
77
while i < 8_u8 {
77
78
let z = cmplx { re : x. re + ( i as f64 ) * incr, im : x. im } ;
78
- if mb ( z) {
79
+ if mb ( z, depth ) {
79
80
rv += 1_u8 << ( 7_u8 - i) ;
80
81
}
81
82
i += 1_u8 ;
82
83
}
83
84
rv
84
85
}
85
86
86
- fn chanmb ( i : uint , size : uint ) -> Line
87
+ fn chanmb ( i : uint , size : uint , depth : uint ) -> Line
87
88
{
88
- let mut crv = ~[ ] ;
89
- let incr = 2f64 /( size as f64 ) ;
90
- let y = incr* ( i as f64 ) - 1f64 ;
91
- let xincr = 8f64 * incr;
92
- for uint:: range( 0_ u, size/8_ u) |j| {
93
- let x = cmplx { re : xincr* ( j as f64 ) - 1.5f64 , im : y} ;
94
- crv. push ( fillbyte ( x, incr) ) ;
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) ) ;
95
97
} ;
96
98
Line { i : i, b : crv}
97
99
}
@@ -121,34 +123,33 @@ fn writer(path: ~str, pport: pipes::Port<Line>, size: uint)
121
123
~[io::Create, io::Truncate]))
122
124
}
123
125
};
124
- cout.write_line(~ " P4 ") ;
126
+ cout.write_line(" P4 ") ;
125
127
cout. write_line ( fmt ! ( "%u %u" , size, size) ) ;
126
- let lines: HashMap < uint , ~ [ u8 ] > = HashMap ( ) ;
128
+ let mut lines: LinearMap < uint , Line > = LinearMap :: new ( ) ;
127
129
let mut done = 0_ u;
128
130
let mut i = 0_ u;
129
131
while i < size {
130
132
let aline = pport. recv ( ) ;
131
133
if aline. i == done {
132
- debug ! ( "W %u" , aline . i ) ;
134
+ debug ! ( "W %u" , done ) ;
133
135
cout. write ( aline. b ) ;
134
136
done += 1_ u;
135
137
let mut prev = done;
136
138
while prev <= i {
137
- if lines. contains_key ( & prev) {
138
- debug ! ( "WS %u" , prev) ;
139
- cout. write ( lines. get ( & prev) ) ;
140
- done += 1_ u;
141
- lines. remove ( & prev) ;
142
- prev += 1_ u;
143
- }
144
- else {
145
- break
146
- }
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;
145
+ }
146
+ None => break
147
+ } ;
147
148
} ;
148
149
}
149
150
else {
150
151
debug ! ( "S %u" , aline. i) ;
151
- lines. insert ( aline. i , copy aline. b ) ; // FIXME: bad for perf
152
+ lines. insert ( aline. i , aline) ;
152
153
} ;
153
154
i += 1_ u;
154
155
}
@@ -157,11 +158,14 @@ fn writer(path: ~str, pport: pipes::Port<Line>, size: uint)
157
158
fn main ( ) {
158
159
let args = os:: args ( ) ;
159
160
let args = if os:: getenv ( ~"RUST_BENCH ") . is_some ( ) {
160
- ~[ ~"", ~"4000 "]
161
+ ~[ ~"", ~"4000 ", ~" 50 " ]
161
162
} else {
162
163
args
163
164
} ;
164
165
166
+ let depth = if vec:: len ( args) < 4_ u { 50_ u }
167
+ else { uint:: from_str ( args[ 3 ] ) . get ( ) } ;
168
+
165
169
let path = if vec:: len ( args) < 3_ u { ~"" }
166
170
else { copy args[ 2 ] } ; // FIXME: bad for perf
167
171
@@ -172,7 +176,7 @@ fn main() {
172
176
let pchan = pipes:: SharedChan ( pchan) ;
173
177
for uint:: range( 0_ u, size) |j| {
174
178
let cchan = pchan. clone ( ) ;
175
- do task:: spawn || { cchan. send ( chanmb ( j, size) ) } ;
179
+ do task:: spawn { cchan. send ( chanmb ( j, size, depth ) ) } ;
176
180
} ;
177
181
writer ( path, pport, size) ;
178
182
}
0 commit comments