aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--src/cuda-fractals.cu84
-rw-r--r--src/fractals.c86
-rw-r--r--src/fractals.h13
-rw-r--r--src/grids.c24
-rw-r--r--src/grids.h13
-rw-r--r--src/serial-fractals.c48
-rw-r--r--src/shared-fractals.c48
8 files changed, 168 insertions, 151 deletions
diff --git a/.gitignore b/.gitignore
index ec428fc..83a65a6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,9 @@
# grid files
*.grid
+# analysis stuff
+analysis/data/*
+
# Presentation Stuff
build/*
*.html
diff --git a/src/cuda-fractals.cu b/src/cuda-fractals.cu
index f6b6e6d..ef94a3f 100644
--- a/src/cuda-fractals.cu
+++ b/src/cuda-fractals.cu
@@ -49,9 +49,9 @@ thrust::complex<CBASE> grid_to_complex(const thrust::complex<CBASE> lower_left,
}
__device__
-size_t mandelbrot(const thrust::complex<CBASE> z0, const size_t max_iterations){
+byte mandelbrot(const thrust::complex<CBASE> z0, const byte max_iterations){
thrust::complex<CBASE> z = z0;
- size_t iteration = 0;
+ byte iteration = 0;
while(thrust::abs(z) <= 2 && iteration < max_iterations){
z = z*z + z0;
iteration++;
@@ -60,7 +60,7 @@ size_t mandelbrot(const thrust::complex<CBASE> z0, const size_t max_iterations){
}
__global__
-void mandelbrot_kernel(size_t* grid_data, const size_t max_iterations, const thrust::complex<CBASE> lower_left, const thrust::complex<CBASE> upper_right, const size_t rows, const size_t cols){
+void mandelbrot_kernel(byte* grid_data, const byte max_iterations, const thrust::complex<CBASE> lower_left, const thrust::complex<CBASE> upper_right, const size_t rows, const size_t cols){
SET_ROW_COL;
const auto z = grid_to_complex(lower_left, upper_right, row, col, rows, cols);
@@ -69,9 +69,9 @@ void mandelbrot_kernel(size_t* grid_data, const size_t max_iterations, const thr
}
__device__
-size_t tricorn(const thrust::complex<CBASE> z0, const size_t max_iterations){
+byte tricorn(const thrust::complex<CBASE> z0, const byte max_iterations){
thrust::complex<CBASE> z = z0;
- size_t iteration = 0;
+ byte iteration = 0;
while(thrust::abs(z) <= 2 && iteration < max_iterations){
z = thrust::conj(z*z) + z0;
iteration++;
@@ -80,7 +80,7 @@ size_t tricorn(const thrust::complex<CBASE> z0, const size_t max_iterations){
}
__global__
-void tricorn_kernel(size_t* grid_data, const size_t max_iterations, const thrust::complex<CBASE> lower_left, const thrust::complex<CBASE> upper_right, const size_t rows, const size_t cols){
+void tricorn_kernel(byte* grid_data, const byte max_iterations, const thrust::complex<CBASE> lower_left, const thrust::complex<CBASE> upper_right, const size_t rows, const size_t cols){
SET_ROW_COL;
const auto z = grid_to_complex(lower_left, upper_right, row, col, rows, cols);
@@ -89,10 +89,10 @@ void tricorn_kernel(size_t* grid_data, const size_t max_iterations, const thrust
}
__device__
-size_t burning_ship(const thrust::complex<CBASE> z0, const size_t max_iterations){
+byte burning_ship(const thrust::complex<CBASE> z0, const byte max_iterations){
thrust::complex<CBASE> z = z0;
thrust::complex<CBASE> z_mod;
- size_t iteration = 0;
+ byte iteration = 0;
while(thrust::abs(z) <= 2 && iteration < max_iterations){
z_mod = thrust::complex<CBASE>(fabs(z.real()), fabs(z.imag()));
z = z_mod * z_mod + z0;
@@ -102,7 +102,7 @@ size_t burning_ship(const thrust::complex<CBASE> z0, const size_t max_iterations
}
__global__
-void burning_ship_kernel(size_t* grid_data, const size_t max_iterations, const thrust::complex<CBASE> lower_left, const thrust::complex<CBASE> upper_right, const size_t rows, const size_t cols){
+void burning_ship_kernel(byte* grid_data, const byte max_iterations, const thrust::complex<CBASE> lower_left, const thrust::complex<CBASE> upper_right, const size_t rows, const size_t cols){
SET_ROW_COL;
const auto z = grid_to_complex(lower_left, upper_right, row, col, rows, cols);
@@ -111,9 +111,9 @@ void burning_ship_kernel(size_t* grid_data, const size_t max_iterations, const t
}
__device__
-size_t multibrot(const thrust::complex<CBASE> z0, const size_t max_iterations, const double d){
+byte multibrot(const thrust::complex<CBASE> z0, const byte max_iterations, const double d){
thrust::complex<CBASE> z = z0;
- size_t iteration = 0;
+ byte iteration = 0;
while(thrust::abs(z) <= 2 && iteration < max_iterations){
z = thrust::pow(z, d) + z0;
iteration++;
@@ -122,7 +122,7 @@ size_t multibrot(const thrust::complex<CBASE> z0, const size_t max_iterations, c
}
__global__
-void multibrot_kernel(size_t* grid_data, const double degree, const size_t max_iterations, const thrust::complex<CBASE> lower_left, const thrust::complex<CBASE> upper_right, const size_t rows, const size_t cols){
+void multibrot_kernel(byte* grid_data, const double degree, const byte max_iterations, const thrust::complex<CBASE> lower_left, const thrust::complex<CBASE> upper_right, const size_t rows, const size_t cols){
SET_ROW_COL;
const auto z = grid_to_complex(lower_left, upper_right, row, col, rows, cols);
@@ -131,9 +131,9 @@ void multibrot_kernel(size_t* grid_data, const double degree, const size_t max_i
}
__device__
-size_t multicorn(const thrust::complex<CBASE> z0, const size_t max_iterations, const double d){
+byte multicorn(const thrust::complex<CBASE> z0, const byte max_iterations, const double d){
thrust::complex<CBASE> z = z0;
- size_t iteration = 0;
+ byte iteration = 0;
while(thrust::abs(z) <= 2 && iteration < max_iterations){
z = thrust::conj(thrust::pow(z, d)) + z0;
iteration++;
@@ -142,7 +142,7 @@ size_t multicorn(const thrust::complex<CBASE> z0, const size_t max_iterations, c
}
__global__
-void multicorn_kernel(size_t* grid_data, const double degree, const size_t max_iterations, const thrust::complex<CBASE> lower_left, const thrust::complex<CBASE> upper_right, const size_t rows, const size_t cols){
+void multicorn_kernel(byte* grid_data, const double degree, const byte max_iterations, const thrust::complex<CBASE> lower_left, const thrust::complex<CBASE> upper_right, const size_t rows, const size_t cols){
SET_ROW_COL;
const auto z = grid_to_complex(lower_left, upper_right, row, col, rows, cols);
@@ -151,9 +151,9 @@ void multicorn_kernel(size_t* grid_data, const double degree, const size_t max_i
}
__device__
-size_t julia(const thrust::complex<CBASE> z0, const size_t max_iterations, const thrust::complex<CBASE> c, const double R){
+byte julia(const thrust::complex<CBASE> z0, const byte max_iterations, const thrust::complex<CBASE> c, const double R){
thrust::complex<CBASE> z = z0;
- size_t iteration = 0;
+ byte iteration = 0;
while(thrust::abs(z) <= R && iteration < max_iterations){
z = z*z + c;
iteration++;
@@ -162,7 +162,7 @@ size_t julia(const thrust::complex<CBASE> z0, const size_t max_iterations, const
}
__global__
-void julia_kernel(size_t* grid_data, const thrust::complex<CBASE> constant, const double radius, const size_t max_iterations, const thrust::complex<CBASE> lower_left, const thrust::complex<CBASE> upper_right, const size_t rows, const size_t cols){
+void julia_kernel(byte* grid_data, const thrust::complex<CBASE> constant, const double radius, const byte max_iterations, const thrust::complex<CBASE> lower_left, const thrust::complex<CBASE> upper_right, const size_t rows, const size_t cols){
SET_ROW_COL;
const auto z = grid_to_complex(lower_left, upper_right, row, col, rows, cols);
@@ -175,12 +175,12 @@ void mandelbrot_grid(grid_t* grid, const grid_gen_params* params){
const size_t size = grid->size;
const size_t rows = grid->y;
const size_t cols = grid->x;
- const size_t max_iterations = grid->max_iterations;
+ const byte max_iterations = grid->max_iterations;
thrust::complex<CBASE> lower_left(grid->lower_left.re, grid->lower_left.im);
thrust::complex<CBASE> upper_right(grid->upper_right.re, grid->upper_right.im);
- size_t* d_grid_data;
- CHECK(cudaMalloc(&d_grid_data, size*sizeof(size_t)));
+ byte* d_grid_data;
+ CHECK(cudaMalloc(&d_grid_data, size*sizeof(byte)));
//TODO: find good sizes
dim3 block_size(BLOCK_SIZE_X, BLOCK_SIZE_Y);
//dim3 grid_size(0,0);
@@ -188,7 +188,7 @@ void mandelbrot_grid(grid_t* grid, const grid_gen_params* params){
mandelbrot_kernel<<<grid_size, block_size>>>(d_grid_data, max_iterations, lower_left, upper_right, rows, cols);
CHECK(cudaDeviceSynchronize());
- CHECK(cudaMemcpy(grid->data, d_grid_data, size*sizeof(size_t), cudaMemcpyDeviceToHost));
+ CHECK(cudaMemcpy(grid->data, d_grid_data, size*sizeof(byte), cudaMemcpyDeviceToHost));
CHECK(cudaFree(d_grid_data));
CHECK(cudaDeviceReset());
@@ -198,18 +198,18 @@ void tricorn_grid(grid_t* grid, const grid_gen_params* params){
const size_t size = grid->size;
const size_t rows = grid->y;
const size_t cols = grid->x;
- const size_t max_iterations = grid->max_iterations;
+ const byte max_iterations = grid->max_iterations;
thrust::complex<CBASE> lower_left(grid->lower_left.re, grid->lower_left.im);
thrust::complex<CBASE> upper_right(grid->upper_right.re, grid->upper_right.im);
- size_t* d_grid_data;
- CHECK(cudaMalloc(&d_grid_data, size*sizeof(size_t)));
+ byte* d_grid_data;
+ CHECK(cudaMalloc(&d_grid_data, size*sizeof(byte)));
dim3 block_size(BLOCK_SIZE_X, BLOCK_SIZE_Y);
dim3 grid_size((cols + block_size.x - 1) / block_size.x, (rows + block_size.y - 1) / block_size.y);
tricorn_kernel<<<grid_size, block_size>>>(d_grid_data, max_iterations, lower_left, upper_right, rows, cols);
CHECK(cudaDeviceSynchronize());
- CHECK(cudaMemcpy(grid->data, d_grid_data, size*sizeof(size_t), cudaMemcpyDeviceToHost));
+ CHECK(cudaMemcpy(grid->data, d_grid_data, size*sizeof(byte), cudaMemcpyDeviceToHost));
CHECK(cudaFree(d_grid_data));
CHECK(cudaDeviceReset());
@@ -219,18 +219,18 @@ void burning_ship_grid(grid_t* grid, const grid_gen_params* params){
const size_t size = grid->size;
const size_t rows = grid->y;
const size_t cols = grid->x;
- const size_t max_iterations = grid->max_iterations;
+ const byte max_iterations = grid->max_iterations;
thrust::complex<CBASE> lower_left(grid->lower_left.re, grid->lower_left.im);
thrust::complex<CBASE> upper_right(grid->upper_right.re, grid->upper_right.im);
- size_t* d_grid_data;
- CHECK(cudaMalloc(&d_grid_data, size*sizeof(size_t)));
+ byte* d_grid_data;
+ CHECK(cudaMalloc(&d_grid_data, size*sizeof(byte)));
dim3 block_size(BLOCK_SIZE_X, BLOCK_SIZE_Y);
dim3 grid_size((cols + block_size.x - 1) / block_size.x, (rows + block_size.y - 1) / block_size.y);
burning_ship_kernel<<<grid_size, block_size>>>(d_grid_data, max_iterations, lower_left, upper_right, rows, cols);
CHECK(cudaDeviceSynchronize());
- CHECK(cudaMemcpy(grid->data, d_grid_data, size*sizeof(size_t), cudaMemcpyDeviceToHost));
+ CHECK(cudaMemcpy(grid->data, d_grid_data, size*sizeof(byte), cudaMemcpyDeviceToHost));
CHECK(cudaFree(d_grid_data));
CHECK(cudaDeviceReset());
@@ -240,19 +240,19 @@ void multibrot_grid(grid_t* grid, const grid_gen_params* params){
const size_t size = grid->size;
const size_t rows = grid->y;
const size_t cols = grid->x;
- const size_t max_iterations = grid->max_iterations;
+ const byte max_iterations = grid->max_iterations;
const double degree = params->degree;
thrust::complex<CBASE> lower_left(grid->lower_left.re, grid->lower_left.im);
thrust::complex<CBASE> upper_right(grid->upper_right.re, grid->upper_right.im);
- size_t* d_grid_data;
- CHECK(cudaMalloc(&d_grid_data, size*sizeof(size_t)));
+ byte* d_grid_data;
+ CHECK(cudaMalloc(&d_grid_data, size*sizeof(byte)));
dim3 block_size(BLOCK_SIZE_X, BLOCK_SIZE_Y);
dim3 grid_size((cols + block_size.x - 1) / block_size.x, (rows + block_size.y - 1) / block_size.y);
multibrot_kernel<<<grid_size, block_size>>>(d_grid_data, degree, max_iterations, lower_left, upper_right, rows, cols);
CHECK(cudaDeviceSynchronize());
- CHECK(cudaMemcpy(grid->data, d_grid_data, size*sizeof(size_t), cudaMemcpyDeviceToHost));
+ CHECK(cudaMemcpy(grid->data, d_grid_data, size*sizeof(byte), cudaMemcpyDeviceToHost));
CHECK(cudaFree(d_grid_data));
CHECK(cudaDeviceReset());
@@ -262,19 +262,19 @@ void multicorn_grid(grid_t* grid, const grid_gen_params* params){
const size_t size = grid->size;
const size_t rows = grid->y;
const size_t cols = grid->x;
- const size_t max_iterations = grid->max_iterations;
+ const byte max_iterations = grid->max_iterations;
const double degree = params->degree;
thrust::complex<CBASE> lower_left(grid->lower_left.re, grid->lower_left.im);
thrust::complex<CBASE> upper_right(grid->upper_right.re, grid->upper_right.im);
- size_t* d_grid_data;
- CHECK(cudaMalloc(&d_grid_data, size*sizeof(size_t)));
+ byte* d_grid_data;
+ CHECK(cudaMalloc(&d_grid_data, size*sizeof(byte)));
dim3 block_size(BLOCK_SIZE_X, BLOCK_SIZE_Y);
dim3 grid_size((cols + block_size.x - 1) / block_size.x, (rows + block_size.y - 1) / block_size.y);
multicorn_kernel<<<grid_size, block_size>>>(d_grid_data, degree, max_iterations, lower_left, upper_right, rows, cols);
CHECK(cudaDeviceSynchronize());
- CHECK(cudaMemcpy(grid->data, d_grid_data, size*sizeof(size_t), cudaMemcpyDeviceToHost));
+ CHECK(cudaMemcpy(grid->data, d_grid_data, size*sizeof(byte), cudaMemcpyDeviceToHost));
CHECK(cudaFree(d_grid_data));
CHECK(cudaDeviceReset());
@@ -286,18 +286,18 @@ void julia_grid(grid_t* grid, const grid_gen_params* params){
const size_t size = grid->size;
const size_t rows = grid->y;
const size_t cols = grid->x;
- const size_t max_iterations = grid->max_iterations;
+ const byte max_iterations = grid->max_iterations;
thrust::complex<CBASE> lower_left(grid->lower_left.re, grid->lower_left.im);
thrust::complex<CBASE> upper_right(grid->upper_right.re, grid->upper_right.im);
- size_t* d_grid_data;
- CHECK(cudaMalloc(&d_grid_data, size*sizeof(size_t)));
+ byte* d_grid_data;
+ CHECK(cudaMalloc(&d_grid_data, size*sizeof(byte)));
dim3 block_size(BLOCK_SIZE_X, BLOCK_SIZE_Y);
dim3 grid_size((cols + block_size.x - 1) / block_size.x, (rows + block_size.y - 1) / block_size.y);
julia_kernel<<<grid_size, block_size>>>(d_grid_data, constant, radius, max_iterations, lower_left, upper_right, rows, cols);
CHECK(cudaDeviceSynchronize());
- CHECK(cudaMemcpy(grid->data, d_grid_data, size*sizeof(size_t), cudaMemcpyDeviceToHost));
+ CHECK(cudaMemcpy(grid->data, d_grid_data, size*sizeof(byte), cudaMemcpyDeviceToHost));
CHECK(cudaFree(d_grid_data));
CHECK(cudaDeviceReset());
diff --git a/src/fractals.c b/src/fractals.c
index f994265..80fcc18 100644
--- a/src/fractals.c
+++ b/src/fractals.c
@@ -22,32 +22,32 @@ void print_usage(FILE* file, const char* program_name){
void print_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.0+-2.0i)\n"
- " -u, --upper-right <value> Set the upper right corner of the fractal area (default: 2.0+2.0i)\n"
- " -z, --magnification <value> Set the magnification factor (default: 1)\n"
- " -d, --degree <value> Set the degree for fractals that use it (default: 1)\n"
- " -c, --constant <value> Set the constant for fractals that use it (default: 0+0i)\n"
- " -r, --radius <value> Set the radius for fractals that use it (default: 2)\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"
- "\ndegree is mutually exclusive with constant and radius\n"
- "\nExits with a status code of 1 if the program encounters an error, exits with 2 if an argument is incorrect\n");
+ " -i, --iterations <value> the number of iterations (default: 25, max 255)\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.0+-2.0i)\n"
+ " -u, --upper-right <value> Set the upper right corner of the fractal area (default: 2.0+2.0i)\n"
+ " -z, --magnification <value> Set the magnification factor (default: 1)\n"
+ " -d, --degree <value> Set the degree for fractals that use it (default: 1)\n"
+ " -c, --constant <value> Set the constant for fractals that use it (default: 0+0i)\n"
+ " -r, --radius <value> Set the radius for fractals that use it (default: 2)\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"
+ "\ndegree is mutually exclusive with constant and radius\n"
+ "\nExits with a status code of 1 if the program encounters an error, exits with 2 if an argument is incorrect\n");
}
void print_info(const char* program_name){
- #ifdef EXTENDED_PRECISION
+#ifdef EXTENDED_PRECISION
printf("Compiled with long double float precision\n");
- #endif
- #ifndef EXTENDED_PRECISION
+#endif
+#ifndef EXTENDED_PRECISION
printf("%s complied with double float precision\n", program_name);
- #endif
+#endif
}
double time_fractal(fractal_generator generator, grid_t* grid, grid_gen_params* params){
@@ -72,7 +72,7 @@ int main(const int argc, char *argv[]) {
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
//default values
- size_t iterations = 100;
+ byte iterations = 25;
size_t x_res = w.ws_col;
size_t y_res = w.ws_row;
complex_t lower_left = { .re = -2, .im = -2};
@@ -116,12 +116,20 @@ int main(const int argc, char *argv[]) {
{0, 0, 0, 0} // Termination element
};
+ unsigned long temp;
//parse command line arguments
int opt;
while((opt = getopt_long(argc, argv, "i:x:y:l:u:z:d:c:r:o:vphf:", long_options, NULL)) != -1){
switch(opt){
case 'i':
- iterations = strtoull(optarg, NULL, 10);
+ temp = strtoul(optarg, NULL, 10);
+ if(temp > 255){
+ fprintf(stderr, "Iterations above maximum, setting to 255\n");
+ iterations = 255;
+ }
+ else {
+ iterations = temp;
+ }
break;
case 'x':
x_res = strtoull(optarg, NULL, 10);
@@ -256,7 +264,7 @@ int main(const int argc, char *argv[]) {
if(performance){
double time = time_fractal(generator, grid, params);
- printf("%s,%s,%zu,%zu,%zu,"
+ printf("%s,%s,%hhu,%zu,%zu,"
CFORMAT","CFORMAT","CFORMAT","CFORMAT",%f\n",
argv[0], fractal_name, iterations, x_res, y_res,
lower_left.re, lower_left.im, upper_right.re, upper_right.im, time);
@@ -268,22 +276,24 @@ int main(const int argc, char *argv[]) {
print_grid_info(grid);
}
- //use "safer" versions of c string functions
- //likely aren't necessary unless a user can pass non-null terminated strings as arguments, but that would likely break something up in getopt
- if(output_filename[0] == '-' && strnlen(output_filename, 16) == 1){
- if(write_grid(stdout, grid) == GRID_WRITE_ERROR){
- fprintf(stderr, "Error occured while writting to file %s\n", output_filename);
- }
- }
- else {
- FILE* file = fopen(output_filename, "wb");
- if(!file){
- perror("Error occured while trying to write");
+ if(!performance){
+ //uses "safer" versions of c string functions
+ //likely aren't necessary unless a user can pass non-null terminated strings as arguments, but that would likely break something up in getopt
+ if(output_filename[0] == '-' && strnlen(output_filename, 16) == 1){
+ if(write_grid(stdout, grid) == GRID_WRITE_ERROR){
+ fprintf(stderr, "Error occured while writting to file %s\n", output_filename);
+ }
}
- else if(write_grid(file, grid) == GRID_WRITE_ERROR){
- fprintf(stderr, "Error occured while writting to file %s\n", output_filename);
+ else {
+ FILE* file = fopen(output_filename, "wb");
+ if(!file){
+ perror("Error occured while trying to write");
+ }
+ else if(write_grid(file, grid) == GRID_WRITE_ERROR){
+ fprintf(stderr, "Error occured while writting to file %s\n", output_filename);
+ }
+ fclose(file);
}
- fclose(file);
}
free(params);
diff --git a/src/fractals.h b/src/fractals.h
index 1c745d9..b31b15f 100644
--- a/src/fractals.h
+++ b/src/fractals.h
@@ -1,5 +1,6 @@
#pragma once
+#include <stdint.h>
#ifndef __NVCC__
#include <complex.h>
#endif
@@ -18,12 +19,12 @@ typedef union {
typedef void (*fractal_generator)(grid_t* , const grid_gen_params* );
#ifndef __NVCC__
-size_t mandelbrot(const CBASE complex z0, const size_t max_iterations);
-size_t tricorn(const CBASE complex z0, const size_t max_iterations);
-size_t burning_ship(const CBASE complex z0, const size_t max_iterations);
-size_t multibrot(const CBASE complex z0, const size_t max_iterations, const double d);
-size_t multicorn(const CBASE complex z0, 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);
+byte mandelbrot(const CBASE complex z0, const byte max_iterations);
+byte tricorn(const CBASE complex z0, const byte max_iterations);
+byte burning_ship(const CBASE complex z0, const byte max_iterations);
+byte multibrot(const CBASE complex z0, const byte max_iterations, const double d);
+byte multicorn(const CBASE complex z0, const byte max_iterations, const double d);
+byte julia(const CBASE complex z0, const CBASE complex c, const byte max_iterations, const double R);
#endif
#ifdef __cplusplus
diff --git a/src/grids.c b/src/grids.c
index 97bb894..e65ba79 100644
--- a/src/grids.c
+++ b/src/grids.c
@@ -12,11 +12,11 @@ static inline bool equal_complex_t(const complex_t z1, const complex_t z2){
/*
* Creates a grid for storing the results of the escape algorithm
*/
-grid_t* create_grid(const size_t x, const size_t y, const size_t max_iterations, complex_t lower_left, complex_t upper_right){
+grid_t* create_grid(const size_t x, const size_t y, const byte max_iterations, complex_t lower_left, complex_t upper_right){
if(x <= 0 || y <= 0) return NULL;
const size_t size = x * y;
- size_t* data = malloc(size * sizeof(size_t));
+ byte* data = malloc(size);
if(!data){
fprintf(stderr, "Error allocating %zu grid points for grid\n", size);
return NULL;
@@ -46,7 +46,7 @@ grid_t* create_grid(const size_t x, const size_t y, const size_t max_iterations,
/*
* Sets all entries of a grid to the value val
*/
-void set_grid(grid_t* grid, const size_t val){
+void set_grid(grid_t* grid, const byte val){
if(!grid || !grid->data) return;
memset(grid->data, val, grid->size);
}
@@ -93,7 +93,7 @@ bool grid_equal(const grid_t* grid1_p, const grid_t* grid2_p){
/*
* Checks if two grids have a given maximum difference
*/
-bool grid_allclose(const grid_t* restrict grid1, const grid_t* restrict grid2, const size_t max_error){
+bool grid_allclose(const grid_t* restrict grid1, const grid_t* restrict grid2, const byte max_error){
if(grid1->x != grid2->x || grid1->y != grid2->y ||
!equal_complex_t(grid1->lower_left, grid2->lower_left) ||
!equal_complex_t(grid1->upper_right, grid2->upper_right)){
@@ -196,14 +196,14 @@ int write_grid(FILE* restrict file, const grid_t *grid){
if(fwrite(&grid->x, sizeof(size_t), 1, file) != 1 ||
fwrite(&grid->y, sizeof(size_t), 1, file) != 1 ||
- fwrite(&grid->max_iterations, sizeof(size_t), 1, file) != 1 ||
+ fwrite(&grid->max_iterations, sizeof(byte), 1, file) != 1 ||
fwrite(&precision, sizeof(size_t), 1, file) != 1 ||
fwrite(&grid->lower_left, precision, 1, file) != 1 ||
fwrite(&grid->upper_right, precision, 1, file) != 1){
return GRID_WRITE_ERROR;
}
- if(fwrite(grid->data, sizeof(size_t), grid->size, file) != grid->size){
+ if(fwrite(grid->data, 1, grid->size, file) != grid->size){
return GRID_WRITE_ERROR;
}
@@ -223,7 +223,7 @@ 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("Max Iterations\t%zu\n", grid->max_iterations);
+ printf("Max Iterations\t%hhu\n", grid->max_iterations);
printf("lower_left\t"CFORMAT"+ "CFORMAT"I\n", grid->lower_left.re, grid->lower_left.im);
printf("upper_right\t"CFORMAT"+ "CFORMAT"I\n", grid->upper_right.re, grid->upper_right.im);
@@ -236,8 +236,8 @@ void print_grid_info(const grid_t* grid){
void print_grid(FILE* file, const grid_t* grid){
const size_t size = grid->size;
const size_t x_res = grid->x;
- const size_t iterations = grid->max_iterations;
- const size_t* data = grid->data;
+ const byte iterations = grid->max_iterations;
+ const byte* data = grid->data;
//TODO: set values in output buffer rather than multiple printf calls
// the buffer needs to be larger to hold newlines
@@ -306,11 +306,11 @@ grid_t* read_grid(FILE* restrict file){
size_t x = 0;
size_t y = 0;
- size_t max_iterations = 0;
+ byte max_iterations = 0;
size_t precision = 0;
if(fread(&x, sizeof(size_t), 1, file) != 1){ longjmp(file_read_error, 1); }
if(fread(&y, sizeof(size_t), 1, file) != 1){ longjmp(file_read_error, 1); }
- if(fread(&max_iterations, sizeof(size_t), 1, file) != 1){ longjmp(file_read_error, 1); }
+ if(fread(&max_iterations, sizeof(byte), 1, file) != 1){ longjmp(file_read_error, 1); }
if(fread(&precision, sizeof(size_t), 1, file) != 1){ longjmp(file_read_error, 1) ; }
if(precision != sizeof(complex_t)){
@@ -330,7 +330,7 @@ grid_t* read_grid(FILE* restrict file){
return NULL;
}
- read_count = fread(grid->data, sizeof(size_t), grid->size, file);
+ read_count = fread(grid->data, 1, grid->size, file);
if(read_count != grid->size){
fprintf(stderr, "Error reading file, expected %zu grid points but only found %zu\n", grid->size, read_count);
free_grid(grid);
diff --git a/src/grids.h b/src/grids.h
index 293ceb5..6bf96f4 100644
--- a/src/grids.h
+++ b/src/grids.h
@@ -20,22 +20,25 @@ typedef struct {
CBASE im;
} complex_t;
+typedef unsigned char byte;
+
typedef struct {
size_t x;
size_t y;
size_t size;
- size_t max_iterations;
+ byte max_iterations;
complex_t lower_left;
complex_t upper_right;
- size_t* data;
+ byte* data;
} grid_t;
-grid_t* create_grid(const size_t x, const size_t y, const size_t max_iterations, complex_t lower_left, complex_t upper_right);
-void set_grid(grid_t* grid, const size_t val);
+grid_t* create_grid(const size_t x, const size_t y, const byte max_iterations, complex_t lower_left, complex_t upper_right);
+void set_grid(grid_t* grid, const byte val);
grid_t* copy_grid(const grid_t* grid);
void free_grid(grid_t* grid);
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);
+// not useful
+bool grid_allclose(const grid_t* grid1, const grid_t* grid2, const byte max_error);
#ifndef __NVCC__
CBASE complex grid_to_complex(const grid_t* grid, const size_t index);
diff --git a/src/serial-fractals.c b/src/serial-fractals.c
index ee55b3b..fd16b00 100644
--- a/src/serial-fractals.c
+++ b/src/serial-fractals.c
@@ -8,9 +8,9 @@
* if the return value is equal to max_iterations, the point lies within the mandelbrot set
* This is an implementation the escape algorithm
*/
-size_t mandelbrot(const CBASE complex z0, const size_t max_iterations) {
+byte mandelbrot(const CBASE complex z0, const byte max_iterations) {
CBASE complex z = z0;
- size_t iteration = 0;
+ byte iteration = 0;
while (CABS(z) <= 2 && iteration < max_iterations) {
z = z * z + z0;
@@ -24,8 +24,8 @@ size_t mandelbrot(const CBASE complex z0, const size_t max_iterations) {
*/
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;
+ const byte max_iterations = grid->max_iterations;
+ byte* data = grid->data;
for(size_t i = 0; i < size; i++){
data[i] = mandelbrot(grid_to_complex(grid, i), max_iterations);
@@ -37,9 +37,9 @@ void mandelbrot_grid(grid_t* grid, const grid_gen_params* params){
* 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){
+byte tricorn(const CBASE complex z0, const byte max_iterations){
CBASE complex z = z0;
- size_t iteration = 0;
+ byte iteration = 0;
while(CABS(z) <= 2 && iteration < max_iterations){
z = CONJ(z * z) + z0;
iteration++;
@@ -52,8 +52,8 @@ size_t tricorn(const CBASE complex z0, const size_t max_iterations){
*/
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;
+ const byte max_iterations = grid->max_iterations;
+ byte* data = grid->data;
for(size_t i = 0; i < size; i++){
data[i] = tricorn(grid_to_complex(grid, i), max_iterations);
@@ -64,10 +64,10 @@ void tricorn_grid(grid_t* grid, const grid_gen_params* params){
* 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) {
+byte burning_ship(const CBASE complex z0, const byte max_iterations) {
CBASE complex z = z0;
CBASE complex z_mod;
- size_t iteration = 0;
+ byte iteration = 0;
while (CABS(z) <= 2 && iteration < max_iterations) {
z_mod = RABS(CREAL(z)) + RABS(CIMAG(z))*I;
@@ -82,8 +82,8 @@ size_t burning_ship(const CBASE complex z0, const size_t max_iterations) {
*/
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;
+ const byte max_iterations = grid->max_iterations;
+ byte* data = grid->data;
for(size_t i = 0; i < size; i++){
data[i] = burning_ship(grid_to_complex(grid, i), max_iterations);
@@ -95,9 +95,9 @@ void burning_ship_grid(grid_t* grid, const grid_gen_params* params){
* 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.
*/
-size_t multibrot(const CBASE complex z0, const size_t max_iterations, const double d){
+byte multibrot(const CBASE complex z0, const byte max_iterations, const double d){
CBASE complex z = z0;
- size_t iteration = 0;
+ byte iteration = 0;
while(CABS(z) <= 2 && iteration < max_iterations){
z = CPOW(z, d) + z0;
iteration++;
@@ -112,8 +112,8 @@ size_t multibrot(const CBASE complex z0, const size_t max_iterations, const doub
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;
+ const byte max_iterations = grid->max_iterations;
+ byte* data = grid->data;
for(size_t i = 0; i < size; i ++){
data[i] = multibrot(grid_to_complex(grid, i), max_iterations, d);
}
@@ -124,9 +124,9 @@ void multibrot_grid(grid_t* grid, const grid_gen_params* params){
* 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){
+byte multicorn(const CBASE complex z0, const byte max_iterations, const double d){
CBASE complex z = z0;
- size_t iteration = 0;
+ byte iteration = 0;
while(CABS(z) <= 2 && iteration < max_iterations){
z = CONJ(CPOW(z, d)) + z0;
iteration++;
@@ -140,8 +140,8 @@ size_t multicorn(const CBASE complex z0, const size_t max_iterations, const doub
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;
+ const byte max_iterations = grid->max_iterations;
+ byte* data = grid->data;
for(size_t i = 0; i < size; i ++){
data[i] = multicorn(grid_to_complex(grid, i), max_iterations, d);
}
@@ -153,10 +153,10 @@ void multicorn_grid(grid_t* grid, const grid_gen_params* params){
*
* This behaves weirdly, needs a very small number of iterations to be visibile
*/
-size_t julia(const CBASE complex z0, const CBASE complex c, const size_t max_iterations, const double R){
+byte julia(const CBASE complex z0, const CBASE complex c, const byte max_iterations, const double R){
double complex z = z0;
- size_t iteration = 0;
+ byte iteration = 0;
while(CABS(z) < R && iteration < max_iterations){
z = z * z + c;
iteration++;
@@ -168,9 +168,9 @@ 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 byte max_iterations = grid->max_iterations;
const CBASE complex c = constant.re + constant.im * I;
- size_t* data = grid->data;
+ byte* data = grid->data;
for(size_t i = 0; i <size; i++){
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 a45d366..5e54a9a 100644
--- a/src/shared-fractals.c
+++ b/src/shared-fractals.c
@@ -10,9 +10,9 @@
* if the return value is equal to max_iterations, the point lies within the mandelbrot set
* This should be identical to the version found in serial-fractals.c
*/
-size_t mandelbrot(const CBASE complex z0, const size_t max_iterations){
+byte mandelbrot(const CBASE complex z0, const byte max_iterations){
CBASE complex z = z0;
- size_t iteration = 0;
+ byte iteration = 0;
while(CABS(z) <= 2 && iteration < max_iterations){
z = z*z + z0;
iteration++;
@@ -26,8 +26,8 @@ size_t mandelbrot(const CBASE complex z0, const size_t max_iterations){
*/
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;
+ const byte max_iterations = grid->max_iterations;
+ byte* 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++){
@@ -40,9 +40,9 @@ void mandelbrot_grid(grid_t* restrict grid, const grid_gen_params* params){
* 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){
+byte tricorn(const CBASE complex z0, const byte max_iterations){
CBASE complex z = z0;
- size_t iteration = 0;
+ byte iteration = 0;
while(CABS(z) <= 2 && iteration < max_iterations){
z = CONJ(z * z) + z0;
iteration++;
@@ -55,8 +55,8 @@ size_t tricorn(const CBASE complex z0, const size_t max_iterations){
*/
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;
+ const byte max_iterations = grid->max_iterations;
+ byte* 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++){
@@ -68,10 +68,10 @@ void tricorn_grid(grid_t* grid, const grid_gen_params* params){
* 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) {
+byte burning_ship(const CBASE complex z0, const byte max_iterations) {
CBASE complex z = z0;
CBASE complex z_mod;
- size_t iteration = 0;
+ byte iteration = 0;
while (CABS(z) <= 2 && iteration < max_iterations) {
z_mod = RABS(CREAL(z)) + RABS(CIMAG(z))*I;
@@ -86,8 +86,8 @@ size_t burning_ship(const CBASE complex z0, const size_t max_iterations) {
*/
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;
+ const byte max_iterations = grid->max_iterations;
+ byte* 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++){
@@ -100,9 +100,9 @@ void burning_ship_grid(grid_t* grid, const grid_gen_params* params){
* 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
*/
-size_t multibrot(const CBASE complex z0, const size_t max_iterations, const double d){
+byte multibrot(const CBASE complex z0, const byte max_iterations, const double d){
CBASE complex z = z0;
- size_t iteration = 0;
+ byte iteration = 0;
while(CABS(z) <= 2 && iteration < max_iterations){
z = CPOW(z, d) + z0;
iteration++;
@@ -116,8 +116,8 @@ size_t multibrot(const CBASE complex z0, const size_t max_iterations, const doub
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;
+ const byte max_iterations = grid->max_iterations;
+ byte* 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 ++){
@@ -130,9 +130,9 @@ void multibrot_grid(grid_t* restrict grid, const grid_gen_params* params){
* 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){
+byte multicorn(const CBASE complex z0, const byte max_iterations, const double d){
CBASE complex z = z0;
- size_t iteration = 0;
+ byte iteration = 0;
while(CABS(z) <= 2 && iteration < max_iterations){
z = CONJ(CPOW(z, d)) + z0;
iteration++;
@@ -146,8 +146,8 @@ size_t multicorn(const CBASE complex z0, const size_t max_iterations, const doub
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;
+ const byte max_iterations = grid->max_iterations;
+ byte* 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);
@@ -161,10 +161,10 @@ void multicorn_grid(grid_t* grid, const grid_gen_params* params){
* This behaves weirdly, needs a very small number of iterations to be visibile
*/
-size_t julia(const CBASE complex z0, const CBASE complex c, const size_t max_iterations, const double R){
+byte julia(const CBASE complex z0, const CBASE complex c, const byte max_iterations, const double R){
double complex z = z0;
- size_t iteration = 0;
+ byte iteration = 0;
while(CABS(z) < R && iteration < max_iterations){
z = z * z + c;
iteration++;
@@ -176,9 +176,9 @@ 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 byte max_iterations = grid->max_iterations;
const CBASE complex c = constant.re + constant.im * I;
- size_t* data = grid->data;
+ byte* data = grid->data;
#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, radius);