summaryrefslogtreecommitdiff
path: root/julia/julia.cu
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2024-11-27 13:41:09 -0800
committer3gg <3gg@shellblade.net>2024-11-27 13:41:09 -0800
commitc8be8496c8a15d0ede8338939a7512109b8e5e46 (patch)
tree1e60112652e9f3c3a20e6bf4cc0b8bef0ebc81fd /julia/julia.cu
Initial commit.
Diffstat (limited to 'julia/julia.cu')
-rw-r--r--julia/julia.cu108
1 files changed, 108 insertions, 0 deletions
diff --git a/julia/julia.cu b/julia/julia.cu
new file mode 100644
index 0000000..f3ecb80
--- /dev/null
+++ b/julia/julia.cu
@@ -0,0 +1,108 @@
1#include <cstdint>
2#include <cstdio>
3#include <cstdlib>
4
5struct Pixel {
6 uint8_t r, g, b;
7};
8
9struct Complex {
10 float r, i;
11
12 __device__ float norm2() const { return r * r + i * i; }
13};
14
15__device__ Complex operator*(Complex a, Complex b) {
16 return Complex{(a.r * b.r) - (a.i * b.i), (a.i * b.r) + (a.r * b.i)};
17}
18
19__device__ Complex operator+(Complex a, Complex b) {
20 return Complex{a.r + b.r, a.i + b.i};
21}
22
23__device__ int julia(int width, int height, int x, int y) {
24 constexpr float scale = 1.5;
25 constexpr int N = 200;
26
27 const float jx = scale * (width / 2 - x) / (width / 2);
28 const float jy = scale * (height / 2 - y) / (height / 2);
29
30 const Complex c{-0.8, 0.156};
31 Complex a{jx, jy};
32
33 for (int i = 0; i < N; ++i) {
34 a = a * a + c;
35 if (a.norm2() > 1000) {
36 return 0;
37 }
38 }
39 return 1;
40}
41
42__global__ void juliaMain(int width, int height, Pixel* image) {
43 const int x = blockIdx.x;
44 const int y = blockIdx.y;
45
46 constexpr Pixel background{41, 95, 152};
47 constexpr Pixel juliaColour{228, 192, 135};
48
49 const Pixel pixel =
50 julia(width, height, x, y) == 1 ? juliaColour : background;
51
52 image[y * width + x] = pixel;
53}
54
55bool write_pbm(const Pixel* image, int width, int height, const char* path) {
56 const size_t num_pixels = width * height;
57
58 FILE* file = fopen(path, "wb");
59 if (!file) {
60 return false;
61 }
62
63 fprintf(file, "P6\n%d %d\n255\n", width, height);
64 if (fwrite(image, sizeof(Pixel), num_pixels, file) != num_pixels) {
65 fclose(file);
66 return false;
67 }
68
69 fclose(file);
70 return true;
71}
72
73int main(int argc, const char** argv) {
74 const int width = argc > 1 ? atoi(argv[1]) : 1920;
75 const int height = argc > 2 ? atoi(argv[2]) : 1080;
76
77 bool success = false;
78
79 const dim3 dim(width, height);
80 const int image_size_bytes = width * height * sizeof(Pixel);
81 auto image_host = new Pixel[width * height];
82 Pixel* image_dev = nullptr;
83
84 if (cudaMalloc(&image_dev, image_size_bytes) != cudaSuccess) {
85 goto cleanup;
86 }
87
88 juliaMain<<<dim, 1>>>(width, height, image_dev);
89
90 if (cudaMemcpy(
91 image_host, image_dev, image_size_bytes, cudaMemcpyDeviceToHost) !=
92 cudaSuccess) {
93 goto cleanup;
94 }
95
96 if (!write_pbm(image_host, width, height, "julia.pbm")) {
97 goto cleanup;
98 }
99
100 success = true;
101
102cleanup:
103 delete[] image_host;
104 if (image_dev) {
105 cudaFree(image_dev);
106 }
107 return success ? 0 : 1;
108}