
#include <SDL.h>
#include <math.h>

void generate_primes(unsigned int primes[], int n);
void diff(unsigned int out[], unsigned int in[], int n);
void diff_pyramid(unsigned int *diff_map, unsigned int primes[], int n);

int main()
{
	SDL_Surface *surface;
	SDL_Event test_event;
	
	if (SDL_Init(SDL_INIT_VIDEO)) {
		fprintf(stderr, "SDL Init failure.\n");
		exit(1);
	}
	
	atexit(SDL_Quit);
	
	surface = SDL_SetVideoMode(640,640,32,SDL_HWSURFACE);

        unsigned int primes[surface->w];
	unsigned int diff_map[(surface->w+1)*surface->w];
	int x, y, i, d;

	for (i = 0; i < (surface->w+1)*surface->w; i++)
	  diff_map[i] = 0;

        generate_primes(primes, surface->w);
	diff_pyramid(diff_map, primes, surface->w);
        
	SDL_LockSurface(surface);
		
	for (y = 0; y < surface->w+1 && y < surface->h; y++) { 
		for (x = 0; x < surface->w; x++) {
		    if (x < (surface->w - y)) {
		       d = diff_map[y*surface->w + x];
		    } else {
		       d = diff_map[(surface->w - x+1)*surface->w+(surface->w - y)];
		    }
	 	    *(unsigned int *) (((unsigned char *) surface->pixels) + y * surface->pitch + x * surface->format->BytesPerPixel) =
		       ((127/(d+1))<<16) +
		       ((64/(d+1))<<8) +
		       (255/(d+1));
		}
	}
		
	SDL_UnlockSurface(surface);
	SDL_UpdateRect(surface, 0, 0, 0, 0);

	do {
	  if (!SDL_WaitEvent(&test_event))
	     break;
	} while (test_event.type != SDL_QUIT && test_event.key.keysym.sym != SDLK_ESCAPE);

	SDL_FreeSurface(surface);
	
	return 0;
}

void generate_primes(unsigned int primes[], int n)
{
   int l = 3, c = 1, i, prime;

   if (n > 0) {
     primes[0] = 2;
     if (n > 1) {
       for (c = 1; c < n; l += 2)
       {
         prime = 1;
         for (i = 0; i < c; i++)
         {
           if (l%primes[i] == 0) {
	      prime = 0;
              break;
	   }
         }
	 if (prime) {
	   primes[c] = l;
	   c++;
	 }
       }
     }
   }
}


void diff(unsigned int *out, unsigned int *in, int n)
{
  int i;

  if (n > 1)
  {
    for (i = 0; i < n-1; i++) {
      out[i] = abs(in[i+1]-in[i]);
    }
  }
}


void diff_pyramid(unsigned int *diff_map, unsigned int primes[], int n)
{
   int i, j, c, d;
   if (n > 0) {
      for (i = 0; i < n; i++)
        *(diff_map+i) = primes[i];
      for (c = n, i = 0; c > 0; c--, i += n)
        diff(diff_map+i+n, diff_map+i, c);
      /*for (c = n, i = n; c > 1; c--, i += n)
      {
        for (j = 0; j < c - 1; j++)
	{
          d = abs(*(diff_map+i-n+j+1) - *(diff_map+i-n+j));
	  *(diff_map+i+j) = d;
	  //*(diff_map+(n-(i/n)+1)+(n-j+1)*n) = d;
	}
      } */
   }
}

