1d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org/*
2d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
3d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org *
4d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org *  Use of this source code is governed by a BSD-style license
5d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org *  that can be found in the LICENSE file in the root of the source
6d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org *  tree. An additional intellectual property rights grant can be found
7d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org *  in the file PATENTS.  All contributing project authors may
8d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org *  be found in the AUTHORS file in the root of the source tree.
9d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org */
10d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
11d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org#include <math.h>
12d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org#include <stdlib.h>
13d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org#include <string.h>
14d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
15d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org#include "third_party/googletest/src/include/gtest/gtest.h"
16f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org#include "test/acm_random.h"
17f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org#include "test/clear_system_state.h"
18f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org#include "test/register_state_check.h"
19f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org#include "test/util.h"
20d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
21f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org#include "./vpx_config.h"
22d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org#include "./vp9_rtcd.h"
23dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org#include "vp9/common/vp9_entropy.h"
2487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#include "vpx/vpx_codec.h"
25d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org#include "vpx/vpx_integer.h"
26d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
27d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.orgusing libvpx_test::ACMRandom;
28d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
29d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.orgnamespace {
30d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org#ifdef _MSC_VER
31d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.orgstatic int round(double x) {
32d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  if (x < 0)
33f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    return static_cast<int>(ceil(x - 0.5));
34d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  else
35f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    return static_cast<int>(floor(x + 0.5));
36d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org}
37d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org#endif
38d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
39f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.orgconst int kNumCoeffs = 1024;
40f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.orgconst double kPi = 3.141592653589793238462643383279502884;
41d95585fb0ec024f6abd96f7b02e0df58019d46afjohannkoenig@chromium.orgvoid reference_32x32_dct_1d(const double in[32], double out[32]) {
42d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  const double kInvSqrt2 = 0.707106781186547524400844362104;
43d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  for (int k = 0; k < 32; k++) {
44d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    out[k] = 0.0;
45d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    for (int n = 0; n < 32; n++)
46d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org      out[k] += in[n] * cos(kPi * (2 * n + 1) * k / 64.0);
47d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    if (k == 0)
48d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org      out[k] = out[k] * kInvSqrt2;
49d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  }
50d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org}
51d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
52f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.orgvoid reference_32x32_dct_2d(const int16_t input[kNumCoeffs],
53f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org                            double output[kNumCoeffs]) {
54d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  // First transform columns
55d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  for (int i = 0; i < 32; ++i) {
56d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    double temp_in[32], temp_out[32];
57d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    for (int j = 0; j < 32; ++j)
58d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org      temp_in[j] = input[j*32 + i];
59d95585fb0ec024f6abd96f7b02e0df58019d46afjohannkoenig@chromium.org    reference_32x32_dct_1d(temp_in, temp_out);
60d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    for (int j = 0; j < 32; ++j)
61d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org      output[j * 32 + i] = temp_out[j];
62d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  }
63d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  // Then transform rows
64d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  for (int i = 0; i < 32; ++i) {
65d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    double temp_in[32], temp_out[32];
66d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    for (int j = 0; j < 32; ++j)
67d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org      temp_in[j] = output[j + i*32];
68d95585fb0ec024f6abd96f7b02e0df58019d46afjohannkoenig@chromium.org    reference_32x32_dct_1d(temp_in, temp_out);
69d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    // Scale by some magic number
70d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    for (int j = 0; j < 32; ++j)
71d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org      output[j + i * 32] = temp_out[j] / 4;
72d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  }
73d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org}
74d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
7587997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.orgtypedef void (*FwdTxfmFunc)(const int16_t *in, tran_low_t *out, int stride);
7687997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.orgtypedef void (*InvTxfmFunc)(const tran_low_t *in, uint8_t *out, int stride);
77d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
7887997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.orgtypedef std::tr1::tuple<FwdTxfmFunc, InvTxfmFunc, int, vpx_bit_depth_t>
7987997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org    Trans32x32Param;
8087997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org
8187997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if CONFIG_VP9_HIGHBITDEPTH
8287997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.orgvoid idct32x32_10(const tran_low_t *in, uint8_t *out, int stride) {
8387997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org  vp9_high_idct32x32_1024_add_c(in, out, stride, 10);
8487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org}
8587997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org
8687997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.orgvoid idct32x32_12(const tran_low_t *in, uint8_t *out, int stride) {
8787997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org  vp9_high_idct32x32_1024_add_c(in, out, stride, 12);
8887997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org}
8987997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif
90d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org
91ac4e313c19203132648a2a271703b6ee76fe4284johannkoenig@chromium.orgclass Trans32x32Test : public ::testing::TestWithParam<Trans32x32Param> {
92f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org public:
93f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  virtual ~Trans32x32Test() {}
94f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  virtual void SetUp() {
95f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    fwd_txfm_ = GET_PARAM(0);
96f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    inv_txfm_ = GET_PARAM(1);
97f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    version_  = GET_PARAM(2);  // 0: high precision forward transform
98f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org                               // 1: low precision version for rd loop
9987997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org    bit_depth_ = GET_PARAM(3);
10087997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org    mask_ = (1 << bit_depth_) - 1;
101d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  }
102923acb6a717b7f2719ed21184c1bc533b0a14888johannkoenig@chromium.org
103f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  virtual void TearDown() { libvpx_test::ClearSystemState(); }
104f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org
105f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org protected:
106f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  int version_;
10787997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org  vpx_bit_depth_t bit_depth_;
10887997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org  int mask_;
109ac4e313c19203132648a2a271703b6ee76fe4284johannkoenig@chromium.org  FwdTxfmFunc fwd_txfm_;
110ac4e313c19203132648a2a271703b6ee76fe4284johannkoenig@chromium.org  InvTxfmFunc inv_txfm_;
111f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org};
112f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org
113f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.orgTEST_P(Trans32x32Test, AccuracyCheck) {
114d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  ACMRandom rnd(ACMRandom::DeterministicSeed());
115f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  uint32_t max_error = 0;
116d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  int64_t total_error = 0;
117d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  const int count_test_block = 1000;
118f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, kNumCoeffs);
11987997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org  DECLARE_ALIGNED_ARRAY(16, tran_low_t, test_temp_block, kNumCoeffs);
120f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs);
121f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs);
12287997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if CONFIG_VP9_HIGHBITDEPTH
12387997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org  DECLARE_ALIGNED_ARRAY(16, uint16_t, dst16, kNumCoeffs);
12487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org  DECLARE_ALIGNED_ARRAY(16, uint16_t, src16, kNumCoeffs);
12587997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif
126d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
127f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  for (int i = 0; i < count_test_block; ++i) {
12887997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org    // Initialize a test block with input range [-mask_, mask_].
129f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    for (int j = 0; j < kNumCoeffs; ++j) {
13087997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org      if (bit_depth_ == 8) {
13187997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        src[j] = rnd.Rand8();
13287997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        dst[j] = rnd.Rand8();
13387997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        test_input_block[j] = src[j] - dst[j];
13487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if CONFIG_VP9_HIGHBITDEPTH
13587997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org      } else {
13687997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        src16[j] = rnd.Rand16() & mask_;
13787997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        dst16[j] = rnd.Rand16() & mask_;
13887997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        test_input_block[j] = src16[j] - dst16[j];
13987997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif
14087997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org      }
141f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    }
142d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
14395aa45d73048f952dcaad0037429cc6751b34f2fjohannkoenig@google.com    ASM_REGISTER_STATE_CHECK(fwd_txfm_(test_input_block, test_temp_block, 32));
14487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org    if (bit_depth_ == VPX_BITS_8) {
14587997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org      ASM_REGISTER_STATE_CHECK(inv_txfm_(test_temp_block, dst, 32));
14687997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if CONFIG_VP9_HIGHBITDEPTH
14787997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org    } else {
14887997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org      ASM_REGISTER_STATE_CHECK(inv_txfm_(test_temp_block,
14987997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org                                         CONVERT_TO_BYTEPTR(dst16), 32));
15087997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif
15187997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org    }
152d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
153f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    for (int j = 0; j < kNumCoeffs; ++j) {
15487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if CONFIG_VP9_HIGHBITDEPTH
15587997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org      const uint32_t diff =
15687997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org          bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
15787997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#else
158f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org      const uint32_t diff = dst[j] - src[j];
15987997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif
160f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org      const uint32_t error = diff * diff;
161d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org      if (max_error < error)
162d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org        max_error = error;
163d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org      total_error += error;
164d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    }
165d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  }
166d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
167f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  if (version_ == 1) {
168f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    max_error /= 2;
169f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    total_error /= 45;
170f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  }
171f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org
17287997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org  EXPECT_GE(1u << 2 * (bit_depth_ - 8), max_error)
173f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org      << "Error: 32x32 FDCT/IDCT has an individual round-trip error > 1";
174d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
17587997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org  EXPECT_GE(count_test_block << 2 * (bit_depth_ - 8), total_error)
176f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org      << "Error: 32x32 FDCT/IDCT has average round-trip error > 1 per block";
177d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org}
178d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
179f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.orgTEST_P(Trans32x32Test, CoeffCheck) {
180d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  ACMRandom rnd(ACMRandom::DeterministicSeed());
181d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  const int count_test_block = 1000;
182f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org
183f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs);
18487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org  DECLARE_ALIGNED_ARRAY(16, tran_low_t, output_ref_block, kNumCoeffs);
18587997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org  DECLARE_ALIGNED_ARRAY(16, tran_low_t, output_block, kNumCoeffs);
186f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org
187d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  for (int i = 0; i < count_test_block; ++i) {
188f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    for (int j = 0; j < kNumCoeffs; ++j)
18987997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org      input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_);
190f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org
1910d106b34dc08439a7c6887d1316a3e1a35f8f0cajohannkoenig@chromium.org    const int stride = 32;
1920d106b34dc08439a7c6887d1316a3e1a35f8f0cajohannkoenig@chromium.org    vp9_fdct32x32_c(input_block, output_ref_block, stride);
19395aa45d73048f952dcaad0037429cc6751b34f2fjohannkoenig@google.com    ASM_REGISTER_STATE_CHECK(fwd_txfm_(input_block, output_block, stride));
194f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org
195f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    if (version_ == 0) {
196f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org      for (int j = 0; j < kNumCoeffs; ++j)
197f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org        EXPECT_EQ(output_block[j], output_ref_block[j])
198f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org            << "Error: 32x32 FDCT versions have mismatched coefficients";
199f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    } else {
200f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org      for (int j = 0; j < kNumCoeffs; ++j)
201f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org        EXPECT_GE(6, abs(output_block[j] - output_ref_block[j]))
202f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org            << "Error: 32x32 FDCT rd has mismatched coefficients";
203f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    }
204f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  }
205f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org}
206f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org
207f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.orgTEST_P(Trans32x32Test, MemCheck) {
208f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  ACMRandom rnd(ACMRandom::DeterministicSeed());
209f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  const int count_test_block = 2000;
210f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org
211f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs);
212f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  DECLARE_ALIGNED_ARRAY(16, int16_t, input_extreme_block, kNumCoeffs);
21387997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org  DECLARE_ALIGNED_ARRAY(16, tran_low_t, output_ref_block, kNumCoeffs);
21487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org  DECLARE_ALIGNED_ARRAY(16, tran_low_t, output_block, kNumCoeffs);
215d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
216f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  for (int i = 0; i < count_test_block; ++i) {
21787997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org    // Initialize a test block with input range [-mask_, mask_].
218f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    for (int j = 0; j < kNumCoeffs; ++j) {
21987997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org      input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_);
22087997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org      input_extreme_block[j] = rnd.Rand8() & 1 ? mask_ : -mask_;
221d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    }
22288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (i == 0) {
223f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org      for (int j = 0; j < kNumCoeffs; ++j)
22487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        input_extreme_block[j] = mask_;
22588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    } else if (i == 1) {
226f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org      for (int j = 0; j < kNumCoeffs; ++j)
22787997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        input_extreme_block[j] = -mask_;
22888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
229d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
2300d106b34dc08439a7c6887d1316a3e1a35f8f0cajohannkoenig@chromium.org    const int stride = 32;
2310d106b34dc08439a7c6887d1316a3e1a35f8f0cajohannkoenig@chromium.org    vp9_fdct32x32_c(input_extreme_block, output_ref_block, stride);
23295aa45d73048f952dcaad0037429cc6751b34f2fjohannkoenig@google.com    ASM_REGISTER_STATE_CHECK(
23395aa45d73048f952dcaad0037429cc6751b34f2fjohannkoenig@google.com        fwd_txfm_(input_extreme_block, output_block, stride));
234d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
235d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    // The minimum quant value is 4.
236f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    for (int j = 0; j < kNumCoeffs; ++j) {
237f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org      if (version_ == 0) {
238f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org        EXPECT_EQ(output_block[j], output_ref_block[j])
239f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org            << "Error: 32x32 FDCT versions have mismatched coefficients";
240f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org      } else {
241f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org        EXPECT_GE(6, abs(output_block[j] - output_ref_block[j]))
242f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org            << "Error: 32x32 FDCT rd has mismatched coefficients";
243f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org      }
24487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org      EXPECT_GE(4 * DCT_MAX_VALUE << (bit_depth_ - 8), abs(output_ref_block[j]))
245f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org          << "Error: 32x32 FDCT C has coefficient larger than 4*DCT_MAX_VALUE";
24687997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org      EXPECT_GE(4 * DCT_MAX_VALUE << (bit_depth_ - 8), abs(output_block[j]))
247f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org          << "Error: 32x32 FDCT has coefficient larger than "
248f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org          << "4*DCT_MAX_VALUE";
249d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    }
250d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  }
251d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org}
252f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org
253f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.orgTEST_P(Trans32x32Test, InverseAccuracy) {
254f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  ACMRandom rnd(ACMRandom::DeterministicSeed());
255f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  const int count_test_block = 1000;
256f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  DECLARE_ALIGNED_ARRAY(16, int16_t, in, kNumCoeffs);
25787997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org  DECLARE_ALIGNED_ARRAY(16, tran_low_t, coeff, kNumCoeffs);
258f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs);
259f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs);
26087997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if CONFIG_VP9_HIGHBITDEPTH
26187997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org  DECLARE_ALIGNED_ARRAY(16, uint16_t, dst16, kNumCoeffs);
26287997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org  DECLARE_ALIGNED_ARRAY(16, uint16_t, src16, kNumCoeffs);
26387997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif
264f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org
265f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  for (int i = 0; i < count_test_block; ++i) {
266f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    double out_r[kNumCoeffs];
267f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org
268f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    // Initialize a test block with input range [-255, 255]
269f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    for (int j = 0; j < kNumCoeffs; ++j) {
27087997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org      if (bit_depth_ == VPX_BITS_8) {
27187997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        src[j] = rnd.Rand8();
27287997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        dst[j] = rnd.Rand8();
27387997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        in[j] = src[j] - dst[j];
27487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if CONFIG_VP9_HIGHBITDEPTH
27587997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org      } else {
27687997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        src16[j] = rnd.Rand16() & mask_;
27787997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        dst16[j] = rnd.Rand16() & mask_;
27887997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        in[j] = src16[j] - dst16[j];
27987997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif
28087997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org      }
281f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    }
282f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org
283f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    reference_32x32_dct_2d(in, out_r);
284f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    for (int j = 0; j < kNumCoeffs; ++j)
285f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org      coeff[j] = round(out_r[j]);
28687997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org    if (bit_depth_ == VPX_BITS_8) {
28787997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org      ASM_REGISTER_STATE_CHECK(inv_txfm_(coeff, dst, 32));
28887997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if CONFIG_VP9_HIGHBITDEPTH
28987997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org    } else {
29087997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org      ASM_REGISTER_STATE_CHECK(inv_txfm_(coeff, CONVERT_TO_BYTEPTR(dst16), 32));
29187997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif
29287997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org    }
293f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    for (int j = 0; j < kNumCoeffs; ++j) {
29487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if CONFIG_VP9_HIGHBITDEPTH
29587997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org      const int diff =
29687997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org          bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
29787997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#else
298f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org      const int diff = dst[j] - src[j];
29987997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif
300f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org      const int error = diff * diff;
301f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org      EXPECT_GE(1, error)
302f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org          << "Error: 32x32 IDCT has error " << error
303f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org          << " at index " << j;
304f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    }
305f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  }
306f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org}
307f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org
308f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.orgusing std::tr1::make_tuple;
309f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org
31087997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if CONFIG_VP9_HIGHBITDEPTH
31187997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.orgINSTANTIATE_TEST_CASE_P(
31287997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org    C, Trans32x32Test,
31387997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org    ::testing::Values(
31487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        make_tuple(&vp9_high_fdct32x32_c,
31587997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org                   &idct32x32_10, 0, VPX_BITS_10),
31687997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        make_tuple(&vp9_high_fdct32x32_rd_c,
31787997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org                   &idct32x32_10, 1, VPX_BITS_10),
31887997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        make_tuple(&vp9_high_fdct32x32_c,
31987997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org                   &idct32x32_12, 0, VPX_BITS_12),
32087997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        make_tuple(&vp9_high_fdct32x32_rd_c,
32187997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org                   &idct32x32_12, 1, VPX_BITS_12),
32287997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        make_tuple(&vp9_fdct32x32_c,
32387997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org                   &vp9_idct32x32_1024_add_c, 0, VPX_BITS_8),
32487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        make_tuple(&vp9_fdct32x32_rd_c,
32587997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org                   &vp9_idct32x32_1024_add_c, 1, VPX_BITS_8)));
32687997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#else
327f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.orgINSTANTIATE_TEST_CASE_P(
328f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    C, Trans32x32Test,
329f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    ::testing::Values(
33087997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        make_tuple(&vp9_fdct32x32_c,
33187997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org                   &vp9_idct32x32_1024_add_c, 0, VPX_BITS_8),
33287997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org        make_tuple(&vp9_fdct32x32_rd_c,
33387997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org                   &vp9_idct32x32_1024_add_c, 1, VPX_BITS_8)));
33487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif
335f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org
33687997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH
337411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.orgINSTANTIATE_TEST_CASE_P(
338411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org    NEON, Trans32x32Test,
339411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org    ::testing::Values(
340411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org        make_tuple(&vp9_fdct32x32_c,
34187997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org                   &vp9_idct32x32_1024_add_neon, 0, VPX_BITS_8),
342411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org        make_tuple(&vp9_fdct32x32_rd_c,
34387997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org                   &vp9_idct32x32_1024_add_neon, 1, VPX_BITS_8)));
344411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org#endif
345411971f94253c85e1866c281860d6344f6aa0c78fgalligan@chromium.org
34687997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH
347f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.orgINSTANTIATE_TEST_CASE_P(
348f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    SSE2, Trans32x32Test,
349f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    ::testing::Values(
3500d106b34dc08439a7c6887d1316a3e1a35f8f0cajohannkoenig@chromium.org        make_tuple(&vp9_fdct32x32_sse2,
35187997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org                   &vp9_idct32x32_1024_add_sse2, 0, VPX_BITS_8),
3520d106b34dc08439a7c6887d1316a3e1a35f8f0cajohannkoenig@chromium.org        make_tuple(&vp9_fdct32x32_rd_sse2,
35387997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org                   &vp9_idct32x32_1024_add_sse2, 1, VPX_BITS_8)));
354f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org#endif
355d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org
35687997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if HAVE_AVX2 && !CONFIG_VP9_HIGHBITDEPTH
357d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.orgINSTANTIATE_TEST_CASE_P(
358d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org    AVX2, Trans32x32Test,
359d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org    ::testing::Values(
360d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org        make_tuple(&vp9_fdct32x32_avx2,
36187997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org                   &vp9_idct32x32_1024_add_sse2, 0, VPX_BITS_8),
362d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org        make_tuple(&vp9_fdct32x32_rd_avx2,
36387997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org                   &vp9_idct32x32_1024_add_sse2, 1, VPX_BITS_8)));
364d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.org#endif
365d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org}  // namespace
366