]> git.proxmox.com Git - rustc.git/blame - src/test/bench/shootout-mandelbrot.rs
Imported Upstream version 1.2.0+dfsg1
[rustc.git] / src / test / bench / shootout-mandelbrot.rs
CommitLineData
1a4d82fc
JJ
1// The Computer Language Benchmarks Game
2// http://benchmarksgame.alioth.debian.org/
3//
4// contributed by the Rust Project Developers
5
6// Copyright (c) 2012-2014 The Rust Project Developers
7//
8// All rights reserved.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions
12// are met:
13//
14// - Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// - Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in
19// the documentation and/or other materials provided with the
20// distribution.
21//
22// - Neither the name of "The Computer Language Benchmarks Game" nor
23// the name of "The Computer Language Shootout Benchmarks" nor the
24// names of its contributors may be used to endorse or promote
25// products derived from this software without specific prior
26// written permission.
27//
28// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39// OF THE POSSIBILITY OF SUCH DAMAGE.
40
62682a34 41#![feature(core_simd, core)]
1a4d82fc
JJ
42
43// ignore-pretty very bad with line comments
44
85aaf69f 45use std::env;
9346a6ac
AL
46use std::io::prelude::*;
47use std::io;
1a4d82fc
JJ
48use std::simd::f64x2;
49use std::sync::Arc;
85aaf69f 50use std::thread;
223e47cc 51
85aaf69f 52const ITER: usize = 50;
1a4d82fc 53const LIMIT: f64 = 2.0;
85aaf69f 54const WORKERS: usize = 16;
223e47cc 55
9346a6ac 56fn mandelbrot<W: Write>(w: usize, mut out: W) -> io::Result<()> {
62682a34 57 assert_eq!(WORKERS % 2, 0);
1a4d82fc
JJ
58
59 // Ensure w and h are multiples of 8.
60 let w = (w + 7) / 8 * 8;
61 let h = w;
62
63 let chunk_size = h / WORKERS;
64
65 // Account for remainders in workload division, e.g. 1000 / 16 = 62.5
66 let last_chunk_size = if h % WORKERS != 0 {
67 chunk_size + h % WORKERS
68 } else {
69 chunk_size
70 };
71
72 // precalc values
73 let inverse_w_doubled = 2.0 / w as f64;
74 let inverse_h_doubled = 2.0 / h as f64;
75 let v_inverses = f64x2(inverse_w_doubled, inverse_h_doubled);
76 let v_consts = f64x2(1.5, 1.0);
77
78 // A lot of this code assumes this (so do other lang benchmarks)
62682a34 79 assert_eq!(w, h);
1a4d82fc
JJ
80 let mut precalc_r = Vec::with_capacity(w);
81 let mut precalc_i = Vec::with_capacity(h);
82
85aaf69f 83 let precalc_futures = (0..WORKERS).map(|i| {
9346a6ac 84 thread::spawn(move|| {
1a4d82fc
JJ
85 let mut rs = Vec::with_capacity(w / WORKERS);
86 let mut is = Vec::with_capacity(w / WORKERS);
87
88 let start = i * chunk_size;
89 let end = if i == (WORKERS - 1) {
90 start + last_chunk_size
91 } else {
92 (i + 1) * chunk_size
93 };
94
95 // This assumes w == h
85aaf69f 96 for x in start..end {
1a4d82fc
JJ
97 let xf = x as f64;
98 let xy = f64x2(xf, xf);
99
100 let f64x2(r, i) = xy * v_inverses - v_consts;
101 rs.push(r);
102 is.push(i);
103 }
104
105 (rs, is)
106 })
107 }).collect::<Vec<_>>();
108
85aaf69f 109 for res in precalc_futures {
9346a6ac 110 let (rs, is) = res.join().unwrap();
62682a34
SL
111 precalc_r.extend(rs);
112 precalc_i.extend(is);
1a4d82fc
JJ
113 }
114
115 assert_eq!(precalc_r.len(), w);
116 assert_eq!(precalc_i.len(), h);
117
118 let arc_init_r = Arc::new(precalc_r);
119 let arc_init_i = Arc::new(precalc_i);
970d7e83 120
85aaf69f 121 let data = (0..WORKERS).map(|i| {
1a4d82fc
JJ
122 let vec_init_r = arc_init_r.clone();
123 let vec_init_i = arc_init_i.clone();
124
9346a6ac 125 thread::spawn(move|| {
1a4d82fc 126 let mut res: Vec<u8> = Vec::with_capacity((chunk_size * w) / 8);
85aaf69f 127 let init_r_slice = vec_init_r;
1a4d82fc
JJ
128
129 let start = i * chunk_size;
130 let end = if i == (WORKERS - 1) {
131 start + last_chunk_size
132 } else {
133 (i + 1) * chunk_size
134 };
135
85aaf69f
SL
136 for &init_i in &vec_init_i[start..end] {
137 write_line(init_i, &init_r_slice, &mut res);
1a4d82fc
JJ
138 }
139
140 res
141 })
142 }).collect::<Vec<_>>();
143
9346a6ac 144 try!(writeln!(&mut out, "P4\n{} {}", w, h));
85aaf69f 145 for res in data {
9346a6ac 146 try!(out.write_all(&res.join().unwrap()));
1a4d82fc
JJ
147 }
148 out.flush()
149}
150
151fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec<u8>) {
152 let v_init_i : f64x2 = f64x2(init_i, init_i);
153 let v_2 : f64x2 = f64x2(2.0, 2.0);
154 const LIMIT_SQUARED: f64 = LIMIT * LIMIT;
155
156 for chunk_init_r in vec_init_r.chunks(8) {
157 let mut cur_byte = 0xff;
158 let mut i = 0;
159
160 while i < 8 {
161 let v_init_r = f64x2(chunk_init_r[i], chunk_init_r[i + 1]);
162 let mut cur_r = v_init_r;
163 let mut cur_i = v_init_i;
164 let mut r_sq = v_init_r * v_init_r;
165 let mut i_sq = v_init_i * v_init_i;
166
167 let mut b = 0;
85aaf69f 168 for _ in 0..ITER {
1a4d82fc
JJ
169 let r = cur_r;
170 let i = cur_i;
171
172 cur_i = v_2 * r * i + v_init_i;
173 cur_r = r_sq - i_sq + v_init_r;
174
175 let f64x2(bit1, bit2) = r_sq + i_sq;
176
177 if bit1 > LIMIT_SQUARED {
178 b |= 2;
179 if b == 3 { break; }
970d7e83
LB
180 }
181
1a4d82fc
JJ
182 if bit2 > LIMIT_SQUARED {
183 b |= 1;
184 if b == 3 { break; }
970d7e83 185 }
1a4d82fc
JJ
186
187 r_sq = cur_r * cur_r;
188 i_sq = cur_i * cur_i;
970d7e83 189 }
1a4d82fc
JJ
190
191 cur_byte = (cur_byte << 2) + b;
192 i += 2;
223e47cc 193 }
1a4d82fc
JJ
194
195 res.push(cur_byte^-1);
223e47cc
LB
196 }
197}
1a4d82fc
JJ
198
199fn main() {
85aaf69f 200 let mut args = env::args();
1a4d82fc
JJ
201 let res = if args.len() < 2 {
202 println!("Test mode: do not dump the image because it's not utf8, \
203 which interferes with the test runner.");
9346a6ac 204 mandelbrot(1000, io::sink())
1a4d82fc 205 } else {
9346a6ac 206 mandelbrot(args.nth(1).unwrap().parse().unwrap(), io::stdout())
1a4d82fc
JJ
207 };
208 res.unwrap();
209}