From 705a085abbcc1e580f537a80c9c200aba55ff848 Mon Sep 17 00:00:00 2001 From: Nikola Date: Fri, 3 Jul 2026 16:04:46 +0200 Subject: [PATCH] Maybe improved SIMD --- Implementierung/tricorn_V0.c | 21 ++++++++------ Implementierung/tricorn_V1.c | 54 +++++++++++++++++++++++------------- Implementierung/tricorn_V2.c | 2 +- 3 files changed, 48 insertions(+), 29 deletions(-) diff --git a/Implementierung/tricorn_V0.c b/Implementierung/tricorn_V0.c index 9a1d762..604cbbf 100644 --- a/Implementierung/tricorn_V0.c +++ b/Implementierung/tricorn_V0.c @@ -1,7 +1,7 @@ #include "tricorn_V0.h" #include -static unsigned converge(float c_rea, float c_imag, unsigned n); +static unsigned converge(float c_real, float c_imag, unsigned n); /** @@ -28,15 +28,17 @@ void tricorn_V0(float complex start, size_t width, ssize_t height, float res, un __m128 four = _mm_set1_ps(4.0f); __m128 minus_two = _mm_set1_ps(-2.0f); + float c_imag = c_start_imag; + __m128 c_imag_vector = _mm_set1_ps(c_imag); + + float four_res = 4 * res; + float vertical_step = imag_step * res; + __m128 vertical_step_vector = _mm_set1_ps(vertical_step); + for(ssize_t y = 0; y < actual_height;y++) { - float c_imag = c_start_imag - (y*imag_step) * res; - __m128 c_imag_vector = _mm_set1_ps(c_imag); - size_t x = 0; + __m128 c_real_vector = _mm_setr_ps(c_start_real,c_start_real + 1.0f*res,c_start_real + 2.0f*res, c_start_real + 3.0f*res); for(; x < simd_width;x += 4) { //SIMD Loop - float c_real = c_start_real + (x*res); - __m128 c_real_vector = _mm_setr_ps(c_real,c_real+1.0f*res,c_real+2.0f*res,c_real+3.0f*res); - __m128 real = _mm_setzero_ps(); __m128 imag = _mm_setzero_ps(); __m128i iterations = _mm_setzero_si128(); @@ -86,6 +88,7 @@ void tricorn_V0(float complex start, size_t width, ssize_t height, float res, un img[position + 2] = ((value*5) % 255); } } + c_real_vector = _mm_add_ps(c_real_vector,_mm_set1_ps(four_res)); } for(;x < width; x++) { @@ -102,8 +105,10 @@ void tricorn_V0(float complex start, size_t width, ssize_t height, float res, un img[position + 1] = ((value*2) % 255); img[position + 2] = ((value*5) % 255); } + c_real += res; } - + c_imag -= vertical_step; + c_imag_vector = _mm_sub_ps(c_imag_vector,vertical_step_vector); } } diff --git a/Implementierung/tricorn_V1.c b/Implementierung/tricorn_V1.c index bab8184..88162e5 100644 --- a/Implementierung/tricorn_V1.c +++ b/Implementierung/tricorn_V1.c @@ -1,7 +1,6 @@ #include "tricorn_V1.h" -static const float convergenceLimit = 2.0f; // Mandelbrot set limit -static unsigned converge(float complex position,unsigned n); +static unsigned converge(float c_real, float c_imag, unsigned n); /** @@ -15,20 +14,30 @@ static unsigned converge(float complex position,unsigned n); * @param img Pointer to the pre-allocated memory buffer where the bitmap data will be stored. */ void tricorn_V1(float complex start, size_t width, ssize_t height, float res, unsigned n, _Bool color, unsigned char* img){ + int bytesPerColor = color ? 3 : 1; // Absolute height for iteration purposes - height = height < 0 ? height*-1 : height; - unsigned bytesPerColor = color ? 3 : 1; + ssize_t actual_height = height < 0 ? (ssize_t)(-height) : height; + ssize_t imag_step = height < 0 ? -1:1; + + float c_start_real = creal(start); + float c_start_imag = cimag(start); + + float c_imag = c_start_imag; + size_t position = 0; + // Simple iteration over every pixel in the picture - for(size_t i = 0; i < width; i++){ - for(ssize_t j = 0; j < height; j++){ + for(ssize_t y = 0; y < actual_height; y++){ - unsigned value = converge(start + (i*res - I*j*res),n+1); + // Calculate imaginary part on each row as it stays the same + + float c_real = c_start_real; + + for(size_t x = 0; x < width; x++){ + unsigned value = converge(c_real,c_imag,n); // Pixel value position in the output array - size_t position = (j*width +i) * bytesPerColor; - if(!color){ // Grayscale colors as specified by the assignment r = g = b img[position] = value; @@ -39,24 +48,29 @@ void tricorn_V1(float complex start, size_t width, ssize_t height, float res, un img[position + 2] = ((value*5) % 255); } + position += bytesPerColor; + c_real += res; + } + c_imag -= imag_step * res; } } // Iterative application of the equation given by the assignment -static unsigned converge(float complex position,unsigned n){ +static inline unsigned converge(float c_real, float c_imag, unsigned n) { + float real = 0.0f; + float imag = 0.0f; - complex float result = 0; - for(unsigned i = 0; i < n; i++){ - // Detection of unbounded behaviour - // If the magnitude of the result vector is greater than the convergence limit, we know that the function will grow unbounded - // Current convergence limit taken from mandelbrot set - if(sqrtf(powf (crealf(result),2)+powf(cimagf(result),2)) > convergenceLimit) - return 255-4*(i % 64); + for (unsigned i = 0; i < n; i++) { + float real2 = real * real; + float imag2 = imag * imag; - // Application of the given complex equation with m = 2 - result = cpowf(conjf(result),2) + position; - + if (real2 + imag2 > 4.0f) { + return 255 - 4 * (i % 64); + } + + imag = -2.0f * real * imag + c_imag; + real = real2 - imag2 + c_real; } return 0; } \ No newline at end of file diff --git a/Implementierung/tricorn_V2.c b/Implementierung/tricorn_V2.c index 6017093..909f1f5 100644 --- a/Implementierung/tricorn_V2.c +++ b/Implementierung/tricorn_V2.c @@ -23,7 +23,7 @@ void tricorn_V2(float complex start, size_t width, ssize_t height, float res, un for(size_t i = 0; i < width; i++){ for(ssize_t j = 0; j < height; j++){ - unsigned value = converge(start + (i*res - I*j*res),n+1); + unsigned value = converge(start + (i*res - I*j*res),n); // Pixel value position in the output array size_t position = (j*width +i) * bytesPerColor;