summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md9
-rw-r--r--Cargo.toml11
-rw-r--r--source/benoit/benoit.rs10
-rw-r--r--source/benoit/benoit/application.rs11
-rw-r--r--source/benoit/benoit/application/get_iterator_function.rs (renamed from source/benoit/benoit/application/get_row_renderer.rs)11
-rw-r--r--source/benoit/benoit/application/initialise.rs6
-rw-r--r--source/benoit/benoit/application/render.rs65
-rw-r--r--source/benoit/benoit/application/render_row.rs (renamed from source/benoit/benoit/application/render_row_burning_ship.rs)49
-rw-r--r--source/benoit/benoit/application/render_row_mandelbrot.rs119
-rw-r--r--source/benoit/benoit/application/render_row_tricorn.rs105
-rw-r--r--source/benoit/benoit/iteration.rs36
-rw-r--r--source/benoit/benoit/iteration/iterate_burning_ship.rs47
-rw-r--r--source/benoit/benoit/iteration/iterate_mandelbrot.rs53
-rw-r--r--source/benoit/benoit/iteration/iterate_tricorn.rs50
-rw-r--r--source/benoit/benoit/render_data.rs44
-rw-r--r--source/benoit/benoit/render_data/new.rs47
-rw-r--r--source/benoit/benoit/render_data/send.rs26
-rw-r--r--source/benoit/benoit/render_data/slice.rs35
-rw-r--r--source/benoit/benoit/render_data/sync.rs26
19 files changed, 423 insertions, 337 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 20a3f88..42fa678 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,12 @@
+# 24
+
+* Optimise rendering
+* Use Rayon for threading
+* Update thread structure (use arc for common data)
+* Use iterator functions instead of row renderers
+* Fix render garbage (somehow)
+* Lower precision
+
# 23
* Support rendering of the Tricorn and Burning Ship fractals
diff --git a/Cargo.toml b/Cargo.toml
index 0fa2bc6..9da17e6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "benoit"
-version = "0.24.0"
+version = "0.28.0"
authors = ["Gabriel Bjørnager Jensen"]
edition = "2021"
description = "Mandelbrot renderer."
@@ -15,7 +15,8 @@ path = "source/benoit/main.rs"
lto = true
[dependencies]
-rug = "1.21.0"
-sdl2 = "0.35.2"
-toml = "0.7.6"
-webp = "0.2.5"
+rayon = "1.7.0"
+rug = "1.21.0"
+sdl2 = "0.35.2"
+toml = "0.7.6"
+webp = "0.2.5"
diff --git a/source/benoit/benoit.rs b/source/benoit/benoit.rs
index 92fe850..dfb4856 100644
--- a/source/benoit/benoit.rs
+++ b/source/benoit/benoit.rs
@@ -21,17 +21,13 @@
If not, see <https://www.gnu.org/licenses/>.
*/
-extern crate rug;
-
-use rug::Float;
-
pub mod application;
pub mod configuration;
+pub mod iteration;
+pub mod render_data;
pub mod video;
-type RowRenderer = fn(&mut [u32], u32, u32, u32, Float, Float, Float, u32);
-
-pub const PRECISION: u32 = 0x100;
+pub const PRECISION: u32 = 0x80;
#[derive(Clone, Copy)]
pub enum Fractal {
diff --git a/source/benoit/benoit/application.rs b/source/benoit/benoit/application.rs
index 186b069..07f3815 100644
--- a/source/benoit/benoit/application.rs
+++ b/source/benoit/benoit/application.rs
@@ -21,7 +21,8 @@
If not, see <https://www.gnu.org/licenses/>.
*/
-use crate::benoit::{Fractal, RowRenderer};
+use crate::benoit::Fractal;
+use crate::benoit::iteration::IteratorFunction;
use crate::benoit::video::Video;
extern crate rug;
@@ -32,14 +33,12 @@ pub mod animate;
pub mod colour;
pub mod draw;
pub mod dump;
-pub mod get_row_renderer;
+pub mod get_iterator_function;
pub mod handle_keys;
pub mod initialise;
pub mod r#loop;
pub mod poll_events;
-pub mod render_row_burning_ship;
-pub mod render_row_mandelbrot;
-pub mod render_row_tricorn;
+pub mod render_row;
pub mod render;
pub mod run;
@@ -66,5 +65,5 @@ pub struct Application {
do_draw: bool,
do_dump: bool,
- render_row: RowRenderer,
+ iterator_function: IteratorFunction,
}
diff --git a/source/benoit/benoit/application/get_row_renderer.rs b/source/benoit/benoit/application/get_iterator_function.rs
index 3418ab7..b2375a0 100644
--- a/source/benoit/benoit/application/get_row_renderer.rs
+++ b/source/benoit/benoit/application/get_iterator_function.rs
@@ -21,15 +21,16 @@
If not, see <https://www.gnu.org/licenses/>.
*/
-use crate::benoit::{Fractal, RowRenderer};
+use crate::benoit::Fractal;
use crate::benoit::application::Application;
+use crate::benoit::iteration::*;
impl Application {
- pub fn get_row_renderer(fractal: Fractal) -> RowRenderer {
+ pub fn get_iterator_function(fractal: Fractal) -> IteratorFunction {
return match fractal {
- Fractal::BurningShip => Application::render_row_burning_ship,
- Fractal::Mandelbrot => Application::render_row_mandelbrot,
- Fractal::Tricorn => Application::render_row_tricorn,
+ Fractal::BurningShip => iterate_burning_ship,
+ Fractal::Mandelbrot => iterate_mandelbrot,
+ Fractal::Tricorn => iterate_tricorn,
};
}
}
diff --git a/source/benoit/benoit/application/initialise.rs b/source/benoit/benoit/application/initialise.rs
index ad70156..97ac4a4 100644
--- a/source/benoit/benoit/application/initialise.rs
+++ b/source/benoit/benoit/application/initialise.rs
@@ -26,8 +26,10 @@ use crate::benoit::application::Application;
use crate::benoit::configuration::Configuration;
use crate::benoit::video::Video;
+extern crate rayon;
extern crate rug;
+use rayon::ThreadPoolBuilder;
use rug::Float;
use std::env::args;
use std::thread::available_parallelism;
@@ -57,6 +59,8 @@ impl Application {
false => None,
};
+ ThreadPoolBuilder::new().num_threads(configuration.thread_count as usize).build_global().unwrap();
+
return Application {
thread_count: thread_count,
@@ -80,7 +84,7 @@ impl Application {
do_draw: true,
do_dump: false,
- render_row: Application::get_row_renderer(configuration.fractal),
+ iterator_function: Application::get_iterator_function(configuration.fractal),
};
}
}
diff --git a/source/benoit/benoit/application/render.rs b/source/benoit/benoit/application/render.rs
index 07ab7ee..e06b168 100644
--- a/source/benoit/benoit/application/render.rs
+++ b/source/benoit/benoit/application/render.rs
@@ -22,76 +22,29 @@
*/
use crate::benoit::application::Application;
+use crate::benoit::render_data::RenderData;
+extern crate rayon;
extern crate rug;
+use rayon::prelude::*;
use rug::Float;
-use std::slice;
-use std::thread::{JoinHandle, spawn};
+use std::sync::Arc;
use std::time::Instant;
-use std::ptr::addr_of_mut;
impl Application {
pub fn render(&self, buffer: &mut [u32], center_real: &Float, center_imaginary: &Float, zoom: &Float, maximum_iteration_count: u32) {
eprint!("rendering...");
- let mut threads = Vec::<JoinHandle<()>>::with_capacity(self.thread_count as usize);
-
let time_start = Instant::now();
- 'render_loop: {
- // We render the set using one thread per row.
-
- let get_slice = |buffer: &mut [u32], y: u32, canvas_width: u32| -> &mut [u32] {
- let slice_start = y as usize * canvas_width as usize;
- let slice = unsafe { slice::from_raw_parts_mut(addr_of_mut!(buffer[slice_start]), canvas_width as usize) };
-
- return slice;
- };
-
- let canvas_width = self.canvas_width;
- let canvas_height = self.canvas_height;
-
- // Firstly, we fill up the thread vector by
- // spawning threads.
-
- let mut y: u32 = 0x0;
- for _thread in 0x0..self.thread_count {
- // We should stop if there are no remaining rows.
- if y == self.canvas_height { break 'render_loop; }
-
- let render_row = self.render_row;
-
- let buffer_slice = get_slice(buffer, y, self.canvas_width);
-
- let center_real = center_real.clone();
- let center_imaginary = center_imaginary.clone();
- let zoom = zoom.clone();
-
- threads.push(spawn(move || { render_row(buffer_slice, y, canvas_width, canvas_height, center_real, center_imaginary, zoom, maximum_iteration_count) }));
-
- y += 0x1;
- }
-
- // Secondly, we continuously join the first thread
- // to spawn another one. This is as to make the
- // threads more "active" by making the take on more
- // rows when they complete.
-
- for y in 0x0..self.canvas_height {
- threads.remove(0x0).join().unwrap();
-
- let render_row = self.render_row;
-
- let buffer_slice = get_slice(buffer, y, self.canvas_width);
+ let iterator = self.iterator_function;
- let center_real = center_real.clone();
- let center_imaginary = center_imaginary.clone();
- let zoom = zoom.clone();
+ let data = Arc::new(RenderData::new(buffer, self.canvas_width, self.canvas_height, center_real.clone(), center_imaginary.clone(), zoom.clone(), maximum_iteration_count));
- threads.push(spawn(move || { render_row(buffer_slice, y, canvas_width, canvas_height, center_real, center_imaginary, zoom, maximum_iteration_count) }));
- }
- }
+ (0x0..self.canvas_height).into_par_iter().for_each_with(data, |data, row| {
+ Application::render_row(data.clone(), row, iterator);
+ });
let duration = time_start.elapsed();
diff --git a/source/benoit/benoit/application/render_row_burning_ship.rs b/source/benoit/benoit/application/render_row.rs
index 1a2fa62..20fabdb 100644
--- a/source/benoit/benoit/application/render_row_burning_ship.rs
+++ b/source/benoit/benoit/application/render_row.rs
@@ -23,31 +23,33 @@
use crate::benoit::PRECISION;
use crate::benoit::application::Application;
+use crate::benoit::iteration::IteratorFunction;
+use crate::benoit::render_data::RenderData;
extern crate rug;
use rug::Float;
+use std::sync::Arc;
impl Application {
- pub fn render_row_burning_ship(data: &mut [u32], y: u32, canvas_width: u32, canvas_height: u32, center_real: Float, center_imaginary: Float, zoom: Float, maximum_iteration_count: u32) {
- for x in 0x0..canvas_width {
- let canvas_width = Float::with_val(PRECISION, canvas_width);
- let canvas_height = Float::with_val(PRECISION, canvas_height);
+ pub fn render_row(task: Arc<RenderData>, y: u32, iterator: IteratorFunction) {
+ let buffer = unsafe { task.slice(y) };
+
+ for x in 0x0..task.canvas_width {
+ let canvas_width = Float::with_val(PRECISION, task.canvas_width);
+ let canvas_height = Float::with_val(PRECISION, task.canvas_height);
let x_float = Float::with_val(PRECISION, x);
let y_float = Float::with_val(PRECISION, y);
- // For more information, see:
- // render_row_mandelbrot
-
let ca = {
let tmp0 = Float::with_val(PRECISION, &canvas_width / 2.0);
let mut ca = Float::with_val(PRECISION, &x_float - &tmp0);
ca *= 4.0;
ca /= &canvas_width;
- ca /= &zoom;
- ca += &center_real;
+ ca /= &task.zoom;
+ ca += &task.real;
ca
};
@@ -58,8 +60,8 @@ impl Application {
let mut cb = Float::with_val(PRECISION, &y_float - &tmp0);
cb *= 4.0;
cb /= &canvas_height;
- cb /= &zoom;
- cb += &center_imaginary;
+ cb /= &task.zoom;
+ cb += &task.imaginary;
cb
};
@@ -70,33 +72,14 @@ impl Application {
let mut iteration_count: u32 = 0x0;
while {
let square_distance = Float::with_val(PRECISION, &za * &za + &zb * &zb);
- square_distance <= 4.0 && iteration_count < maximum_iteration_count
+ square_distance <= 4.0 && iteration_count < task.maximum_iteration_count
} {
- {
- // The Burning Ship is different in that - during
- // iteration - the real and imaginary parts of (z)
- // are made absolute:
- //
- // z = (abs(Re(z))+i*abs(Im(z)))^2+c
-
- za = za.abs();
- zb = zb.abs();
-
- let za_temporary = Float::with_val(PRECISION, &za);
-
- za = za.square();
- za -= &zb * &zb;
- za += &ca;
-
- zb *= &za_temporary;
- zb *= 2.0;
- zb += &cb;
- }
+ iterator(&mut za, &mut zb, &ca, &cb);
iteration_count += 0x1;
}
- unsafe { *data.get_unchecked_mut(x as usize) = iteration_count }
+ unsafe { *buffer.get_unchecked_mut(x as usize) = iteration_count }
}
}
}
diff --git a/source/benoit/benoit/application/render_row_mandelbrot.rs b/source/benoit/benoit/application/render_row_mandelbrot.rs
deleted file mode 100644
index f74170b..0000000
--- a/source/benoit/benoit/application/render_row_mandelbrot.rs
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- Copyright 2021, 2023 Gabriel Bjørnager Jensen.
-
- This file is part of Benoit.
-
- Benoit is free software: you can redistribute it
- and/or modify it under the terms of the GNU
- Affero General Public License as published by
- the Free Software Foundation, either version 3
- of the License, or (at your option) any later
- version.
-
- Benoit is distributed in the hope that it will
- be useful, but WITHOUT ANY WARRANTY; without
- even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Affero General Public License for more details.
-
- You should have received a copy of the GNU
- Affero General Public License along with Benoit.
- If not, see <https://www.gnu.org/licenses/>.
-*/
-
-use crate::benoit::PRECISION;
-use crate::benoit::application::Application;
-
-extern crate rug;
-
-use rug::Float;
-
-impl Application {
- pub fn render_row_mandelbrot(data: &mut [u32], y: u32, canvas_width: u32, canvas_height: u32, center_real: Float, center_imaginary: Float, zoom: Float, maximum_iteration_count: u32) {
- for x in 0x0..canvas_width {
- let canvas_width = Float::with_val(PRECISION, canvas_width);
- let canvas_height = Float::with_val(PRECISION, canvas_height);
-
- let x_float = Float::with_val(PRECISION, x);
- let y_float = Float::with_val(PRECISION, y);
-
- // Re(c) = (x-canvas_width/2)*4/canvas_width/zoom+Re(z)
- let ca = {
- let tmp0 = Float::with_val(PRECISION, &canvas_width / 2.0);
-
- let mut ca = Float::with_val(PRECISION, &x_float - &tmp0);
- ca *= 4.0;
- ca /= &canvas_width;
- ca /= &zoom;
- ca += &center_real;
-
- ca
- };
-
- // Im(c) = (x-canvas_height/2)*4/canvas_height/zoom+Im(z)
- let cb = {
- let tmp0 = Float::with_val(PRECISION, &canvas_height / 2.0);
-
- let mut cb = Float::with_val(PRECISION, &y_float - &tmp0);
- cb *= 4.0;
- cb /= &canvas_height;
- cb /= &zoom;
- cb += &center_imaginary;
-
- cb
- };
-
- // Formaly, the initial condition that
- //
- // z = 0
- //
- // may be skipped as the first two iterations will
- // always be
- //
- // z0 = 0
- // z1 = z0^2+c = 0^2+c = 0+c = c
- //
- // That is, the result of the second iteration will
- // always be the value of (c).
- let mut za = Float::with_val(PRECISION, &ca);
- let mut zb = Float::with_val(PRECISION, &cb);
-
- let mut iteration_count: u32 = 0x0;
- while {
- let square_distance = Float::with_val(PRECISION, &za * &za + &zb * &zb);
- square_distance <= 4.0 && iteration_count < maximum_iteration_count
- } {
- {
- // The Mandelbrot Set (M) is defined as the set of
- // values in the complex plane where the iterating
- // function
- //
- // z = z^2+c
- //
- // stays bounded: I.e. the absolute value of (z) stays bounded:
- //
- // abs(z) = sqrt(Re(z)^2+Im(z)^2) <= 2^2 = 4
-
- let za_temporary = Float::with_val(PRECISION, &za);
-
- // We can calculate the square of a complex number
- // as:
- //
- // (a+ib)^2 = (a+ib)(a+ib) = a^2+iab+iab-b^2 = a^2-b^2+2iab
-
- za = za.square();
- za -= &zb * &zb;
- za += &ca;
-
- zb *= &za_temporary;
- zb *= 2.0;
- zb += &cb;
- }
-
- iteration_count += 0x1;
- }
-
- unsafe { *data.get_unchecked_mut(x as usize) = iteration_count }
- }
- }
-}
diff --git a/source/benoit/benoit/application/render_row_tricorn.rs b/source/benoit/benoit/application/render_row_tricorn.rs
deleted file mode 100644
index 9cefc6e..0000000
--- a/source/benoit/benoit/application/render_row_tricorn.rs
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- Copyright 2021, 2023 Gabriel Bjørnager Jensen.
-
- This file is part of Benoit.
-
- Benoit is free software: you can redistribute it
- and/or modify it under the terms of the GNU
- Affero General Public License as published by
- the Free Software Foundation, either version 3
- of the License, or (at your option) any later
- version.
-
- Benoit is distributed in the hope that it will
- be useful, but WITHOUT ANY WARRANTY; without
- even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Affero General Public License for more details.
-
- You should have received a copy of the GNU
- Affero General Public License along with Benoit.
- If not, see <https://www.gnu.org/licenses/>.
-*/
-
-use crate::benoit::PRECISION;
-use crate::benoit::application::Application;
-
-extern crate rug;
-
-use rug::Float;
-
-impl Application {
- pub fn render_row_tricorn(data: &mut [u32], y: u32, canvas_width: u32, canvas_height: u32, center_real: Float, center_imaginary: Float, zoom: Float, maximum_iteration_count: u32) {
- for x in 0x0..canvas_width {
- let canvas_width = Float::with_val(PRECISION, canvas_width);
- let canvas_height = Float::with_val(PRECISION, canvas_height);
-
- let x_float = Float::with_val(PRECISION, x);
- let y_float = Float::with_val(PRECISION, y);
-
- // For more information, see:
- // render_row_mandelbrot
-
- let ca = {
- let tmp0 = Float::with_val(PRECISION, &canvas_width / 2.0);
-
- let mut ca = Float::with_val(PRECISION, &x_float - &tmp0);
- ca *= 4.0;
- ca /= &canvas_width;
- ca /= &zoom;
- ca += &center_real;
-
- ca
- };
-
- let cb = {
- let tmp0 = Float::with_val(PRECISION, &canvas_height / 2.0);
-
- let mut cb = Float::with_val(PRECISION, &y_float - &tmp0);
- cb *= 4.0;
- cb /= &canvas_height;
- cb /= &zoom;
- cb += &center_imaginary;
-
- cb
- };
-
- let mut za = Float::with_val(PRECISION, &ca);
- let mut zb = Float::with_val(PRECISION, &cb);
-
- let mut iteration_count: u32 = 0x0;
- while {
- let square_distance = Float::with_val(PRECISION, &za * &za + &zb * &zb);
- square_distance <= 4.0 && iteration_count < maximum_iteration_count
- } {
- {
- // The Tricorn is only different from the
- // Mandelbrot Set in that the conjugate of (z) is
- // used instead of just (z):
- //
- // z = (Re(z)-Im(z))^2+c
-
- let za_temporary = Float::with_val(PRECISION, &za);
-
- za = za.square();
- za -= &zb * &zb;
- za += &ca;
-
- zb *= &za_temporary;
- // We can negate the value by multiplying with
- // (-1). A multiplication can be saved, as
- //
- // a*2*(-1) = a*(-2)
- //
- // so we may combine these two multiplications.
- zb *= -2.0;
- zb += &cb;
- }
-
- iteration_count += 0x1;
- }
-
- unsafe { *data.get_unchecked_mut(x as usize) = iteration_count }
- }
- }
-}
diff --git a/source/benoit/benoit/iteration.rs b/source/benoit/benoit/iteration.rs
new file mode 100644
index 0000000..6c81b80
--- /dev/null
+++ b/source/benoit/benoit/iteration.rs
@@ -0,0 +1,36 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+extern crate rug;
+
+use rug::Float;
+
+pub mod iterate_burning_ship;
+pub mod iterate_mandelbrot;
+pub mod iterate_tricorn;
+
+pub use iterate_burning_ship::iterate_burning_ship;
+pub use iterate_mandelbrot::iterate_mandelbrot;
+pub use iterate_tricorn::iterate_tricorn;
+
+pub type IteratorFunction = fn(&mut Float, &mut Float, &Float, &Float);
diff --git a/source/benoit/benoit/iteration/iterate_burning_ship.rs b/source/benoit/benoit/iteration/iterate_burning_ship.rs
new file mode 100644
index 0000000..596c021
--- /dev/null
+++ b/source/benoit/benoit/iteration/iterate_burning_ship.rs
@@ -0,0 +1,47 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+extern crate rug;
+
+use rug::Float;
+
+pub fn iterate_burning_ship(za: &mut Float, zb: &mut Float, ca: &Float, cb: &Float) {
+ // The Burning Ship is different in that - during
+ // iteration - the real and imaginary parts of (z)
+ // are made absolute:
+ //
+ // z(n) = (abs(Re(z(n)))+i*abs(Im(z(n))))^2+c
+
+ za.abs_mut();
+ zb.abs_mut();
+
+ let za_temporary = za.clone();
+
+ za.square_mut();
+ *za -= &*zb * &*zb;
+ *za += ca;
+
+ *zb *= za_temporary;
+ *zb *= 2.0;
+ *zb += cb;
+}
diff --git a/source/benoit/benoit/iteration/iterate_mandelbrot.rs b/source/benoit/benoit/iteration/iterate_mandelbrot.rs
new file mode 100644
index 0000000..34a3c79
--- /dev/null
+++ b/source/benoit/benoit/iteration/iterate_mandelbrot.rs
@@ -0,0 +1,53 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+extern crate rug;
+
+use rug::Float;
+
+pub fn iterate_mandelbrot(za: &mut Float, zb: &mut Float, ca: &Float, cb: &Float) {
+ // The Mandelbrot Set (M) is defined as the set of
+ // values in the complex plane where the iterating
+ // function
+ //
+ // z(n+1) = z(n)^2+c
+ //
+ // stays bounded: I.e. the absolute value of (z) stays bounded:
+ //
+ // abs(z) = sqrt(Re(z)^2+Im(z)^2) <= 2^2 = 4
+
+ let za_temporary = za.clone();
+
+ // We can calculate the square of a complex number
+ // as:
+ //
+ // (a+ib)^2 = (a+ib)(a+ib) = a^2+iab+iab-b^2 = a^2-b^2+2iab
+
+ za.square_mut();
+ *za -= &*zb * &*zb;
+ *za += ca;
+
+ *zb *= za_temporary;
+ *zb *= 2.0;
+ *zb += cb;
+}
diff --git a/source/benoit/benoit/iteration/iterate_tricorn.rs b/source/benoit/benoit/iteration/iterate_tricorn.rs
new file mode 100644
index 0000000..2edea53
--- /dev/null
+++ b/source/benoit/benoit/iteration/iterate_tricorn.rs
@@ -0,0 +1,50 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+extern crate rug;
+
+use rug::Float;
+
+pub fn iterate_tricorn(za: &mut Float, zb: &mut Float, ca: &Float, cb: &Float) {
+ // The Tricorn is only different from the
+ // Mandelbrot Set in that the conjugate of (z) is
+ // used instead of just (z):
+ //
+ // z(n+1) = (Re(z(n))-Im(z(n)))^2+c
+
+ let za_temporary = za.clone();
+
+ za.square_mut();
+ *za -= &*zb * &*zb;
+ *za += ca;
+
+ *zb *= za_temporary;
+ // We can negate the value by multiplying with
+ // (-1). A multiplication can be saved, as
+ //
+ // a*2*(-1) = a*(-2)
+ //
+ // Thus, we may combine these two multiplications.
+ *zb *= -2.0;
+ *zb += cb;
+}
diff --git a/source/benoit/benoit/render_data.rs b/source/benoit/benoit/render_data.rs
new file mode 100644
index 0000000..602521e
--- /dev/null
+++ b/source/benoit/benoit/render_data.rs
@@ -0,0 +1,44 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+extern crate rug;
+
+use rug::Float;
+
+pub mod new;
+pub mod slice;
+pub mod send;
+pub mod sync;
+
+pub struct RenderData {
+ pub canvas_width: u32,
+ pub canvas_height: u32,
+
+ pub real: Float,
+ pub imaginary: Float,
+ pub zoom: Float,
+
+ pub maximum_iteration_count: u32,
+
+ buffer: *mut u32,
+}
diff --git a/source/benoit/benoit/render_data/new.rs b/source/benoit/benoit/render_data/new.rs
new file mode 100644
index 0000000..fb45390
--- /dev/null
+++ b/source/benoit/benoit/render_data/new.rs
@@ -0,0 +1,47 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+use crate::benoit::render_data::RenderData;
+
+extern crate rug;
+
+use rug::Float;
+
+impl RenderData {
+ pub fn new(buffer: &mut [u32], canvas_width: u32, canvas_height: u32, real: Float, imaginary: Float, zoom: Float, maximum_iteration_count: u32) -> RenderData {
+ let buffer_pointer = buffer.as_mut_ptr();
+
+ return RenderData {
+ canvas_width: canvas_width,
+ canvas_height: canvas_height,
+
+ real: real,
+ imaginary: imaginary,
+ zoom: zoom,
+
+ maximum_iteration_count: maximum_iteration_count,
+
+ buffer: buffer_pointer,
+ };
+ }
+}
diff --git a/source/benoit/benoit/render_data/send.rs b/source/benoit/benoit/render_data/send.rs
new file mode 100644
index 0000000..b351cdd
--- /dev/null
+++ b/source/benoit/benoit/render_data/send.rs
@@ -0,0 +1,26 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+use crate::benoit::render_data::RenderData;
+
+unsafe impl Send for RenderData {}
diff --git a/source/benoit/benoit/render_data/slice.rs b/source/benoit/benoit/render_data/slice.rs
new file mode 100644
index 0000000..6783aae
--- /dev/null
+++ b/source/benoit/benoit/render_data/slice.rs
@@ -0,0 +1,35 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+use crate::benoit::render_data::RenderData;
+
+use std::slice::from_raw_parts_mut;
+
+impl RenderData {
+ pub unsafe fn slice(&self, row: u32) -> &mut [u32] {
+ let offset = row as isize * self.canvas_width as isize;
+ let slice = from_raw_parts_mut(self.buffer.offset(offset), self.canvas_width as usize);
+
+ return slice;
+ }
+}
diff --git a/source/benoit/benoit/render_data/sync.rs b/source/benoit/benoit/render_data/sync.rs
new file mode 100644
index 0000000..454ebb1
--- /dev/null
+++ b/source/benoit/benoit/render_data/sync.rs
@@ -0,0 +1,26 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+use crate::benoit::render_data::RenderData;
+
+unsafe impl Sync for RenderData {}