From: Randy McShandy Date: Fri, 15 Dec 2023 02:29:02 +0000 (-0600) Subject: Huge cleanup to pull things out of main etc, small improvements, etc X-Git-Url: http://git.mcshandy.xyz/gitweb.cgi?a=commitdiff_plain;h=52a4f3cfd3647a34c7e6e6faafbfa0282463a8b8;p=barrow_crawler Huge cleanup to pull things out of main etc, small improvements, etc --- diff --git a/main.c b/main.c index d232420..6efd62d 100755 --- a/main.c +++ b/main.c @@ -1,411 +1,22 @@ -#include -#include #include -#include -#include -#include -#include -#define STB_IMAGE_WRITE_IMPLEMENTATION -#include "stb_image_write.h" - -#define GRID_X 512 -#define GRID_Y GRID_X - -#define SHADOW 0 -#if SHADOW -#define printf(a,...) -#endif - -typedef struct -{ - double v[3][3]; - -} Mat3; - -typedef struct -{ - float a; - float b; -} FVec2; - -typedef struct -{ - int max_iterations; - double diff_a; - double diff_b; - double feed; - double kill; - double delta_t; - - char name[32]; -} RD_Opts; - -typedef struct -{ - RD_Opts opts; - FVec2** source; - FVec2** dest; - int start_x; - int start_y; - int width; - int height; - - pthread_mutex_t* mutex; - pthread_mutex_t worker_mutex; - pthread_cond_t* worker_cond; - pthread_cond_t* boss_cond; - pthread_barrier_t* barrier; - - int* waiting_workers; - int worker_count; - int iterations; - int max_iterations; - int worker_id; -} worker_arg; - -FVec2 ** grid; -FVec2 ** grid_prime; -FVec2 ** grid_temp; -int master_iteration_done; - -// Connectivity increases as time passes (iterations or time delta)? -// Seems we like <1.0 time deltas and higher iterations -// diff values influence tightness, delta between them shouldn't get wider than ~0.5 or narrower than ~0.4 -RD_Opts puffer = -{ - .max_iterations = 1e4, - .diff_a = 0.7f, - .diff_b = 0.3f, - .feed = 0.055f, - .kill = 0.062f, - .delta_t = 1.0f, - - .name = "puffer" -}; - -RD_Opts worms = -{ - .max_iterations = 1e4, - .diff_a = 0.7f, - .diff_b = 0.3f, - .feed = 0.082, - .kill = 0.06f, - .delta_t = 0.6f, - - .name = "worms" -}; - -RD_Opts meiosis = -{ - .max_iterations = 1e4, - .diff_a = 0.7f, - .diff_b = 0.3f, - .feed = 0.0367f, - .kill = 0.0649f, - .delta_t = 1.0f, - - .name = "meiosis" -}; - -const Mat3 laplacian_kernel = -{ - // oh shit - // Sum of all members must balance to 0.0 (or outer members have to do 1.0) - // it looks like any modifications should be on the order of 0.01 or less - // upper value of 22 <> 23 seems to be a good point - .v = { - {0.05f, 0.20f, 0.05f}, - {0.20f, -1.0f, 0.20f}, - {0.05f, 0.20f, 0.05f} - } -}; - -float kernel_sum(Mat3 kernel, Mat3 source) -{ - float result = 0.0f; - - // Convolve kernel at grid[x,y] - for (int ix = 0; ix < 3; ix++) - { - for (int iy = 0; iy < 3; iy++) - { - result += (kernel.v[ix][iy] * source.v[ix][iy]); - } - } - - return result; -} - -float rd_a_prime(FVec2** source_grid, RD_Opts opts, int x, int y, Mat3 kernel, float A, float B) -{ - float a_prime = 1.0f; - int x_less = (x-1 < 0) ? x : x-1; - int y_less = (y-1 < 0) ? y : y-1; - int x_more = (x+1 == GRID_X) ? x : x+1; - int y_more = (y+1 == GRID_Y) ? y : y+1; - // Use species A in the convolution, b_prime will need B - // For now we won't iterate over edge rows and columns to avoid special case vomit - Mat3 source = - { - .v = - { - {grid[x_less][y_less].a, grid[x][y_less].a, grid[x_more][y_less].a}, - {grid[x_less][y+0].a, grid[x][y+0].a, grid[x_more][y+0].a}, - {grid[x_less][y_more].a, grid[x][y_more].a, grid[x_more][y_more].a}, - } - }; - - a_prime = A + (opts.diff_a*(kernel_sum(kernel, source)) - (A*B*B) + opts.feed*(1.0f-A)) * opts.delta_t; - return a_prime; -} - -float rd_b_prime(FVec2** source_grid, RD_Opts opts, int x, int y, Mat3 kernel, float A, float B) -{ - float b_prime = 1.0f; - int x_less = (x-1 < 0) ? x : x-1; - int y_less = (y-1 < 0) ? y : y-1; - int x_more = (x+1 == GRID_X) ? x : x+1; - int y_more = (y+1 == GRID_Y) ? y : y+1; - // Use species A in the convolution, b_prime will need B - Mat3 source = - { - .v = - { - {grid[x_less][y_less].b, grid[x][y_less].b, grid[x_more][y_less].b}, - {grid[x_less][y+0].b, grid[x][y+0].b, grid[x_more][y+0].b}, - {grid[x_less][y_more].b, grid[x][y_more].b, grid[x_more][y_more].b}, - } - }; - - b_prime = B + (opts.diff_b*(kernel_sum(kernel, source)) + A*(B*B) - (opts.kill + opts.feed)*B) * opts.delta_t; - return b_prime; -} - -void* iterator(void* _arg) -{ - worker_arg* warg = (worker_arg*)_arg; - RD_Opts opts = warg->opts; - int start_x = warg->start_x; - int start_y = warg->start_y; - int w = warg->width; - int h = warg->height; - - for (warg->iterations = 0; warg->iterations < warg->max_iterations; warg->iterations++) - { - printf("worker %d: work unit %d/%d\n", warg->worker_id, warg->iterations, warg->max_iterations); - for (int x = start_x; x < w + start_x && x < GRID_X; x++) - { - for (int y = start_y; y < h + start_y && y < GRID_Y; y++) - { - FVec2 each = grid[x][y]; - grid_prime[x][y].a = rd_a_prime(grid, opts, x, y, laplacian_kernel, each.a, each.b); - grid_prime[x][y].b = rd_b_prime(grid, opts, x, y, laplacian_kernel, each.a, each.b); - } - } - - pthread_mutex_lock(warg->mutex); - if (++*warg->waiting_workers == warg->worker_count) - { - grid_temp = grid; - grid = grid_prime; - grid_prime = grid_temp; - *warg->waiting_workers = 0; - printf("worker-boss %d: completing report\n", warg->worker_id); - if ((warg->iterations % 100 == 0)) - { - char buffer[GRID_X][GRID_Y]; - for (int x = 0; x < GRID_X; x++) - { - for (int y = 0; y < GRID_Y; y++) - { - buffer[x][y] = (uint8_t)(255.0f * grid[x][y].a); - } - } - char name[64] = {0}; - sprintf(name, "img/%s/%d.png", opts.name, warg->iterations); - stbi_write_png(name, GRID_X, GRID_Y, 1, buffer, GRID_X * sizeof(uint8_t)); - } - } - pthread_mutex_unlock(warg->mutex); - - pthread_barrier_wait(warg->barrier); - -#if 0 - // Last one done should wake up the boss thread - int last_worker = 0; - pthread_mutex_lock(warg->mutex); - if (++*warg->waiting_workers == warg->worker_count) - { - last_worker = 1; - } - pthread_mutex_unlock(warg->mutex); - - if (last_worker == 0) - { - pthread_cond_wait(warg->worker_cond, &warg->worker_mutex); - } - else - { - grid_temp = grid; - grid = grid_prime; - grid_prime = grid_temp; - - // segfault somewhere in here lmao - if ((warg->iterations % 100 == 0)) - { - char buffer[GRID_X][GRID_Y]; - for (int x = 0; x < GRID_X; x++) - { - for (int y = 0; y < GRID_Y; y++) - { - buffer[x][y] = (uint8_t)(255.0f * grid[x][y].a); - } - } - char name[64] = {0}; - sprintf(name, "img/%s/%d.png", opts.name, warg->iterations); - stbi_write_png(name, GRID_X, GRID_Y, 1, buffer, GRID_X * sizeof(uint8_t)); - } - printf("worker-boss %d: completing report\n", warg->worker_id); - - *warg->waiting_workers = 0; - pthread_cond_broadcast(warg->worker_cond); - } -#endif - } - - printf("worker %d: exiting\n", warg->worker_id); - return _arg; -} - -void* iterator_old(void* _arg) -{ - worker_arg* warg = (worker_arg*)_arg; - RD_Opts opts = warg->opts; - int start_x = warg->start_x; - int start_y = warg->start_y; - int w = warg->width; - int h = warg->height; - - for (int iterations = 0; iterations < warg->max_iterations; iterations++) - { - printf("worker %d: work unit %d/%d\n", warg->worker_id, iterations, warg->max_iterations); - for (int x = start_x; x < w + start_x; x++) - { - for (int y = start_y; y < h + start_y; y++) - { - FVec2 each = grid[x][y]; - grid_prime[x][y].a = rd_a_prime(grid, opts, x, y, laplacian_kernel, each.a, each.b); - grid_prime[x][y].b = rd_b_prime(grid, opts, x, y, laplacian_kernel, each.a, each.b); - } - } - - // Last one done should wake up the boss thread - pthread_mutex_lock(warg->mutex); - ++*warg->waiting_workers; - if (*warg->waiting_workers == warg->worker_count) - { - printf("worker %d: waking up boss\n", warg->worker_id); - pthread_cond_signal(warg->boss_cond); - } - pthread_mutex_unlock(warg->mutex); - - pthread_cond_wait(warg->worker_cond, &warg->worker_mutex); - - } - - printf("worker %d: exiting\n", warg->worker_id); - return _arg; -} +#include "structs.h" int main(int argc, char** argv) { - char chars[6] = {' ', ' ', ' ', '+', '#', '@'}; - const int max_chars = sizeof(chars) / sizeof(chars[0]) - 1; - - grid = (FVec2**)malloc(GRID_X * sizeof(FVec2*)); - for (int n = 0; n < GRID_X; n++) - { - grid[n] = (FVec2*)malloc(GRID_Y * sizeof(FVec2)); - } - - grid_prime = (FVec2**)malloc(GRID_X * sizeof(FVec2*)); - for (int n = 0; n < GRID_X; n++) - { - grid_prime[n] = (FVec2*)malloc(GRID_Y * sizeof(FVec2)); - } - - srand(time(NULL)); - - RD_Opts opts = puffer; - - for (int x = 0; x < GRID_X; x++) - { - for (int y = 0; y < GRID_Y; y++) - { - grid[x][y].a = 1.0f; - grid[x][y].b = 0.0f; - } - } - const int max_rand = sqrt(GRID_X); - for (int n = 0; n < max_rand; n++) + RD_Opts meiosis_2 = { - grid[rand() % GRID_X][rand() % GRID_Y].b = 1.0f; - } + .max_iterations = 1e4, + .diff_a = 0.8f, + .diff_b = 0.4f, + .feed = 0.0367f, + .kill = 0.0649f, + .delta_t = 1.0f, - int waiting_workers = 0; - worker_arg warg = { - opts, grid, grid_prime, 0, 0, (GRID_X), (GRID_Y), .worker_count = 8, .waiting_workers = &waiting_workers, .max_iterations = 1e4, + .name = "meiosis_2" }; - pthread_t threads[warg.worker_count]; - pthread_mutex_t mutex; - pthread_cond_t worker_cond; - pthread_cond_t boss_cond; - pthread_barrier_t barrier; - - pthread_mutex_init(&mutex, NULL); - pthread_cond_init(&worker_cond, NULL); - pthread_cond_init(&boss_cond, NULL); - pthread_barrier_init(&barrier, NULL, warg.worker_count); - - warg.worker_cond = &worker_cond; - warg.boss_cond = &boss_cond; - warg.mutex = &mutex; - warg.barrier = &barrier; - - worker_arg wargs[warg.worker_count]; - - for (int t = 0; t < warg.worker_count; t++) - { - wargs[t] = warg; - wargs[t].worker_id = t; - wargs[t].width = (GRID_X/warg.worker_count) + ((t == warg.worker_count-1) ? 0 : 4); - wargs[t].start_x = (wargs[t].width * t); - pthread_mutex_init(&wargs[t].worker_mutex, NULL); - printf("worker %d x_span %d, %d\n", t, wargs[t].start_x, wargs[t].width); - pthread_create(&threads[t], NULL, iterator, &wargs[t]); - } - - int should_quit = 0; - while(!should_quit) - { - pthread_mutex_lock(warg.mutex); - if (wargs[0].iterations == wargs[0].max_iterations-1) - should_quit = 1; - pthread_mutex_unlock(warg.mutex); - } - - printf("boss: exiting loop\n"); - for (int t = 0; t < warg.worker_count; t++) - { - pthread_join(threads[t], NULL); - } - - printf("Opts: {\nIterations: %d\nTime delta: %f\nDiffA: %f\nDiffB: %f\nFeed: %f\nKill: %f\n\n}\n", wargs[0].max_iterations, opts.delta_t, opts.diff_a, opts.diff_b, opts.feed, opts.kill); - // It's end of execution, who cares - free(grid); - free(grid_prime); + generate_rd(4, puffer); return 0; } diff --git a/structs.c b/structs.c new file mode 100644 index 0000000..fa2591f --- /dev/null +++ b/structs.c @@ -0,0 +1,57 @@ +#include "structs.h" + +// Connectivity increases as time passes (iterations or time delta)? +// Seems we like <1.0 time deltas and higher iterations +// diff values influence tightness, delta between them shouldn't get wider than ~0.5 or narrower than ~0.4 +RD_Opts puffer = +{ + .max_iterations = 1e4, + .diff_a = 0.8f, + .diff_b = 0.3f, + .feed = 0.055f, + .kill = 0.062f, + .delta_t = 0.6f, + + .name = "puffer" +}; + +RD_Opts worms = +{ + .max_iterations = 1e4, + .diff_a = 0.7f, + .diff_b = 0.3f, + .feed = 0.082, + .kill = 0.06f, + .delta_t = 0.6f, + + .name = "worms" +}; + +RD_Opts meiosis = +{ + .max_iterations = 1e4, + .diff_a = 0.7f, + .diff_b = 0.3f, + .feed = 0.0367f, + .kill = 0.0649f, + .delta_t = 1.0f, + + .name = "meiosis" +}; + +const Mat3 laplacian_kernel = +{ + // oh shit + // Sum of all members must balance to 0.0 (or outer members have to do 1.0) + // it looks like any modifications should be on the order of 0.01 or less + // upper value of 22 <> 23 seems to be a good point + .v = { + {0.05f, 0.20f, 0.05f}, + {0.20f, -1.0f, 0.20f}, + {0.05f, 0.20f, 0.05f} + } +}; + +const char chars[6] = {' ', ' ', ' ', '+', '#', '@'}; +const int max_chars = sizeof(chars) / sizeof(chars[0]) - 1; + diff --git a/structs.h b/structs.h index c10ed09..50153bb 100644 --- a/structs.h +++ b/structs.h @@ -1,24 +1,56 @@ -#define GRID_X 256 -#define GRID_Y 256 +#ifndef __RD_STRUCTS__ +#define __RD_STRUCTS__ + +#include + +#define GRID_X 128 +#define GRID_Y GRID_X typedef struct { - float v[3][3]; + double v[3][3]; } Mat3; typedef struct { - float a; - float b; + float a; + float b; } FVec2; typedef struct { - float diff_a; - float diff_b; - float feed; - float kill; - float delta_t; + int max_iterations; + double diff_a; + double diff_b; + double feed; + double kill; + double delta_t; + + char name[32]; } RD_Opts; +typedef struct +{ + RD_Opts opts; + FVec2** source; + FVec2** dest; + int start_x; + int start_y; + int width; + int height; + + int worker_count; + int iterations; + int max_iterations; + int worker_id; +} worker_arg; + +extern RD_Opts puffer; +extern RD_Opts worms; +extern RD_Opts meiosis; +extern const Mat3 laplacian_kernel; + +int generate_rd(int worker_count, RD_Opts opts); +#endif //__RD_STRUCTS__ + diff --git a/utils.c b/utils.c index b20db76..28664a1 100644 --- a/utils.c +++ b/utils.c @@ -1,60 +1,227 @@ +#include +#include +#include +#include #include "structs.h" +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" -FVec2 grid[GRID_X][GRID_Y]; -FVec2 grid_prime[GRID_X][GRID_Y]; +#define SHADOW 0 +#if SHADOW +#define printf(a,...) +#endif -float convolve(Mat3 kernel, Mat3 source) -{ - float result = 0.0f; - - // Convolve kernel at grid[x,y] - for (int ix = 0; ix < 3; ix++) - { - for (int iy = 0; iy < 3; iy++) - { - result += (kernel.v[ix][iy] * source.v[ix][iy]); - } +worker_arg warg; +int waiting_workers = 0; +int should_quit = 0; + +pthread_t* threads; +pthread_mutex_t mutex; +pthread_barrier_t barrier; + +FVec2 ** grid; +FVec2 ** grid_prime; +FVec2 ** grid_temp; + +float kernel_sum(Mat3 kernel, Mat3 source) { + float result = 0.0f; + + // Convolve kernel at grid[x,y] + for (int ix = 0; ix < 3; ix++) { + for (int iy = 0; iy < 3; iy++) { + result += (kernel.v[ix][iy] * source.v[ix][iy]); } + } + + return result; +} + +float rd_a_prime(FVec2 **source_grid, RD_Opts opts, int x, int y, Mat3 kernel, + float A, float B) { + float a_prime = 1.0f; + int x_less = (x - 1 < 0) ? x : x - 1; + int y_less = (y - 1 < 0) ? y : y - 1; + int x_more = (x + 1 == GRID_X) ? x : x + 1; + int y_more = (y + 1 == GRID_Y) ? y : y + 1; + + // Use species A in the convolution, b_prime will need B + // For now we won't iterate over edge rows and columns to avoid special case + // vomit + Mat3 source = { + .v = { + {grid[x_less][y_less].a, grid[x][y_less].a, grid[x_more][y_less].a}, + {grid[x_less][y + 0].a, grid[x][y + 0].a, grid[x_more][y + 0].a}, + {grid[x_less][y_more].a, grid[x][y_more].a, grid[x_more][y_more].a}, + }}; + + a_prime = A + (opts.diff_a * (kernel_sum(kernel, source)) - (A * B * B) + + opts.feed * (1.0f - A)) * + opts.delta_t; + return a_prime; +} + +float rd_b_prime(FVec2** source_grid, RD_Opts opts, int x, int y, Mat3 kernel, float A, float B) +{ + float b_prime = 1.0f; + int x_less = (x-1 < 0) ? x : x-1; + int y_less = (y-1 < 0) ? y : y-1; + int x_more = (x+1 == GRID_X) ? x : x+1; + int y_more = (y+1 == GRID_Y) ? y : y+1; + + // Use species A in the convolution, b_prime will need B + Mat3 source = + { + .v = + { + {grid[x_less][y_less].b, grid[x][y_less].b, grid[x_more][y_less].b}, + {grid[x_less][y+0].b, grid[x][y+0].b, grid[x_more][y+0].b}, + {grid[x_less][y_more].b, grid[x][y_more].b, grid[x_more][y_more].b}, + } + }; + + b_prime = B + (opts.diff_b*(kernel_sum(kernel, source)) + A*(B*B) - (opts.kill + opts.feed)*B) * opts.delta_t; + return b_prime; +} + +void* iterator(void* _arg) +{ + worker_arg* warg = (worker_arg*)_arg; + RD_Opts opts = warg->opts; + int start_x = warg->start_x; + int start_y = warg->start_y; + int w = warg->width; + int h = warg->height; + + for (warg->iterations = 0; warg->iterations < warg->max_iterations; warg->iterations++) + { + printf("worker %d: work unit %d/%d\n", warg->worker_id, warg->iterations, warg->max_iterations); + for (int x = start_x; x < w + start_x && x < GRID_X; x++) + { + for (int y = start_y; y < h + start_y && y < GRID_Y; y++) + { + FVec2 each = grid[x][y]; + grid_prime[x][y].a = rd_a_prime(grid, opts, x, y, laplacian_kernel, each.a, each.b); + grid_prime[x][y].b = rd_b_prime(grid, opts, x, y, laplacian_kernel, each.a, each.b); + } + } - return result; + pthread_mutex_lock(&mutex); + if (++waiting_workers == warg->worker_count) + { + grid_temp = grid; + grid = grid_prime; + grid_prime = grid_temp; + waiting_workers = 0; + printf("worker-boss %d: completing report\n", warg->worker_id); + if ((warg->iterations % 100 == 0)) + { + char buffer[GRID_X][GRID_Y]; + for (int x = 0; x < GRID_X; x++) + { + for (int y = 0; y < GRID_Y; y++) + { + buffer[x][y] = (uint8_t)(255.0f * grid[x][y].a); + } + } + char name[64] = {0}; + sprintf(name, "img/%s/%d.png", opts.name, warg->iterations); + stbi_write_png(name, GRID_X, GRID_Y, 1, buffer, GRID_X * sizeof(uint8_t)); + } + } + pthread_mutex_unlock(&mutex); + pthread_barrier_wait(&barrier); + + } + + // One last synchronization so boss thread doesn't die early + pthread_barrier_wait(&barrier); + should_quit = 1; + + printf("worker %d: exiting\n", warg->worker_id); + return _arg; } -float rd_a_prime(RD_Opts opts, int x, int y, Mat3 kernel, float A, float B) +int initialize(int worker_count, RD_Opts active_opt) { - float a_prime = 1.0f; - // Use species A in the convolution, b_prime will need B - // For now we won't iterate over edge rows and columns to avoid special case vomit - Mat3 source = - { - .v = - { - {grid[x-1][y-1].a, grid[x][y-1].a, grid[x+1][y-1].a}, - {grid[x-1][y+0].a, grid[x][y+0].a, grid[x+1][y+0].a}, - {grid[x-1][y+1].a, grid[x][y+1].a, grid[x+1][y+1].a}, - } - }; - - a_prime = A + (opts.diff_a*(convolve(kernel, source)) - (A*B*B) + opts.feed*(1.0f-A)) * opts.delta_t; - - return a_prime; + grid = (FVec2**)malloc(GRID_X * sizeof(FVec2*)); + for (int n = 0; n < GRID_X; n++) + { + grid[n] = (FVec2*)malloc(GRID_Y * sizeof(FVec2)); + } + + grid_prime = (FVec2**)malloc(GRID_X * sizeof(FVec2*)); + for (int n = 0; n < GRID_X; n++) + { + grid_prime[n] = (FVec2*)malloc(GRID_Y * sizeof(FVec2)); + } + + srand(time(NULL)); + + for (int x = 0; x < GRID_X; x++) + { + for (int y = 0; y < GRID_Y; y++) + { + grid[x][y].a = 1.0f; + grid[x][y].b = 0.0f; + } + } + + const int max_rand = sqrt(GRID_X); + for (int n = 0; n < max_rand; n++) + { + grid[rand() % GRID_X][rand() % GRID_Y].b = 1.0f; + } + + warg = (worker_arg){ + active_opt, grid, grid_prime, + 0, 0, (GRID_X), (GRID_Y), + .worker_count = worker_count, + .max_iterations = active_opt.max_iterations + }; + + threads = (pthread_t*)malloc(sizeof(pthread_t) * worker_count); + pthread_mutex_init(&mutex, NULL); + pthread_barrier_init(&barrier, NULL, warg.worker_count); + + worker_arg wargs[worker_count]; + + for (int t = 0; t < warg.worker_count; t++) + { + wargs[t] = warg; + wargs[t].worker_id = t; + wargs[t].width = (GRID_X/worker_count) + ((t == worker_count-1) ? 0 : 4); + wargs[t].start_x = (wargs[t].width * t); + printf("worker %d x_span %d, %d\n", t, wargs[t].start_x, wargs[t].width); + pthread_create(&threads[t], NULL, iterator, &wargs[t]); + } + return 0; } -float rd_b_prime(RD_Opts opts, int x, int y, Mat3 kernel, float A, float B) +int cleanup() { - float b_prime = 1.0f; - // Use species A in the convolution, b_prime will need B - Mat3 source = - { - .v = - { - {grid[x-1][y-1].b, grid[x][y-1].b, grid[x+1][y-1].b}, - {grid[x-1][y+0].b, grid[x][y+0].b, grid[x+1][y+0].b}, - {grid[x-1][y+1].b, grid[x][y+1].b, grid[x+1][y+1].b}, - } - }; - - b_prime = B + (opts.diff_b*(convolve(kernel, source)) + A*(B*B) - (opts.kill + opts.feed)*B) * opts.delta_t; - - return b_prime; + printf("boss: exiting loop\n"); + for (int t = 0; t < warg.worker_count; t++) + { + pthread_join(threads[t], NULL); + } + + free(grid); + free(grid_prime); + free(threads); + + return 0; +} + +int generate_rd(int worker_count, RD_Opts active_opt) +{ + initialize(worker_count, active_opt); + + // Would be smart to set up a semaphore and move per-workload processing here + while(!should_quit) {} + + printf("Opts: {\nIterations: %d\nTime delta: %f\nDiffA: %f\nDiffB: %f\nFeed: %f\nKill: %f\n\n}\n", active_opt.max_iterations, active_opt.delta_t, active_opt.diff_a, active_opt.diff_b, active_opt.feed, active_opt.kill); + + cleanup(); + return 0; } diff --git a/utils.h b/utils.h deleted file mode 100644 index 8121a81..0000000 --- a/utils.h +++ /dev/null @@ -1,8 +0,0 @@ - -float convolve(Mat3 kernel, Mat3 source); -float rd_a_prime(RD_Opts opts, int x, int y, Mat3 kernel, float A, float B); -float rd_b_prime(RD_Opts opts, int x, int y, Mat3 kernel, float A, float B); - -extern FVec2 grid[GRID_X][GRID_Y]; -extern FVec2 grid_prime[GRID_X][GRID_Y]; -