diff --git a/.gitignore b/.gitignore index 175eb5c..891672d 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ undefined-behaviour multibrot-openmp multibrot-openmp.png hello-openmp +mandelbrot-openmp diff --git a/Makefile b/Makefile index 6386617..29c93e3 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ CFLAGS=-std=c99 -Wextra -pedantic -g -O0 CC_OPENMP=gcc # no OpenMP in our clang CFLAGS_OPENMP=$(CFLAGS) -fopenmp -TARGETS=approximate-pi linked-list mandelbrot threads circular-buffer structs ncurses-pong bit-fuckery bit-fuckery2 checkcheck multibrot bloom wo-lernen lua-foo binsearch test-inline-assembly uiowa-threads-example mtrace-test av-variance undefined-behaviour multibrot-openmp hello-openmp +TARGETS=approximate-pi linked-list mandelbrot threads circular-buffer structs ncurses-pong bit-fuckery bit-fuckery2 checkcheck multibrot bloom wo-lernen lua-foo binsearch test-inline-assembly uiowa-threads-example mtrace-test av-variance undefined-behaviour multibrot-openmp hello-openmp mandelbrot-openmp EXTRAS=mandelbrot.bmp multibrot.png test-inline-assembly.s tags mtrace-test.trace mtrace-test.txt .PHONY: all @@ -72,3 +72,6 @@ hello-openmp: hello-openmp.c multibrot-openmp: multibrot-openmp.c $(CC_OPENMP) $(CFLAGS_OPENMP) -o $@ $< -lm -lpng + +mandelbrot-openmp: mandelbrot-openmp.c + $(CC_OPENMP) $(CFLAGS_OPENMP) $(shell sdl-config --cflags) -o $@ $< $(shell sdl-config --libs) -lm diff --git a/mandelbrot-openmp.c b/mandelbrot-openmp.c new file mode 100644 index 0000000..4dfbae6 --- /dev/null +++ b/mandelbrot-openmp.c @@ -0,0 +1,93 @@ +#include "SDL.h" +#include +#include + +/* The maximum iteration count. */ +const int max_it = 170; + +/* Compute the out-coloring based on the iteration counter. */ +Uint32 outcolor(int it) { + return 0x00010001 * ((it * 0xff) / max_it); +} + +/* "Compute" the in-coloring. */ +Uint32 incolor() { + return 0x00000000; /* black */ +} + +void drawmandelbrot(SDL_Surface * surface) { + if (SDL_MUSTLOCK(surface)) { + SDL_LockSurface(surface); + } + Uint32 *pixels = (Uint32 *) surface->pixels; + + #pragma omp parallel for + for (int i = 0; i < surface->w * surface->h; i++) { + int y = i / surface->w; + int x = i % surface->w; + + float complex c = ((3.0f * x / surface->w) - 2.0f) + + I * ((2.0f * y / surface->h) - 1.0f); + + bool diverges = false; + float complex z = 0; + int it; + for (it = 1; it <= max_it; it++) { + /* z = z² + c */ + z = cpowf(z, 2) + c; + + /* If |z| ever gets greater than 2, it diverges. */ + if (cabsf(z) > 2) { + diverges = true; + break; + } + } + + Uint32 color; + if (diverges) { + color = outcolor(it); + } else { + color = incolor(); + } + + pixels[i] = color; + + /* Update the screen every 10 lines. */ + #pragma omp critical + { + if (y % 10 == 0 && x == 0) { + SDL_Flip(surface); + } + } + } + + /* Update the screen a final time. */ + SDL_Flip(surface); + if (SDL_MUSTLOCK(surface)) { + SDL_UnlockSurface(surface); + } +} + +int main(void) { + /* Set up SDL. */ + if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { + fprintf(stderr, "Error: Could not initialize SDL: %s.\n", + SDL_GetError()); + exit(1); + } + SDL_Surface *screen = SDL_SetVideoMode(1024, 768, 32, SDL_SWSURFACE); + + /* Do the mandelbrot. */ + drawmandelbrot(screen); + + /* Save BMP */ + char *file = "mandelbrot.bmp"; + if (SDL_SaveBMP(screen, file) != 0) { + fprintf(stderr, "Could not write %s!\n", file); + } + + /* Quit. */ + /* FIXME: wait for key press here */ + SDL_Delay(0*20000); + SDL_Quit(); +}