dct32x32_test.cc revision 5ae7ac49f08a179e4f054d99fcfc9dce78d26e58
1ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/*
2ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
3ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *
4ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  Use of this source code is governed by a BSD-style license
5ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  that can be found in the LICENSE file in the root of the source
6ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  tree. An additional intellectual property rights grant can be found
7ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  in the file PATENTS.  All contributing project authors may
8ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  be found in the AUTHORS file in the root of the source tree.
9ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
10ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
11ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include <math.h>
12ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include <stdlib.h>
13ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include <string.h>
14ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
15ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "third_party/googletest/src/include/gtest/gtest.h"
161184aebb761cbeac9124c37189a80a1a58f04b6bhkuang#include "test/acm_random.h"
171184aebb761cbeac9124c37189a80a1a58f04b6bhkuang#include "test/clear_system_state.h"
181184aebb761cbeac9124c37189a80a1a58f04b6bhkuang#include "test/register_state_check.h"
191184aebb761cbeac9124c37189a80a1a58f04b6bhkuang#include "test/util.h"
20ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
21ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangextern "C" {
221184aebb761cbeac9124c37189a80a1a58f04b6bhkuang#include "./vpx_config.h"
23ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "vp9/common/vp9_entropy.h"
24ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "./vp9_rtcd.h"
25ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
26ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
27ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "vpx/vpx_integer.h"
28ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
29ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangusing libvpx_test::ACMRandom;
30ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
31ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangnamespace {
32ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#ifdef _MSC_VER
33ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic int round(double x) {
34ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (x < 0)
351184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    return static_cast<int>(ceil(x - 0.5));
36ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  else
371184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    return static_cast<int>(floor(x + 0.5));
38ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
39ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#endif
40ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
411184aebb761cbeac9124c37189a80a1a58f04b6bhkuangconst int kNumCoeffs = 1024;
421184aebb761cbeac9124c37189a80a1a58f04b6bhkuangconst double kPi = 3.141592653589793238462643383279502884;
431184aebb761cbeac9124c37189a80a1a58f04b6bhkuangvoid reference_32x32_dct_1d(const double in[32], double out[32], int stride) {
44ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  const double kInvSqrt2 = 0.707106781186547524400844362104;
45ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for (int k = 0; k < 32; k++) {
46ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    out[k] = 0.0;
47ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for (int n = 0; n < 32; n++)
48ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      out[k] += in[n] * cos(kPi * (2 * n + 1) * k / 64.0);
49ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (k == 0)
50ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      out[k] = out[k] * kInvSqrt2;
51ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
52ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
53ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
541184aebb761cbeac9124c37189a80a1a58f04b6bhkuangvoid reference_32x32_dct_2d(const int16_t input[kNumCoeffs],
551184aebb761cbeac9124c37189a80a1a58f04b6bhkuang                            double output[kNumCoeffs]) {
56ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  // First transform columns
57ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for (int i = 0; i < 32; ++i) {
58ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    double temp_in[32], temp_out[32];
59ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for (int j = 0; j < 32; ++j)
60ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      temp_in[j] = input[j*32 + i];
61ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    reference_32x32_dct_1d(temp_in, temp_out, 1);
62ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for (int j = 0; j < 32; ++j)
63ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      output[j * 32 + i] = temp_out[j];
64ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
65ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  // Then transform rows
66ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for (int i = 0; i < 32; ++i) {
67ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    double temp_in[32], temp_out[32];
68ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for (int j = 0; j < 32; ++j)
69ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      temp_in[j] = output[j + i*32];
70ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    reference_32x32_dct_1d(temp_in, temp_out, 1);
71ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    // Scale by some magic number
72ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for (int j = 0; j < 32; ++j)
73ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      output[j + i * 32] = temp_out[j] / 4;
74ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
75ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
76ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
775ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangtypedef void (*fwd_txfm_t)(const int16_t *in, int16_t *out, int stride);
785ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangtypedef void (*inv_txfm_t)(const int16_t *in, uint8_t *out, int stride);
79ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
801184aebb761cbeac9124c37189a80a1a58f04b6bhkuangclass Trans32x32Test : public PARAMS(fwd_txfm_t, inv_txfm_t, int) {
811184aebb761cbeac9124c37189a80a1a58f04b6bhkuang public:
821184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  virtual ~Trans32x32Test() {}
831184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  virtual void SetUp() {
841184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    fwd_txfm_ = GET_PARAM(0);
851184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    inv_txfm_ = GET_PARAM(1);
861184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    version_  = GET_PARAM(2);  // 0: high precision forward transform
871184aebb761cbeac9124c37189a80a1a58f04b6bhkuang                               // 1: low precision version for rd loop
88ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
89ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
901184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  virtual void TearDown() { libvpx_test::ClearSystemState(); }
911184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
921184aebb761cbeac9124c37189a80a1a58f04b6bhkuang protected:
931184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  int version_;
941184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  fwd_txfm_t fwd_txfm_;
951184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  inv_txfm_t inv_txfm_;
961184aebb761cbeac9124c37189a80a1a58f04b6bhkuang};
971184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
981184aebb761cbeac9124c37189a80a1a58f04b6bhkuangTEST_P(Trans32x32Test, AccuracyCheck) {
99ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  ACMRandom rnd(ACMRandom::DeterministicSeed());
1001184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  uint32_t max_error = 0;
101ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  int64_t total_error = 0;
102ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  const int count_test_block = 1000;
1031184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, kNumCoeffs);
1041184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  DECLARE_ALIGNED_ARRAY(16, int16_t, test_temp_block, kNumCoeffs);
1051184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs);
1061184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs);
107ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1081184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  for (int i = 0; i < count_test_block; ++i) {
1091184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    // Initialize a test block with input range [-255, 255].
1101184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    for (int j = 0; j < kNumCoeffs; ++j) {
111ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      src[j] = rnd.Rand8();
112ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      dst[j] = rnd.Rand8();
113ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      test_input_block[j] = src[j] - dst[j];
1141184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    }
115ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1165ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    REGISTER_STATE_CHECK(fwd_txfm_(test_input_block, test_temp_block, 32));
1171184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    REGISTER_STATE_CHECK(inv_txfm_(test_temp_block, dst, 32));
118ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1191184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    for (int j = 0; j < kNumCoeffs; ++j) {
1201184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      const uint32_t diff = dst[j] - src[j];
1211184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      const uint32_t error = diff * diff;
122ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (max_error < error)
123ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        max_error = error;
124ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      total_error += error;
125ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
126ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
127ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1281184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  if (version_ == 1) {
1291184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    max_error /= 2;
1301184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    total_error /= 45;
1311184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  }
1321184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
133ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  EXPECT_GE(1u, max_error)
1341184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      << "Error: 32x32 FDCT/IDCT has an individual round-trip error > 1";
135ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
136ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  EXPECT_GE(count_test_block, total_error)
1371184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      << "Error: 32x32 FDCT/IDCT has average round-trip error > 1 per block";
138ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
139ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1401184aebb761cbeac9124c37189a80a1a58f04b6bhkuangTEST_P(Trans32x32Test, CoeffCheck) {
141ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  ACMRandom rnd(ACMRandom::DeterministicSeed());
142ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  const int count_test_block = 1000;
1431184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
1441184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs);
1451184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  DECLARE_ALIGNED_ARRAY(16, int16_t, output_ref_block, kNumCoeffs);
1461184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  DECLARE_ALIGNED_ARRAY(16, int16_t, output_block, kNumCoeffs);
1471184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
148ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for (int i = 0; i < count_test_block; ++i) {
1491184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    for (int j = 0; j < kNumCoeffs; ++j)
1501184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      input_block[j] = rnd.Rand8() - rnd.Rand8();
1511184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
1525ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    const int stride = 32;
1535ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    vp9_fdct32x32_c(input_block, output_ref_block, stride);
1545ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    REGISTER_STATE_CHECK(fwd_txfm_(input_block, output_block, stride));
1551184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
1561184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    if (version_ == 0) {
1571184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      for (int j = 0; j < kNumCoeffs; ++j)
1581184aebb761cbeac9124c37189a80a1a58f04b6bhkuang        EXPECT_EQ(output_block[j], output_ref_block[j])
1591184aebb761cbeac9124c37189a80a1a58f04b6bhkuang            << "Error: 32x32 FDCT versions have mismatched coefficients";
1601184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    } else {
1611184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      for (int j = 0; j < kNumCoeffs; ++j)
1621184aebb761cbeac9124c37189a80a1a58f04b6bhkuang        EXPECT_GE(6, abs(output_block[j] - output_ref_block[j]))
1631184aebb761cbeac9124c37189a80a1a58f04b6bhkuang            << "Error: 32x32 FDCT rd has mismatched coefficients";
1641184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    }
1651184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  }
1661184aebb761cbeac9124c37189a80a1a58f04b6bhkuang}
1671184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
1681184aebb761cbeac9124c37189a80a1a58f04b6bhkuangTEST_P(Trans32x32Test, MemCheck) {
1691184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  ACMRandom rnd(ACMRandom::DeterministicSeed());
1701184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  const int count_test_block = 2000;
1711184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
1721184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs);
1731184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  DECLARE_ALIGNED_ARRAY(16, int16_t, input_extreme_block, kNumCoeffs);
1741184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  DECLARE_ALIGNED_ARRAY(16, int16_t, output_ref_block, kNumCoeffs);
1751184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  DECLARE_ALIGNED_ARRAY(16, int16_t, output_block, kNumCoeffs);
176ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1771184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  for (int i = 0; i < count_test_block; ++i) {
178ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    // Initialize a test block with input range [-255, 255].
1791184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    for (int j = 0; j < kNumCoeffs; ++j) {
180ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      input_block[j] = rnd.Rand8() - rnd.Rand8();
1811184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      input_extreme_block[j] = rnd.Rand8() & 1 ? 255 : -255;
182ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
183ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (i == 0)
1841184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      for (int j = 0; j < kNumCoeffs; ++j)
185ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        input_extreme_block[j] = 255;
1861184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    if (i == 1)
1871184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      for (int j = 0; j < kNumCoeffs; ++j)
1881184aebb761cbeac9124c37189a80a1a58f04b6bhkuang        input_extreme_block[j] = -255;
189ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1905ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    const int stride = 32;
1915ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    vp9_fdct32x32_c(input_extreme_block, output_ref_block, stride);
1925ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    REGISTER_STATE_CHECK(fwd_txfm_(input_extreme_block, output_block, stride));
193ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
194ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    // The minimum quant value is 4.
1951184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    for (int j = 0; j < kNumCoeffs; ++j) {
1961184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      if (version_ == 0) {
1971184aebb761cbeac9124c37189a80a1a58f04b6bhkuang        EXPECT_EQ(output_block[j], output_ref_block[j])
1981184aebb761cbeac9124c37189a80a1a58f04b6bhkuang            << "Error: 32x32 FDCT versions have mismatched coefficients";
1991184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      } else {
2001184aebb761cbeac9124c37189a80a1a58f04b6bhkuang        EXPECT_GE(6, abs(output_block[j] - output_ref_block[j]))
2011184aebb761cbeac9124c37189a80a1a58f04b6bhkuang            << "Error: 32x32 FDCT rd has mismatched coefficients";
2021184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      }
2031184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      EXPECT_GE(4 * DCT_MAX_VALUE, abs(output_ref_block[j]))
2041184aebb761cbeac9124c37189a80a1a58f04b6bhkuang          << "Error: 32x32 FDCT C has coefficient larger than 4*DCT_MAX_VALUE";
2051184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      EXPECT_GE(4 * DCT_MAX_VALUE, abs(output_block[j]))
2061184aebb761cbeac9124c37189a80a1a58f04b6bhkuang          << "Error: 32x32 FDCT has coefficient larger than "
2071184aebb761cbeac9124c37189a80a1a58f04b6bhkuang          << "4*DCT_MAX_VALUE";
208ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
209ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
210ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
2111184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
2121184aebb761cbeac9124c37189a80a1a58f04b6bhkuangTEST_P(Trans32x32Test, InverseAccuracy) {
2131184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  ACMRandom rnd(ACMRandom::DeterministicSeed());
2141184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  const int count_test_block = 1000;
2151184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  DECLARE_ALIGNED_ARRAY(16, int16_t, in, kNumCoeffs);
2161184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  DECLARE_ALIGNED_ARRAY(16, int16_t, coeff, kNumCoeffs);
2171184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs);
2181184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs);
2191184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
2201184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  for (int i = 0; i < count_test_block; ++i) {
2211184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    double out_r[kNumCoeffs];
2221184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
2231184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    // Initialize a test block with input range [-255, 255]
2241184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    for (int j = 0; j < kNumCoeffs; ++j) {
2251184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      src[j] = rnd.Rand8();
2261184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      dst[j] = rnd.Rand8();
2271184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      in[j] = src[j] - dst[j];
2281184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    }
2291184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
2301184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    reference_32x32_dct_2d(in, out_r);
2311184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    for (int j = 0; j < kNumCoeffs; ++j)
2321184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      coeff[j] = round(out_r[j]);
2331184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    REGISTER_STATE_CHECK(inv_txfm_(coeff, dst, 32));
2341184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    for (int j = 0; j < kNumCoeffs; ++j) {
2351184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      const int diff = dst[j] - src[j];
2361184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      const int error = diff * diff;
2371184aebb761cbeac9124c37189a80a1a58f04b6bhkuang      EXPECT_GE(1, error)
2381184aebb761cbeac9124c37189a80a1a58f04b6bhkuang          << "Error: 32x32 IDCT has error " << error
2391184aebb761cbeac9124c37189a80a1a58f04b6bhkuang          << " at index " << j;
2401184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    }
2411184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  }
2421184aebb761cbeac9124c37189a80a1a58f04b6bhkuang}
2431184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
2441184aebb761cbeac9124c37189a80a1a58f04b6bhkuangusing std::tr1::make_tuple;
2451184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
2461184aebb761cbeac9124c37189a80a1a58f04b6bhkuangINSTANTIATE_TEST_CASE_P(
2471184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    C, Trans32x32Test,
2481184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    ::testing::Values(
2495ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang        make_tuple(&vp9_fdct32x32_c, &vp9_idct32x32_1024_add_c, 0),
2505ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang        make_tuple(&vp9_fdct32x32_rd_c, &vp9_idct32x32_1024_add_c, 1)));
2511184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
2521184aebb761cbeac9124c37189a80a1a58f04b6bhkuang#if HAVE_SSE2
2531184aebb761cbeac9124c37189a80a1a58f04b6bhkuangINSTANTIATE_TEST_CASE_P(
2541184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    SSE2, Trans32x32Test,
2551184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    ::testing::Values(
2565ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang        make_tuple(&vp9_fdct32x32_sse2,
2575ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang                   &vp9_idct32x32_1024_add_sse2, 0),
2585ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang        make_tuple(&vp9_fdct32x32_rd_sse2,
2595ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang                   &vp9_idct32x32_1024_add_sse2, 1)));
2601184aebb761cbeac9124c37189a80a1a58f04b6bhkuang#endif
261ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}  // namespace
262