LCOV - code coverage report
Current view: top level - src - simd.c (source / functions) Coverage Total Hit
Test: colopresso Coverage Report Lines: 100.0 % 12 12
Test Date: 2026-11-09 10:50:48 Functions: 100.0 % 2 2
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-or-later
       3              :  *
       4              :  * This file is part of colopresso
       5              :  *
       6              :  * Copyright (C) 2025-2026 COLOPL, Inc.
       7              :  *
       8              :  * Author: Go Kudo <g-kudo@colopl.co.jp>
       9              :  * Developed with AI (LLM) code assistance. See `NOTICE` for details.
      10              :  */
      11              : 
      12              : #include "internal/simd.h"
      13              : 
      14              : #if defined(CPRES_SIMD_SSE41) || defined(CPRES_SIMD_SSE2)
      15              : 
      16     47677831 : static inline uint32_t color_distance_sq_sse(uint32_t lhs, uint32_t rhs)
      17              : {
      18    143033493 :     __m128i a = _mm_cvtsi32_si128((int)lhs), b = _mm_cvtsi32_si128((int)rhs), a16, b16, diff,
      19              :             diff_sq;
      20              :     int result;
      21              : 
      22     95355662 :     a16 = _mm_unpacklo_epi8(a, _mm_setzero_si128());
      23     95355662 :     b16 = _mm_unpacklo_epi8(b, _mm_setzero_si128());
      24              : 
      25     47677831 :     diff = _mm_sub_epi16(a16, b16);
      26              : 
      27     47677831 :     diff_sq = _mm_madd_epi16(diff, diff);
      28              : 
      29     47677831 :     diff_sq = _mm_add_epi32(diff_sq, _mm_srli_si128(diff_sq, 8));
      30     95355662 :     diff_sq = _mm_add_epi32(diff_sq, _mm_srli_si128(diff_sq, 4));
      31              : 
      32     47677831 :     result = _mm_cvtsi128_si32(diff_sq);
      33              : 
      34     47677831 :     return (uint32_t)result;
      35              : }
      36              : 
      37              : #elif defined(CPRES_SIMD_NEON)
      38              : 
      39              : static inline uint32_t color_distance_sq_neon(uint32_t lhs, uint32_t rhs)
      40              : {
      41              :     uint8x8_t a = vreinterpret_u8_u32(vdup_n_u32(lhs)), b = vreinterpret_u8_u32(vdup_n_u32(rhs));
      42              :     int16x4_t a16 = vreinterpret_s16_u16(vget_low_u16(vmovl_u8(a))),
      43              :               b16 = vreinterpret_s16_u16(vget_low_u16(vmovl_u8(b))), diff = vsub_s16(a16, b16);
      44              :     int32x4_t diff_sq = vmull_s16(diff, diff);
      45              :     int32_t result = vgetq_lane_s32(diff_sq, 0) + vgetq_lane_s32(diff_sq, 1) +
      46              :                      vgetq_lane_s32(diff_sq, 2) + vgetq_lane_s32(diff_sq, 3);
      47              : 
      48              :     return (uint32_t)result;
      49              : }
      50              : 
      51              : #elif defined(CPRES_SIMD_WASM128)
      52              : 
      53              : static inline uint32_t color_distance_sq_wasm(uint32_t lhs, uint32_t rhs)
      54              : {
      55              :     v128_t a = wasm_i32x4_splat((int32_t)lhs), b = wasm_i32x4_splat((int32_t)rhs),
      56              :            a16 = wasm_u16x8_extend_low_u8x16(a), b16 = wasm_u16x8_extend_low_u8x16(b),
      57              :            diff = wasm_i16x8_sub(a16, b16), diff_sq = wasm_i32x4_extmul_low_i16x8(diff, diff);
      58              :     int32_t result = wasm_i32x4_extract_lane(diff_sq, 0) + wasm_i32x4_extract_lane(diff_sq, 1) +
      59              :                      wasm_i32x4_extract_lane(diff_sq, 2) + wasm_i32x4_extract_lane(diff_sq, 3);
      60              : 
      61              :     return (uint32_t)result;
      62              : }
      63              : 
      64              : #else
      65              : 
      66              : static inline uint32_t color_distance_sq_scalar(uint32_t lhs, uint32_t rhs)
      67              : {
      68              :     int32_t r1 = (int32_t)(lhs & 0xFF), g1 = (int32_t)((lhs >> 8) & 0xFF),
      69              :             b1 = (int32_t)((lhs >> 16) & 0xFF), a1 = (int32_t)((lhs >> 24) & 0xFF),
      70              :             r2 = (int32_t)(rhs & 0xFF), g2 = (int32_t)((rhs >> 8) & 0xFF),
      71              :             b2 = (int32_t)((rhs >> 16) & 0xFF), a2 = (int32_t)((rhs >> 24) & 0xFF), dr = r1 - r2,
      72              :             dg = g1 - g2, db = b1 - b2, da = a1 - a2;
      73              : 
      74              :     return (uint32_t)(dr * dr + dg * dg + db * db + da * da);
      75              : }
      76              : 
      77              : #endif
      78              : 
      79     47677831 : extern uint32_t simd_color_distance_sq_u32(uint32_t lhs, uint32_t rhs)
      80              : {
      81              : #if defined(CPRES_SIMD_WASM128)
      82              :     return color_distance_sq_wasm(lhs, rhs);
      83              : #elif defined(CPRES_SIMD_SSE41) || defined(CPRES_SIMD_SSE2)
      84     47677831 :     return color_distance_sq_sse(lhs, rhs);
      85              : #elif defined(CPRES_SIMD_NEON)
      86              :     return color_distance_sq_neon(lhs, rhs);
      87              : #else
      88              :     return color_distance_sq_scalar(lhs, rhs);
      89              : #endif
      90              : }
        

Generated by: LCOV version 2.0-1