aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/fractals.c103
-rw-r--r--src/fractals.h18
-rw-r--r--src/grids.c12
-rw-r--r--src/serial-fractals.c59
-rw-r--r--src/shared-fractals.c55
5 files changed, 221 insertions, 26 deletions
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 <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
+#include <getopt.h>
#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;
@@ -58,6 +85,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
@@ -34,6 +34,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
* This should be identical to the version found in serial-fractals.c
@@ -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
*/
@@ -63,6 +89,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
*