/*
 * Copyright (c) 2021, Alliance for Open Media. All rights reserved.
 *
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
 */

#include <emmintrin.h>  // SSE2

#include "config/av1_rtcd.h"
#include "aom_dsp/x86/synonyms.h"

static int64_t k_means_horizontal_sum_sse2(__m128i a) {
  const __m128i sum1 = _mm_unpackhi_epi64(a, a);
  const __m128i sum2 = _mm_add_epi64(a, sum1);
  int64_t res;
  _mm_storel_epi64((__m128i *)&res, sum2);
  return res;
}

void av1_calc_indices_dim1_sse2(const int16_t *data, const int16_t *centroids,
                                uint8_t *indices, int64_t *total_dist, int n,
                                int k) {
  const __m128i v_zero = _mm_setzero_si128();
  __m128i sum = _mm_setzero_si128();
  __m128i cents[PALETTE_MAX_SIZE];
  for (int j = 0; j < k; ++j) {
    cents[j] = _mm_set1_epi16(centroids[j]);
  }

  for (int i = 0; i < n; i += 8) {
    const __m128i in = _mm_loadu_si128((__m128i *)data);
    __m128i ind = _mm_setzero_si128();
    // Compute the distance to the first centroid.
    __m128i d1 = _mm_sub_epi16(in, cents[0]);
    __m128i d2 = _mm_sub_epi16(cents[0], in);
    __m128i dist_min = _mm_max_epi16(d1, d2);

    for (int j = 1; j < k; ++j) {
      // Compute the distance to the centroid.
      d1 = _mm_sub_epi16(in, cents[j]);
      d2 = _mm_sub_epi16(cents[j], in);
      const __m128i dist = _mm_max_epi16(d1, d2);
      // Compare to the minimal one.
      const __m128i cmp = _mm_cmpgt_epi16(dist_min, dist);
      dist_min = _mm_min_epi16(dist_min, dist);
      const __m128i ind1 = _mm_set1_epi16(j);
      ind = _mm_or_si128(_mm_andnot_si128(cmp, ind), _mm_and_si128(cmp, ind1));
    }
    if (total_dist) {
      // Square, convert to 32 bit and add together.
      dist_min = _mm_madd_epi16(dist_min, dist_min);
      // Convert to 64 bit and add to sum.
      const __m128i dist1 = _mm_unpacklo_epi32(dist_min, v_zero);
      const __m128i dist2 = _mm_unpackhi_epi32(dist_min, v_zero);
      sum = _mm_add_epi64(sum, dist1);
      sum = _mm_add_epi64(sum, dist2);
    }
    __m128i p2 = _mm_packus_epi16(ind, v_zero);
    _mm_storel_epi64((__m128i *)indices, p2);
    indices += 8;
    data += 8;
  }
  if (total_dist) {
    *total_dist = k_means_horizontal_sum_sse2(sum);
  }
}

void av1_calc_indices_dim2_sse2(const int16_t *data, const int16_t *centroids,
                                uint8_t *indices, int64_t *total_dist, int n,
                                int k) {
  const __m128i v_zero = _mm_setzero_si128();
  __m128i sum = _mm_setzero_si128();
  __m128i ind[2];
  __m128i cents[PALETTE_MAX_SIZE];
  for (int j = 0; j < k; ++j) {
    const int16_t cx = centroids[2 * j], cy = centroids[2 * j + 1];
    cents[j] = _mm_set_epi16(cy, cx, cy, cx, cy, cx, cy, cx);
  }

  for (int i = 0; i < n; i += 8) {
    for (int l = 0; l < 2; ++l) {
      const __m128i in = _mm_loadu_si128((__m128i *)data);
      ind[l] = _mm_setzero_si128();
      // Compute the distance to the first centroid.
      __m128i d1 = _mm_sub_epi16(in, cents[0]);
      __m128i dist_min = _mm_madd_epi16(d1, d1);

      for (int j = 1; j < k; ++j) {
        // Compute the distance to the centroid.
        d1 = _mm_sub_epi16(in, cents[j]);
        const __m128i dist = _mm_madd_epi16(d1, d1);
        // Compare to the minimal one.
        const __m128i cmp = _mm_cmpgt_epi32(dist_min, dist);
        const __m128i dist1 = _mm_andnot_si128(cmp, dist_min);
        const __m128i dist2 = _mm_and_si128(cmp, dist);
        dist_min = _mm_or_si128(dist1, dist2);
        const __m128i ind1 = _mm_set1_epi32(j);
        ind[l] = _mm_or_si128(_mm_andnot_si128(cmp, ind[l]),
                              _mm_and_si128(cmp, ind1));
      }
      if (total_dist) {
        // Convert to 64 bit and add to sum.
        const __m128i dist1 = _mm_unpacklo_epi32(dist_min, v_zero);
        const __m128i dist2 = _mm_unpackhi_epi32(dist_min, v_zero);
        sum = _mm_add_epi64(sum, dist1);
        sum = _mm_add_epi64(sum, dist2);
      }
      data += 8;
    }
    // Cast to 8 bit and store.
    const __m128i d2 = _mm_packus_epi16(ind[0], ind[1]);
    const __m128i d3 = _mm_packus_epi16(d2, v_zero);
    _mm_storel_epi64((__m128i *)indices, d3);
    indices += 8;
  }
  if (total_dist) {
    *total_dist = k_means_horizontal_sum_sse2(sum);
  }
}
