More C++ fun

I’m loathe to turn this into a Fun Things To Make And Do with C++ blog, but this one is kind of neat. One of the first things all programmers do when they first get their hands on a graphics library is draw a Mandelbrot Set as defined by the equation z → z2 + c. I’ve been toying around with templates and stuff recently, and someone suggested that I should give writing a mandelbrot set generator using template metaprogramming a go. So I did:

#include <iostream>

template <int iter, int zx, int zy, int cx, int cy>
class Mand
{
public:
  static const int zxPrime = (int) (
    (
      (
        ((float)(Mand<iter-1, zx, zy, cx, cy>::zxPrime)/10000.0f) *
        ((float)(Mand<iter-1, zx, zy, cx, cy>::zxPrime)/10000.0f)
        –
        ((float)(Mand<iter-1, zx, zy, cx, cy>::zyPrime)/10000.0f) *
        ((float)(Mand<iter-1, zx, zy, cx, cy>::zyPrime)/10000.0f)
      ) +
      (cx/10000.0f)
    ) * 10000.0f
  );

  static const int zyPrime = (int) (
    (
      (
        2.0f *
        ((float)(Mand<iter-1, zx, zy, cx, cy>::zxPrime)/10000.0f) *
        ((float)(Mand<iter-1, zx, zy, cx, cy>::zyPrime)/10000.0f)
      ) –
      (cy/10000.0f)
    ) * 10000.0f
  );
};

template<int cx, int cy>
class Mand<0, 0, 0, cx, cy>
{
public:
  static const int zxPrime = cx;
  static const int zyPrime = -cy;
};

int x = Mand<100, 0, 0, 1000, 1000>::zxPrime;
int y = Mand<100, 0, 0, 1000, 1000>::zyPrime;

int main(void)
{
  std::cout << “Mandlebrot metaprogramming” << std::endl;
  std::cout << (float)x/10000.0f << “, ” << (float)y/10000.0f << std::endl;
}

This will calculate 100 iterations of the Mandlebrot function for the point c=(0.1, 0.1) and print out the result. The neat trick is that it’s actually the compiler that does the calculation, not the executable (however, as it requires float-casts in a constant expression, some compilers [including gcc 3.4] will barf on it – gcc 3.3.3 seems fine). Because you can’t have floats as parameters to templates, I’ve had to pass all the values around as ints, hence all the /10000.0f and *10000.0f all over the place.

I discovered this whilst I was looking for ideas; it actually prints out the set in ASCII as well, which is very nice indeed. He uses enums rather than static consts, which may break fewer compilers; I don’t know.

Comments are closed.