/* Trash code to pre-calculate circles for nuke */
/* use gcc -std=c99 */

#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <time.h>

#ifndef M_PI
# define M_PI		3.14159265358979323846	/* pi */
#endif
#ifndef M_PI_2
# define M_PI_2		1.57079632679489661923	/* pi/2 */
#endif

int min(int a, int b) { return (a < b) ? a : b; }
int max(int a, int b) { return (a > b) ? a : b; }

#define MIN_RADIUS	3
#define MAX_RADIUS	300	/* actually, one less than this! */
#define CENTRE_Y	MAX_RADIUS

#define DIVISIONS	10000.0	/* divisions of pi */

struct {
    int half_width[MAX_RADIUS*2]; /* half-width of each span */
} circles[MAX_RADIUS];

int main(int argc, char *argv[])
{
    (void)argc;

    /* Initialise */

    for (int i = 0; i < MAX_RADIUS; i++)
	for (int j = 0; j < MAX_RADIUS*2; j++)
	    circles[i].half_width[j] = -1;

    /* Calculate spans */

    for (int r = MIN_RADIUS; r < MAX_RADIUS; r++) {
	for (double theta = -M_PI_2; theta <= M_PI_2; theta += 2.*M_PI_2/DIVISIONS) {
	    int x = (int)round((double)r*cos(theta));
	    int y = CENTRE_Y + (int)round((double)r*sin(theta));
	    circles[r].half_width[y] = max(x, circles[r].half_width[y]);
	}
    }

    /* Print out */

    time_t now;
    time(&now);
    printf("/* auto-generated by %s on %s */\n", argv[0], ctime(&now));

    printf("#define MIN_CIRCLE_RADIUS %d\n", MIN_RADIUS);
    printf("#define MAX_CIRCLE_RADIUS %d\n", MAX_RADIUS-1);

    for (int i = MIN_RADIUS; i < MAX_RADIUS; i++) {
	int y1, y2;

	for (y1 = 0; y1 < MAX_RADIUS*2; y1++)
	    if (circles[i].half_width[y1] >= 0)
		break;
	for (y2 = y1; y2 < MAX_RADIUS*2; y2++)
	    if (circles[i].half_width[y2] < 0)
		break;
	y2--;

	assert(y1 <= y2);
	assert(y1 < MAX_RADIUS*2);
	assert(y2 < MAX_RADIUS*2);

	printf("static int _s%d[] = {", i);
	for (int j = y1; j <= y2; j++) {
	    printf("%d%c", circles[i].half_width[j], (j < y2) ? ',' : ' ');
	}
	printf("};\n");

	printf("static struct span_list _c%d = { %d, _s%d };\n", i, y2-y1+1, i);
    }

    printf("static struct span_list* circles[] = { ");
    for (int i = 0; i < MAX_RADIUS; i++) {
	if (i < MIN_RADIUS)
	    printf("0,");
	else
	    printf("&_c%d%c", i, i < MAX_RADIUS-1 ? ',' : ' ');
    }
    printf("};\n");

    return 0;
}
