summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs129
1 files changed, 105 insertions, 24 deletions
diff --git a/src/main.rs b/src/main.rs
index 0e1e5ff..c36da4f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,7 +2,6 @@ extern crate rand;
extern crate num_complex;
extern crate png;
-use std::io;
use num_complex::Complex;
//stuff for PNG output
@@ -14,6 +13,12 @@ use png::HasParameters;
use std::cmp;
+use std::thread;
+use std::sync::mpsc;
+use std::time;
+
+use std::ops::{Add,AddAssign};
+
use rand::distributions::{IndependentSample, Range};
struct Trajectory
@@ -30,7 +35,6 @@ struct Pixel
r : u32,
g : u32,
b : u32,
- a : u32
}
impl Trajectory {
@@ -63,6 +67,34 @@ impl Trajectory {
}
}
+impl Add for Pixel
+{
+ type Output = Pixel;
+
+ fn add(self, other:Pixel) -> Pixel{
+ Pixel{
+ r: self.r + other.r,
+ g: self.g + other.g,
+ b: self.b + other.b,
+ }
+ }
+}
+
+impl<'a> AddAssign<&'a Pixel> for Pixel
+{
+ fn add_assign(&mut self, other: &Pixel) {
+ self.r += other.r;
+ self.g += other.g;
+ self.b += other.b;
+ }
+}
+
+impl Pixel{
+ fn max(&self) -> u32{
+ cmp::max(self.r,cmp::max(self.g,self.b))
+ }
+}
+
fn write_png(filename : &str, pixels : &Vec<Pixel>, max_cnt : u32, width : u32, height : u32){
let mut png_data : Vec<u8> = Vec::with_capacity(pixels.len()*4);
for pix in pixels.iter()
@@ -94,32 +126,20 @@ fn get_pixel(path_point : &Complex<f64>, width : i32, height : i32) -> i32{
return x_index + y_index*width;
}
-
-fn main() {
-
- let x = 1920;
- let y = 1080;
-
- let trajectory_count = 1000000;
- let path_length = 10000;
-
- let bailout = 50.0;
-
- //arrays would do, if we knew size at compile time. We do right now, but we want them tweakable later on
+fn buddhabrot(x : usize, y : usize, path_length : usize, bailout : f64, returner : mpsc::Sender<Vec<Pixel>>, syncer : mpsc::Receiver<bool>) {
+ //thread_local workspace
let mut workspace = Vec::with_capacity(x*y);
for _number in 0..x*y {
- workspace.push(Pixel{r:0, g:0, b:0,a:1});
+ workspace.push(Pixel{r:0, g:0, b:0});
}
-
-
- let mut max_cnt = 1;
-
+
let x_range = Range::new(-2.5,1.0);
let y_range = Range::new(-1.0,1.0);
let mut rng = rand::thread_rng();
-
-
- for _traj in 0..trajectory_count {
+
+ //println!("Worker initialized, starting calculation");
+ //keep on generating until main thread signals us to stop:
+ while let Err(_e) = syncer.try_recv(){
let offset = Complex::new(x_range.ind_sample(&mut rng),y_range.ind_sample(&mut rng));
let mut traj = Trajectory::new(path_length,offset);
traj.run(bailout);
@@ -139,13 +159,74 @@ fn main() {
item.r = item.r + 1;
item.g = item.g + 1;
item.b = item.g + 1;
- max_cnt = cmp::max(cmp::max(max_cnt,item.b),cmp::max(item.r,item.g));
}
}
-
}
+ //just send the result.
+ returner.send(workspace).unwrap();
+}
+
+
+fn main() {
+ let x = 1920;
+ let y = 1080;
+ let path_length = 10000;
+
+ let bailout = 50.0;
+
+ let threads = 16;
+
+ let mut generation_time = 30;
+
+ println!("Starting Threads");
+
+ let mut thread_handles = Vec::with_capacity(threads);
+ let mut stop_senders = Vec::with_capacity(threads);
+
+ let (ret_sender, ret_receiver) = mpsc::channel();
+
+ for _i in 0..threads{
+ let (stop_sender, stop_receiver) = mpsc::channel();
+ let ret_sender_clone = ret_sender.clone();
+ let handle = thread::spawn(move|| {
+ buddhabrot(x,y,path_length,bailout,ret_sender_clone,stop_receiver);
+ });
+ thread_handles.push(handle);
+ stop_senders.push(stop_sender);
+ }
+
+ println!("Letting workers work");
+ while generation_time > 0{
+ println!("Remaining time: {}",generation_time);
+ thread::sleep(time::Duration::from_secs(cmp::min(5,generation_time)));
+ generation_time -= 5;
+ }
+
+ println!("Telling workers to stop");
+ //inform worker threads that they should stop
+ for sender in stop_senders{
+ sender.send(true).unwrap();
+ }
+
+ println!("Transmitting first result");
+ //wait for all messages. We use the first workspace to come back to accumulate the data
+ let mut workspace = ret_receiver.recv().unwrap();
+ println!("Reading other results and combining them");
+ for _i in 1..threads{
+ let otherworkspace = ret_receiver.recv().unwrap();
+ for idx in 0..workspace.len(){
+ workspace[idx] += &otherworkspace[idx];
+ }
+ }
+
+ println!("Normalizing colors");
+ let mut max_cnt = 1;
+ for pixel in &workspace{
+ max_cnt = cmp::max(max_cnt,pixel.max());
+ }
+ println!("Writing png");
write_png(r"image.png",&workspace, max_cnt,x as u32,y as u32);
}