fdct8x8_test.cc revision 91037db265ecdd914a26e056cf69207b4f50924e
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"
1691037db265ecdd914a26e056cf69207b4f50924ehkuang#include "vpx_ports/mem.h"
17ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
18ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangextern "C" {
19ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "vp9_rtcd.h"
20ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangvoid vp9_short_idct8x8_add_c(short *input, uint8_t *output, int pitch);
21ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
22ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
23ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "acm_random.h"
24ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "vpx/vpx_integer.h"
25ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
26ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangusing libvpx_test::ACMRandom;
27ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
28ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangnamespace {
2991037db265ecdd914a26e056cf69207b4f50924ehkuangvoid fdct8x8(int16_t *in, int16_t *out, uint8_t* /*dst*/,
3091037db265ecdd914a26e056cf69207b4f50924ehkuang             int stride, int /*tx_type*/) {
3191037db265ecdd914a26e056cf69207b4f50924ehkuang  vp9_short_fdct8x8_c(in, out, stride);
3291037db265ecdd914a26e056cf69207b4f50924ehkuang}
3391037db265ecdd914a26e056cf69207b4f50924ehkuangvoid idct8x8_add(int16_t* /*in*/, int16_t *out, uint8_t *dst,
3491037db265ecdd914a26e056cf69207b4f50924ehkuang                 int stride, int /*tx_type*/) {
3591037db265ecdd914a26e056cf69207b4f50924ehkuang  vp9_short_idct8x8_add_c(out, dst, stride >> 1);
3691037db265ecdd914a26e056cf69207b4f50924ehkuang}
3791037db265ecdd914a26e056cf69207b4f50924ehkuangvoid fht8x8(int16_t *in, int16_t *out, uint8_t* /*dst*/,
3891037db265ecdd914a26e056cf69207b4f50924ehkuang            int stride, int tx_type) {
3991037db265ecdd914a26e056cf69207b4f50924ehkuang  // TODO(jingning): need to refactor this to test both _c and _sse2 functions,
4091037db265ecdd914a26e056cf69207b4f50924ehkuang  // when we have all inverse dct functions done sse2.
4191037db265ecdd914a26e056cf69207b4f50924ehkuang#if HAVE_SSE2
4291037db265ecdd914a26e056cf69207b4f50924ehkuang  vp9_short_fht8x8_sse2(in, out, stride >> 1, tx_type);
4391037db265ecdd914a26e056cf69207b4f50924ehkuang#else
4491037db265ecdd914a26e056cf69207b4f50924ehkuang  vp9_short_fht8x8_c(in, out, stride >> 1, tx_type);
4591037db265ecdd914a26e056cf69207b4f50924ehkuang#endif
4691037db265ecdd914a26e056cf69207b4f50924ehkuang}
4791037db265ecdd914a26e056cf69207b4f50924ehkuangvoid iht8x8_add(int16_t* /*in*/, int16_t *out, uint8_t *dst,
4891037db265ecdd914a26e056cf69207b4f50924ehkuang                int stride, int tx_type) {
4991037db265ecdd914a26e056cf69207b4f50924ehkuang  vp9_short_iht8x8_add_c(out, dst, stride >> 1, tx_type);
5091037db265ecdd914a26e056cf69207b4f50924ehkuang}
5191037db265ecdd914a26e056cf69207b4f50924ehkuang
5291037db265ecdd914a26e056cf69207b4f50924ehkuangclass FwdTrans8x8Test : public ::testing::TestWithParam<int> {
5391037db265ecdd914a26e056cf69207b4f50924ehkuang public:
5491037db265ecdd914a26e056cf69207b4f50924ehkuang  virtual ~FwdTrans8x8Test() {}
5591037db265ecdd914a26e056cf69207b4f50924ehkuang  virtual void SetUp() {
5691037db265ecdd914a26e056cf69207b4f50924ehkuang    tx_type_ = GetParam();
5791037db265ecdd914a26e056cf69207b4f50924ehkuang    if (tx_type_ == 0) {
5891037db265ecdd914a26e056cf69207b4f50924ehkuang      fwd_txfm = fdct8x8;
5991037db265ecdd914a26e056cf69207b4f50924ehkuang      inv_txfm = idct8x8_add;
6091037db265ecdd914a26e056cf69207b4f50924ehkuang    } else {
6191037db265ecdd914a26e056cf69207b4f50924ehkuang      fwd_txfm = fht8x8;
6291037db265ecdd914a26e056cf69207b4f50924ehkuang      inv_txfm = iht8x8_add;
6391037db265ecdd914a26e056cf69207b4f50924ehkuang    }
6491037db265ecdd914a26e056cf69207b4f50924ehkuang  }
6591037db265ecdd914a26e056cf69207b4f50924ehkuang
6691037db265ecdd914a26e056cf69207b4f50924ehkuang protected:
6791037db265ecdd914a26e056cf69207b4f50924ehkuang  void RunFwdTxfm(int16_t *in, int16_t *out, uint8_t *dst,
6891037db265ecdd914a26e056cf69207b4f50924ehkuang                  int stride, int tx_type) {
6991037db265ecdd914a26e056cf69207b4f50924ehkuang    (*fwd_txfm)(in, out, dst, stride, tx_type);
7091037db265ecdd914a26e056cf69207b4f50924ehkuang  }
7191037db265ecdd914a26e056cf69207b4f50924ehkuang  void RunInvTxfm(int16_t *in, int16_t *out, uint8_t *dst,
7291037db265ecdd914a26e056cf69207b4f50924ehkuang                  int stride, int tx_type) {
7391037db265ecdd914a26e056cf69207b4f50924ehkuang    (*inv_txfm)(in, out, dst, stride, tx_type);
7491037db265ecdd914a26e056cf69207b4f50924ehkuang  }
7591037db265ecdd914a26e056cf69207b4f50924ehkuang
7691037db265ecdd914a26e056cf69207b4f50924ehkuang  int tx_type_;
7791037db265ecdd914a26e056cf69207b4f50924ehkuang  void (*fwd_txfm)(int16_t*, int16_t*, uint8_t*, int, int);
7891037db265ecdd914a26e056cf69207b4f50924ehkuang  void (*inv_txfm)(int16_t*, int16_t*, uint8_t*, int, int);
7991037db265ecdd914a26e056cf69207b4f50924ehkuang};
80ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
8191037db265ecdd914a26e056cf69207b4f50924ehkuangTEST_P(FwdTrans8x8Test, SignBiasCheck) {
82ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  ACMRandom rnd(ACMRandom::DeterministicSeed());
8391037db265ecdd914a26e056cf69207b4f50924ehkuang  DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, 64);
8491037db265ecdd914a26e056cf69207b4f50924ehkuang  DECLARE_ALIGNED_ARRAY(16, int16_t, test_output_block, 64);
85ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  const int pitch = 16;
86ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  int count_sign_block[64][2];
87ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  const int count_test_block = 100000;
88ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
89ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  memset(count_sign_block, 0, sizeof(count_sign_block));
90ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
91ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for (int i = 0; i < count_test_block; ++i) {
92ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    // Initialize a test block with input range [-255, 255].
93ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for (int j = 0; j < 64; ++j)
94ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      test_input_block[j] = rnd.Rand8() - rnd.Rand8();
95ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
9691037db265ecdd914a26e056cf69207b4f50924ehkuang    RunFwdTxfm(test_input_block, test_output_block, NULL, pitch, tx_type_);
97ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
98ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for (int j = 0; j < 64; ++j) {
99ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (test_output_block[j] < 0)
100ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        ++count_sign_block[j][0];
101ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      else if (test_output_block[j] > 0)
102ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        ++count_sign_block[j][1];
103ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
104ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
105ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
106ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for (int j = 0; j < 64; ++j) {
107ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]);
108ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int max_diff = 1125;
109ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    EXPECT_LT(diff, max_diff)
11091037db265ecdd914a26e056cf69207b4f50924ehkuang        << "Error: 8x8 FDCT/FHT has a sign bias > "
111ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        << 1. * max_diff / count_test_block * 100 << "%"
112ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        << " for input range [-255, 255] at index " << j
113ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        << " count0: " << count_sign_block[j][0]
114ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        << " count1: " << count_sign_block[j][1]
115ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        << " diff: " << diff;
116ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
117ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
118ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  memset(count_sign_block, 0, sizeof(count_sign_block));
119ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
120ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for (int i = 0; i < count_test_block; ++i) {
121ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    // Initialize a test block with input range [-15, 15].
122ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for (int j = 0; j < 64; ++j)
123ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      test_input_block[j] = (rnd.Rand8() >> 4) - (rnd.Rand8() >> 4);
124ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
12591037db265ecdd914a26e056cf69207b4f50924ehkuang    RunFwdTxfm(test_input_block, test_output_block, NULL, pitch, tx_type_);
126ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
127ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for (int j = 0; j < 64; ++j) {
128ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (test_output_block[j] < 0)
129ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        ++count_sign_block[j][0];
130ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      else if (test_output_block[j] > 0)
131ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        ++count_sign_block[j][1];
132ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
133ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
134ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
135ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for (int j = 0; j < 64; ++j) {
136ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]);
137ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int max_diff = 10000;
138ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    EXPECT_LT(diff, max_diff)
13991037db265ecdd914a26e056cf69207b4f50924ehkuang        << "Error: 4x4 FDCT/FHT has a sign bias > "
140ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        << 1. * max_diff / count_test_block * 100 << "%"
141ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        << " for input range [-15, 15] at index " << j
142ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        << " count0: " << count_sign_block[j][0]
143ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        << " count1: " << count_sign_block[j][1]
144ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        << " diff: " << diff;
145ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
14691037db265ecdd914a26e056cf69207b4f50924ehkuang}
147ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
14891037db265ecdd914a26e056cf69207b4f50924ehkuangTEST_P(FwdTrans8x8Test, RoundTripErrorCheck) {
149ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  ACMRandom rnd(ACMRandom::DeterministicSeed());
150ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  int max_error = 0;
151ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  double total_error = 0;
152ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  const int count_test_block = 100000;
153ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for (int i = 0; i < count_test_block; ++i) {
15491037db265ecdd914a26e056cf69207b4f50924ehkuang    DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, 64);
15591037db265ecdd914a26e056cf69207b4f50924ehkuang    DECLARE_ALIGNED_ARRAY(16, int16_t, test_temp_block, 64);
15691037db265ecdd914a26e056cf69207b4f50924ehkuang    DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, 64);
15791037db265ecdd914a26e056cf69207b4f50924ehkuang    DECLARE_ALIGNED_ARRAY(16, uint8_t, src, 64);
158ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
159ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for (int j = 0; j < 64; ++j) {
160ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      src[j] = rnd.Rand8();
161ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      dst[j] = rnd.Rand8();
162ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
163ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    // Initialize a test block with input range [-255, 255].
164ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for (int j = 0; j < 64; ++j)
165ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      test_input_block[j] = src[j] - dst[j];
166ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
167ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int pitch = 16;
16891037db265ecdd914a26e056cf69207b4f50924ehkuang    RunFwdTxfm(test_input_block, test_temp_block, dst, pitch, tx_type_);
169ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for (int j = 0; j < 64; ++j){
170ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if(test_temp_block[j] > 0) {
171ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          test_temp_block[j] += 2;
172ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          test_temp_block[j] /= 4;
173ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          test_temp_block[j] *= 4;
174ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        } else {
175ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          test_temp_block[j] -= 2;
176ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          test_temp_block[j] /= 4;
177ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          test_temp_block[j] *= 4;
178ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        }
179ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
18091037db265ecdd914a26e056cf69207b4f50924ehkuang    RunInvTxfm(test_input_block, test_temp_block, dst, pitch, tx_type_);
181ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
182ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for (int j = 0; j < 64; ++j) {
183ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      const int diff = dst[j] - src[j];
184ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      const int error = diff * diff;
185ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (max_error < error)
186ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        max_error = error;
187ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      total_error += error;
188ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
189ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
190ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
191ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  EXPECT_GE(1, max_error)
19291037db265ecdd914a26e056cf69207b4f50924ehkuang    << "Error: 8x8 FDCT/IDCT or FHT/IHT has an individual roundtrip error > 1";
193ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
194ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  EXPECT_GE(count_test_block/5, total_error)
19591037db265ecdd914a26e056cf69207b4f50924ehkuang    << "Error: 8x8 FDCT/IDCT or FHT/IHT has average roundtrip "
19691037db265ecdd914a26e056cf69207b4f50924ehkuang        "error > 1/5 per block";
19791037db265ecdd914a26e056cf69207b4f50924ehkuang}
198ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
19991037db265ecdd914a26e056cf69207b4f50924ehkuangTEST_P(FwdTrans8x8Test, ExtremalCheck) {
200ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  ACMRandom rnd(ACMRandom::DeterministicSeed());
201ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  int max_error = 0;
202ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  double total_error = 0;
203ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  const int count_test_block = 100000;
204ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for (int i = 0; i < count_test_block; ++i) {
20591037db265ecdd914a26e056cf69207b4f50924ehkuang    DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, 64);
20691037db265ecdd914a26e056cf69207b4f50924ehkuang    DECLARE_ALIGNED_ARRAY(16, int16_t, test_temp_block, 64);
20791037db265ecdd914a26e056cf69207b4f50924ehkuang    DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, 64);
20891037db265ecdd914a26e056cf69207b4f50924ehkuang    DECLARE_ALIGNED_ARRAY(16, uint8_t, src, 64);
209ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
210ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for (int j = 0; j < 64; ++j) {
211ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      src[j] = rnd.Rand8() % 2 ? 255 : 0;
212ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      dst[j] = src[j] > 0 ? 0 : 255;
213ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
214ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    // Initialize a test block with input range [-255, 255].
215ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for (int j = 0; j < 64; ++j)
216ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      test_input_block[j] = src[j] - dst[j];
217ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
218ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int pitch = 16;
21991037db265ecdd914a26e056cf69207b4f50924ehkuang    RunFwdTxfm(test_input_block, test_temp_block, dst, pitch, tx_type_);
22091037db265ecdd914a26e056cf69207b4f50924ehkuang    RunInvTxfm(test_input_block, test_temp_block, dst, pitch, tx_type_);
221ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
222ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for (int j = 0; j < 64; ++j) {
223ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      const int diff = dst[j] - src[j];
224ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      const int error = diff * diff;
225ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (max_error < error)
226ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        max_error = error;
227ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      total_error += error;
228ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
229ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
230ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    EXPECT_GE(1, max_error)
23191037db265ecdd914a26e056cf69207b4f50924ehkuang        << "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has an"
232ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        << " individual roundtrip error > 1";
233ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
234ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    EXPECT_GE(count_test_block/5, total_error)
23591037db265ecdd914a26e056cf69207b4f50924ehkuang        << "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has average"
236ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        << " roundtrip error > 1/5 per block";
237ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
23891037db265ecdd914a26e056cf69207b4f50924ehkuang}
239ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
24091037db265ecdd914a26e056cf69207b4f50924ehkuangINSTANTIATE_TEST_CASE_P(VP9, FwdTrans8x8Test, ::testing::Range(0, 4));
241ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}  // namespace
242