-1

Recently I modified my mandelbrot fractal generation program to be able to integrate gmp and mpfr in order to zoom deeper into the fractal.

But since I did this I have a segmentation error when I try to run the program

I’m pretty new to c language (but not in development) so excuse me if it’s a basic error

Here my code:

#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION

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

#include "stb_image.h"
#include "stb_image_write.h"

#define CHANNELS 3

typedef struct{
    mpfr_t x, y;
} Point;

typedef struct{
    int r, g, b;
} Color;

int width = 1000;
int height = 1000;
int maxIteration = 255;
int nbColors = 100;

char fileName[100] = "mandelbrot.bmp";

Color colors[100] = {
    {0, 0, 0},
    {255, 255, 255}
};

Color hexToRGB(const char *hex) {
    Color rgb;

    if (strlen(hex) == 6) {
        sscanf(hex, "%2x%2x%2x", &rgb.r, &rgb.g, &rgb.b);
    } else {
        rgb.r = 0;
        rgb.g = 0;
        rgb.b = 0;
    }

    return rgb;
}

Color interpolate(Color colors[], int numColors, long double t) {
    if (numColors <= 1) {
        return colors[0];
    }

    long double segmentLength = 1.0 / (numColors - 1);
    int segment = t / segmentLength;
    long double segmentT = (t - segment * segmentLength) / segmentLength;

    Color c1 = colors[segment];
    Color c2 = colors[segment + 1];

    Color result;
    result.r = (unsigned char)(c1.r * (1 - segmentT) + c2.r * segmentT);
    result.g = (unsigned char)(c1.g * (1 - segmentT) + c2.g * segmentT);
    result.b = (unsigned char)(c1.b * (1 - segmentT) + c2.b * segmentT);

    return result;
}

double floatingMod(double x, double y) {
    double quotient = x / y;
    double wholePart;
    modf(quotient, &wholePart); // Récupère la partie entière du quotient

    double result = x - wholePart * y;
    return result;
}

int mandelbrot(Point point, int maxIteration) {
    Point z, c;
    mpfr_t temp, threshold, temp1, temp2;

    mpfr_inits(z.x, z.y, c.x, c.y, temp, threshold, temp1, temp2);

    //if((point.x < sqrt((point.x - 0.25)*(point.x - 0.25) + point.y*point.y) - 2*((point.x - 0.25)*(point.x - 0.25) + point.y*point.y) + 0.25) || ((point.x + 1) * (point.x + 1) + point.y*point.y < 0.0625)) return 0;

    mpfr_set(z.x, point.x, MPFR_RNDN);
    mpfr_set(z.y, point.y, MPFR_RNDN);
    mpfr_set(c.x, point.x, MPFR_RNDN);
    mpfr_set(c.y, point.y, MPFR_RNDN);

    mpfr_set_str(threshold, "2.0", 10, MPFR_RNDN);

    for(int iteration = 0; iteration < maxIteration; iteration++) {
        mpfr_mul(temp1, z.x, z.x, MPFR_RNDN);
        mpfr_mul(temp2, z.y, z.y, MPFR_RNDN);
        mpfr_sub(temp, temp1, temp2, MPFR_RNDN);
        mpfr_add(temp, temp, c.x, MPFR_RNDN);
        
        mpfr_mul(z.y, z.x, z.y, MPFR_RNDN);
        mpfr_mul_d(z.y, z.y, 2.0, MPFR_RNDN);
        mpfr_add(z.y, z.y, c.y, MPFR_RNDN);

        mpfr_set(z.x, temp, MPFR_RNDN);

        mpfr_add(temp1, temp1, temp2, MPFR_RNDN);
        
        if(mpfr_cmp(temp1, threshold) > 0) {
            mpfr_clears(z.x, z.y, c.x, c.y, temp, threshold, temp1, temp2, NULL);
            return iteration;
        }
    }

    return 0;
}

int main(int argc, char *argv[]) {
    long double zoomFactor;

    mpfr_set_default_prec(256);

    mpfr_t Xmin, Xmax, Ymin, Ymax;

    mpfr_inits(Xmin, Xmax, Ymin, Ymax);

    mpfr_set_str(Xmin, "-2.1", 10, MPFR_RNDN);
    mpfr_set_str(Xmax, "0.6", 10, MPFR_RNDN);
    mpfr_set_str(Ymin, "-1.2", 10, MPFR_RNDN);
    mpfr_set_str(Ymax, "1.2", 10, MPFR_RNDN);

    Point zoomCenter;

    mpfr_inits(zoomCenter.x, zoomCenter.y);

    mpfr_set_str(zoomCenter.x, "-0.75", 10, MPFR_RNDN);
    mpfr_set_str(zoomCenter.y, "0.0", 10, MPFR_RNDN);

    for(int arg = 1; arg < argc; arg+=2 ) {
        if(strcmp(argv[arg], "--width") == 0) {
            width = strtod(argv[arg + 1], NULL);

        } else if(strcmp(argv[arg], "--height") == 0) {
            height = strtod(argv[arg + 1], NULL);

        } else if(strcmp(argv[arg], "--maxIteration") == 0) {
            maxIteration = strtod(argv[arg + 1], NULL);

        } else if(strcmp(argv[arg], "--zoomFactor") == 0) {
            zoomFactor = strtold(argv[arg + 1], NULL);

        } else if(strcmp(argv[arg], "--nbColors") == 0) {
            nbColors = strtold(argv[arg + 1], NULL);

        } else if(strcmp(argv[arg], "--fileName") == 0) {
            sprintf(fileName, "%s", argv[arg + 1]);

        } else if(strcmp(argv[arg], "--zoomCenter") == 0) {
            mpfr_set_str(zoomCenter.x, strtok(argv[arg + 1], ","), 10, MPFR_RNDN);
            mpfr_set_str(zoomCenter.y, strtok(NULL, ","), 10, MPFR_RNDN);

        } else if(strcmp(argv[arg], "--palette") == 0) {
            char *hexColorTokens[strlen(argv[arg + 1]) / 7 + 1];
            char *token = strtok((char *)argv[arg + 1], ",");
            int numColors = 0;

            while (token != NULL) {
                hexColorTokens[numColors++] = token;
                token = strtok(NULL, ",");
            }
            
            for (int i = 0; i < numColors; i++) {
                colors[i] = hexToRGB(hexColorTokens[i]);
            }
        }
    }

    unsigned char *imageData = (unsigned char *)malloc(width * height * CHANNELS);

    long double colorNumber;

    mpfr_t aspectRatio, valueX, valueY, temp1, temp2;

    mpfr_inits(aspectRatio, valueX, valueY, temp1, temp2);

    Point point;

    mpfr_inits(point.x, point.y);

    Color iterationColor;

    int numColors = sizeof(colors) / sizeof(Color);
    int iteration;

    //aspect ratio
    mpfr_set_d(aspectRatio, width, MPFR_RNDN);
    mpfr_div_d(aspectRatio, aspectRatio, height, MPFR_RNDN);

    if(width > height) {
        mpfr_mul(Xmin, Xmin, aspectRatio, MPFR_RNDN);
        mpfr_mul(Xmax, Xmax, aspectRatio, MPFR_RNDN);
    } else if(width < height) {
        mpfr_mul(Ymin, Ymin, aspectRatio, MPFR_RNDN);
        mpfr_mul(Ymax, Ymax, aspectRatio, MPFR_RNDN);
    }

    /*zoom*/
    zoomFactor *= 2;
    //valueX
    mpfr_sub(temp1, Xmax, Xmin, MPFR_RNDN);
    mpfr_div_d(valueX, temp1, zoomFactor, MPFR_RNDN);

    //valueY
    mpfr_sub(temp1, Ymax, Ymin, MPFR_RNDN);
    mpfr_div_d(valueY, temp1, zoomFactor, MPFR_RNDN);

    mpfr_sub(Xmin, zoomCenter.x, valueX, MPFR_RNDN);
    mpfr_add(Xmax, zoomCenter.x, valueX, MPFR_RNDN);

    mpfr_sub(Ymin, zoomCenter.y, valueY, MPFR_RNDN);
    mpfr_add(Ymin, zoomCenter.y, valueY, MPFR_RNDN);

    for(int px = 0; px < width*height; px++) {
        mpfr_sub(point.x, Xmax, Xmin, MPFR_RNDN);
        mpfr_div_d(point.x, point.x, (width-1), MPFR_RNDN);
        mpfr_mul_d(point.x, point.x, (px % width), MPFR_RNDN);
        mpfr_add(point.x, point.x, Xmin, MPFR_RNDN);

        mpfr_sub(point.y, Ymax, Ymin, MPFR_RNDN);
        mpfr_div_d(point.y, point.y, (height-1), MPFR_RNDN);
        mpfr_mul_d(point.y, point.y, floor(px / width), MPFR_RNDN);
        mpfr_add(point.y, point.y, Ymin, MPFR_RNDN);
        
        iteration = mandelbrot(point, maxIteration);

        colorNumber = (long double)iteration/(long double)nbColors;

        iterationColor = interpolate(colors, numColors, floatingMod((double)iteration/(double)nbColors, 1.0));
        
        imageData[px*CHANNELS + 0] = iterationColor.r;
        imageData[px*CHANNELS + 1] = iterationColor.g;
        imageData[px*CHANNELS + 2] = iterationColor.b;
    }

    mpfr_clears(aspectRatio, valueX, valueY, temp1, temp2, point.x, point.y, NULL);

    stbi_write_bmp(fileName, width, height, CHANNELS, imageData);

    free(imageData);

    return 0;
}

I did not try much because I do not understand the error well, nevertheless I tried to free the memory with `mpfr_clears’, but it did not change anything

ena0
  • 1
  • 1
  • 3
    Where exactly does the seg fault occur? Run it through a debugger and see which line it crashes at. Seg fault just means array out of bounds access, incorrect use of pointers or similar bugs which would lead to the program accessing the wrong memory which it shouldn't be accessing. – Lundin Aug 25 '23 at 11:27
  • 3
    Welcome to Stack Overflow! Please [edit] your code to reduce it to a [mcve] of your problem. Your current code includes much that is peripheral to your problem - a minimal sample normally looks similar to a good unit test: only performing one task, with input values specified for reproducibility. – Toby Speight Aug 25 '23 at 11:47
  • In `interpolate`, `segment` must be in the range `0` through `numColors-1`. Is it? Maybe add a check for it. – Tom Karzes Aug 25 '23 at 12:10
  • Also, in `main` you calculate `colorNumber`, but never use it. Was that intentional? – Tom Karzes Aug 25 '23 at 12:12
  • All your `mpfr_inits()` calls are missing the sentinel parameter `(mpfr_ptr)0` on the end. Other problems include `zoomFactor` is not initialized, `colorNumber` is never used, `#include ` and `#include ` are missing. – Ian Abbott Aug 25 '23 at 13:33

0 Answers0