mandelbrot.h (2902B)
1 #ifndef MANDELBROT_H 2 #define MANDELBROT_H 3 4 #include <assert.h> 5 #include <inttypes.h> 6 #include <limits.h> 7 #include <stdint.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <unistd.h> 12 13 #include <math.h> 14 15 #include <sys/socket.h> 16 17 /* =========================================================================== 18 */ 19 20 #define LERP(v0, v1, t) (((v0) * (1 - (t))) + ((v1) * (t))) 21 22 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 23 #define MAX(a, b) ((a) > (b) ? (a) : (b)) 24 #define CLAMP(v, v0, v1) MIN(MAX((v), (v0)), (v1)) 25 26 #define ARRLEN(arr) (sizeof (arr) / sizeof (arr)[0]) 27 28 #define FLATIDX(y, width, x) ((y) * (width) + (x)) 29 30 struct render_region { 31 uint32_t xres, yres; 32 uint32_t escape_val; 33 uint32_t max_iters; 34 float x0, y0, x1, y1; // TODO: store in fixed point? 35 }; 36 37 static inline uint32_t 38 pixel(uint8_t r, uint8_t g, uint8_t b, uint8_t a) 39 { 40 return (uint32_t) a << 24 | 41 (uint32_t) r << 16 | 42 (uint32_t) g << 8 | 43 (uint32_t) b; 44 } 45 46 static inline uint32_t 47 render_point(float x, float y, uint32_t max_iters, uint32_t escape_val, float *out) 48 { 49 // z = 0+0i 50 // c = x + i*y 51 // z_i = z_j ^ 2 + c 52 // = (re_j + i * im_j) ^ 2 + (x + i * y) 53 // = ((re_j + i * im_j) * (re_j + i * im_j)) + (x + i * y) 54 // = (re_j^2 + 2 * (re_j * i * im_j) + (i^2 + im_j^2)) + (x + i * y) 55 // = (re_j^2 - im_j^2) + i * (2 * re_j * im_j) + (x + i * y) 56 // = (re_j^2 - im_j^2 + x) + i * ((2 * re_j * im_j) + y) 57 58 float re = 0.0, im = 0.0, abs2 = 0.0, esc2 = (float) escape_val * escape_val; 59 60 uint32_t i = 0; 61 while (abs2 < esc2 && i < max_iters) { 62 float new_re = (re * re) - (im * im) + x; 63 float new_im = (2 * re * im) + y; 64 65 abs2 = (new_re * new_re) + (new_im * new_im); 66 re = new_re; 67 im = new_im; 68 69 i++; 70 } 71 72 *out = abs2; 73 74 return i; 75 } 76 77 static inline void 78 render_region(struct render_region *region, uint32_t *iterbuf, float *abs2buf) 79 { 80 for (uint32_t py = 0; py < region->yres; py++) { 81 float yfrac = ((float) py / region->yres); 82 float y = LERP(region->y0, region->y1, yfrac); 83 84 for (uint32_t px = 0; px < region->xres; px++) { 85 float xfrac = ((float) px / region->xres); 86 float x = LERP(region->x0, region->x1, xfrac); 87 88 float abs2; 89 uint32_t iters = render_point(x, y, region->max_iters, 90 region->escape_val, &abs2); 91 92 iterbuf[FLATIDX(py, region->xres, px)] = iters; 93 abs2buf[FLATIDX(py, region->xres, px)] = abs2; 94 } 95 } 96 } 97 98 static inline size_t 99 sendall(int fd, void *buf, size_t len) 100 { 101 size_t total = 0; 102 do { 103 ssize_t curr = send(fd, (uint8_t *) buf + total, len - total, 0); 104 if (curr <= 0) break; 105 total += curr; 106 } while (total < len); 107 108 return total; 109 } 110 111 static inline size_t 112 recvall(int fd, void *buf, size_t len) 113 { 114 size_t total = 0; 115 do { 116 ssize_t curr = recv(fd, (uint8_t *) buf + total , len - total, 0); 117 if (curr <= 0) break; 118 total += curr; 119 } while (total < len); 120 121 return total; 122 } 123 124 #endif /* MANDELBROT_H */