Search code examples
cmandelbrot

Mandelbrot code not exciting when resolution is higher than 320 pixels?


I am learning C and trying new things to test what I can do. I have written code which produces a Mandelbrot set with a given resolution (RES) which is #define RES in the .h file. This works and produces good output for resolutions less than 321. For some reason when RES > 321 then the code no longer executes.

I am running using GCC and plotting the output using Gnuplot. I have tried debugging with a debugger however for RES > 321 the main function no longer gets run? I have added a print in the first line of main() to see and this doesn't get run. An executable is made and the program compiles with no errors?

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

#define MAX_DEPTH 100
#define RES       321

typedef struct complex_t {
    double re;
    double im;
} complex;

void init_complex_grid(complex complex_grid[RES][RES], double left, double right, double top, double bottom);
int converge(complex a);
complex add_complex(complex a, complex b);
complex square_complex(complex a);
double mag_complex(complex a);
void output_grid(unsigned int grid[RES][RES]);

int main(void) {
    // printf("HERE\n");
    int i, j;
    unsigned int convergence_grid[RES][RES];
    complex complex_grid[RES][RES];
    init_complex_grid(complex_grid, -2.5, 1, 1, -1);
    for (i = 0; i < RES; i++) {
        for (j = 0; j < RES; j++) {
            convergence_grid[i][j] = converge(complex_grid[i][j]);
        }
    }
    output_grid(convergence_grid);
    return 0;
}

void init_complex_grid(complex complex_grid[RES][RES], 
                       double left, double right, 
                       double top, double bottom) {
    int i, j;
    double restep = (top - bottom) / RES;
    double imstep = (right - left) / RES;
    for (i = 0; i < RES; i++) {
        for (j = 0; j < RES; j++) {
            complex_grid[i][j].re = left + j * imstep;
            complex_grid[i][j].im = bottom + i * restep;
        }
    }
}

int converge(complex a) {
    complex z = { 0, 0 };
    int cnt = 0;
    while (cnt <= MAX_DEPTH && mag_complex(z) <= 2) {
        z = add_complex(square_complex(z), a);
        cnt++;
    }   
    return cnt;
}

complex add_complex(complex a, complex b) {
    complex added = { a.re + b.re, a.im + b.im };
    return added;
}

complex square_complex(complex a) {
    complex b;
    b.re = a.re * a.re - a.im * a.im;
    b.im = 2 * a.re * b.im;
    return b;
}

double mag_complex(complex a) {
    return sqrt(a.re * a.re + a.im * a.im);
}

void output_grid(unsigned int grid[RES][RES]) {
    FILE *f = fopen("mandelbrot.dat", "w");
    int i, j;
    for (i = 0; i < RES; i++) {
        for (j = 0; j < RES; j++) {
            fprintf(f, "%d ", grid[i][j]);
        }
        fprintf(f, "\n");
    }
    fclose(f);
    printf("\nFILE CLOSED\n");
}

I also added the line printf("\nFILE CLOSED\n"); so I would know that the output had been written to the file but this does not get run either with RES > 321.


Solution

  • You are defining too much data with automatic storage in the main() function: either make the large arrays global, static or allocate them from the heap.

    Here is a simple fix you can try:

    int main(void) {
        int i, j;
        static unsigned int convergence_grid[RES][RES];
        static complex complex_grid[RES][RES];
        init_complex_grid(complex_grid, -2.5, 1, 1, -1);
        for (i = 0; i < RES; i++) {
            for (j = 0; j < RES; j++) {
                convergence_grid[i][j] = converge(complex_grid[i][j]);
            }
        }
        output_grid(convergence_grid);
        return 0;
    }
    

    Here is an alternative using heap allocation:

    int main(void) {
        int i, j;
        unsigned int (*convergence_grid)[RES] = calloc(sizeof(*convergence_grid), RES);
        complex (*complex_grid)[RES] = calloc(sizeof(*complex_grid), RES);
        if (!convergence_grid || !complex_grid) {
            fprintf(stderr, "cannot allocate arrays\n");
            return 1;
        }
        init_complex_grid(complex_grid, -2.5, 1, 1, -1);
        for (i = 0; i < RES; i++) {
            for (j = 0; j < RES; j++) {
                convergence_grid[i][j] = converge(complex_grid[i][j]);
            }
        }
        output_grid(convergence_grid);
        free(complex_grid);
        free(convergence_grid);
        return 0;
    }