From 9ba9c47a952ce6966b333af579bd39c636080fbc Mon Sep 17 00:00:00 2001 From: JP Appel Date: Tue, 23 Apr 2024 15:58:54 -0400 Subject: added preprocessor to change precision at compile time --- src/fractals.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/fractals.h') diff --git a/src/fractals.h b/src/fractals.h index d27eb00..69e5215 100644 --- a/src/fractals.h +++ b/src/fractals.h @@ -4,12 +4,13 @@ #include #include #include "grids.h" +#include "precision.h" -size_t mandelbrot(const long double complex z0, const size_t max_iterations); +size_t mandelbrot(const CBASE complex z0, const size_t max_iterations); void mandelbrot_grid(grid_t* grid, const size_t max_iterations); -size_t multibrot(const long double complex z0, const size_t max_iterations, const double d); +size_t multibrot(const CBASE complex z0, const size_t max_iterations, const double d); void multibrot_grid(grid_t* grid, const size_t max_iterations, const double d); -size_t julia(const long double complex z0, const long double complex c, const size_t max_iterations, const double R); -void julia_grid(grid_t* grid, const size_t max_iterations, const long double complex c, const double R); +size_t julia(const CBASE complex z0, const CBASE complex c, const size_t max_iterations, const double R); +void julia_grid(grid_t* grid, const size_t max_iterations, const CBASE complex c, const double R); -- cgit v1.2.3 From 9e5fa12291500d52ccc554519e9692c5f003c63f Mon Sep 17 00:00:00 2001 From: JP Appel Date: Wed, 24 Apr 2024 00:10:48 -0400 Subject: improved cli, implemented tricorn and multicorn --- src/fractals.c | 103 ++++++++++++++++++++++++++++++++++++++++++-------- src/fractals.h | 18 ++++++++- src/grids.c | 12 +++--- src/serial-fractals.c | 59 +++++++++++++++++++++++++++-- src/shared-fractals.c | 55 ++++++++++++++++++++++++++- 5 files changed, 221 insertions(+), 26 deletions(-) (limited to 'src/fractals.h') diff --git a/src/fractals.c b/src/fractals.c index b43ad0e..82e4ef6 100644 --- a/src/fractals.c +++ b/src/fractals.c @@ -2,17 +2,36 @@ #include #include #include +#include #include "grids.h" #include "precision.h" #include "fractals.h" + +void print_usage(FILE* file, char* program_name){ + fprintf(file, "Usage: %s [-v] [-i iterations] [-x x_res] [-y y_res] [-z magnification] [-l lower_left] [-u upper_right]\n", program_name); +} + +void print_help(){ + //TODO: add help +} + +void print_info(){ + #ifdef EXTENDED_PRECISION + printf("Compiled with long double float precision\n"); + #endif + #ifndef EXTENDED_PRECISION + printf("Compiled with double float precision\n"); + #endif +} + int main(const int argc, char *argv[]) { struct winsize w; ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); //default values - size_t iterations = 1000; + size_t iterations = 100; size_t x_res = w.ws_col; size_t y_res = w.ws_row; CBASE re_lower_left = -2; @@ -21,10 +40,32 @@ int main(const int argc, char *argv[]) { CBASE im_upper_right = 2; CBASE magnification = 1; bool verbose = false; + bool print = false; + //TODO: allocate adequate size buffer + bool output_to_file = false; + char* output_filename = "fractal.grid"; + + // TODO: have output format option + // TODO: have output file + + + static struct option long_options[] = { + {"iterations", required_argument, NULL, 'i'}, + {"x-res", required_argument, NULL, 'x'}, + {"y-res", required_argument, NULL, 'y'}, + {"lower-left", required_argument, NULL, 'l'}, + {"upper-right", required_argument, NULL, 'u'}, + {"magnification", required_argument, NULL, 'z'}, + {"output", required_argument, NULL, 'o'}, + {"print", no_argument, NULL, 'p'}, + {"verbose", no_argument, NULL, 'v'}, + {"help", no_argument, NULL, 'h'}, + {0, 0, 0, 0} // Termination element + }; //parse command line arguments int opt; - while((opt = getopt(argc, argv, "vhi:x:y:l:u:z:")) != -1){ + while((opt = getopt_long(argc, argv, "i:x:y:l:u:z:o:pvh", long_options, NULL)) != -1){ switch(opt){ case 'i': iterations = strtoull(optarg, NULL, 10); @@ -41,6 +82,13 @@ int main(const int argc, char *argv[]) { case 'u': sscanf(optarg, CFORMAT"+"CFORMAT"i", &re_upper_right, &im_upper_right); break; + case 'o': + //TODO: check if within length + //TODO: + break; + case 'p': + print = true; + break; case 'z': sscanf(optarg, CFORMAT, &magnification); if(magnification <= 0){ @@ -52,10 +100,10 @@ int main(const int argc, char *argv[]) { verbose = true; break; case 'h': - fprintf(stderr, "Usage: %s [-v] [-i iterations] [-x x_res] [-y y_res] [-z magnification] [-l lower_left] [-u upper_right]\n", argv[0]); + print_usage(stdout, argv[0]); return 0; default: - fprintf(stderr, "Usage: %s [-v] [-i iterations] [-x x_res] [-y y_res] [-z magnification] [-l lower_left] [-u upper_right]\n", argv[0]); + print_usage(stderr, argv[0]); return 1; } } @@ -72,21 +120,44 @@ int main(const int argc, char *argv[]) { zoom_grid(grid, magnification); } + // params for different fractals + const double degree = 3.0; + const CBASE complex constant = 0.285L + 0.01L*I; + // const CBASE complex constant = -0.835L -0.321L* I; + const double radius = 100; - //const long double complex c = 0.285L + 0.01L*I; - // const long double complex c = -0.835L -0.321L* I; - // const double R = 100; - // julia_grid(grid, iterations, c, R); - mandelbrot_grid(grid, iterations); - //multibrot_grid(grid, iterations, 3); + enum fractal f = MULTICORN; + switch(f){ + case MANDELBROT: + mandelbrot_grid(grid, iterations); + break; + case TRICORN: + tricorn_grid(grid, iterations); + break; + case MULTIBROT: + multibrot_grid(grid, iterations, degree); + break; + case MULTICORN: + multicorn_grid(grid, iterations, degree); + break; + case JULIA: + julia_grid(grid, iterations, constant, radius); + break; + default: + //TODO: update fractal type + fprintf(stderr, "Unrecognized fractal\n"); + return 1; + } if(verbose)print_grid_info(grid); - print_grid(grid, iterations); + if(print)print_grid(grid, iterations); - // //write grid to file - // FILE* write_file = fopen("test.grid", "wb"); - // write_grid(write_file , grid); - // fclose(write_file); + //write grid to file + if(output_to_file){ + FILE* write_file = fopen("test.grid", "wb"); + write_grid(write_file , grid); + fclose(write_file); + } // // //attempt to read grid from file // FILE* read_file = fopen("test2.grid", "rb"); @@ -94,4 +165,6 @@ int main(const int argc, char *argv[]) { // fclose(read_file); // // printf("Grids are %s equal\n", grid_equal(grid, grid2) ? "exactly" :"not exactly"); + + return 0; } diff --git a/src/fractals.h b/src/fractals.h index 69e5215..3f2757d 100644 --- a/src/fractals.h +++ b/src/fractals.h @@ -6,11 +6,27 @@ #include "grids.h" #include "precision.h" +enum fractal { + MANDELBROT, // IMPLEMENTED IN SERIAL SHARED + TRICORN, // IMPLEMENTED IN SERIAL SHARED + MULTIBROT, // IMPLEMENTED IN SERIAL SHARED + MULTICORN, // IMPLEMENTED in SERIAL SHARED + BURNING_SHIP, // NOT IMPLEMENTED IN ANY VERSION + //NEWTON, // MIGHT NEVER BE IMPLEMENTED, REQUIRES SPECIAL COLORING + JULIA // IMPLEMENTED IN SERIAL SHARED +}; + size_t mandelbrot(const CBASE complex z0, const size_t max_iterations); -void mandelbrot_grid(grid_t* grid, const size_t max_iterations); +void mandelbrot_grid(grid_t* grid, const size_t max_iterations); + +size_t tricorn(const CBASE complex z0, const size_t max_iterations); +void tricorn_grid(grid_t* grid, const size_t max_iterations); size_t multibrot(const CBASE complex z0, const size_t max_iterations, const double d); void multibrot_grid(grid_t* grid, const size_t max_iterations, const double d); +size_t multicorn(const CBASE complex z0, const size_t max_iterations, const double d); +void multicorn_grid(grid_t* grid, const size_t max_iterations, const double d); + size_t julia(const CBASE complex z0, const CBASE complex c, const size_t max_iterations, const double R); void julia_grid(grid_t* grid, const size_t max_iterations, const CBASE complex c, const double R); diff --git a/src/grids.c b/src/grids.c index 6941d66..09c5c49 100644 --- a/src/grids.c +++ b/src/grids.c @@ -104,10 +104,10 @@ bool grid_allclose(const grid_t* restrict grid1, const grid_t* restrict grid2, c CBASE complex grid_to_complex(const grid_t* grid, const size_t index) { const size_t x_res = grid->x; const size_t y_res = grid->y; - const CBASE x_min = creal(grid->lower_left); - const CBASE x_max = creal(grid->upper_right); - const CBASE y_min = cimag(grid->lower_left); - const CBASE y_max = cimag(grid->upper_right); + const CBASE x_min = CREAL(grid->lower_left); + const CBASE x_max = CREAL(grid->upper_right); + const CBASE y_min = CIMAG(grid->lower_left); + const CBASE y_max = CIMAG(grid->upper_right); const CBASE x_step = (x_max - x_min) / (double)x_res; const CBASE y_step = (y_max - y_min) / (double)y_res; @@ -190,8 +190,8 @@ void print_grid_info(const grid_t* grid){ printf("x\t%zu\n", grid->x); printf("y\t%zu\n", grid->y); printf("size\t%zu\n", grid->size); - printf("lower_left\t"CFORMAT"+ "CFORMAT"I\n", creal(grid->lower_left), cimag(grid->lower_left)); - printf("upper_right\t"CFORMAT"+ "CFORMAT"I\n", creal(grid->upper_right), cimag(grid->upper_right)); + printf("lower_left\t"CFORMAT"+ "CFORMAT"I\n", CREAL(grid->lower_left), CIMAG(grid->lower_left)); + printf("upper_right\t"CFORMAT"+ "CFORMAT"I\n", CREAL(grid->upper_right), CIMAG(grid->upper_right)); printf("Data is %s NULL\n", grid->data ? "not" : ""); } diff --git a/src/serial-fractals.c b/src/serial-fractals.c index 5831f92..2647d11 100644 --- a/src/serial-fractals.c +++ b/src/serial-fractals.c @@ -3,7 +3,7 @@ #include "grids.h" /* - * Computes the number of iterations it takes for a point z0 to diverge + * Computes the number of iterations it takes for a point z0 to become unbounded * if the return value is equal to max_iterations, the point lies within the mandelbrot set * This is an implementation the escape algorithm */ @@ -31,7 +31,34 @@ void mandelbrot_grid(grid_t* grid, const size_t max_iterations){ } /* - * Computes the number of iterations it takes for a point z0 to diverge + * Computes the number of iterations it takes for a point z0 to become unbounded + * if the return value is equal to max_iterations, the point lies within the tricorn set + * This is nearly identical to mandelbrot, except for the complex conjugate + */ +size_t tricorn(const CBASE complex z0, const size_t max_iterations){ + CBASE complex z = z0; + size_t iteration = 0; + while(CABS(z) <= 2 && iteration < max_iterations){ + z = CONJ(z * z) + z0; + iteration++; + } + return iteration; +} + +/* + * Fills a grid with tricorn values + */ +void tricorn_grid(grid_t* grid, const size_t max_iterations){ + const size_t size = grid->size; + size_t* data = grid->data; + + for(size_t i = 0; i < size; i++){ + data[i] = tricorn(grid_to_complex(grid, i), max_iterations); + } +} + +/* + * Computes the number of iterations it takes for a point z0 to become unbounded * if the return value is equal to max_iterations, the point lies within the multibrot set * This is implementation closely matches mandelbrot, but uses cpow which might degrade performance. */ @@ -39,7 +66,7 @@ size_t multibrot(const CBASE complex z0, const size_t max_iterations, const doub CBASE complex z = z0; size_t iteration = 0; while(CABS(z) <= 2 && iteration < max_iterations){ - z = cpow(z, d) + z0; + z = CPOW(z, d) + z0; iteration++; } return iteration; @@ -57,6 +84,32 @@ void multibrot_grid(grid_t* grid, const size_t max_iterations, const double d){ } } +/* + * Computes the number ofiterations it takes for a point z0 to become unbounded + * if the return value is equal to max_iterations, the point lies within the multicorn set + * This function is to tricorn as multibrot is to mandelbrot + */ +size_t multicorn(const CBASE complex z0, const size_t max_iterations, const double d){ + CBASE complex z = z0; + size_t iteration = 0; + while(CABS(z) <= 2 && iteration < max_iterations){ + z = CONJ(CPOW(z, d)) + z0; + iteration++; + } + return iteration; +} + +/* + * Fills a grid with multicorn values + */ +void multicorn_grid(grid_t* grid, const size_t max_iterations, const double d){ + const size_t size = grid->size; + size_t* data = grid->data; + for(size_t i = 0; i < size; i ++){ + data[i] = multicorn(grid_to_complex(grid, i), max_iterations, d); + } +} + /* * Computes ????? for a julia set * implementation of https://en.wikipedia.org/wiki/Julia_set#Pseudocode diff --git a/src/shared-fractals.c b/src/shared-fractals.c index c44224a..3390e14 100644 --- a/src/shared-fractals.c +++ b/src/shared-fractals.c @@ -33,6 +33,33 @@ void mandelbrot_grid(grid_t* restrict grid, const size_t max_iterations){ } } +/* + * Computes the number of iterations it takes for a point z0 to become unbounded + * if the return value is equal to max_iterations, the point lies within the tricorn set + * This is nearly identical to mandelbrot, except for the complex conjugate + */ +size_t tricorn(const CBASE complex z0, const size_t max_iterations){ + CBASE complex z = z0; + size_t iteration = 0; + while(CABS(z) <= 2 && iteration < max_iterations){ + z = CONJ(z * z) + z0; + iteration++; + } + return iteration; +} + +/* + * Fills a grid with tricorn values + */ +void tricorn_grid(grid_t* grid, const size_t max_iterations){ + const size_t size = grid->size; + size_t* data = grid->data; + + #pragma omp parallel for default(none) shared(data, size, grid, max_iterations) schedule(dynamic) + for(size_t i = 0; i < size; i++){ + data[i] = tricorn(grid_to_complex(grid, i), max_iterations); + } +} /* * Computes the number of iterations it takes for a point z0 to diverge * if the return value is equal to max_iterations, the point lies within the multibrot set @@ -48,7 +75,6 @@ size_t multibrot(const CBASE complex z0, const size_t max_iterations, const doub return iteration; } - /* * Fills a grid with multibrot values */ @@ -62,6 +88,33 @@ void multibrot_grid(grid_t* restrict grid, const size_t max_iterations, const do } } +/* + * Computes the number ofiterations it takes for a point z0 to become unbounded + * if the return value is equal to max_iterations, the point lies within the multicorn set + * This function is to tricorn as multibrot is to mandelbrot + */ +size_t multicorn(const CBASE complex z0, const size_t max_iterations, const double d){ + CBASE complex z = z0; + size_t iteration = 0; + while(CABS(z) <= 2 && iteration < max_iterations){ + z = CONJ(CPOW(z, d)) + z0; + iteration++; + } + return iteration; +} + +/* + * Fills a grid with multicorn values + */ +void multicorn_grid(grid_t* grid, const size_t max_iterations, const double d){ + const size_t size = grid->size; + size_t* data = grid->data; + #pragma omp parallel for default(none) shared(data, size, grid, max_iterations, d) schedule(dynamic) + for(size_t i = 0; i < size; i ++){ + data[i] = multicorn(grid_to_complex(grid, i), max_iterations, d); + } +} + /* * Computes ????? for a julia set * implementation of https://en.wikipedia.org/wiki/Julia_set#Pseudocode -- cgit v1.2.3 From 223c2a359a02602951771d960bd517d7cf6f3f9f Mon Sep 17 00:00:00 2001 From: JP Appel Date: Wed, 24 Apr 2024 00:30:57 -0400 Subject: implemented the burning ship fractal --- src/fractals.c | 5 ++++- src/fractals.h | 7 +++++-- src/precision.h | 2 ++ src/serial-fractals.c | 30 ++++++++++++++++++++++++++++++ src/shared-fractals.c | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 3 deletions(-) (limited to 'src/fractals.h') diff --git a/src/fractals.c b/src/fractals.c index 82e4ef6..269bfaf 100644 --- a/src/fractals.c +++ b/src/fractals.c @@ -126,7 +126,7 @@ int main(const int argc, char *argv[]) { // const CBASE complex constant = -0.835L -0.321L* I; const double radius = 100; - enum fractal f = MULTICORN; + enum fractal f = BURNING_SHIP; switch(f){ case MANDELBROT: mandelbrot_grid(grid, iterations); @@ -140,6 +140,9 @@ int main(const int argc, char *argv[]) { case MULTICORN: multicorn_grid(grid, iterations, degree); break; + case BURNING_SHIP: + burning_ship_grid(grid, iterations); + break; case JULIA: julia_grid(grid, iterations, constant, radius); break; diff --git a/src/fractals.h b/src/fractals.h index 3f2757d..2b296eb 100644 --- a/src/fractals.h +++ b/src/fractals.h @@ -10,8 +10,8 @@ enum fractal { MANDELBROT, // IMPLEMENTED IN SERIAL SHARED TRICORN, // IMPLEMENTED IN SERIAL SHARED MULTIBROT, // IMPLEMENTED IN SERIAL SHARED - MULTICORN, // IMPLEMENTED in SERIAL SHARED - BURNING_SHIP, // NOT IMPLEMENTED IN ANY VERSION + MULTICORN, // IMPLEMENTED IN SERIAL SHARED + BURNING_SHIP, // IMPLEMENTED IN SERIAL SHARED //NEWTON, // MIGHT NEVER BE IMPLEMENTED, REQUIRES SPECIAL COLORING JULIA // IMPLEMENTED IN SERIAL SHARED }; @@ -22,6 +22,9 @@ void mandelbrot_grid(grid_t* grid, const size_t max_iterations); size_t tricorn(const CBASE complex z0, const size_t max_iterations); void tricorn_grid(grid_t* grid, const size_t max_iterations); +size_t burning_ship(const CBASE complex z0, const size_t max_iterations); +void burning_ship_grid(grid_t* grid, const size_t max_iterations); + size_t multibrot(const CBASE complex z0, const size_t max_iterations, const double d); void multibrot_grid(grid_t* grid, const size_t max_iterations, const double d); diff --git a/src/precision.h b/src/precision.h index e83122a..4bca354 100644 --- a/src/precision.h +++ b/src/precision.h @@ -13,6 +13,7 @@ #define CPOW cpowl #define CONJ conjl #define CABS cabsl +#define RABS fabsl #define CFORMAT "%Lf" #endif @@ -24,6 +25,7 @@ #define CPOW cpow #define CONJ conj #define CABS cabs +#define RABS fabs #define CFORMAT "%lf" #endif diff --git a/src/serial-fractals.c b/src/serial-fractals.c index 2647d11..4e081c3 100644 --- a/src/serial-fractals.c +++ b/src/serial-fractals.c @@ -1,4 +1,5 @@ #include "fractals.h" +#include #include "precision.h" #include "grids.h" @@ -57,6 +58,35 @@ void tricorn_grid(grid_t* grid, const size_t max_iterations){ } } +/* + * Computes the number of iterations it takes for a point z0 to become unbounded + * if the return value is equal to max_iterations, the point lies within the burningship set (oh no! I hope they have fire safety gear) + */ +size_t burning_ship(const CBASE complex z0, const size_t max_iterations) { + CBASE complex z = z0; + CBASE complex z_mod; + size_t iteration = 0; + + while (CABS(z) <= 2 && iteration < max_iterations) { + z_mod = RABS(CREAL(z)) + RABS(CIMAG(z))*I; + z = z_mod * z_mod + z0; + iteration++; + } + return iteration; +} + +/* + * Fills a grid with burning_ship values + */ +void burning_ship_grid(grid_t* grid, const size_t max_iterations){ + const size_t size = grid->size; + size_t* data = grid->data; + + for(size_t i = 0; i < size; i++){ + data[i] = burning_ship(grid_to_complex(grid, i), max_iterations); + } +} + /* * Computes the number of iterations it takes for a point z0 to become unbounded * if the return value is equal to max_iterations, the point lies within the multibrot set diff --git a/src/shared-fractals.c b/src/shared-fractals.c index 3390e14..92c8c9a 100644 --- a/src/shared-fractals.c +++ b/src/shared-fractals.c @@ -1,6 +1,7 @@ #include "fractals.h" #include +#include #include "fractals.h" #include "precision.h" @@ -60,6 +61,37 @@ void tricorn_grid(grid_t* grid, const size_t max_iterations){ data[i] = tricorn(grid_to_complex(grid, i), max_iterations); } } + +/* + * Computes the number of iterations it takes for a point z0 to become unbounded + * if the return value is equal to max_iterations, the point lies within the burningship set (oh no! I hope they have fire safety gear) + */ +size_t burning_ship(const CBASE complex z0, const size_t max_iterations) { + CBASE complex z = z0; + CBASE complex z_mod; + size_t iteration = 0; + + while (CABS(z) <= 2 && iteration < max_iterations) { + z_mod = RABS(CREAL(z)) + RABS(CIMAG(z))*I; + z = z_mod * z_mod + z0; + iteration++; + } + return iteration; +} + +/* + * Fills a grid with burning_ship values + */ +void burning_ship_grid(grid_t* grid, const size_t max_iterations){ + const size_t size = grid->size; + size_t* data = grid->data; + + #pragma omp parallel for default(none) shared(data, size, grid, max_iterations) schedule(dynamic) + for(size_t i = 0; i < size; i++){ + data[i] = burning_ship(grid_to_complex(grid, i), max_iterations); + } +} + /* * Computes the number of iterations it takes for a point z0 to diverge * if the return value is equal to max_iterations, the point lies within the multibrot set -- cgit v1.2.3