av1_convolve_ x,y _avx2() -- use 256 bit load/store
[aom.git] / test / av1_inv_txfm2d_test.cc
blobd8ddd2e3353f1c16cb8c20e100bf520510c0b734
1 /*
2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
4 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
12 #include <math.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <vector>
17 #include "./av1_rtcd.h"
18 #include "test/acm_random.h"
19 #include "test/util.h"
20 #include "test/av1_txfm_test.h"
21 #include "av1/common/av1_inv_txfm1d_cfg.h"
23 using libaom_test::ACMRandom;
24 using libaom_test::input_base;
25 using libaom_test::bd;
26 using libaom_test::compute_avg_abs_error;
27 using libaom_test::Fwd_Txfm2d_Func;
28 using libaom_test::Inv_Txfm2d_Func;
30 using std::vector;
32 namespace {
34 // AV1InvTxfm2dParam argument list:
35 // tx_type_, tx_size_, max_error_, max_avg_error_
36 typedef std::tr1::tuple<TX_TYPE, TX_SIZE, int, double> AV1InvTxfm2dParam;
38 class AV1InvTxfm2d : public ::testing::TestWithParam<AV1InvTxfm2dParam> {
39 public:
40 virtual void SetUp() {
41 tx_type_ = GET_PARAM(0);
42 tx_size_ = GET_PARAM(1);
43 max_error_ = GET_PARAM(2);
44 max_avg_error_ = GET_PARAM(3);
47 void RunRoundtripCheck() {
48 int tx_w = tx_size_wide[tx_size_];
49 int tx_h = tx_size_high[tx_size_];
50 int txfm2d_size = tx_w * tx_h;
51 const Fwd_Txfm2d_Func fwd_txfm_func =
52 libaom_test::fwd_txfm_func_ls[tx_size_];
53 const Inv_Txfm2d_Func inv_txfm_func =
54 libaom_test::inv_txfm_func_ls[tx_size_];
55 double avg_abs_error = 0;
56 ACMRandom rnd(ACMRandom::DeterministicSeed());
58 const int count = 500;
60 for (int ci = 0; ci < count; ci++) {
61 DECLARE_ALIGNED(16, int16_t, input[64 * 64]) = { 0 };
62 ASSERT_LE(txfm2d_size, NELEMENTS(input));
64 for (int ni = 0; ni < txfm2d_size; ++ni) {
65 if (ci == 0) {
66 int extreme_input = input_base - 1;
67 input[ni] = extreme_input; // extreme case
68 } else {
69 input[ni] = rnd.Rand16() % input_base;
73 DECLARE_ALIGNED(16, uint16_t, expected[64 * 64]) = { 0 };
74 ASSERT_LE(txfm2d_size, NELEMENTS(expected));
75 if (TxfmUsesApproximation()) {
76 // Compare reference forward HT + inverse HT vs forward HT + inverse HT.
77 double ref_input[64 * 64];
78 ASSERT_LE(txfm2d_size, NELEMENTS(ref_input));
79 for (int ni = 0; ni < txfm2d_size; ++ni) {
80 ref_input[ni] = input[ni];
82 double ref_coeffs[64 * 64] = { 0 };
83 ASSERT_LE(txfm2d_size, NELEMENTS(ref_coeffs));
84 ASSERT_EQ(tx_type_, DCT_DCT);
85 libaom_test::reference_hybrid_2d(ref_input, ref_coeffs, tx_type_,
86 tx_size_);
87 DECLARE_ALIGNED(16, int32_t, ref_coeffs_int[64 * 64]) = { 0 };
88 ASSERT_LE(txfm2d_size, NELEMENTS(ref_coeffs_int));
89 for (int ni = 0; ni < txfm2d_size; ++ni) {
90 ref_coeffs_int[ni] = (int32_t)round(ref_coeffs[ni]);
92 inv_txfm_func(ref_coeffs_int, expected, tx_w, tx_type_, bd);
93 } else {
94 // Compare original input vs forward HT + inverse HT.
95 for (int ni = 0; ni < txfm2d_size; ++ni) {
96 expected[ni] = input[ni];
100 DECLARE_ALIGNED(16, int32_t, coeffs[64 * 64]) = { 0 };
101 ASSERT_LE(txfm2d_size, NELEMENTS(coeffs));
102 fwd_txfm_func(input, coeffs, tx_w, tx_type_, bd);
104 DECLARE_ALIGNED(16, uint16_t, actual[64 * 64]) = { 0 };
105 ASSERT_LE(txfm2d_size, NELEMENTS(actual));
106 inv_txfm_func(coeffs, actual, tx_w, tx_type_, bd);
108 double actual_max_error = 0;
109 for (int ni = 0; ni < txfm2d_size; ++ni) {
110 const double this_error = abs(expected[ni] - actual[ni]);
111 actual_max_error = AOMMAX(actual_max_error, this_error);
113 EXPECT_GE(max_error_, actual_max_error)
114 << " tx_w: " << tx_w << " tx_h " << tx_h << " tx_type: " << tx_type_;
115 if (actual_max_error > max_error_) { // exit early.
116 break;
118 avg_abs_error += compute_avg_abs_error<uint16_t, uint16_t>(
119 expected, actual, txfm2d_size);
122 avg_abs_error /= count;
123 EXPECT_GE(max_avg_error_, avg_abs_error)
124 << " tx_w: " << tx_w << " tx_h " << tx_h << " tx_type: " << tx_type_;
127 private:
128 bool TxfmUsesApproximation() {
129 #if CONFIG_TX64X64
130 if (tx_size_wide[tx_size_] == 64 || tx_size_high[tx_size_] == 64) {
131 return true;
133 #endif // CONFIG_TX64X64
134 return false;
137 int max_error_;
138 double max_avg_error_;
139 TX_TYPE tx_type_;
140 TX_SIZE tx_size_;
143 vector<AV1InvTxfm2dParam> GetInvTxfm2dParamList() {
144 vector<AV1InvTxfm2dParam> param_list;
145 for (int t = 0; t <= FLIPADST_ADST; ++t) {
146 const TX_TYPE tx_type = static_cast<TX_TYPE>(t);
147 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_4X4, 2, 0.002));
148 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_8X8, 2, 0.025));
149 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_16X16, 2, 0.04));
150 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_32X32, 4, 0.4));
151 #if CONFIG_TX64X64
152 if (tx_type == DCT_DCT) { // Other types not supported by these tx sizes.
153 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_64X64, 3, 0.2));
155 #endif // CONFIG_TX64X64
157 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_4X8, 2, 0.016));
158 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_8X4, 2, 0.016));
159 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_8X16, 2, 0.2));
160 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_16X8, 2, 0.2));
161 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_16X32, 3, 0.4));
162 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_32X16, 3, 0.4));
164 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_4X16, 2, 0.2));
165 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_16X4, 2, 0.2));
166 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_8X32, 2, 0.2));
167 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_32X8, 2, 0.2));
169 #if CONFIG_TX64X64
170 if (tx_type == DCT_DCT) { // Other types not supported by these tx sizes.
171 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_32X64, 5, 0.38));
172 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_64X32, 5, 0.38));
173 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_16X64, 3, 0.38));
174 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_64X16, 3, 0.38));
176 #endif // CONFIG_TX64X64
178 return param_list;
181 INSTANTIATE_TEST_CASE_P(C, AV1InvTxfm2d,
182 ::testing::ValuesIn(GetInvTxfm2dParamList()));
184 TEST_P(AV1InvTxfm2d, RunRoundtripCheck) { RunRoundtripCheck(); }
186 TEST(AV1InvTxfm2d, CfgTest) {
187 for (int bd_idx = 0; bd_idx < BD_NUM; ++bd_idx) {
188 int bd = libaom_test::bd_arr[bd_idx];
189 int8_t low_range = libaom_test::low_range_arr[bd_idx];
190 int8_t high_range = libaom_test::high_range_arr[bd_idx];
191 for (int tx_size = 0; tx_size < TX_SIZES_ALL; ++tx_size) {
192 for (int tx_type = 0; tx_type < TX_TYPES; ++tx_type) {
193 #if CONFIG_TX64X64
194 if ((tx_size_wide[tx_size] == 64 || tx_size_high[tx_size] == 64) &&
195 tx_type != DCT_DCT) {
196 continue;
198 #endif // CONFIG_TX64X64
199 TXFM_2D_FLIP_CFG cfg;
200 av1_get_inv_txfm_cfg(static_cast<TX_TYPE>(tx_type),
201 static_cast<TX_SIZE>(tx_size), &cfg);
202 int8_t stage_range_col[MAX_TXFM_STAGE_NUM];
203 int8_t stage_range_row[MAX_TXFM_STAGE_NUM];
204 av1_gen_inv_stage_range(stage_range_col, stage_range_row, &cfg,
205 (TX_SIZE)tx_size, bd);
206 const TXFM_1D_CFG *col_cfg = cfg.col_cfg;
207 const TXFM_1D_CFG *row_cfg = cfg.row_cfg;
208 libaom_test::txfm_stage_range_check(stage_range_col, col_cfg->stage_num,
209 col_cfg->cos_bit, low_range,
210 high_range);
211 libaom_test::txfm_stage_range_check(stage_range_row, row_cfg->stage_num,
212 row_cfg->cos_bit, low_range,
213 high_range);
218 } // namespace