The Computer Language
Benchmarks Game

mandelbrot C gcc #5 program

source code

/* The Computer Language Benchmarks Game
 http://benchmarksgame.alioth.debian.org/
 contributed by Ralph Ganszky
 modified for Swift 3.0 by Daniel Muellenborn
 modified for C & gcc by Dominic Letz rev2 macro power

 Compile with: gcc -O3 -mno-fma -march=native -fopenmp main.c
 */

#include <stdio.h>
#include <stdlib.h>

int Iter = 50;

#ifdef __AVX__
#define VEC_SIZE 4
#define _LOOP(F, S) F S F
#else
#define VEC_SIZE 2
#define _LOOP(F, S) F S F S F S F
#endif

#define LOOP_SIZE (8/VEC_SIZE)
#define LOOP(F) {X=0; _LOOP(F, ;X++;)}
#define AND(F)  (X=0, _LOOP(F, &&))
#define BOR(F)  (X=0, _LOOP(F, |))
typedef double Vec __attribute__ ((vector_size(VEC_SIZE*8)));
typedef unsigned char Byte;

int bt(Vec lhs, double rhs) {
  for (int i = 0; i < VEC_SIZE; i++)
    if (lhs[i] <= rhs)
      return 0;
  return 1;
}

// Calculate mandelbrot set for four Vec into one byte
Byte mand(Vec* cr, Vec ci) {
      int X = 0;
      Vec Zr[LOOP_SIZE] = {{0.0}};
      Vec Zi[LOOP_SIZE] = {{0.0}};
      Vec Tr[LOOP_SIZE] = {{0.0}};
      Vec Ti[LOOP_SIZE] = {{0.0}};

      for (int i = 0; i < Iter/5; i++) {
        for (int j = 0; j < 5; j++) {
LOOP(   Zi[X] = (Zr[X] + Zr[X]) * Zi[X] + ci;                                   )
LOOP(   Zr[X] = Tr[X] - Ti[X] + cr[X];                                          )
LOOP(   Tr[X] = Zr[X] * Zr[X];
          Ti[X] = Zi[X] * Zi[X];                                                )
        }
        if (AND(bt(Tr[X] + Ti[X++], 4.0))) {
           return 0;
        }
      }

      Byte byte[LOOP_SIZE] = {0};
      Vec t[LOOP_SIZE];
LOOP( t[X] = Tr[X] + Ti[X];                                                     )
      for (int i = 0; i < VEC_SIZE; i++) {
LOOP(   byte[X] |= t[X][i] <= 4.0 ? (0x80 >> (i + X * VEC_SIZE)) : 0;           )
      }
      return BOR(byte[X++]);
}

// Parse command line arguments
int main(int argc, char* argv[])
{
  int n = (argc > 1) ? atoi(argv[1]) : 200;
  int N = (n + VEC_SIZE - 1) & ~(VEC_SIZE - 1);
  double inv = 2.0 / ((double)n);
  Vec xvals[N/VEC_SIZE];
  Vec yvals[N];
  Byte *rows = malloc(n*N/8);

  for (int i = 0; i < N; i++) {
    xvals[i/VEC_SIZE][i%VEC_SIZE] = ((double)i) * inv - 1.5;
    for (int j = 0; j < VEC_SIZE; j++) {
      yvals[i][j] = ((double)i) * inv - 1.0;
    }
  }

#pragma omp parallel for schedule(guided)
  for (int y = 0; y < n; y++) {
    for (int x = 0; x < N/VEC_SIZE; x+=8/VEC_SIZE) {
      rows[y*N/8+x/(8/VEC_SIZE)] =
        mand(xvals + x, yvals[y]);
    }
  }

  FILE* out = (argc == 3) ? fopen(argv[2], "wb") : stdout;
  fprintf(out, "P4\n%u %u\n", n, n);
  fwrite(&rows[0], n*N/8, 1, out);

  if (out != stdout)
  {
      fclose(out);
  }
  free(rows);
  return 0;
}
    

notes, command-line, and program output

NOTES:
64-bit Ubuntu quad core
gcc (Ubuntu 6.3.0-12ubuntu2) 6.3.0 20170406


Fri, 14 Apr 2017 01:56:22 GMT

MAKE:
/usr/bin/gcc -pipe -Wall -O3 -fomit-frame-pointer -march=native -mno-fma -fno-finite-math-only -mfpmath=sse -msse2 -fopenmp mandelbrot.gcc-5.c -o mandelbrot.gcc-5.gcc_run 
mandelbrot.gcc-5.c: In function ‘mand’:
mandelbrot.gcc-5.c:52:32: warning: operation on ‘X’ may be undefined [-Wsequence-point]
         if (AND(bt(Tr[X] + Ti[X++], 4.0))) {
                               ~^
mandelbrot.gcc-5.c:20:21: note: in definition of macro ‘_LOOP’
 #define _LOOP(F, S) F S F S F S F
                     ^
mandelbrot.gcc-5.c:52:13: note: in expansion of macro ‘AND’
         if (AND(bt(Tr[X] + Ti[X++], 4.0))) {
             ^~~
mandelbrot.gcc-5.c:63:24: warning: operation on ‘X’ may be undefined [-Wsequence-point]
       return BOR(byte[X++]);
                       ~^
mandelbrot.gcc-5.c:20:29: note: in definition of macro ‘_LOOP’
 #define _LOOP(F, S) F S F S F S F
                             ^
mandelbrot.gcc-5.c:63:14: note: in expansion of macro ‘BOR’
       return BOR(byte[X++]);
              ^~~
mandelbrot.gcc-5.c:63:24: warning: operation on ‘X’ may be undefined [-Wsequence-point]
       return BOR(byte[X++]);
                       ~^
mandelbrot.gcc-5.c:20:29: note: in definition of macro ‘_LOOP’
 #define _LOOP(F, S) F S F S F S F
                             ^
mandelbrot.gcc-5.c:63:14: note: in expansion of macro ‘BOR’
       return BOR(byte[X++]);
              ^~~
mandelbrot.gcc-5.c:63:24: warning: operation on ‘X’ may be undefined [-Wsequence-point]
       return BOR(byte[X++]);
                       ~^
mandelbrot.gcc-5.c:20:29: note: in definition of macro ‘_LOOP’
 #define _LOOP(F, S) F S F S F S F
                             ^
mandelbrot.gcc-5.c:63:14: note: in expansion of macro ‘BOR’
       return BOR(byte[X++]);
              ^~~
rm mandelbrot.gcc-5.c
0.17s to complete and log all make actions

COMMAND LINE:
./mandelbrot.gcc-5.gcc_run 16000

(BINARY) PROGRAM OUTPUT NOT SHOWN