/*
libspecbleach - A spectral processing library

Copyright 2024 Luciano Dato <lucianodato@gmail.com>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifndef SHARED_UTILS_SIMD_UTILS_H
#define SHARED_UTILS_SIMD_UTILS_H

#include <math.h>
#include <stdint.h>
#include <string.h>

#if defined(_M_X64) || defined(_M_AMD64) ||                                    \
    (defined(_M_IX86_FP) && _M_IX86_FP >= 1)
#ifndef __SSE__
#define __SSE__ 1
#endif
#ifndef __SSE2__
#define __SSE2__ 1
#endif
#endif

#if defined(_M_AVX) || defined(_M_AVX2)
#ifndef __AVX__
#define __AVX__ 1
#endif
#endif

#ifdef __ARM_NEON
#include <arm_neon.h>
#elif defined(__SSE__)
#include <xmmintrin.h>
#ifdef __AVX__
#include <immintrin.h>
#endif
#ifdef __SSE4_1__
#include <smmintrin.h>
#endif
#endif

#if defined(__GNUC__) || defined(__clang__)
#define SB_SIMD_INLINE static inline __attribute__((unused))
#elif defined(_MSC_VER)
#define SB_SIMD_INLINE static __inline
#else
#define SB_SIMD_INLINE static inline
#endif

/* ------------------------------------------------------------------------- */
/* DENORMAL HANDLING (FTZ/DAZ)                                               */
/* ------------------------------------------------------------------------- */

#if defined(__ARM_NEON) && defined(__aarch64__)
typedef uint64_t sb_simd_state_t;
#else
typedef uint32_t sb_simd_state_t;
#endif

/**
 * Enables "Flush-to-Zero" and "Denormals-are-Zero" modes.
 * returns the previous state to be restored later.
 */

#ifdef __SSE__
#define SB_SIMD_MXCSR_FTZ (1U << 15)
#define SB_SIMD_MXCSR_DAZ (1U << 6)
#elif defined(__ARM_NEON) && defined(__aarch64__)
#define SB_SIMD_FPCR_FZ (1U << 24)
#endif

SB_SIMD_INLINE sb_simd_state_t sb_simd_enable_ftz_daz(void) {
  sb_simd_state_t old_state = 0;
#ifdef __SSE__
  old_state = _mm_getcsr();
  _mm_setcsr(old_state | SB_SIMD_MXCSR_FTZ |
             SB_SIMD_MXCSR_DAZ); // MXCSR: bits 15 (FTZ) and 6 (DAZ)
#elif defined(__ARM_NEON) && defined(__aarch64__)
  // On ARM64, we manipulate the FPCR (Floating-point Control Register)
  // Bit 24 is FZ (Flush-to-zero)
  __asm__ __volatile__("mrs %0, fpcr" : "=r"(old_state));
  sb_simd_state_t new_state = old_state | SB_SIMD_FPCR_FZ;
  __asm__ __volatile__("msr fpcr, %0" : : "r"(new_state));
#endif
  return old_state;
}

/**
 * Restores a previously saved SIMD state.
 */
SB_SIMD_INLINE void sb_simd_restore_state(sb_simd_state_t state) {
#ifdef __SSE__
  _mm_setcsr(state);
#elif defined(__ARM_NEON) && defined(__aarch64__)
  __asm__ __volatile__("msr fpcr, %0" : : "r"(state));
#else
  (void)state;
#endif
}

/* ------------------------------------------------------------------------- */
/* 8-WIDE VECTOR ABSTRACTION (Ideal for 8x8 patches)                         */
/* ------------------------------------------------------------------------- */

#ifdef __AVX__
typedef __m256 sb_vec8_t;
#elif defined(__SSE__)
typedef struct {
  __m128 v1, v2;
} sb_vec8_t;
#elif defined(__ARM_NEON)
typedef struct {
  float32x4_t v1, v2;
} sb_vec8_t;
#else
typedef struct {
  float v[8];
} sb_vec8_t;
#endif

/**
 * Loads 8 unaligned floats into an 8-wide vector.
 */
SB_SIMD_INLINE sb_vec8_t sb_load8(const float* p) {
#ifdef __AVX__
  return _mm256_loadu_ps(p);
#elif defined(__SSE__)
  sb_vec8_t r;
  r.v1 = _mm_loadu_ps(p);
  r.v2 = _mm_loadu_ps(p + 4);
  return r;
#elif defined(__ARM_NEON)
  sb_vec8_t r;
  r.v1 = vld1q_f32(p);
  r.v2 = vld1q_f32(p + 4);
  return r;
#else
  sb_vec8_t r;
  memcpy(r.v, p, 8 * sizeof(float));
  return r;
#endif
}

/**
 * Computes Sum of Squared Differences (SSD) between two 8-wide vectors.
 */
SB_SIMD_INLINE float sb_vec8_ssd(sb_vec8_t a, sb_vec8_t b) {
#ifdef __AVX__
  __m256 d = _mm256_sub_ps(a, b);
  d = _mm256_mul_ps(d, d);

  // Horizontal Sum
  __m128 low = _mm256_castps256_ps128(d);
  __m128 high = _mm256_extractf128_ps(d, 1);
  __m128 sum128 = _mm_add_ps(low, high);
  __m128 shuf = _mm_shuffle_ps(sum128, sum128, _MM_SHUFFLE(2, 3, 0, 1));
  __m128 sums = _mm_add_ps(sum128, shuf);
  shuf = _mm_movehl_ps(shuf, sums);
  sums = _mm_add_ss(sums, shuf);
  float f;
  _mm_store_ss(&f, sums);
  return f;
#elif defined(__SSE__)
  __m128 d1 = _mm_sub_ps(a.v1, b.v1);
  __m128 d2 = _mm_sub_ps(a.v2, b.v2);
  d1 = _mm_mul_ps(d1, d1);
  d2 = _mm_mul_ps(d2, d2);
  __m128 sum = _mm_add_ps(d1, d2);

  // Horizontal Sum
  __m128 shuf = _mm_shuffle_ps(sum, sum, _MM_SHUFFLE(2, 3, 0, 1));
  __m128 sums = _mm_add_ps(sum, shuf);
  shuf = _mm_movehl_ps(shuf, sums);
  sums = _mm_add_ss(sums, shuf);
  float f;
  _mm_store_ss(&f, sums);
  return f;
#elif defined(__ARM_NEON)
  float32x4_t d1 = vsubq_f32(a.v1, b.v1);
  float32x4_t d2 = vsubq_f32(a.v2, b.v2);
  d1 = vmulq_f32(d1, d1);
  d2 = vmulq_f32(d2, d2);
  float32x4_t sum = vaddq_f32(d1, d2);
  return vgetq_lane_f32(sum, 0) + vgetq_lane_f32(sum, 1) +
         vgetq_lane_f32(sum, 2) + vgetq_lane_f32(sum, 3);
#else
  float ssd = 0.0f;
  for (int i = 0; i < 8; i++) {
    float d = a.v[i] - b.v[i];
    ssd += d * d;
  }
  return ssd;
#endif
}

/**
 * Accumulates Sum of Squared Differences into an accumulator vector.
 * Useful for loops like register blocking.
 */
#ifdef __AVX__
typedef __m256 sb_acc8_t;
#elif defined(__SSE__)
typedef __m128 sb_acc8_t;
#elif defined(__ARM_NEON)
typedef float32x4_t sb_acc8_t;
#else
typedef float sb_acc8_t;
#endif

SB_SIMD_INLINE sb_acc8_t sb_acc8_zero(void) {
#ifdef __AVX__
  return _mm256_setzero_ps();
#elif defined(__SSE__)
  return _mm_setzero_ps();
#elif defined(__ARM_NEON)
  return vdupq_n_f32(0.0f);
#else
  return 0.0f;
#endif
}

SB_SIMD_INLINE sb_acc8_t sb_acc8_add_ssd(sb_acc8_t acc, sb_vec8_t a,
                                         sb_vec8_t b) {
#if defined(__FMA__) && defined(__AVX__)
  __m256 d = _mm256_sub_ps(a, b);
  return _mm256_fmadd_ps(d, d, acc);
#elif defined(__AVX__)
  __m256 d = _mm256_sub_ps(a, b);
  return _mm256_add_ps(acc, _mm256_mul_ps(d, d));
#elif defined(__SSE__)
  __m128 d1 = _mm_sub_ps(a.v1, b.v1);
  __m128 d2 = _mm_sub_ps(a.v2, b.v2);
  return _mm_add_ps(acc, _mm_add_ps(_mm_mul_ps(d1, d1), _mm_mul_ps(d2, d2)));
#elif defined(__ARM_NEON)
  float32x4_t d1 = vsubq_f32(a.v1, b.v1);
  float32x4_t d2 = vsubq_f32(a.v2, b.v2);
#ifdef __aarch64__
  acc = vfmaq_f32(acc, d1, d1);
  return vfmaq_f32(acc, d2, d2);
#else
  // Fallback for ARMv7 where vfmaq_f32 is not available
  acc = vaddq_f32(acc, vmulq_f32(d1, d1));
  return vaddq_f32(acc, vmulq_f32(d2, d2));
#endif
#else
  float ssd = 0.0f;
  for (int i = 0; i < 8; i++) {
    float d = a.v[i] - b.v[i];
    ssd += d * d;
  }
  return acc + ssd;
#endif
}

SB_SIMD_INLINE float sb_acc8_hsum(sb_acc8_t acc) {
#ifdef __AVX__
  __m128 low = _mm256_castps256_ps128(acc);
  __m128 high = _mm256_extractf128_ps(acc, 1);
  __m128 sum128 = _mm_add_ps(low, high);
  __m128 shuf = _mm_shuffle_ps(sum128, sum128, _MM_SHUFFLE(2, 3, 0, 1));
  __m128 sums = _mm_add_ps(sum128, shuf);
  shuf = _mm_movehl_ps(shuf, sums);
  sums = _mm_add_ss(sums, shuf);
  float f;
  _mm_store_ss(&f, sums);
  return f;
#elif defined(__SSE__)
  __m128 shuf = _mm_shuffle_ps(acc, acc, _MM_SHUFFLE(2, 3, 0, 1));
  __m128 sums = _mm_add_ps(acc, shuf);
  shuf = _mm_movehl_ps(shuf, sums);
  sums = _mm_add_ss(sums, shuf);
  float f;
  _mm_store_ss(&f, sums);
  return f;
#elif defined(__ARM_NEON)
  return vgetq_lane_f32(acc, 0) + vgetq_lane_f32(acc, 1) +
         vgetq_lane_f32(acc, 2) + vgetq_lane_f32(acc, 3);
#else
  return acc;
#endif
}

/**
 * Basic Arithmetic for 8-wide vectors
 */
SB_SIMD_INLINE sb_vec8_t sb_add8(sb_vec8_t a, sb_vec8_t b) {
#ifdef __AVX__
  return _mm256_add_ps(a, b);
#elif defined(__SSE__)
  sb_vec8_t r;
  r.v1 = _mm_add_ps(a.v1, b.v1);
  r.v2 = _mm_add_ps(a.v2, b.v2);
  return r;
#elif defined(__ARM_NEON)
  sb_vec8_t r;
  r.v1 = vaddq_f32(a.v1, b.v1);
  r.v2 = vaddq_f32(a.v2, b.v2);
  return r;
#else
  sb_vec8_t r;
  for (int i = 0; i < 8; i++)
    r.v[i] = a.v[i] + b.v[i];
  return r;
#endif
}

SB_SIMD_INLINE sb_vec8_t sb_sub8(sb_vec8_t a, sb_vec8_t b) {
#ifdef __AVX__
  return _mm256_sub_ps(a, b);
#elif defined(__SSE__)
  sb_vec8_t r;
  r.v1 = _mm_sub_ps(a.v1, b.v1);
  r.v2 = _mm_sub_ps(a.v2, b.v2);
  return r;
#elif defined(__ARM_NEON)
  sb_vec8_t r;
  r.v1 = vsubq_f32(a.v1, b.v1);
  r.v2 = vsubq_f32(a.v2, b.v2);
  return r;
#else
  sb_vec8_t r;
  for (int i = 0; i < 8; i++)
    r.v[i] = a.v[i] - b.v[i];
  return r;
#endif
}

SB_SIMD_INLINE sb_vec8_t sb_mul8(sb_vec8_t a, sb_vec8_t b) {
#ifdef __AVX__
  return _mm256_mul_ps(a, b);
#elif defined(__SSE__)
  sb_vec8_t r;
  r.v1 = _mm_mul_ps(a.v1, b.v1);
  r.v2 = _mm_mul_ps(a.v2, b.v2);
  return r;
#elif defined(__ARM_NEON)
  sb_vec8_t r;
  r.v1 = vmulq_f32(a.v1, b.v1);
  r.v2 = vmulq_f32(a.v2, b.v2);
  return r;
#else
  sb_vec8_t r;
  for (int i = 0; i < 8; i++)
    r.v[i] = a.v[i] * b.v[i];
  return r;
#endif
}

SB_SIMD_INLINE sb_vec8_t sb_div8(sb_vec8_t a, sb_vec8_t b) {
#ifdef __AVX__
  return _mm256_div_ps(a, b);
#elif defined(__SSE__)
  sb_vec8_t r;
  r.v1 = _mm_div_ps(a.v1, b.v1);
  r.v2 = _mm_div_ps(a.v2, b.v2);
  return r;
#elif defined(__ARM_NEON)
#ifdef __aarch64__
  sb_vec8_t r;
  r.v1 = vdivq_f32(a.v1, b.v1);
  r.v2 = vdivq_f32(a.v2, b.v2);
  return r;
#else
  // NEON doesn't have a direct div instruction on ARMv7, use reciprocal or
  // scalar
  float ta1[4];
  float tb1[4];
  float tr1[4];
  float ta2[4];
  float tb2[4];
  float tr2[4];
  vst1q_f32(ta1, a.v1);
  vst1q_f32(tb1, b.v1);
  vst1q_f32(ta2, a.v2);
  vst1q_f32(tb2, b.v2);
  for (int i = 0; i < 4; i++) {
    tr1[i] = ta1[i] / tb1[i];
    tr2[i] = ta2[i] / tb2[i];
  }
  sb_vec8_t r;
  r.v1 = vld1q_f32(tr1);
  r.v2 = vld1q_f32(tr2);
  return r;
#endif
#else
  sb_vec8_t r;
  for (int i = 0; i < 8; i++)
    r.v[i] = a.v[i] / b.v[i];
  return r;
#endif
}

SB_SIMD_INLINE sb_vec8_t sb_sqrt8(sb_vec8_t a) {
#ifdef __AVX__
  return _mm256_sqrt_ps(a);
#elif defined(__SSE__)
  sb_vec8_t r;
  r.v1 = _mm_sqrt_ps(a.v1);
  r.v2 = _mm_sqrt_ps(a.v2);
  return r;
#elif defined(__ARM_NEON)
#ifdef __aarch64__
  sb_vec8_t r;
  r.v1 = vsqrtq_f32(a.v1);
  r.v2 = vsqrtq_f32(a.v2);
  return r;
#else
  sb_vec8_t r;
  float32x4_t zero = vdupq_n_f32(0.0f);
  float32x4_t nan_val = vdupq_n_f32(0.0f / 0.0f);

  // Process a.v1
  float32x4_t e1 = vrsqrteq_f32(a.v1);
  e1 = vmulq_f32(e1, vrsqrtsq_f32(vmulq_f32(a.v1, e1), e1));
  e1 = vmulq_f32(e1, vrsqrtsq_f32(vmulq_f32(a.v1, e1), e1));
  float32x4_t s1 = vmulq_f32(a.v1, e1);
  s1 = vbslq_f32(vceqq_f32(a.v1, zero), zero, s1);
  r.v1 = vbslq_f32(vcltq_f32(a.v1, zero), nan_val,
                   vbslq_f32(vcgtq_f32(a.v1, zero), s1, a.v1));

  // Process a.v2
  float32x4_t e2 = vrsqrteq_f32(a.v2);
  e2 = vmulq_f32(e2, vrsqrtsq_f32(vmulq_f32(a.v2, e2), e2));
  e2 = vmulq_f32(e2, vrsqrtsq_f32(vmulq_f32(a.v2, e2), e2));
  float32x4_t s2 = vmulq_f32(a.v2, e2);
  s2 = vbslq_f32(vceqq_f32(a.v2, zero), zero, s2);
  r.v2 = vbslq_f32(vcltq_f32(a.v2, zero), nan_val,
                   vbslq_f32(vcgtq_f32(a.v2, zero), s2, a.v2));

  return r;
#endif
#else
  sb_vec8_t r;
  for (int i = 0; i < 8; i++)
    r.v[i] = sqrtf(a.v[i]);
  return r;
#endif
}

SB_SIMD_INLINE sb_vec8_t sb_max8(sb_vec8_t a, sb_vec8_t b) {
#ifdef __AVX__
  return _mm256_max_ps(a, b);
#elif defined(__SSE__)
  sb_vec8_t r;
  r.v1 = _mm_max_ps(a.v1, b.v1);
  r.v2 = _mm_max_ps(a.v2, b.v2);
  return r;
#elif defined(__ARM_NEON)
  sb_vec8_t r;
  r.v1 = vmaxq_f32(a.v1, b.v1);
  r.v2 = vmaxq_f32(a.v2, b.v2);
  return r;
#else
  sb_vec8_t r;
  for (int i = 0; i < 8; i++)
    r.v[i] = (a.v[i] > b.v[i]) ? a.v[i] : b.v[i];
  return r;
#endif
}

SB_SIMD_INLINE void sb_store8(float* p, sb_vec8_t v) {
#ifdef __AVX__
  _mm256_storeu_ps(p, v);
#elif defined(__SSE__)
  _mm_storeu_ps(p, v.v1);
  _mm_storeu_ps(p + 4, v.v2);
#elif defined(__ARM_NEON)
  vst1q_f32(p, v.v1);
  vst1q_f32(p + 4, v.v2);
#else
  memcpy(p, v.v, 8 * sizeof(float));
#endif
}

SB_SIMD_INLINE sb_vec8_t sb_set8(float f) {
#ifdef __AVX__
  return _mm256_set1_ps(f);
#elif defined(__SSE__)
  sb_vec8_t r;
  r.v1 = _mm_set1_ps(f);
  r.v2 = r.v1;
  return r;
#elif defined(__ARM_NEON)
  sb_vec8_t r;
  r.v1 = vdupq_n_f32(f);
  r.v2 = r.v1;
  return r;
#else
  sb_vec8_t r;
  for (int i = 0; i < 8; i++)
    r.v[i] = f;
  return r;
#endif
}

/* ------------------------------------------------------------------------- */
/* 4-WIDE VECTOR ABSTRACTION                                                 */
/* ------------------------------------------------------------------------- */

#if defined(__SSE__) || defined(__AVX__)
typedef __m128 sb_vec4_t;
#elif defined(__ARM_NEON)
typedef float32x4_t sb_vec4_t;
#else
typedef struct {
  float v[4];
} sb_vec4_t;
#endif

SB_SIMD_INLINE sb_vec4_t sb_load4(const float* p) {
#if defined(__SSE__) || defined(__AVX__)
  return _mm_loadu_ps(p);
#elif defined(__ARM_NEON)
  return vld1q_f32(p);
#else
  sb_vec4_t r;
  memcpy(r.v, p, 4 * sizeof(float));
  return r;
#endif
}

SB_SIMD_INLINE float sb_vec4_ssd(sb_vec4_t a, sb_vec4_t b) {
#if defined(__SSE__) || defined(__AVX__)
  __m128 d = _mm_sub_ps(a, b);
  d = _mm_mul_ps(d, d);
  __m128 shuf = _mm_shuffle_ps(d, d, _MM_SHUFFLE(2, 3, 0, 1));
  __m128 sums = _mm_add_ps(d, shuf);
  shuf = _mm_movehl_ps(shuf, sums);
  sums = _mm_add_ss(sums, shuf);
  float f;
  _mm_store_ss(&f, sums);
  return f;
#elif defined(__ARM_NEON)
  float32x4_t d = vsubq_f32(a, b);
  d = vmulq_f32(d, d);
  return vgetq_lane_f32(d, 0) + vgetq_lane_f32(d, 1) + vgetq_lane_f32(d, 2) +
         vgetq_lane_f32(d, 3);
#else
  float ssd = 0.0f;
  for (int i = 0; i < 4; i++) {
    float d = a.v[i] - b.v[i];
    ssd += d * d;
  }
  return ssd;
#endif
}

/**
 * 8-Wide Bitwise/Logic (for masks)
 */
SB_SIMD_INLINE sb_vec8_t sb_gt8(sb_vec8_t a, sb_vec8_t b) {
#ifdef __AVX__
  return _mm256_cmp_ps(a, b, _CMP_GT_OQ);
#elif defined(__SSE__)
  sb_vec8_t r;
  r.v1 = _mm_cmpgt_ps(a.v1, b.v1);
  r.v2 = _mm_cmpgt_ps(a.v2, b.v2);
  return r;
#elif defined(__ARM_NEON)
  sb_vec8_t r;
  r.v1 = (float32x4_t)vcgtq_f32(a.v1, b.v1);
  r.v2 = (float32x4_t)vcgtq_f32(a.v2, b.v2);
  return r;
#else
  sb_vec8_t r;
  for (int i = 0; i < 8; i++)
    r.v[i] = (a.v[i] > b.v[i]) ? 1.0f : 0.0f;
  return r;
#endif
}

/**
 * Selects elements from 'a' or 'b' based on 'mask'.
 * Contract: 'mask' must be a comparison bitmask (all-bits-1 for true,
 * all-bits-0 for false) or a value where non-zero lanes mean true.
 * This function normalizes the mask so that all backends behave identically.
 */
SB_SIMD_INLINE sb_vec8_t sb_sel8(sb_vec8_t mask, sb_vec8_t a, sb_vec8_t b) {
  // Normalize mask: any non-zero value becomes a full-bit mask (all 1s)
#ifdef __AVX__
  sb_vec8_t zero = _mm256_set1_ps(0.0f);
  sb_vec8_t normalized_mask = _mm256_cmp_ps(mask, zero, _CMP_NEQ_UQ);
  return _mm256_blendv_ps(b, a, normalized_mask);
#elif defined(__SSE__)
  sb_vec8_t zero;
  zero.v1 = _mm_setzero_ps();
  zero.v2 = _mm_setzero_ps();
  sb_vec8_t normalized_mask;
  normalized_mask.v1 = _mm_cmpneq_ps(mask.v1, zero.v1);
  normalized_mask.v2 = _mm_cmpneq_ps(mask.v2, zero.v2);

// SSE4.1 blendv_ps or manual bitwise
#ifdef __SSE4_1__
  return (sb_vec8_t){_mm_blendv_ps(b.v1, a.v1, normalized_mask.v1),
                     _mm_blendv_ps(b.v2, a.v2, normalized_mask.v2)};
#else
  __m128 res1 = _mm_or_ps(_mm_and_ps(normalized_mask.v1, a.v1),
                          _mm_andnot_ps(normalized_mask.v1, b.v1));
  __m128 res2 = _mm_or_ps(_mm_and_ps(normalized_mask.v2, a.v2),
                          _mm_andnot_ps(normalized_mask.v2, b.v2));
  return (sb_vec8_t){res1, res2};
#endif
#elif defined(__ARM_NEON)
  sb_vec8_t zero;
  zero.v1 = vdupq_n_f32(0.0f);
  zero.v2 = vdupq_n_f32(0.0f);
  sb_vec8_t normalized_mask;
  normalized_mask.v1 = (float32x4_t)vmvnq_u32(vceqq_f32(mask.v1, zero.v1));
  normalized_mask.v2 = (float32x4_t)vmvnq_u32(vceqq_f32(mask.v2, zero.v2));

  return (sb_vec8_t){vbslq_f32((uint32x4_t)normalized_mask.v1, a.v1, b.v1),
                     vbslq_f32((uint32x4_t)normalized_mask.v2, a.v2, b.v2)};
#else
  sb_vec8_t r;
  for (int i = 0; i < 8; i++)
    r.v[i] = (mask.v[i] != 0.0f) ? a.v[i] : b.v[i];
  return r;
#endif
}

/**
 * Computes the Sum of Squared Differences (SSD) for an 8x8 patch block.
 * Target vectors are provided as an array of 8 pre-loaded sb_vec8_t registers.
 * Candidate pointers are loaded from row_ptrs[8] to compare against the target.
 */
SB_SIMD_INLINE float sb_vec8_patch_ssd(const sb_vec8_t* target_vecs,
                                       float* const* cand_row_ptrs) {
  sb_acc8_t sum = sb_acc8_zero();

  // Unroll 8 row comparisons
  sum = sb_acc8_add_ssd(sum, target_vecs[0], sb_load8(cand_row_ptrs[0]));
  sum = sb_acc8_add_ssd(sum, target_vecs[1], sb_load8(cand_row_ptrs[1]));
  sum = sb_acc8_add_ssd(sum, target_vecs[2], sb_load8(cand_row_ptrs[2]));
  sum = sb_acc8_add_ssd(sum, target_vecs[3], sb_load8(cand_row_ptrs[3]));
  sum = sb_acc8_add_ssd(sum, target_vecs[4], sb_load8(cand_row_ptrs[4]));
  sum = sb_acc8_add_ssd(sum, target_vecs[5], sb_load8(cand_row_ptrs[5]));
  sum = sb_acc8_add_ssd(sum, target_vecs[6], sb_load8(cand_row_ptrs[6]));
  sum = sb_acc8_add_ssd(sum, target_vecs[7], sb_load8(cand_row_ptrs[7]));

  return sb_acc8_hsum(sum);
}

/* ------------------------------------------------------------------------- */
/* FAST MATH APPROXIMATIONS                                                  */
/* ------------------------------------------------------------------------- */

/**
 * Fast exponential approximation for stability and performance.
 * Based on the Schraudolph (1999) approximation, but refined for float
 * accuracy. exp(x) approx (1 + x/n)^n, or using the IEEE 754
 * bit-representation trick. Accuracy: ~4% relative error, suitable for NLM
 * weight computation where small errors are averaged across many candidates.
 * Note: The integer reinterpretation trick with (uint32_t)(12102203.0f * x +
 * 1064866805.0f) is intentional and handles negative values (underflow) via
 * bit-level wrap-around.
 */
SB_SIMD_INLINE float sb_fast_expf(float x) {
  // Use a simple but effective approximation for exp(-x) where x > 0
  // v = (12102203 * x + 1064866805)
  // This is for exp(x). Since NLM uses exp(-dist/h2), x is usually negative.
  if (x < -20.0f) {
    return 0.0f; // Underflow protection for NLM weights
  }

  union {
    uint32_t i;
    float f;
  } v;
  v.i = (uint32_t)((12102203.0f * x) + 1064866805.0f);
  return v.f;
}

#endif // SHARED_UTILS_SIMD_UTILS_H
