55using namespace sycl ;
66using namespace std ;
77
8- std::complex <double > complex_square (std::complex <double > c)
8+ template < typename T> std::complex <T > complex_square (std::complex <T > c)
99{
10- return std::complex <double >(c.real () * c.real () - c.imag () * c.imag (), c.real () * c.imag () * 2 );
10+ return std::complex <T >(c.real () * c.real () - c.imag () * c.imag (), c.real () * c.imag () * 2 );
1111}
1212
13- struct MandelParameters {
14- int width;
15- int height;
16- int maxIterations;
17-
18- double xmin;
19- double xmax;
20- double ymin;
21- double ymax;
22-
23- using ComplexF = std::complex <double >;
24-
25- MandelParameters (int width, int height, int maxIterations, double xmin, double xmax, double ymin, double ymax) :
26- width (width),
27- height (height),
28- maxIterations (maxIterations),
29- xmin (xmin),
30- xmax (xmax),
31- ymin (ymin),
32- ymax (ymax) {}
33-
34- // Scale from 0..width to xmin..xmax
35- double ScaleRow (int i) const { return xmin + (i * (xmax - xmin) / width); }
36-
37- // Scale from 0..height to ymin..ymax
38- double ScaleCol (int i) const { return -(ymin + (i * (ymax - ymin) / height)); }
39-
40- // Mandelbrot set are points that do not diverge within max_iterations.
41- int Point (const ComplexF& c) const {
42- int count = 0 ;
43- ComplexF z = 0 ;
44-
45- for (int i = 0 ; i < maxIterations; ++i) {
46- auto r = z.real ();
47- auto im = z.imag ();
48-
49- // Leave loop if diverging.
50- if (((r * r) + (im * im)) >= 4 .0f ) {
51- break ;
13+ template <typename T> class MandelParameters {
14+ using ComplexF = std::complex <T>;
15+
16+ public:
17+ MandelParameters () {}
18+ MandelParameters (int width, int height, int maxIterations, T xmin, T xmax, T ymin, T ymax):
19+ width (width),
20+ height (height),
21+ maxIterations (maxIterations),
22+ xmin (xmin),
23+ xmax (xmax),
24+ ymin (ymin),
25+ ymax (ymax) {}
26+
27+ T ScaleRow (int i) const { return xmin + (i * (xmax - xmin) / width); }
28+
29+ // Scale from 0..height to ymin..ymax
30+ T ScaleCol (int i) const { return -(ymin + (i * (ymax - ymin) / height)); }
31+
32+ // Mandelbrot set are points that do not diverge within max_iterations.
33+ int Point (const ComplexF& c) const {
34+ int count = 0 ;
35+ ComplexF z = 0 ;
36+
37+ for (int i = 0 ; i < maxIterations; ++i) {
38+ auto r = z.real ();
39+ auto im = z.imag ();
40+
41+ // Leave loop if diverging.
42+ if (((r * r) + (im * im)) >= 4 .0f ) {
43+ break ;
44+ }
45+
46+ // z = z * z + c;
47+ z = complex_square<T>(z) + c;
48+ count++;
5249 }
5350
54- // z = z * z + c;
55- z = complex_square (z) + c;
56- count++;
51+ return count;
5752 }
5853
59- return count;
60- }
54+ void scale (T xoffset, T yoffset, T scale) {
55+ // calculate cursour position in the mandelbrot space
56+ T x = xmin + (xmax - xmin) * xoffset;
57+ T y = ymin + (ymax - ymin) * yoffset;
58+
59+ // scale the space
60+ xmin *= 1 + 0.02 * scale;
61+ xmax *= 1 + 0.02 * scale;
62+ ymin *= 1 + 0.02 * scale;
63+ ymax *= 1 + 0.02 * scale;
64+
65+ // calculate coursor position in the scaled mandelbrot space
66+ T x2 = xmin + (xmax - xmin) * xoffset;
67+ T y2 = ymin + (ymax - ymin) * yoffset;
68+
69+ // calculate the offset between position before and after scaling
70+ T offset_x = x2 - x;
71+ T offset_y = y2 - y;
72+
73+ // move the space by offset
74+ xmin -= offset_x;
75+ xmax -= offset_x;
76+ ymin -= offset_y;
77+ ymax -= offset_y;
78+ }
79+
80+ void pan (T xoffset, T yoffset) {
81+ // convert the camera movment from 0 - 1.0 range to distance in mandelbrot space.
82+ T w = (xmax - xmin) * xoffset;
83+ T h = (ymax - ymin) * yoffset;
84+
85+ // move the space by offset
86+ xmin -= w;
87+ xmax -= w;
88+ ymin -= h;
89+ ymax -= h;
90+ }
91+
92+ int width;
93+ int height;
94+ int maxIterations;
95+ T xmin;
96+ T xmax;
97+ T ymin;
98+ T ymax;
6199};
62100
63101
64102class Mandelbrot {
65103public:
66104 Mandelbrot (int width, int height, int maxIterations, double xmin, double xmax, double ymin, double ymax, queue& q);
105+ Mandelbrot (int width, int height, int maxIterations, float xmin, float xmax, float ymin, float ymax, queue& q);
67106 void Calculate (uint32_t * pixels);
68- MandelParameters getParameters () const { return parameters; }
69107 void scale (double xoffset, double yoffset, double scale);
70108 void pan (double xoffset, double yoffset);
109+ MandelParameters<float > getSPParameters () const { return sp_parameters; }
110+ MandelParameters<double > getDPParameters () const { return dp_parameters; }
71111
72112private:
113+ void CalculateSP (uint32_t * pixels);
114+ void CalculateDP (uint32_t * pixels);
73115 queue& q;
74- MandelParameters parameters;
116+ MandelParameters<float > sp_parameters;
117+ MandelParameters<double > dp_parameters;
118+ bool singlePrecision;
75119};
76120
77121Mandelbrot::Mandelbrot (int width, int height, int maxIterations, double xmin, double xmax, double ymin, double ymax, queue& q) :
78122 q(q),
79- parameters(width, height, maxIterations, xmin, xmax, ymin, ymax)
123+ dp_parameters(width, height, maxIterations, xmin, xmax, ymin, ymax),
124+ singlePrecision(false )
125+ {
126+ }
127+
128+ Mandelbrot::Mandelbrot (int width, int height, int maxIterations, float xmin, float xmax, float ymin, float ymax, queue& q) :
129+ q(q),
130+ sp_parameters(width, height, maxIterations, xmin, xmax, ymin, ymax),
131+ singlePrecision(true )
80132{
81133}
82134
83135void Mandelbrot::Calculate (uint32_t * pixels) {
84136
85- MandelParameters p = getParameters ();
86- const int width = p.width ;
87- const int height = p.height ;
88- const int maxIterations = p.maxIterations ;
137+ if (singlePrecision)
138+ CalculateSP (pixels);
139+ else
140+ Calculate (pixels);
141+ }
142+
143+ void Mandelbrot::CalculateSP (uint32_t * pixels) {
144+ MandelParameters<float > parameters = getSPParameters ();
145+ const int width = parameters.width ;
146+ const int height = parameters.height ;
147+ const int maxIterations = parameters.maxIterations ;
148+ buffer pixelsBuf (pixels, range (width * height));
149+
150+ // We submit a command group to the queue.
151+ q.submit ([&](handler& h) {
152+
153+ accessor ldata (pixelsBuf, h, write_only, no_init);
154+ // Iterate over image and compute mandel for each point.
155+ h.parallel_for (range<1 >(height * width), [=](auto index) {
156+ int y = index / height;
157+ int x = index % height;
158+ auto c = std::complex <float >(parameters.ScaleRow (x), parameters.ScaleCol (y));
159+ int value = parameters.Point (c);
160+ float normalized = (1 .0f * value) / maxIterations;
161+ ldata[index] = uint32_t (normalized * 0xFFFFFF );
162+ ldata[index] <<= 8 ;
163+ ldata[index] |= 0xFF ;
164+ });
165+ }).wait ();
166+ }
167+
168+ void Mandelbrot::CalculateDP (uint32_t * pixels) {
169+ MandelParameters<double > parameters = getDPParameters ();
170+ const int width = parameters.width ;
171+ const int height = parameters.height ;
172+ const int maxIterations = parameters.maxIterations ;
89173 buffer pixelsBuf (pixels, range (width * height));
90174
91175 // We submit a command group to the queue.
@@ -96,8 +180,8 @@ void Mandelbrot::Calculate(uint32_t* pixels) {
96180 h.parallel_for (range<1 >(height * width), [=](auto index) {
97181 int y = index / height;
98182 int x = index % height;
99- auto c = std::complex <double >(p .ScaleRow (x), p .ScaleCol (y));
100- int value = p .Point (c);
183+ auto c = std::complex <double >(parameters .ScaleRow (x), parameters .ScaleCol (y));
184+ int value = parameters .Point (c);
101185 double normalized = (1.0 * value) / maxIterations;
102186 ldata[index] = uint32_t (normalized * 0xFFFFFF );
103187 ldata[index] <<= 8 ;
@@ -108,41 +192,17 @@ void Mandelbrot::Calculate(uint32_t* pixels) {
108192
109193void Mandelbrot::scale (double xoffset, double yoffset, double scale)
110194{
111- // calculate cursour position in the mandelbrot space
112- double x = parameters.xmin + (parameters.xmax - parameters.xmin ) * xoffset;
113- double y = parameters.ymin + (parameters.ymax - parameters.ymin ) * yoffset;
114-
115- // scale the space
116- parameters.xmin *= 1 + 0.02 * scale;
117- parameters.xmax *= 1 + 0.02 * scale;
118- parameters.ymin *= 1 + 0.02 * scale;
119- parameters.ymax *= 1 + 0.02 * scale;
120-
121- // calculate coursor position in the scaled mandelbrot space
122- double x2 = parameters.xmin + (parameters.xmax - parameters.xmin ) * xoffset;
123- double y2 = parameters.ymin + (parameters.ymax - parameters.ymin ) * yoffset;
124-
125- // calculate the offset between position before and after scaling
126- double offset_x = x2 - x;
127- double offset_y = y2 - y;
128-
129- // move the space by offset
130- parameters.xmin -= offset_x;
131- parameters.xmax -= offset_x;
132- parameters.ymin -= offset_y;
133- parameters.ymax -= offset_y;
195+ if (singlePrecision)
196+ sp_parameters.scale ((float ) xoffset, (float ) yoffset, (float ) scale);
197+ else
198+ dp_parameters.scale (xoffset, yoffset, scale);
134199}
135200
136201void Mandelbrot::pan (double xoffset, double yoffset)
137202{
138- // convert the camera movment from 0 - 1.0 range to distance in mandelbrot space.
139- double w = (parameters.xmax - parameters.xmin ) * xoffset;
140- double h = (parameters.ymax - parameters.ymin ) * yoffset;
141-
142- // move the space by offset
143- parameters.xmin -= w;
144- parameters.xmax -= w;
145- parameters.ymin -= h;
146- parameters.ymax -= h;
203+ if (singlePrecision)
204+ sp_parameters.pan ((float ) xoffset, (float ) yoffset);
205+ else
206+ dp_parameters.pan (xoffset, yoffset);
147207}
148208
0 commit comments