/*
 * Copyright (c) 2016, 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>
#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_load_si128((const __m128i *)addr);
    const __m128i x1 = _mm_load_si128((const __m128i *)addr + 1);
    const __m128i x2 = _mm_load_si128((const __m128i *)addr + 2);
    const __m128i x3 = _mm_load_si128((const __m128i *)addr + 3);
    *c0 = _mm_packs_epi32(x0, x1);
    *c1 = _mm_packs_epi32(x2, x3);
  } else {
    *c0 = _mm_load_si128((const __m128i *)addr);
    *c1 = _mm_load_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_load_si128((const __m128i *)(iscan_ptr + n_coeffs));
    const __m128i iscan1 =
        _mm_load_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 int16_t *zbin_ptr, const int16_t *round_ptr,
                          const int16_t *quant_ptr,
                          const int16_t *quant_shift_ptr,
                          tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
                          const int16_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_load_si128((const __m128i *)round_ptr);
  const __m128i round1 = _mm_unpackhi_epi64(round0, round0);
  const __m128i quant0 = _mm_load_si128((const __m128i *)quant_ptr);
  const __m128i quant1 = _mm_unpackhi_epi64(quant0, quant0);
  const __m128i dequant0 = _mm_load_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);
  }
}
