mandelbrot.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #include <stdio.h>
  2. #include <pthread.h>
  3. #include <semaphore.h>
  4. #include <unistd.h>
  5. #include "../libpng/img.h"
  6. #include "config.h"
  7. typedef struct mandel_field_t {
  8. int h, w;
  9. int * arr;
  10. pthread_mutex_t mut;
  11. } mandel_field_t;
  12. typedef struct mandel_t {
  13. int x, y;
  14. int bail_out;
  15. int max_iter;
  16. mandel_field_t field;
  17. } mandel_t;
  18. typedef struct inner {
  19. pthread_mutex_t mut;
  20. } inner;
  21. typedef struct buffer {
  22. sem_t empty;
  23. sem_t full;
  24. pthread_mutex_t mut;
  25. int pos;
  26. mandel_t ** pix;
  27. inner * in;
  28. } buffer;
  29. double map(int value, int min, int max, int map_min, int map_max)
  30. {
  31. double R = (double) (map_max - map_min) / (double) (max - min);
  32. double y = map_min + (value * R) + R;
  33. return y;
  34. }
  35. int mandelbrot_pix(double x, double y, int bail_out, int max_iter)
  36. {
  37. int k;
  38. double real, imaginary, x2, y2;
  39. x2 = x;
  40. y2 = y;
  41. // iterate a^2 - b^2 + 2ab
  42. for (k = 0; k < max_iter; k++) {
  43. // a^2 - b^2
  44. real = x * x - y * y;
  45. // 2ab
  46. imaginary = 2 * x * y;
  47. // x = real + c
  48. x = real + x2;
  49. // y = imaginary + c
  50. y = imaginary +y2;
  51. if ((x * x + y * y) > bail_out) {
  52. return k;
  53. }
  54. }
  55. return max_iter;
  56. }
  57. void init_buffer(buffer * buf)
  58. {
  59. sem_init(&buf->empty, 0, 0);
  60. sem_init(&buf->full, 0, BUFFER_SIZE);
  61. buf->in = malloc(sizeof(inner));
  62. buf->pos = 0;
  63. buf->pix = malloc(sizeof(mandel_t) * BUFFER_SIZE);
  64. for (int i = 0; i < BUFFER_SIZE; i++) {
  65. buf->pix[i] = NULL;
  66. }
  67. }
  68. void mandel_field_setXY(mandel_field_t m, int x, int y, int value){
  69. pthread_mutex_lock(&m.mut);
  70. m.arr[x * m.h + y] = value;
  71. pthread_mutex_unlock(&m.mut);
  72. }
  73. void * mandel_consumer(void *buff)
  74. {
  75. buffer * buf = (buffer *) buff;
  76. mandel_t * pix;
  77. int count = 0;
  78. double xPrime, yPrime;
  79. while(1) {
  80. int tw = sem_trywait(&buf->empty);
  81. if (tw == 0) {
  82. pthread_mutex_lock(&buf->mut);
  83. buf->pos = buf->pos - 1;
  84. pix = buf->pix[buf->pos];
  85. count ++;
  86. sem_post(&buf->full);
  87. xPrime = map(pix->x, 0, pix->field.w, -2, 2);
  88. yPrime = map(pix->y, 0, pix->field.h, -2, 2);
  89. int k = mandelbrot_pix(xPrime, yPrime, pix->bail_out, pix->max_iter);
  90. mandel_field_setXY(pix->field, pix->x, pix->y, k);
  91. pthread_mutex_unlock(&buf->mut);
  92. } else {
  93. int rc = pthread_mutex_trylock(&buf->in->mut);
  94. if (rc == 0){
  95. printf("\ngot lock");
  96. pthread_mutex_unlock(&buf->in->mut);
  97. pthread_exit(NULL);
  98. }
  99. }
  100. }
  101. }
  102. void mandelbrot(int * field, int w, int h, int bail_out, int max_iter,
  103. int thread_count)
  104. {
  105. double xPrime, yPrime;
  106. int x, y, k;
  107. buffer *buf;
  108. buf = malloc(sizeof(buffer));
  109. init_buffer(buf);
  110. pthread_t t[thread_count];
  111. pthread_attr_t attr;
  112. pthread_attr_init(&attr);
  113. pthread_mutex_lock(&buf->in->mut);
  114. for (int i=0;i<thread_count;i++) {
  115. pthread_create(&t[i], &attr, mandel_consumer, buf);
  116. }
  117. for (int i=0; i<w;i++) {
  118. for (int j=0; j<h;j++) {
  119. sem_wait(&buf->full);
  120. pthread_mutex_lock(&buf->mut);
  121. buf->pix[buf->pos] = malloc(sizeof(mandel_t));
  122. buf->pix[buf->pos]->x = i;
  123. buf->pix[buf->pos]->y = j;
  124. buf->pix[buf->pos]->bail_out = bail_out;
  125. buf->pix[buf->pos]->max_iter = max_iter;
  126. buf->pix[buf->pos]->field.arr = field;
  127. buf->pix[buf->pos]->field.h = h;
  128. buf->pix[buf->pos]->field.w = w;
  129. buf->pos += 1;
  130. sem_post(&buf->empty);
  131. pthread_mutex_unlock(&buf->mut);
  132. }
  133. }
  134. pthread_mutex_unlock(&buf->in->mut);
  135. printf("Finished filling the buffer");
  136. for (int i=0;i<thread_count;i++) {
  137. pthread_join(t[i], NULL);
  138. }
  139. free(buf->in);
  140. free(buf->pix);
  141. free(buf);
  142. }
  143. int main(int argc, char **argv)
  144. {
  145. int * pix_field;
  146. pix_field = malloc(WIDTH * HEIGHT * sizeof(int));
  147. printf
  148. ("WIDTH: %d\nHEIGHT %d\nBAIL OUT %d\nMAX ITER %d\nTHREAD COUNT %d",
  149. WIDTH, HEIGHT, BAIL_OUT, MAX_ITER, THREAD_COUNT);
  150. mandelbrot(pix_field, WIDTH, HEIGHT, BAIL_OUT, MAX_ITER,
  151. THREAD_COUNT);
  152. pix_row rows[WIDTH];
  153. pix p;
  154. char filename[30];
  155. image img;
  156. p.r = 200;
  157. p.g = 200;
  158. p.b = 200;
  159. for (int i = 0; i < WIDTH; i++) {
  160. rows[i].p = malloc(HEIGHT * sizeof(pix));
  161. for (int j = 0; j < HEIGHT; j++) {
  162. p.r =
  163. map(pix_field[i * HEIGHT + j], 0, MAX_ITER, 0,
  164. 255);
  165. p.g =
  166. map(pix_field[i * HEIGHT + j], 0, MAX_ITER, 0,
  167. 255);
  168. p.b =
  169. map(pix_field[i * HEIGHT + j], 0, MAX_ITER, 0,
  170. 255);
  171. rows[i].p[j] = p;
  172. }
  173. }
  174. sprintf(filename, "mandel.png");
  175. img = initialize_png("mandelbrot", filename, WIDTH, HEIGHT);
  176. write_image(&img, rows);
  177. finish_image(&img);
  178. for (int i = 0; i < WIDTH; i++) {
  179. free(rows[i].p);
  180. }
  181. free(pix_field);
  182. return (0);
  183. }