aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/fractals.c49
-rw-r--r--src/fractals.h7
-rw-r--r--src/grids.c78
-rw-r--r--src/grids.h3
-rw-r--r--src/serial-fractals.c36
5 files changed, 151 insertions, 22 deletions
diff --git a/src/fractals.c b/src/fractals.c
index 80ff32e..a2a43db 100644
--- a/src/fractals.c
+++ b/src/fractals.c
@@ -8,16 +8,21 @@
#include "grids.h"
#include "fractals.h"
-
int main(const int argc, char *argv[]) {
//default values
size_t iterations = 1000;
size_t x_res = 100;
size_t y_res = 100;
+ double re_lower_left = -2;
+ double im_lower_left = -2;
+ double re_upper_right = 2;
+ double im_upper_right = 2;
+ double magnification = 1;
+ bool verbose = false;
//parse command line arguments
int opt;
- while((opt =getopt(argc, argv, "i:x:y:")) != -1){
+ while((opt = getopt(argc, argv, "vhi:x:y:l:u:z:")) != -1){
switch(opt){
case 'i':
iterations = strtoull(optarg, NULL, 10);
@@ -28,26 +33,46 @@ int main(const int argc, char *argv[]) {
case 'y':
y_res = strtoull(optarg, NULL, 10);
break;
+ case 'l':
+ sscanf(optarg, "%lf+%lfi", &re_lower_left, &im_lower_left);
+ break;
+ case 'u':
+ sscanf(optarg, "%lf+%lfi", &re_upper_right, &im_upper_right);
+ break;
+ case 'z':
+ sscanf(optarg, "%lf", &magnification);
+ if(magnification <= 0){
+ fprintf(stderr, "Invalid magnification %f, exitting\n", magnification);
+ return 1;
+ }
+ break;
+ case 'v':
+ 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]);
+ return 0;
default:
- fprintf(stderr, "Usage: %s [-i iterations] [-x x_res] [-y y_res]\n", argv[0]);
+ fprintf(stderr, "Usage: %s [-v] [-i iterations] [-x x_res] [-y y_res] [-z magnification] [-l lower_left] [-u upper_right]\n", argv[0]);
return 1;
}
}
+ const double complex lower_left = re_lower_left + im_lower_left * I;
+ const double complex upper_right = re_upper_right + im_upper_right * I;
- const double complex lower_left = -2 + -2*I;
- const double complex upper_right = 2 + 2*I;
grid_t* grid = create_grid(x_res, y_res, lower_left, upper_right);
if(!grid) return 1;
- const size_t size = grid->size;
- size_t* data = grid->data;
- for(size_t i = 0; i < size;i++){
- data[i] = multibrot(grid_to_complex(grid, i), iterations, 3);
+ if(magnification != 1){
+ if(verbose) printf("Magnification: %f\n", magnification);
+ zoom_grid(grid, magnification);
}
- for(size_t i = 0; i < size; i++){
- printf("%zu%s", data[i], (i % x_res == x_res - 1) ? "\n" : "\t");
- }
+
+ mandelbrot_grid(grid, iterations);
+
+ if(verbose)print_grid_info(grid);
+ print_grid(grid, iterations);
}
diff --git a/src/fractals.h b/src/fractals.h
index 60d9013..dc6783e 100644
--- a/src/fractals.h
+++ b/src/fractals.h
@@ -3,7 +3,12 @@
#include <complex.h>
#include <stddef.h>
#include <stdint.h>
+#include "grids.h"
size_t mandelbrot(const double complex z0, const size_t max_iterations);
-size_t multibrot(const double complex z0, const size_t max_iterations, const uintmax_t d);
+void mandelbrot_grid(grid_t* grid, const size_t max_iterations);
+
+size_t multibrot(const double 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 double R, const double complex z0, const double complex c, const size_t max_iterations);
diff --git a/src/grids.c b/src/grids.c
index a6d35df..89347db 100644
--- a/src/grids.c
+++ b/src/grids.c
@@ -1,3 +1,4 @@
+#include <complex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -26,6 +27,7 @@ grid_t* create_grid(const size_t x, const size_t y, double complex lower_left, d
*grid = (grid_t){
.x = x,
.y = y,
+ .size = x*y,
.lower_left = lower_left,
.upper_right = upper_right,
.data = data
@@ -120,6 +122,23 @@ double complex grid_to_complex(const grid_t* grid, const size_t index) {
}
/*
+ * Zoom a grid in or out based on its current center
+ *
+ * Resets all grid values to 0
+ */
+void zoom_grid(grid_t* grid, const double magnification){
+ set_grid(grid, 0);
+ const double complex upper_right = grid->upper_right;
+ const double complex lower_left = grid->lower_left;
+
+ const double complex center = (lower_left + upper_right) / 2.0;
+ const double complex offset = (upper_right - lower_left) / magnification;
+
+ grid->lower_left = center - offset;
+ grid->upper_right = center + offset;
+}
+
+/*
* Writes a grid to a file in the .grid format
*
* Returns 0 on success
@@ -157,6 +176,65 @@ int write_grid(FILE* restrict file, const grid_t *grid){
}
/*
+ * Prints info about a grid to stdout
+ */
+void print_grid_info(const grid_t* grid){
+ if(!grid){
+ printf("Grid is NULL!\n");
+ return;
+ }
+
+ 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%f + %fI\n", creal(grid->lower_left), cimag(grid->lower_left));
+ printf("upper_right\t%f + %fI\n", creal(grid->upper_right), cimag(grid->upper_right));
+
+ printf("Data is %s NULL\n", grid->data ? "not" : "");
+}
+
+/*
+ * Attempts an ASCII print of the grid
+ */
+void print_grid(const grid_t* grid, const size_t iterations){
+ const size_t size = grid->size;
+ const size_t x_res = grid->x;
+ const size_t* data = grid->data;
+
+ // char* output_buffer = malloc(size);
+ // if(!output_buffer){
+ // fprintf(stderr, "Failed to allocate output buffer for %zu points\n");
+ // return;
+ // }
+
+ const char point_types[] = { ' ', '.', '*', '%', '#'};
+ size_t bin_width = iterations/3;
+ size_t last_bin = iterations - bin_width;
+ char point;
+
+ //TODO: set values in output buffer rather than multiple printf calls
+ for(size_t i = 0; i < size; i++){
+ const size_t value = data[i];
+ if(value == iterations){
+ point = point_types[4];
+ }
+ else if(value == 0){
+ point = point_types[0];
+ }
+ else if(value <= bin_width){
+ point = point_types[1];
+ }
+ else if(value >= last_bin){
+ point = point_types[3];
+ }
+ else {
+ point = point_types[2];
+ }
+ printf("%c%s", point, (i % x_res == x_res - 1) ? "\n" : "");
+ }
+}
+
+/*
* Creates a grid from a .grid file, reading the amount of data as specified by the file
* For more details on the .grid format see write_grid
*
diff --git a/src/grids.h b/src/grids.h
index 8c9db91..bba6f68 100644
--- a/src/grids.h
+++ b/src/grids.h
@@ -28,6 +28,9 @@ bool grid_equal(const grid_t* grid1, const grid_t* grid2);
bool grid_allclose(const grid_t* grid1, const grid_t* grid2, const size_t max_error);
double complex grid_to_complex(const grid_t* grid, const size_t index);
+void zoom_grid(grid_t* grid, const double magnification);
+void print_grid_info(const grid_t* grid);
+void print_grid(const grid_t* grid, const size_t iterations);
int write_grid(FILE* restrict file, const grid_t* grid);
grid_t* read_grid(FILE* restrict file);
diff --git a/src/serial-fractals.c b/src/serial-fractals.c
index a5f9841..9f4013d 100644
--- a/src/serial-fractals.c
+++ b/src/serial-fractals.c
@@ -1,4 +1,5 @@
#include "fractals.h"
+#include "grids.h"
/*
* 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 mandelbrot set
@@ -15,28 +16,45 @@ size_t mandelbrot(const double complex z0, const size_t max_iterations) {
return iteration;
}
+/*
+ * Fills a grid with mandelbrot values
+ */
+void mandelbrot_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] = mandelbrot(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 is implementation closely matches mandelbrot
- * Note, only positive integer powers are supported
+ * This is implementation closely matches mandelbrot, but uses cpow which might degrade performance.
*/
-size_t multibrot(const double complex z0, const size_t max_iterations, const uintmax_t d){
+size_t multibrot(const double complex z0, const size_t max_iterations, const double d){
double complex z = z0;
- double complex ztemp;
size_t iteration = 0;
while(cabs(z) <= 2 && iteration < max_iterations){
- ztemp = z;
- for(size_t i = 0; i < d; i ++){
- ztemp *= ztemp;
- }
- z = ztemp + z0;
+ z = cpowl(z, d) + z0;
iteration++;
}
return iteration;
}
+
+/*
+ * Fills a grid with multibrot values
+ */
+void multibrot_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] = multibrot(grid_to_complex(grid, i), max_iterations, d);
+ }
+}
+
/*
* Computes ????? for a julia set
* implementation of https://en.wikipedia.org/wiki/Julia_set#Pseudocode