mandelbrot_common/
lib.rs

1mod mandelbrot;
2
3use crate::mandelbrot::mandelbrot;
4use ndarray::prelude::*;
5use num_complex::Complex;
6
7#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
8use rayon::prelude::*;
9
10/// Generate an image from the Mandelbrot set.
11///
12/// # Examples
13///
14/// ```
15/// use ndarray::prelude::*;
16///
17/// let img = mandelbrot_common::generate(8, 4f64, 50);
18/// let correct: Array2<u8> = arr2(&[
19///     [253, 253, 252, 252, 252],
20///     [253, 252, 252, 251, 205],
21///     [253, 251, 249, 205, 205],
22///     [253, 205, 205, 205, 205],
23///     [253, 251, 249, 205, 205]
24/// ]).reversed_axes();
25/// assert_eq!(img, correct);
26/// ```
27pub fn generate(n: usize, threshold: f64, max_steps: u8) -> Array2<u8> {
28    let x_lower = 0;
29    let x_upper = (5 * n) / 8;
30    let y_lower = (2 * n) / 10;
31    let y_upper = (8 * n) / 10;
32
33    #[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
34    let vec_storage: Vec<u8> = (x_lower..x_upper)
35        .into_par_iter()
36        .flat_map(move |x| {
37            (y_lower..y_upper).into_par_iter().map(move |y| {
38                let c = Complex {
39                    re: 4f64 * (x as f64 - n as f64 / 2f64) / n as f64,
40                    im: 4f64 * (y as f64 - n as f64 / 2f64) / n as f64,
41                };
42                255u8 - mandelbrot(c, threshold, max_steps)
43            })
44        })
45        .collect();
46
47    #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
48    let vec_storage: Vec<u8> = (x_lower..x_upper)
49        .flat_map(move |x| {
50            (y_lower..y_upper).map(move |y| {
51                let c = Complex {
52                    re: 4f64 * (x as f64 - n as f64 / 2f64) / n as f64,
53                    im: 4f64 * (y as f64 - n as f64 / 2f64) / n as f64,
54                };
55                255u8 - mandelbrot(c, threshold, max_steps)
56            })
57        })
58        .collect();
59
60    Array2::from_shape_vec((x_upper, y_upper - y_lower), vec_storage).unwrap()
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66
67    #[test]
68    fn it_works() {
69        let img = generate(8, 4f64, 50);
70        let correct: Array2<u8> = arr2(&[
71            [253, 253, 252, 252, 252],
72            [253, 252, 252, 251, 205],
73            [253, 251, 249, 205, 205],
74            [253, 205, 205, 205, 205],
75            [253, 251, 249, 205, 205],
76        ])
77        .reversed_axes();
78        assert_eq!(img, correct);
79    }
80}