MandelbrotThread Class Reference

#include <mandelbrot.h>

+ Inheritance diagram for MandelbrotThread:

Public Member Functions

 MandelbrotThread (MandelbrotWidget *w, int i)
 
void run ()
 
template<typename Real >
void render (int img_width, int img_height)
 

Private Attributes

MandelbrotWidgetwidget
 
long long total_iter
 
int id
 
int max_iter
 
bool single_precision
 

Friends

class MandelbrotWidget
 

Constructor & Destructor Documentation

◆ MandelbrotThread()

MandelbrotThread::MandelbrotThread ( MandelbrotWidget w,
int  i 
)
inline
28 : widget(w), id(i) {}
int i
Definition: BiCGSTAB_step_by_step.cpp:9
RowVector3d w
Definition: Matrix_resize_int.cpp:3
int id
Definition: mandelbrot.h:24
MandelbrotWidget * widget
Definition: mandelbrot.h:22

Member Function Documentation

◆ render()

template<typename Real >
void MandelbrotThread::render ( int  img_width,
int  img_height 
)
36  {
37  enum { packetSize = Eigen::internal::packet_traits<Real>::size }; // number of reals in a Packet
38  typedef Eigen::Array<Real, packetSize, 1> Packet; // wrap a Packet as a vector
39 
42  const int alignedWidth = (img_width / packetSize) * packetSize;
43  unsigned char *const buffer = widget->buffer;
44  const double xradius = widget->xradius;
45  const double yradius = xradius * img_height / img_width;
46  const int threadcount = widget->threadcount;
47  typedef Eigen::Array<Real, 2, 1> Vector2;
48  Vector2 start(widget->center.x() - widget->xradius, widget->center.y() - yradius);
49  Vector2 step(2 * widget->xradius / img_width, 2 * yradius / img_height);
50  total_iter = 0;
51 
52  for (int y = id; y < img_height; y += threadcount) {
53  int pix = y * img_width;
54 
55  // for each pixel, we're going to do the iteration z := z^2 + c where z and c are complex numbers,
56  // starting with z = c = complex coord of the pixel. pzi and pzr denote the real and imaginary parts of z.
57  // pci and pcr denote the real and imaginary parts of c.
58 
59  Packet pzi_start, pci_start;
60  for (int i = 0; i < packetSize; i++) pzi_start[i] = pci_start[i] = start.y() + y * step.y();
61 
62  for (int x = 0; x < alignedWidth; x += packetSize, pix += packetSize) {
63  Packet pcr, pci = pci_start, pzr, pzi = pzi_start, pzr_buf;
64  for (int i = 0; i < packetSize; i++) pzr[i] = pcr[i] = start.x() + (x + i) * step.x();
65 
66  // do the iterations. Every iters_before_test iterations we check for divergence,
67  // in which case we can stop iterating.
68  int j = 0;
69  typedef Eigen::Matrix<int, packetSize, 1> Packeti;
70  Packeti pix_iter = Packeti::Zero(), // number of iteration per pixel in the packet
71  pix_dont_diverge; // whether or not each pixel has already diverged
72  do {
73  for (int i = 0; i < iters_before_test / 4; i++) // peel the inner loop by 4
74  {
75 #define ITERATE \
76  pzr_buf = pzr; \
77  pzr = pzr.square(); \
78  pzr -= pzi.square(); \
79  pzr += pcr; \
80  pzi = (2 * pzr_buf) * pzi; \
81  pzi += pci;
83  }
84  pix_dont_diverge =
85  ((pzr.square() + pzi.square()).eval() // temporary fix as what follows is not yet vectorized by Eigen
86  <= Packet::Constant(4))
87  // the 4 here is not a magic value, it's a math fact that if
88  // the square modulus is >4 then divergence is inevitable.
89  .template cast<int>();
90  pix_iter += iters_before_test * pix_dont_diverge;
91  j++;
92  total_iter += iters_before_test * packetSize;
93  } while (j < max_iter / iters_before_test && pix_dont_diverge.any()); // any() is not yet vectorized by Eigen
94 
95  // compute pixel colors
96  for (int i = 0; i < packetSize; i++) {
97  buffer[4 * (pix + i)] = 255 * pix_iter[i] / max_iter;
98  buffer[4 * (pix + i) + 1] = 0;
99  buffer[4 * (pix + i) + 2] = 0;
100  }
101  }
102 
103  // if the width is not a multiple of packetSize, fill the remainder in black
104  for (int x = alignedWidth; x < img_width; x++, pix++)
105  buffer[4 * pix] = buffer[4 * pix + 1] = buffer[4 * pix + 2] = 0;
106  }
107  return;
108 }
internal::packet_traits< Scalar >::type Packet
Definition: benchmark-blocking-sizes.cpp:54
General-purpose arrays with easy API for coefficient-wise operations.
Definition: Array.h:48
The matrix class, also used for vectors and row-vectors.
Definition: Eigen/Eigen/src/Core/Matrix.h:186
int max_iter
Definition: mandelbrot.h:24
long long total_iter
Definition: mandelbrot.h:23
Eigen::Vector2d center
Definition: mandelbrot.h:38
double xradius
Definition: mandelbrot.h:39
int threadcount
Definition: mandelbrot.h:45
unsigned char * buffer
Definition: mandelbrot.h:41
Scalar * y
Definition: level1_cplx_impl.h:128
#define ITERATE
void start(const unsigned &i)
(Re-)start i-th timer
Definition: oomph_utilities.cc:243
double Zero
Definition: pseudosolid_node_update_elements.cc:35
list x
Definition: plotDoE.py:28
internal::nested_eval< T, 1 >::type eval(const T &xpr)
Definition: sparse_permutations.cpp:47
Definition: GenericPacketMath.h:108
Definition: mandelbrot.cpp:27
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References MandelbrotWidget::buffer, MandelbrotWidget::center, eval(), i, ITERATE, j, max_iter, oomph::CumulativeTimings::start(), MandelbrotWidget::threadcount, total_iter, widget, plotDoE::x, MandelbrotWidget::xradius, y, and oomph::PseudoSolidHelper::Zero.

◆ run()

void MandelbrotThread::run ( )
110  {
111  setTerminationEnabled(true);
112  double resolution = widget->xradius * 2 / widget->width();
113  max_iter = 128;
114  if (resolution < 1e-4f) max_iter += 128 * (-4 - std::log10(resolution));
115  int img_width = widget->width() / widget->draft;
116  int img_height = widget->height() / widget->draft;
117  single_precision = resolution > 1e-7f;
118 
119  if (single_precision)
120  render<float>(img_width, img_height);
121  else
122  render<double>(img_width, img_height);
123 }
bool single_precision
Definition: mandelbrot.h:25
int draft
Definition: mandelbrot.h:43
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 log10(const bfloat16 &a)
Definition: BFloat16.h:620

References MandelbrotWidget::draft, Eigen::bfloat16_impl::log10(), max_iter, single_precision, widget, and MandelbrotWidget::xradius.

Friends And Related Function Documentation

◆ MandelbrotWidget

friend class MandelbrotWidget
friend

Member Data Documentation

◆ id

int MandelbrotThread::id
private

◆ max_iter

int MandelbrotThread::max_iter
private

Referenced by render(), and run().

◆ single_precision

bool MandelbrotThread::single_precision
private

◆ total_iter

long long MandelbrotThread::total_iter
private

◆ widget

MandelbrotWidget* MandelbrotThread::widget
private

Referenced by render(), and run().


The documentation for this class was generated from the following files: