ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
sse2/luminance.c
Go to the documentation of this file.
3#include <string.h>
4#include <immintrin.h>
6
7int glyph_shape_correlation_sse2(const int16_t samples[16], const int16_t mask[16]) {
8 __m128i a0 = _mm_loadu_si128((const __m128i *)(const void *)samples);
9 __m128i a1 = _mm_loadu_si128((const __m128i *)(const void *)(samples + 8));
10 __m128i b0 = _mm_loadu_si128((const __m128i *)(const void *)mask);
11 __m128i b1 = _mm_loadu_si128((const __m128i *)(const void *)(mask + 8));
12 __m128i sums = _mm_add_epi32(_mm_madd_epi16(a0, b0), _mm_madd_epi16(a1, b1));
13 int32_t lanes[4];
14 _mm_storeu_si128((__m128i *)(void *)lanes, sums);
15 return lanes[0] + lanes[1] + lanes[2] + lanes[3];
16}
17void simd_luminance_sse2(const uint8_t *rgb, uint8_t *out, size_t width) {
18 const rgb_pixel_t *row = (const rgb_pixel_t *)rgb;
19 size_t x = 0;
20 for (; width - x >= 16; x += 16) {
21 // Manual deinterleave RGB components (SSE2 limitation vs NEON's vld3q_u8)
22 uint8_t r_array[16], g_array[16], b_array[16];
23 for (int j = 0; j < 16; j++) {
24 r_array[j] = row[x + j].r;
25 g_array[j] = row[x + j].g;
26 b_array[j] = row[x + j].b;
27 }
28
29 // Load full 16 bytes into SSE2 registers (process in two 8-pixel batches)
30 __m128i r_vec_lo = _mm_loadl_epi64((__m128i *)(r_array + 0)); // First 8 pixels
31 __m128i r_vec_hi = _mm_loadl_epi64((__m128i *)(r_array + 8)); // Second 8 pixels
32 __m128i g_vec_lo = _mm_loadl_epi64((__m128i *)(g_array + 0));
33 __m128i g_vec_hi = _mm_loadl_epi64((__m128i *)(g_array + 8));
34 __m128i b_vec_lo = _mm_loadl_epi64((__m128i *)(b_array + 0));
35 __m128i b_vec_hi = _mm_loadl_epi64((__m128i *)(b_array + 8));
36
37 // Process first 8 pixels
38 __m128i r_16_lo = _mm_unpacklo_epi8(r_vec_lo, _mm_setzero_si128());
39 __m128i g_16_lo = _mm_unpacklo_epi8(g_vec_lo, _mm_setzero_si128());
40 __m128i b_16_lo = _mm_unpacklo_epi8(b_vec_lo, _mm_setzero_si128());
41
42 __m128i luma_r_lo = _mm_mullo_epi16(r_16_lo, _mm_set1_epi16(LUMA_RED));
43 __m128i luma_g_lo = _mm_mullo_epi16(g_16_lo, _mm_set1_epi16(150));
44 __m128i luma_b_lo = _mm_mullo_epi16(b_16_lo, _mm_set1_epi16(29));
45
46 __m128i luma_sum_lo = _mm_add_epi16(luma_r_lo, luma_g_lo);
47 luma_sum_lo = _mm_add_epi16(luma_sum_lo, luma_b_lo);
48 luma_sum_lo = _mm_add_epi16(luma_sum_lo, _mm_set1_epi16(128));
49 luma_sum_lo = _mm_srli_epi16(luma_sum_lo, 8);
50
51 // Process second 8 pixels
52 __m128i r_16_hi = _mm_unpacklo_epi8(r_vec_hi, _mm_setzero_si128());
53 __m128i g_16_hi = _mm_unpacklo_epi8(g_vec_hi, _mm_setzero_si128());
54 __m128i b_16_hi = _mm_unpacklo_epi8(b_vec_hi, _mm_setzero_si128());
55
56 __m128i luma_r_hi = _mm_mullo_epi16(r_16_hi, _mm_set1_epi16(LUMA_RED));
57 __m128i luma_g_hi = _mm_mullo_epi16(g_16_hi, _mm_set1_epi16(150));
58 __m128i luma_b_hi = _mm_mullo_epi16(b_16_hi, _mm_set1_epi16(29));
59
60 __m128i luma_sum_hi = _mm_add_epi16(luma_r_hi, luma_g_hi);
61 luma_sum_hi = _mm_add_epi16(luma_sum_hi, luma_b_hi);
62 luma_sum_hi = _mm_add_epi16(luma_sum_hi, _mm_set1_epi16(128));
63 luma_sum_hi = _mm_srli_epi16(luma_sum_hi, 8);
64
65 // Pack both halves to 8-bit
66 __m128i luminance_lo = _mm_packus_epi16(luma_sum_lo, _mm_setzero_si128());
67 __m128i luminance_hi = _mm_packus_epi16(luma_sum_hi, _mm_setzero_si128());
68
69 // Store and convert to ASCII characters
70 uint8_t luma_array[16];
71 _mm_storel_epi64((__m128i *)(luma_array + 0), luminance_lo);
72 _mm_storel_epi64((__m128i *)(luma_array + 8), luminance_hi);
73
74 memcpy(out + x, luma_array, 16);
75 }
76 simd_luminance_scalar((const uint8_t *)(row + x), out + x, width - x);
77}
void simd_luminance_scalar(const uint8_t *rgb, uint8_t *out, size_t count)
Definition dispatch.c:57
unsigned int width
Definition fft.c:23
unsigned char uint8_t
Definition common.h:60
#define LUMA_RED
Luminance red coefficient (0.299 * 256 = 77).
static bool size_t gotel_query_t * out
Definition queries.h:8
int glyph_shape_correlation_sse2(const int16_t samples[16], const int16_t mask[16])
void simd_luminance_sse2(const uint8_t *rgb, uint8_t *out, size_t width)
🔤 String Manipulation and Shell Escaping Utilities
uint8_t b
Blue color component (0-255).
uint8_t g
Green color component (0-255).
uint8_t r
Red color component (0-255).
SIMD-optimized ASCII conversion interface.