Skip to content

Commit ce44af0

Browse files
committed
Added avx512 struct for future portability
1 parent 5b293ec commit ce44af0

8 files changed

+62
-54
lines changed

CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ add_library(
2626
source/graphics/color_conversions/color_conversions.cpp
2727
source/graphics/aspect_ratio/aspect_ratio.cpp
2828
source/mandelbrot/equations_simd.cpp
29+
source/mandelbrot/equations.cpp
2930
)
3031

3132
target_include_directories(

source/mandelbrot/equations.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include "equations.hpp"
2+
3+
#include "config.hpp"
4+
5+
namespace fractal {
6+
// https://en.wikipedia.org/wiki/Mandelbrot_set#Formal_definition
7+
std::complex<complex_underlying>
8+
step(std::complex<complex_underlying> z_n, std::complex<complex_underlying> constant)
9+
{
10+
return z_n * z_n + constant;
11+
}
12+
13+
iteration_count compute_iterations(
14+
std::complex<complex_underlying> z_0, std::complex<complex_underlying> constant,
15+
iteration_count max_iters
16+
)
17+
{
18+
iteration_count iterations = 0;
19+
std::complex<complex_underlying> z_n = z_0;
20+
21+
while (iterations < max_iters && std::norm(z_n) < MANDELBROT_DIVERGENCE_NORM) {
22+
z_n = step(z_n, constant);
23+
++iterations;
24+
}
25+
26+
return iterations;
27+
}
28+
} // namespace fractal

source/mandelbrot/equations.hpp

+4-19
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,14 @@
11
#pragma once
22

3-
#include "config.hpp"
43
#include "units.hpp"
54

65
namespace fractal {
76
// https://en.wikipedia.org/wiki/Mandelbrot_set#Formal_definition
8-
inline std::complex<complex_underlying>
9-
step(std::complex<complex_underlying> z_n, std::complex<complex_underlying> constant)
10-
{
11-
return z_n * z_n + constant;
12-
}
7+
std::complex<complex_underlying>
8+
step(std::complex<complex_underlying> z_n, std::complex<complex_underlying> constant);
139

14-
inline iteration_count compute_iterations(
10+
iteration_count compute_iterations(
1511
std::complex<complex_underlying> z_0, std::complex<complex_underlying> constant,
1612
iteration_count max_iters
17-
)
18-
{
19-
iteration_count iterations = 0;
20-
std::complex<complex_underlying> z_n = z_0;
21-
22-
while (iterations < max_iters && std::norm(z_n) < MANDELBROT_DIVERGENCE_NORM) {
23-
z_n = step(z_n, constant);
24-
++iterations;
25-
}
26-
27-
return iterations;
28-
}
13+
);
2914
} // namespace fractal

source/mandelbrot/equations_simd.cpp

+7-19
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,19 @@
1+
#include "config.hpp"
12
#include "equations.hpp"
3+
#include "units.hpp"
24

35
namespace fractal {
46
std::array<iteration_count, 8> compute_iterations(
5-
const std::array<std::complex<complex_underlying>, 8>& z_0,
6-
const std::array<std::complex<complex_underlying>, 8>& constant,
7-
iteration_count max_iters
7+
const avx512_complex& z_0, const avx512_complex& constant, iteration_count max_iters
88
)
99
{
1010
static const auto SQUARED_DIVERGENCE =
1111
MANDELBROT_DIVERGENCE_NORM * MANDELBROT_DIVERGENCE_NORM;
1212

13-
alignas(64) std::array<double, 8> reals = {z_0[0].real(), z_0[1].real(),
14-
z_0[2].real(), z_0[3].real(),
15-
z_0[4].real(), z_0[5].real(),
16-
z_0[6].real(), z_0[7].real()};
17-
alignas(64) std::array<double, 8> imags = {z_0[0].imag(), z_0[1].imag(),
18-
z_0[2].imag(), z_0[3].imag(),
19-
z_0[4].imag(), z_0[5].imag(),
20-
z_0[6].imag(), z_0[7].imag()};
21-
alignas(64) std::array<double, 8> const_reals = {
22-
constant[0].real(), constant[1].real(), constant[2].real(), constant[3].real(),
23-
constant[4].real(), constant[5].real(), constant[6].real(), constant[7].real()
24-
};
25-
alignas(64) std::array<double, 8> const_imags = {
26-
constant[0].imag(), constant[1].imag(), constant[2].imag(), constant[3].imag(),
27-
constant[4].imag(), constant[5].imag(), constant[6].imag(), constant[7].imag()
28-
};
13+
alignas(64) std::array<double, 8> reals = z_0.real;
14+
alignas(64) std::array<double, 8> imags = z_0.imaginary;
15+
alignas(64) std::array<double, 8> const_reals = constant.real;
16+
alignas(64) std::array<double, 8> const_imags = constant.imaginary;
2917

3018
std::array<iteration_count, 8> solved_its = {0};
3119

source/mandelbrot/equations_simd.hpp

+1-7
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,8 @@
66
#include <immintrin.h>
77

88
namespace fractal {
9-
// https://en.wikipedia.org/wiki/Mandelbrot_set#Formal_definition
10-
11-
std::complex<complex_underlying>
12-
step(std::complex<complex_underlying> z_n, std::complex<complex_underlying> constant);
139

1410
std::array<iteration_count, 8> compute_iterations(
15-
const std::array<std::complex<complex_underlying>, 8>& z_0,
16-
const std::array<std::complex<complex_underlying>, 8>& constant,
17-
iteration_count max_iters
11+
const avx512_complex& z_0, const avx512_complex& constant, iteration_count max_iters
1812
);
1913
} // namespace fractal

source/mandelbrot/mandelbrot_window.cpp

+9-7
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,12 @@
2424

2525
namespace fractal {
2626
void MandelbrotWindow::draw_coordinate_(
27-
display_coordinate display_coord,
28-
const std::array<std::complex<complex_underlying>, 8>& complex_coords
27+
display_coordinate display_coord, const avx512_complex& complex_coords
2928
)
3029
{
31-
static constexpr std::array<std::complex<complex_underlying>, 8> starts = {
32-
std::complex<complex_underlying>{0, 0}
33-
};
30+
static constexpr avx512_complex START{};
3431
auto iterations =
35-
compute_iterations(starts, complex_coords, MANDELBROT_MAX_ITERATIONS);
32+
compute_iterations(START, complex_coords, MANDELBROT_MAX_ITERATIONS);
3633

3734
for (size_t i = 0; i < 8; i++) {
3835
float iteration_ratio =
@@ -59,7 +56,12 @@ void MandelbrotWindow::on_resize_(display_domain new_domain_selection)
5956
coords[i] = to_complex.to_complex_projection(start_display_coord);
6057
start_display_coord.first++;
6158
}
62-
draw_coordinate_(t, coords);
59+
avx512_complex coords2{};
60+
for (size_t i = 0; i < 8; i++) {
61+
coords2.real[i] = coords[i].real();
62+
coords2.imaginary[i] = coords[i].imag();
63+
}
64+
draw_coordinate_(t, coords2);
6365
};
6466

6567
auto process_chunk = [&](display_domain::DisplayCoordinateIterator start,

source/mandelbrot/mandelbrot_window.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "config.hpp"
44
#include "coordinates.hpp"
55
#include "graphics/display_event_observer.hpp"
6+
#include "units.hpp"
67

78
#include <SFML/Graphics/Drawable.hpp>
89
#include <SFML/Graphics/Image.hpp>
@@ -22,8 +23,7 @@ class MandelbrotWindow : public DisplayEventObserver {
2223

2324
void on_resize_(display_domain new_domain_selection);
2425
void draw_coordinate_(
25-
display_coordinate display_coord,
26-
const std::array<std::complex<complex_underlying>, 8>& complex_coords
26+
display_coordinate display_coord, const avx512_complex& complex_coords
2727
);
2828

2929
public:

source/units.hpp

+10
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,16 @@ using complex = boost::multiprecision::complex_adaptor<small_float>;*/
1515

1616
using complex_underlying = double;
1717

18+
struct avx512_complex {
19+
std::array<complex_underlying, 8> real;
20+
std::array<complex_underlying, 8> imaginary;
21+
22+
std::complex<complex_underlying> get_complex(uint8_t index)
23+
{
24+
return {real[index], imaginary[index]};
25+
}
26+
};
27+
1828
struct color {
1929
uint8_t red;
2030
uint8_t green;

0 commit comments

Comments
 (0)