graphics/fractal.cpp
/*******************************************************
*
* The complete license agreement can be obtained at:
********************************************************/
#include <arrayfire.h>
#include <stdio.h>
#include <cmath>
#include <cstdlib>
#include <iostream>
#define WIDTH 400 // Width of image
#define HEIGHT 400 // Width of image
using namespace af;
using std::abs;
array complex_grid(int width, int height, float zoom, float center[2]) {
// Generate sequences of length width, height
array X =
(iota(dim4(1, height), dim4(width, 1)) - (float)height / 2.0) / zoom +
center[0];
array Y =
(iota(dim4(width, 1), dim4(1, height)) - (float)width / 2.0) / zoom +
center[1];
// Return the locations as a complex grid
return complex(X, Y);
}
array mandelbrot(const array &in, int iter, float maxval) {
array C = in;
array Z = C;
array mag = constant(0, C.dims());
for (int ii = 1; ii < iter; ii++) {
// Do the calculation
Z = Z * Z + C;
// Get indices where abs(Z) crosses maxval
array cond = (abs(Z) > maxval).as(f32);
mag = af::max(mag, cond * ii);
// If abs(Z) cross maxval, turn off those locations
C = C * (1 - cond);
Z = Z * (1 - cond);
// Ensuring the JIT does not become too large
af::eval(C, Z);
mag.eval();
}
// Normalize
return mag / maxval;
}
array normalize(array a) {
float mx = af::max<float>(a);
float mn = af::min<float>(a);
return (a - mn) / (mx - mn);
}
int main(int argc, char **argv) {
int device = argc > 1 ? atoi(argv[1]) : 0;
int iter = argc > 2 ? atoi(argv[2]) : 100;
bool console = argc > 2 ? argv[2][0] == '-' : false;
try {
af::setDevice(device);
info();
printf("** ArrayFire Fractals Demo **\n");
af::Window wnd(WIDTH, HEIGHT, "Fractal Demo");
wnd.setColorMap(AF_COLORMAP_SPECTRUM);
float center[] = {-0.75f, 0.1f};
// Keep zomming out for each frame
for (int i = 10; i < 400; i++) {
int zoom = i * i;
if (!(i % 10)) {
printf("iteration: %d zoom: %d\n", i, zoom);
fflush(stdout);
}
// Generate the grid at the current zoom factor
array c = complex_grid(WIDTH, HEIGHT, zoom, center);
iter = sqrt(abs(2 * sqrt(abs(1 - sqrt(5 * zoom))))) * 100;
// Generate the mandelbrot image
array mag = mandelbrot(c, iter, 1000);
if (!console) {
if (wnd.close()) break;
array mag_norm = normalize(mag);
wnd.image(mag_norm);
}
}
} catch (af::exception &e) {
fprintf(stderr, "%s\n", e.what());
throw;
}
return 0;
}
af::dim4
Generic object that represents size and shape.
Definition: dim4.hpp:33
af::complex
AFAPI array complex(const array &real, const array &imaginary)
af::info
AFAPI void info()
af::constant
array constant(T val, const dim4 &dims, const dtype ty=(af_dtype) dtype_traits< T >::ctype)
AF_COLORMAP_SPECTRUM
@ AF_COLORMAP_SPECTRUM
Spectrum map (390nm-830nm, in sRGB colorspace)
Definition: defines.h:455
af::setDevice
AFAPI void setDevice(const int device)
Sets the current device.
af::abs
AFAPI array abs(const array &in)
C++ Interface for absolute value.
af::array
A multi dimensional data container.
Definition: array.h:35
af
Definition: algorithm.h:15
af::max
AFAPI array max(const array &in, const int dim=-1)
C++ Interface for maximum values in an array.
af::array::eval
void eval() const
Evaluate any JIT expressions to generate data for the array.
af::sqrt
AFAPI array sqrt(const array &in)
C++ Interface for square root of input.
af::exception
An ArrayFire exception class.
Definition: exception.h:29
af::iota
AFAPI array iota(const dim4 &dims, const dim4 &tile_dims=dim4(1), const dtype ty=f32)
af::array::dims
dim4 dims() const
Get dimensions of the array.
arrayfire.h
af::eval
array & eval(array &a)
Evaluate an expression (nonblocking).
Definition: array.h:1354
af::exception::what
virtual const char * what() const
Returns an error message for the exception in a string format.
Definition: exception.h:60
af::Window
Window object to render af::arrays.
Definition: graphics.h:37
f32
@ f32
32-bit floating point values
Definition: defines.h:211