aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
authorJP Appel <jeanpierre.appel01@gmail.com>2024-04-25 19:24:49 -0400
committerJP Appel <jeanpierre.appel01@gmail.com>2024-04-25 19:24:49 -0400
commitf15d4cdb413d2fe28ff20cfccb784cf739aad8e6 (patch)
treef7b61e3eb8beb4536118471a72ce59c0a242ddfa /src
parent4d11db63f237423036f7daa41a1213ddcf30d532 (diff)
added help and allow changing of fractal at runtime
Diffstat (limited to 'src')
-rw-r--r--src/fractals.c176
-rw-r--r--src/fractals.h30
-rw-r--r--src/grids.h2
-rw-r--r--src/serial-fractals.c18
-rw-r--r--src/shared-fractals.c20
5 files changed, 139 insertions, 107 deletions
diff --git a/src/fractals.c b/src/fractals.c
index 1c0c4ea..be8c917 100644
--- a/src/fractals.c
+++ b/src/fractals.c
@@ -3,29 +3,54 @@
#include <stdlib.h>
#include <sys/ioctl.h>
#include <getopt.h>
+#include <string.h>
+#include <time.h>
#include "grids.h"
#include "precision.h"
#include "fractals.h"
+#define NUM_RUNS 5
-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_usage(FILE* file, const char* program_name){
+ fprintf(file, "Usage: %s [-v] [-i iterations] [-x x_res] [-y y_res] [-z magnification] [-l lower_left] [-u upper_right] [-o output_grid] -f fractal\n", program_name);
}
void print_help(){
- //TODO: add help
+ printf("Options:\n"
+ " -i, --iterations <value> the number of iterations (default: 100)\n"
+ " -x, --x-res <value> the horizontal resolution (default: terminal width)\n"
+ " -y, --y-res <value> the vertical resolution (default: terminal height)\n"
+ " -l, --lower-left <value> Set the lower left corner of the fractal area (default: -2-2i)\n"
+ " -u, --upper-right <value> Set the upper right corner of the fractal area (default: 2+2i)\n"
+ " -z, --magnification <value> Set the magnification factor (default: 1)\n"
+ " -o, --output <filename> the output filename (default: fractal.grid)\n"
+ " -f, --fractal <type> the fractal type (default: mandelbrot)\n"
+ " supported fractals: mandelbrot, tricorn, multibrot, multicorn, burning_ship, julia\n"
+ " -p, --performance print performance info\n"
+ " -v, --verbose verbose output\n"
+ " -h, --help prints this help message\n");
}
-void print_info(){
+void print_info(const char* program_name){
#ifdef EXTENDED_PRECISION
printf("Compiled with long double float precision\n");
#endif
#ifndef EXTENDED_PRECISION
- printf("Compiled with double float precision\n");
+ printf("%s complied with double float precision\n", program_name);
#endif
}
+double time_fractal(fractal_generator generator, grid_t* grid, grid_gen_params* params){
+ struct timespec start, end;
+ clock_gettime(CLOCK_MONOTONIC, &start);
+ for(size_t i = 0; i < NUM_RUNS; i++){
+ generator(grid, params);
+ }
+ clock_gettime(CLOCK_MONOTONIC, &end);
+ return (end.tv_sec - start.tv_sec + (end.tv_nsec - start.tv_nsec) * 1.0e-9) / NUM_RUNS;
+}
+
int main(const int argc, char *argv[]) {
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
@@ -34,20 +59,16 @@ int main(const int argc, char *argv[]) {
size_t iterations = 100;
size_t x_res = w.ws_col;
size_t y_res = w.ws_row;
- CBASE re_lower_left = -2;
- CBASE im_lower_left = -2;
- CBASE re_upper_right = 2;
- CBASE im_upper_right = 2;
+ complex_t lower_left = { .re = -2, .im = -2};
+ complex_t upper_right = { .re = 2, .im = 2};
CBASE magnification = 1;
bool verbose = false;
- //TODO: allocate adequate size buffer
- bool output_to_file = true;
+ bool performance = false;
+ grid_gen_params* params;
+ char* fractal_name;
+ fractal_generator generator = mandelbrot_grid;
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'},
@@ -57,13 +78,15 @@ int main(const int argc, char *argv[]) {
{"magnification", required_argument, NULL, 'z'},
{"output", required_argument, NULL, 'o'},
{"verbose", no_argument, NULL, 'v'},
+ {"performance", no_argument, NULL, 'p'},
{"help", no_argument, NULL, 'h'},
+ {"fractal", required_argument, NULL, 'f'},
{0, 0, 0, 0} // Termination element
};
//parse command line arguments
int opt;
- while((opt = getopt_long(argc, argv, "i:x:y:l:u:z:o:vh", long_options, NULL)) != -1){
+ while((opt = getopt_long(argc, argv, "i:x:y:l:u:z:o:vphf:", long_options, NULL)) != -1){
switch(opt){
case 'i':
iterations = strtoull(optarg, NULL, 10);
@@ -75,15 +98,50 @@ int main(const int argc, char *argv[]) {
y_res = strtoull(optarg, NULL, 10);
break;
case 'l':
- sscanf(optarg, CFORMAT"+"CFORMAT"i", &re_lower_left, &im_lower_left);
+ sscanf(optarg, CFORMAT"+"CFORMAT"i", &lower_left.re, &lower_left.im);
break;
case 'u':
- sscanf(optarg, CFORMAT"+"CFORMAT"i", &re_upper_right, &im_upper_right);
+ sscanf(optarg, CFORMAT"+"CFORMAT"i", &upper_right.re, &upper_right.im);
break;
case 'o':
- //TODO: check if can write to location
- output_to_file = true;
- //TODO:
+ output_filename = optarg;
+ break;
+ case 'f':
+ if(strncmp(optarg, "mandelbrot", strlen("mandelbrot")) == 0) {
+ fractal_name = "mandelbrot";
+ generator = mandelbrot_grid;
+ }
+ else if(strncmp(optarg, "tricorn", strlen("tricorn")) == 0) {
+ fractal_name = "tricorn";
+ generator = tricorn_grid;
+ }
+ else if(strncmp(optarg, "multibrot", strlen("multibrot")) == 0) {
+ fractal_name = "multibrot";
+ generator = multibrot_grid;
+ params = malloc(sizeof(grid_gen_params));
+ params->degree = 3;
+ }
+ else if(strncmp(optarg, "multicorn", strlen("multicorn")) == 0) {
+ fractal_name = "multicorn";
+ generator = multicorn_grid;
+ params = malloc(sizeof(grid_gen_params));
+ params->degree = 3;
+ }
+ else if(strncmp(optarg, "burning_ship", strlen("burning_ship")) == 0) {
+ fractal_name = "burning ship";
+ generator = burning_ship_grid;
+ }
+ else if(strncmp(optarg, "julia", strlen("julia")) == 0) {
+ fractal_name = "julia";
+ generator = julia_grid;
+ params = malloc(sizeof(grid_gen_params));
+ params->cr.radius = 100;
+ params->cr.constant = (complex_t){ .re = 0.285, .im = 0.01 };
+ }
+ else {
+ fprintf(stderr, "Invalid fractal type: %s, see --help for a list of supported fractals\n", optarg);
+ return 1;
+ }
break;
case 'z':
sscanf(optarg, CFORMAT, &magnification);
@@ -95,8 +153,12 @@ int main(const int argc, char *argv[]) {
case 'v':
verbose = true;
break;
+ case 'p':
+ performance = true;
+ break;
case 'h':
print_usage(stdout, argv[0]);
+ print_help();
return 0;
default:
print_usage(stderr, argv[0]);
@@ -104,75 +166,37 @@ int main(const int argc, char *argv[]) {
}
}
- //const CBASE complex lower_left = re_lower_left + im_lower_left * I;
- const complex_t lower_left = { .re=re_lower_left, .im=im_lower_left};
- //const CBASE complex upper_right = re_upper_right + im_upper_right * I;
- const complex_t upper_right = { .re=re_upper_right, .im=im_upper_right};
-
grid_t* grid = create_grid(x_res, y_res, iterations, lower_left, upper_right);
if(!grid) return 1;
if(magnification != 1){
- if(verbose) printf("Magnification: "CFORMAT"\n", magnification);
zoom_grid(grid, magnification);
}
- // params for different fractals
- const double degree = 3.0;
- // const CBASE complex constant = 0.285L + 0.01L*I;
- const complex_t constant = {
- .re = 0.285,
- .im = 0.01
- };
- // const CBASE complex constant = -0.835L -0.321L* I;
- const double radius = 100;
-
- // enum fractal f = BURNING_SHIP;
- enum fractal f = JULIA;
- switch(f){
- case MANDELBROT:
- mandelbrot_grid(grid);
- break;
- case TRICORN:
- tricorn_grid(grid);
- break;
- case MULTIBROT:
- multibrot_grid(grid, degree);
- break;
- case MULTICORN:
- multicorn_grid(grid, degree);
- break;
- case BURNING_SHIP:
- burning_ship_grid(grid);
- break;
- case JULIA:
- julia_grid(grid, constant, radius);
- break;
- default:
- fprintf(stderr, "Unrecognized fractal\n");
- return 1;
+ // TODO: make additional param to fractals that take these in
+
+ generator(grid, params);
+
+ if(performance){
+ double time = time_fractal(generator, grid, params);
+ printf("%s,%f\n", fractal_name, time);
}
- if(verbose)print_grid_info(grid);
+ if(verbose){
+ print_info(argv[0]);
+ printf("Magnification:\t"CFORMAT"\n", magnification);
+ print_grid_info(grid);
+ }
- //write grid to file
- if(output_to_file){
- FILE* write_file = fopen("test.grid", "wb");
- int err = write_grid(write_file , grid);
- if(err == GRID_WRITE_ERROR){
- fprintf(stderr, "Error writing occured while writting to file %s\n", output_filename);
- }
- fclose(write_file);
+ FILE* file = fopen(output_filename, "wb");
+ if(write_grid(file, grid) == GRID_WRITE_ERROR){
+ fprintf(stderr, "Error writing occured while writting to file %s\n", output_filename);
}
+ fclose(file);
+ free(params);
free_grid(grid);
- // //attempt to read grid from file
- // FILE* read_file = fopen("test2.grid", "rb");
- // grid_t* grid2 = read_grid(read_file);
- // 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 2262d82..611e4e6 100644
--- a/src/fractals.h
+++ b/src/fractals.h
@@ -6,30 +6,30 @@
#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, // IMPLEMENTED IN SERIAL SHARED
- //NEWTON, // MIGHT NEVER BE IMPLEMENTED, REQUIRES SPECIAL COLORING
- JULIA // IMPLEMENTED IN SERIAL SHARED
-};
+typedef union {
+ CBASE degree;
+ struct {
+ complex_t constant;
+ double radius;
+ } cr ;
+} grid_gen_params ;
+
+typedef void (*fractal_generator)(grid_t* , const grid_gen_params* );
size_t mandelbrot(const CBASE complex z0, const size_t max_iterations);
-void mandelbrot_grid(grid_t* grid);
+void mandelbrot_grid(grid_t* grid, const grid_gen_params* params);
size_t tricorn(const CBASE complex z0, const size_t max_iterations);
-void tricorn_grid(grid_t* grid);
+void tricorn_grid(grid_t* grid, const grid_gen_params* params);
size_t burning_ship(const CBASE complex z0, const size_t max_iterations);
-void burning_ship_grid(grid_t* grid);
+void burning_ship_grid(grid_t* grid, const grid_gen_params* params);
size_t multibrot(const CBASE complex z0, const size_t max_iterations, const double d);
-void multibrot_grid(grid_t* grid, const double d);
+void multibrot_grid(grid_t* grid, const grid_gen_params* params);
size_t multicorn(const CBASE complex z0, const size_t max_iterations, const double d);
-void multicorn_grid(grid_t* grid, const double d);
+void multicorn_grid(grid_t* grid, const grid_gen_params* params);
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 complex_t c, const double R);
+void julia_grid(grid_t* grid, const grid_gen_params* params);
diff --git a/src/grids.h b/src/grids.h
index 37e5538..942bb7f 100644
--- a/src/grids.h
+++ b/src/grids.h
@@ -12,7 +12,7 @@
#define GRID_MAGIC_NUMBER 0xA6005E
-// hack to determine variable precision at compile time
+// hack to allow variable precision at compile time
typedef struct {
CBASE re;
CBASE im;
diff --git a/src/serial-fractals.c b/src/serial-fractals.c
index 72fb205..ee55b3b 100644
--- a/src/serial-fractals.c
+++ b/src/serial-fractals.c
@@ -22,7 +22,7 @@ size_t mandelbrot(const CBASE complex z0, const size_t max_iterations) {
/*
* Fills a grid with mandelbrot values
*/
-void mandelbrot_grid(grid_t* grid){
+void mandelbrot_grid(grid_t* grid, const grid_gen_params* params){
const size_t size = grid->size;
const size_t max_iterations = grid->max_iterations;
size_t* data = grid->data;
@@ -50,7 +50,7 @@ size_t tricorn(const CBASE complex z0, const size_t max_iterations){
/*
* Fills a grid with tricorn values
*/
-void tricorn_grid(grid_t* grid){
+void tricorn_grid(grid_t* grid, const grid_gen_params* params){
const size_t size = grid->size;
const size_t max_iterations = grid->max_iterations;
size_t* data = grid->data;
@@ -80,7 +80,7 @@ size_t burning_ship(const CBASE complex z0, const size_t max_iterations) {
/*
* Fills a grid with burning_ship values
*/
-void burning_ship_grid(grid_t* grid){
+void burning_ship_grid(grid_t* grid, const grid_gen_params* params){
const size_t size = grid->size;
const size_t max_iterations = grid->max_iterations;
size_t* data = grid->data;
@@ -109,7 +109,8 @@ size_t multibrot(const CBASE complex z0, const size_t max_iterations, const doub
/*
* Fills a grid with multibrot values
*/
-void multibrot_grid(grid_t* grid, const double d){
+void multibrot_grid(grid_t* grid, const grid_gen_params* params){
+ const double d = params->degree;
const size_t size = grid->size;
const size_t max_iterations = grid->max_iterations;
size_t* data = grid->data;
@@ -136,7 +137,8 @@ size_t multicorn(const CBASE complex z0, const size_t max_iterations, const doub
/*
* Fills a grid with multicorn values
*/
-void multicorn_grid(grid_t* grid, const double d){
+void multicorn_grid(grid_t* grid, const grid_gen_params* params){
+ const double d = params->degree;
const size_t size = grid->size;
const size_t max_iterations = grid->max_iterations;
size_t* data = grid->data;
@@ -162,12 +164,14 @@ size_t julia(const CBASE complex z0, const CBASE complex c, const size_t max_ite
return iteration;
}
-void julia_grid(grid_t* grid, const complex_t constant, const double R){
+void julia_grid(grid_t* grid, const grid_gen_params* params){
+ const complex_t constant = params->cr.constant;
+ const double radius = params->cr.radius;
const size_t size = grid->size;
const size_t max_iterations = grid->max_iterations;
const CBASE complex c = constant.re + constant.im * I;
size_t* data = grid->data;
for(size_t i = 0; i <size; i++){
- data[i] = julia(grid_to_complex(grid, i), c, max_iterations, R);
+ data[i] = julia(grid_to_complex(grid, i), c, max_iterations, radius);
}
}
diff --git a/src/shared-fractals.c b/src/shared-fractals.c
index 836d271..a45d366 100644
--- a/src/shared-fractals.c
+++ b/src/shared-fractals.c
@@ -24,7 +24,7 @@ size_t mandelbrot(const CBASE complex z0, const size_t max_iterations){
/*
* Fills a grid with mandelbrot values
*/
-void mandelbrot_grid(grid_t* restrict grid){
+void mandelbrot_grid(grid_t* restrict grid, const grid_gen_params* params){
const size_t size = grid->size;
const size_t max_iterations = grid->max_iterations;
size_t* data = grid->data;
@@ -53,7 +53,7 @@ size_t tricorn(const CBASE complex z0, const size_t max_iterations){
/*
* Fills a grid with tricorn values
*/
-void tricorn_grid(grid_t* grid){
+void tricorn_grid(grid_t* grid, const grid_gen_params* params){
const size_t size = grid->size;
const size_t max_iterations = grid->max_iterations;
size_t* data = grid->data;
@@ -84,7 +84,7 @@ size_t burning_ship(const CBASE complex z0, const size_t max_iterations) {
/*
* Fills a grid with burning_ship values
*/
-void burning_ship_grid(grid_t* grid){
+void burning_ship_grid(grid_t* grid, const grid_gen_params* params){
const size_t size = grid->size;
const size_t max_iterations = grid->max_iterations;
size_t* data = grid->data;
@@ -113,7 +113,8 @@ size_t multibrot(const CBASE complex z0, const size_t max_iterations, const doub
/*
* Fills a grid with multibrot values
*/
-void multibrot_grid(grid_t* restrict grid, const double d){
+void multibrot_grid(grid_t* restrict grid, const grid_gen_params* params){
+ const double d = params->degree;
const size_t size = grid->size;
const size_t max_iterations = grid->max_iterations;
size_t* data = grid->data;
@@ -142,7 +143,8 @@ size_t multicorn(const CBASE complex z0, const size_t max_iterations, const doub
/*
* Fills a grid with multicorn values
*/
-void multicorn_grid(grid_t* grid, const double d){
+void multicorn_grid(grid_t* grid, const grid_gen_params* params){
+ const double d = params->degree;
const size_t size = grid->size;
const size_t max_iterations = grid->max_iterations;
size_t* data = grid->data;
@@ -170,13 +172,15 @@ size_t julia(const CBASE complex z0, const CBASE complex c, const size_t max_ite
return iteration;
}
-void julia_grid(grid_t* restrict grid, const complex_t constant, const double R){
+void julia_grid(grid_t* grid, const grid_gen_params* params){
+ const complex_t constant = params->cr.constant;
+ const double radius = params->cr.radius;
const size_t size = grid->size;
const size_t max_iterations = grid->max_iterations;
const CBASE complex c = constant.re + constant.im * I;
size_t* data = grid->data;
- #pragma omp parallel for default(none) shared(data, size, grid, max_iterations, c, R) schedule(dynamic)
+ #pragma omp parallel for default(none) shared(data, size, grid, max_iterations, c, radius) schedule(dynamic)
for(size_t i = 0; i < size; i++){
- data[i] = julia(grid_to_complex(grid, i), c, max_iterations, R);
+ data[i] = julia(grid_to_complex(grid, i), c, max_iterations, radius);
}
}