/*
 * Copyright (c) 2021, Alliance for Open Media. All rights reserved
 *
 * This source code is subject to the terms of the BSD 3-Clause Clear License
 * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
 * License was not distributed with this source code in the LICENSE file, you
 * can obtain it at aomedia.org/license/software-license/bsd-3-c-c/.  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
 * aomedia.org/license/patent-license/.
 */

#include <emmintrin.h>
#include <xmmintrin.h>

#include "config/av1_rtcd.h"

#include "aom/aom_integer.h"
static INLINE void read_coeff(const tran_low_t *coeff, intptr_t offset,
                              __m128i *c0, __m128i *c1) {
  const tran_low_t *addr = coeff + offset;
  if (sizeof(tran_low_t) == 4) {
    const __m128i x0 = _mm_loadu_si128((const __m128i *)addr);
    const __m128i x1 = _mm_loadu_si128((const __m128i *)addr + 1);
    const __m128i x2 = _mm_loadu_si128((const __m128i *)addr + 2);
    const __m128i x3 = _mm_loadu_si128((const __m128i *)addr + 3);
    *c0 = _mm_packs_epi32(x0, x1);
    *c1 = _mm_packs_epi32(x2, x3);
  } else {
    *c0 = _mm_loadu_si128((const __m128i *)addr);
    *c1 = _mm_loadu_si128((const __m128i *)addr + 1);
  }
}

static INLINE void write_qcoeff(const __m128i *qc0, const __m128i *qc1,
                                tran_low_t *qcoeff, intptr_t offset) {
  tran_low_t *addr = qcoeff + offset;
  if (sizeof(tran_low_t) == 4) {
    const __m128i zero = _mm_setzero_si128();
    __m128i sign_bits = _mm_cmplt_epi16(*qc0, zero);
    __m128i y0 = _mm_unpacklo_epi16(*qc0, sign_bits);
    __m128i y1 = _mm_unpackhi_epi16(*qc0, sign_bits);
    _mm_store_si128((__m128i *)addr, y0);
    _mm_store_si128((__m128i *)addr + 1, y1);

    sign_bits = _mm_cmplt_epi16(*qc1, zero);
    y0 = _mm_unpacklo_epi16(*qc1, sign_bits);
    y1 = _mm_unpackhi_epi16(*qc1, sign_bits);
    _mm_store_si128((__m128i *)addr + 2, y0);
    _mm_store_si128((__m128i *)addr + 3, y1);
  } else {
    _mm_store_si128((__m128i *)addr, *qc0);
    _mm_store_si128((__m128i *)addr + 1, *qc1);
  }
}

static INLINE void write_zero(tran_low_t *qcoeff, intptr_t offset) {
  const __m128i zero = _mm_setzero_si128();
  tran_low_t *addr = qcoeff + offset;
  if (sizeof(tran_low_t) == 4) {
    _mm_store_si128((__m128i *)addr, zero);
    _mm_store_si128((__m128i *)addr + 1, zero);
    _mm_store_si128((__m128i *)addr + 2, zero);
    _mm_store_si128((__m128i *)addr + 3, zero);
  } else {
    _mm_store_si128((__m128i *)addr, zero);
    _mm_store_si128((__m128i *)addr + 1, zero);
  }
}

static INLINE void quantize(const int16_t *iscan_ptr,
                            const tran_low_t *coeff_ptr, intptr_t n_coeffs,
                            tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
                            const __m128i *round0, const __m128i *round1,
                            const __m128i *quant0, const __m128i *quant1,
                            const __m128i *dequant0, const __m128i *dequant1,
                            const __m128i *thr0, const __m128i *thr1,
                            __m128i *eob) {
  __m128i coeff0, coeff1;
  // Do DC and first 15 AC
  read_coeff(coeff_ptr, n_coeffs, &coeff0, &coeff1);

  // Poor man's sign extract
  const __m128i coeff0_sign = _mm_srai_epi16(coeff0, 15);
  const __m128i coeff1_sign = _mm_srai_epi16(coeff1, 15);
  __m128i qcoeff0 = _mm_xor_si128(coeff0, coeff0_sign);
  __m128i qcoeff1 = _mm_xor_si128(coeff1, coeff1_sign);
  qcoeff0 = _mm_sub_epi16(qcoeff0, coeff0_sign);
  qcoeff1 = _mm_sub_epi16(qcoeff1, coeff1_sign);
  const __m128i mask0 = _mm_or_si128(_mm_cmpgt_epi16(qcoeff0, *thr0),
                                     _mm_cmpeq_epi16(qcoeff0, *thr0));
  const __m128i mask1 = _mm_or_si128(_mm_cmpgt_epi16(qcoeff1, *thr1),
                                     _mm_cmpeq_epi16(qcoeff1, *thr1));
  const int nzflag = _mm_movemask_epi8(mask0) | _mm_movemask_epi8(mask1);

  if (nzflag) {
    qcoeff0 = _mm_adds_epi16(qcoeff0, *round0);
    qcoeff1 = _mm_adds_epi16(qcoeff1, *round1);
    const __m128i qtmp0 = _mm_mulhi_epi16(qcoeff0, *quant0);
    const __m128i qtmp1 = _mm_mulhi_epi16(qcoeff1, *quant1);

    // Reinsert signs
    qcoeff0 = _mm_xor_si128(qtmp0, coeff0_sign);
    qcoeff1 = _mm_xor_si128(qtmp1, coeff1_sign);
    qcoeff0 = _mm_sub_epi16(qcoeff0, coeff0_sign);
    qcoeff1 = _mm_sub_epi16(qcoeff1, coeff1_sign);

    write_qcoeff(&qcoeff0, &qcoeff1, qcoeff_ptr, n_coeffs);

    coeff0 = _mm_mullo_epi16(qcoeff0, *dequant0);
    coeff1 = _mm_mullo_epi16(qcoeff1, *dequant1);

    write_qcoeff(&coeff0, &coeff1, dqcoeff_ptr, n_coeffs);

    const __m128i zero = _mm_setzero_si128();
    // Scan for eob
    const __m128i zero_coeff0 = _mm_cmpeq_epi16(coeff0, zero);
    const __m128i zero_coeff1 = _mm_cmpeq_epi16(coeff1, zero);
    const __m128i nzero_coeff0 = _mm_cmpeq_epi16(zero_coeff0, zero);
    const __m128i nzero_coeff1 = _mm_cmpeq_epi16(zero_coeff1, zero);
    const __m128i iscan0 =
        _mm_loadu_si128((const __m128i *)(iscan_ptr + n_coeffs));
    const __m128i iscan1 =
        _mm_loadu_si128((const __m128i *)(iscan_ptr + n_coeffs) + 1);
    // Add one to convert from indices to counts
    const __m128i iscan0_nz = _mm_sub_epi16(iscan0, nzero_coeff0);
    const __m128i iscan1_nz = _mm_sub_epi16(iscan1, nzero_coeff1);
    const __m128i eob0 = _mm_and_si128(iscan0_nz, nzero_coeff0);
    const __m128i eob1 = _mm_and_si128(iscan1_nz, nzero_coeff1);
    const __m128i eob2 = _mm_max_epi16(eob0, eob1);
    *eob = _mm_max_epi16(*eob, eob2);
  } else {
    write_zero(qcoeff_ptr, n_coeffs);
    write_zero(dqcoeff_ptr, n_coeffs);
  }
}

void av1_quantize_fp_sse2(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
                          const int32_t *zbin_ptr, const int32_t *round_ptr,
                          const int32_t *quant_ptr,
                          const int32_t *quant_shift_ptr,
                          tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
                          const int32_t *dequant_ptr, uint16_t *eob_ptr,
                          const int16_t *scan_ptr, const int16_t *iscan_ptr) {
  (void)scan_ptr;
  (void)zbin_ptr;
  (void)quant_shift_ptr;

  coeff_ptr += n_coeffs;
  iscan_ptr += n_coeffs;
  qcoeff_ptr += n_coeffs;
  dqcoeff_ptr += n_coeffs;
  n_coeffs = -n_coeffs;
  const __m128i round0 = _mm_loadu_si128((const __m128i *)round_ptr);
  const __m128i round1 = _mm_unpackhi_epi64(round0, round0);
  const __m128i quant0 = _mm_loadu_si128((const __m128i *)quant_ptr);
  const __m128i quant1 = _mm_unpackhi_epi64(quant0, quant0);
  const __m128i dequant0 = _mm_loadu_si128((const __m128i *)dequant_ptr);
  const __m128i dequant1 = _mm_unpackhi_epi64(dequant0, dequant0);
  const __m128i thr0 = _mm_srai_epi16(dequant0, 1);
  const __m128i thr1 = _mm_srai_epi16(dequant1, 1);
  __m128i eob = _mm_setzero_si128();

  quantize(iscan_ptr, coeff_ptr, n_coeffs, qcoeff_ptr, dqcoeff_ptr, &round0,
           &round1, &quant0, &quant1, &dequant0, &dequant1, &thr0, &thr1, &eob);

  n_coeffs += 8 * 2;

  // AC only loop
  while (n_coeffs < 0) {
    quantize(iscan_ptr, coeff_ptr, n_coeffs, qcoeff_ptr, dqcoeff_ptr, &round1,
             &round1, &quant1, &quant1, &dequant1, &dequant1, &thr1, &thr1,
             &eob);
    n_coeffs += 8 * 2;
  }

  // Accumulate EOB
  {
    __m128i eob_shuffled;
    eob_shuffled = _mm_shuffle_epi32(eob, 0xe);
    eob = _mm_max_epi16(eob, eob_shuffled);
    eob_shuffled = _mm_shufflelo_epi16(eob, 0xe);
    eob = _mm_max_epi16(eob, eob_shuffled);
    eob_shuffled = _mm_shufflelo_epi16(eob, 0x1);
    eob = _mm_max_epi16(eob, eob_shuffled);
    *eob_ptr = _mm_extract_epi16(eob, 1);
  }
}
