Skip to content

Commit f83905f

Browse files
authored
Merge pull request #37 from rust-fractal/development
Development
2 parents 4667235 + b078719 commit f83905f

File tree

12 files changed

+407
-131
lines changed

12 files changed

+407
-131
lines changed

Cargo.lock

Lines changed: 15 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "rust_fractal"
3-
version = "0.13.0"
3+
version = "0.14.0"
44
authors = ["jackyarndley <34801340+jackyarndley@users.noreply.github.com>"]
55
description = "Fast, efficient mandelbrot set renderer."
66
edition = "2018"
@@ -15,6 +15,8 @@ smallvec = "^1.4.2"
1515
clap = "^3.0.0-beta.1"
1616
config = "^0.9"
1717
half = "^1.6.0"
18+
atomic-counter = "^1.0.1"
19+
color_space = "^0.5.3"
1820

1921
[dependencies.rug]
2022
version = "1.10"
@@ -27,3 +29,4 @@ lto = "fat"
2729
codegen-units = 1
2830
#debug = true
2931
opt-level=3
32+
#incremental = true

high.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ glitch_percentage = 0.001
66
frames = 1
77
frame_offset = 0
88
zoom_scale = 2.0
9-
display_glitches = false
9+
display_glitches = true
1010
auto_adjust_iterations = true
1111
remove_centre = false
12-
export = "exr"
12+
export = "png"
1313

1414
glitch_tolerance = 1.4e-6
1515

@@ -22,5 +22,5 @@ valid_iteration_probe_multiplier = 0.01
2222

2323
experimental = true
2424

25-
analytic_derivative = true
25+
analytic_derivative = false
2626
jitter = false

locations/dragon_detail.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
real = "-0.749999987350877481864108888020013802837969258626230419972587823828734338471228477079750588709551510361714463695461745528645748607681279674273355384334270208362211787387351792878073779449767292692440"
2+
imag = "0.001000038688236832013124581230049849132759425863378894883003211011278068229551274712347955044740933397589760194545872789087012331273586364914484522575986336846199522726507205442204060303594956029930"
3+
zoom = "9.099999999999616E191"
4+
iterations = 5000000
5+
rotate = 0

src/math/perturbation.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,22 @@ use crate::math::reference::Reference;
55

66
use crate::util::ComplexExtended;
77

8+
use atomic_counter::{AtomicCounter, RelaxedCounter};
9+
10+
use std::sync::Arc;
11+
812
pub struct Perturbation {}
913

1014
impl Perturbation {
11-
pub fn iterate_normal(pixel_data: &mut [PixelData], reference: &Reference) {
15+
pub fn iterate_normal(pixel_data: &mut [PixelData], reference: &Reference, pixels_complete: &Arc<RelaxedCounter>, stop_flag: &Arc<RelaxedCounter>) {
1216
pixel_data.par_chunks_mut(4)
1317
.for_each(|pixel_data| {
18+
if stop_flag.get() >= 1 {
19+
return;
20+
}
21+
22+
let mut new_pixels_complete = 0;
23+
1424
for pixel in pixel_data {
1525
let mut scaled_iterations = 0;
1626
let mut scaled_scale_factor_1 = 1.0f64.ldexp(pixel.delta_current.exponent);
@@ -41,6 +51,7 @@ impl Perturbation {
4151
pixel.escaped = true;
4252
pixel.delta_current.mantissa = pixel.delta_current.to_float();
4353
pixel.delta_current.exponent = 0;
54+
new_pixels_complete += 1;
4455
break;
4556
}
4657
}
@@ -81,14 +92,23 @@ impl Perturbation {
8192

8293
if !pixel.escaped && !pixel.glitched {
8394
pixel.iteration = reference.current_iteration;
95+
new_pixels_complete += 1;
8496
}
8597
}
98+
99+
pixels_complete.add(new_pixels_complete);
86100
});
87101
}
88102

89-
pub fn iterate_normal_plus_derivative(pixel_data: &mut [PixelData], reference: &Reference) {
103+
pub fn iterate_normal_plus_derivative(pixel_data: &mut [PixelData], reference: &Reference, pixels_complete: &Arc<RelaxedCounter>, stop_flag: &Arc<RelaxedCounter>) {
90104
pixel_data.par_chunks_mut(4)
91105
.for_each(|pixel_data| {
106+
if stop_flag.get() >= 1 {
107+
return;
108+
}
109+
110+
let mut new_pixels_complete = 0;
111+
92112
for pixel in pixel_data {
93113
let mut scaled_iterations = 0;
94114
let mut scaled_scale_factor_1 = 1.0f64.ldexp(pixel.delta_current.exponent);
@@ -120,6 +140,7 @@ impl Perturbation {
120140
pixel.escaped = true;
121141
pixel.delta_current.mantissa = pixel.delta_current.to_float();
122142
pixel.delta_current.exponent = 0;
143+
new_pixels_complete += 1;
123144
break;
124145
}
125146
}
@@ -172,8 +193,11 @@ impl Perturbation {
172193

173194
if !pixel.escaped && !pixel.glitched {
174195
pixel.iteration = reference.current_iteration;
196+
new_pixels_complete += 1;
175197
}
176198
}
199+
200+
pixels_complete.add(new_pixels_complete);
177201
});
178202
}
179203
}

src/math/reference.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
use crate::util::{ComplexArbitrary, ComplexFixed, ComplexExtended, FloatExtended, to_fixed, to_extended};
22

3+
use atomic_counter::{AtomicCounter, RelaxedCounter};
4+
5+
use std::sync::Arc;
6+
37
#[derive(Clone)]
48
pub struct Reference {
59
pub start_iteration: usize,
@@ -69,7 +73,7 @@ impl Reference {
6973
}
7074

7175

72-
pub fn run(&mut self) {
76+
pub fn run(&mut self, reference_counter: &Arc<RelaxedCounter>, reference_maximum_iteration_counter: &Arc<RelaxedCounter>, stop_flag: &Arc<RelaxedCounter>) {
7377
let z_fixed = to_fixed(&self.z);
7478
let z_tolerance = self.glitch_tolerance * z_fixed.norm_sqr();
7579

@@ -96,7 +100,15 @@ impl Reference {
96100
}
97101
}
98102

103+
if stop_flag.get() >= 1 {
104+
return
105+
};
106+
107+
reference_counter.inc();
108+
99109
if !self.step() {
110+
reference_maximum_iteration_counter.add(usize::max_value() - self.maximum_iteration + reference_counter.get() + 1);
111+
100112
break;
101113
};
102114
}

src/math/series_approximation.rs

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ use rayon::prelude::*;
77

88
use std::cmp::max;
99

10+
use atomic_counter::{AtomicCounter, RelaxedCounter};
11+
12+
use std::sync::Arc;
13+
1014
pub struct SeriesApproximation {
1115
pub maximum_iteration: usize,
1216
pub delta_pixel_square: FloatExtended,
@@ -16,6 +20,7 @@ pub struct SeriesApproximation {
1620
approximation_probes: Vec<Vec<ComplexExtended>>,
1721
approximation_probes_derivative: Vec<Vec<ComplexExtended>>,
1822
pub min_valid_iteration: usize,
23+
pub max_valid_iteration: usize,
1924
pub valid_iterations: Vec<usize>,
2025
pub valid_interpolation: Vec<usize>,
2126
pub probe_sampling: usize,
@@ -45,6 +50,7 @@ impl SeriesApproximation {
4550
approximation_probes: Vec::new(),
4651
approximation_probes_derivative: Vec::new(),
4752
min_valid_iteration: 1,
53+
max_valid_iteration: 1,
4854
valid_iterations: Vec::new(),
4955
valid_interpolation: Vec::new(),
5056
probe_sampling,
@@ -55,7 +61,7 @@ impl SeriesApproximation {
5561
}
5662
}
5763

58-
pub fn generate_approximation(&mut self, center_reference: &Reference) {
64+
pub fn generate_approximation(&mut self, center_reference: &Reference, series_approximation_counter: &Arc<RelaxedCounter>, stop_flag: &Arc<RelaxedCounter>) {
5965
// Reset the coefficients
6066
self.coefficients = vec![vec![ComplexExtended::new2(0.0, 0.0, 0); self.order as usize + 1]; 1];
6167

@@ -66,11 +72,14 @@ impl SeriesApproximation {
6672
let add_value = ComplexExtended::new2(1.0, 0.0, 0);
6773

6874
let mut previous_coefficients = self.coefficients[0].clone();
75+
let mut next_coefficients = vec![ComplexExtended::new2(0.0, 0.0, 0); self.order as usize + 1];
6976

7077
// Can be changed later into a better loop - this function could also return some more information
7178
// Go through all remaining iterations
7279
for i in 1..self.maximum_iteration {
73-
let mut next_coefficients = vec![ComplexExtended::new2(0.0, 0.0, 0); self.order as usize + 1];
80+
if stop_flag.get() >= 1 {
81+
return
82+
};
7483

7584
// This is checking if the approximation can step forward so takes the next iteration
7685
next_coefficients[0] = center_reference.reference_data[i].z_extended;
@@ -98,11 +107,12 @@ impl SeriesApproximation {
98107

99108
previous_coefficients = next_coefficients.clone();
100109

101-
110+
series_approximation_counter.inc();
111+
102112
// only every 100th iteration (101, 201 etc)
103113
// This is 0, 100, 200 -> 1, 101, 201
104114
if i % self.data_storage_interval == 0 {
105-
self.coefficients.push(next_coefficients);
115+
self.coefficients.push(next_coefficients.clone());
106116
}
107117

108118
// self.coefficients.push(next_coefficients);
@@ -117,7 +127,8 @@ impl SeriesApproximation {
117127
delta_pixel: f64,
118128
image_width: usize,
119129
image_height: usize,
120-
center_reference: &Reference) {
130+
center_reference: &Reference,
131+
series_validation_counter: &Arc<RelaxedCounter>) {
121132
// Delete the previous probes and calculate new ones
122133
self.probe_start = Vec::new();
123134
self.approximation_probes = Vec::new();
@@ -203,6 +214,8 @@ impl SeriesApproximation {
203214
first_valid_iterations += 1;
204215
}
205216

217+
series_validation_counter.inc();
218+
206219
self.min_valid_iteration = first_valid_iterations;
207220

208221
// println!("{}", self.min_valid_iteration);
@@ -260,6 +273,8 @@ impl SeriesApproximation {
260273
derivative_probe += next_coefficients[k] * self.approximation_probes_derivative[i][k - 1];
261274
};
262275

276+
probe.reduce();
277+
263278
let relative_error = (probe - series_probe).norm_square();
264279
let mut derivative = derivative_probe.norm_square();
265280

@@ -269,10 +284,14 @@ impl SeriesApproximation {
269284
derivative.exponent = 0;
270285
}
271286

287+
// println!("checking at: {}", *probe_iteration_level);
288+
// println!("relative error: {} derivative: {} delta_square: {}", relative_error, derivative, self.delta_pixel_square);
289+
// println!("probe: {} series_probe: {}", probe, series_probe);
290+
272291
// The first element is reduced, the second might need to be reduced a little more
273292
// Check that the error over the derivative is less than the pixel spacing
274-
if relative_error / derivative > self.delta_pixel_square {
275-
// println!("{} ", *probe_iteration_level);
293+
if relative_error / derivative > self.delta_pixel_square || relative_error.exponent > 0 {
294+
// println!("exceeded at: {} ", *probe_iteration_level);
276295

277296
if *probe_iteration_level <= (current_probe_check_value + self.data_storage_interval + 1) {
278297
*probe_iteration_level = next_probe_check_value;
@@ -322,6 +341,8 @@ impl SeriesApproximation {
322341
}
323342
}
324343

344+
series_validation_counter.inc();
345+
325346
self.valid_iterations = valid_iterations;
326347

327348
// Also, here we do the interpolation and set up the array
@@ -341,7 +362,20 @@ impl SeriesApproximation {
341362
}
342363
}
343364

344-
// println!("{:?}", self.valid_interpolation);
365+
self.max_valid_iteration = self.valid_interpolation.iter().max().unwrap().clone();
366+
367+
// println!("series approximation valid interpolation buffer:");
368+
// let temp_size = self.probe_sampling - 1;
369+
// for i in 0..temp_size {
370+
// let test = &self.valid_interpolation[(i * temp_size)..((i + 1) * temp_size)];
371+
// print!("[");
372+
373+
// for element in test {
374+
// print!("{:>8},", element);
375+
// }
376+
377+
// print!("\x08]\n");
378+
// }
345379

346380
if !self.experimental {
347381
self.valid_interpolation = vec![self.min_valid_iteration; (self.probe_sampling - 1) * (self.probe_sampling - 1)];

0 commit comments

Comments
 (0)