xref: /aosp_15_r20/external/libaom/test/av1_txfm_test.cc (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker  * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker  *
4*77c1e3ccSAndroid Build Coastguard Worker  * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker  * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker  * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker  */
11*77c1e3ccSAndroid Build Coastguard Worker 
12*77c1e3ccSAndroid Build Coastguard Worker #include "test/av1_txfm_test.h"
13*77c1e3ccSAndroid Build Coastguard Worker 
14*77c1e3ccSAndroid Build Coastguard Worker #include <stdio.h>
15*77c1e3ccSAndroid Build Coastguard Worker 
16*77c1e3ccSAndroid Build Coastguard Worker #include <memory>
17*77c1e3ccSAndroid Build Coastguard Worker #include <new>
18*77c1e3ccSAndroid Build Coastguard Worker 
19*77c1e3ccSAndroid Build Coastguard Worker namespace libaom_test {
20*77c1e3ccSAndroid Build Coastguard Worker 
21*77c1e3ccSAndroid Build Coastguard Worker const char *tx_type_name[] = {
22*77c1e3ccSAndroid Build Coastguard Worker   "DCT_DCT",
23*77c1e3ccSAndroid Build Coastguard Worker   "ADST_DCT",
24*77c1e3ccSAndroid Build Coastguard Worker   "DCT_ADST",
25*77c1e3ccSAndroid Build Coastguard Worker   "ADST_ADST",
26*77c1e3ccSAndroid Build Coastguard Worker   "FLIPADST_DCT",
27*77c1e3ccSAndroid Build Coastguard Worker   "DCT_FLIPADST",
28*77c1e3ccSAndroid Build Coastguard Worker   "FLIPADST_FLIPADST",
29*77c1e3ccSAndroid Build Coastguard Worker   "ADST_FLIPADST",
30*77c1e3ccSAndroid Build Coastguard Worker   "FLIPADST_ADST",
31*77c1e3ccSAndroid Build Coastguard Worker   "IDTX",
32*77c1e3ccSAndroid Build Coastguard Worker   "V_DCT",
33*77c1e3ccSAndroid Build Coastguard Worker   "H_DCT",
34*77c1e3ccSAndroid Build Coastguard Worker   "V_ADST",
35*77c1e3ccSAndroid Build Coastguard Worker   "H_ADST",
36*77c1e3ccSAndroid Build Coastguard Worker   "V_FLIPADST",
37*77c1e3ccSAndroid Build Coastguard Worker   "H_FLIPADST",
38*77c1e3ccSAndroid Build Coastguard Worker };
39*77c1e3ccSAndroid Build Coastguard Worker 
get_txfm1d_size(TX_SIZE tx_size)40*77c1e3ccSAndroid Build Coastguard Worker int get_txfm1d_size(TX_SIZE tx_size) { return tx_size_wide[tx_size]; }
41*77c1e3ccSAndroid Build Coastguard Worker 
get_txfm1d_type(TX_TYPE txfm2d_type,TYPE_TXFM * type0,TYPE_TXFM * type1)42*77c1e3ccSAndroid Build Coastguard Worker void get_txfm1d_type(TX_TYPE txfm2d_type, TYPE_TXFM *type0, TYPE_TXFM *type1) {
43*77c1e3ccSAndroid Build Coastguard Worker   switch (txfm2d_type) {
44*77c1e3ccSAndroid Build Coastguard Worker     case DCT_DCT:
45*77c1e3ccSAndroid Build Coastguard Worker       *type0 = TYPE_DCT;
46*77c1e3ccSAndroid Build Coastguard Worker       *type1 = TYPE_DCT;
47*77c1e3ccSAndroid Build Coastguard Worker       break;
48*77c1e3ccSAndroid Build Coastguard Worker     case ADST_DCT:
49*77c1e3ccSAndroid Build Coastguard Worker       *type0 = TYPE_ADST;
50*77c1e3ccSAndroid Build Coastguard Worker       *type1 = TYPE_DCT;
51*77c1e3ccSAndroid Build Coastguard Worker       break;
52*77c1e3ccSAndroid Build Coastguard Worker     case DCT_ADST:
53*77c1e3ccSAndroid Build Coastguard Worker       *type0 = TYPE_DCT;
54*77c1e3ccSAndroid Build Coastguard Worker       *type1 = TYPE_ADST;
55*77c1e3ccSAndroid Build Coastguard Worker       break;
56*77c1e3ccSAndroid Build Coastguard Worker     case ADST_ADST:
57*77c1e3ccSAndroid Build Coastguard Worker       *type0 = TYPE_ADST;
58*77c1e3ccSAndroid Build Coastguard Worker       *type1 = TYPE_ADST;
59*77c1e3ccSAndroid Build Coastguard Worker       break;
60*77c1e3ccSAndroid Build Coastguard Worker     case FLIPADST_DCT:
61*77c1e3ccSAndroid Build Coastguard Worker       *type0 = TYPE_ADST;
62*77c1e3ccSAndroid Build Coastguard Worker       *type1 = TYPE_DCT;
63*77c1e3ccSAndroid Build Coastguard Worker       break;
64*77c1e3ccSAndroid Build Coastguard Worker     case DCT_FLIPADST:
65*77c1e3ccSAndroid Build Coastguard Worker       *type0 = TYPE_DCT;
66*77c1e3ccSAndroid Build Coastguard Worker       *type1 = TYPE_ADST;
67*77c1e3ccSAndroid Build Coastguard Worker       break;
68*77c1e3ccSAndroid Build Coastguard Worker     case FLIPADST_FLIPADST:
69*77c1e3ccSAndroid Build Coastguard Worker       *type0 = TYPE_ADST;
70*77c1e3ccSAndroid Build Coastguard Worker       *type1 = TYPE_ADST;
71*77c1e3ccSAndroid Build Coastguard Worker       break;
72*77c1e3ccSAndroid Build Coastguard Worker     case ADST_FLIPADST:
73*77c1e3ccSAndroid Build Coastguard Worker       *type0 = TYPE_ADST;
74*77c1e3ccSAndroid Build Coastguard Worker       *type1 = TYPE_ADST;
75*77c1e3ccSAndroid Build Coastguard Worker       break;
76*77c1e3ccSAndroid Build Coastguard Worker     case FLIPADST_ADST:
77*77c1e3ccSAndroid Build Coastguard Worker       *type0 = TYPE_ADST;
78*77c1e3ccSAndroid Build Coastguard Worker       *type1 = TYPE_ADST;
79*77c1e3ccSAndroid Build Coastguard Worker       break;
80*77c1e3ccSAndroid Build Coastguard Worker     case IDTX:
81*77c1e3ccSAndroid Build Coastguard Worker       *type0 = TYPE_IDTX;
82*77c1e3ccSAndroid Build Coastguard Worker       *type1 = TYPE_IDTX;
83*77c1e3ccSAndroid Build Coastguard Worker       break;
84*77c1e3ccSAndroid Build Coastguard Worker     case H_DCT:
85*77c1e3ccSAndroid Build Coastguard Worker       *type0 = TYPE_IDTX;
86*77c1e3ccSAndroid Build Coastguard Worker       *type1 = TYPE_DCT;
87*77c1e3ccSAndroid Build Coastguard Worker       break;
88*77c1e3ccSAndroid Build Coastguard Worker     case V_DCT:
89*77c1e3ccSAndroid Build Coastguard Worker       *type0 = TYPE_DCT;
90*77c1e3ccSAndroid Build Coastguard Worker       *type1 = TYPE_IDTX;
91*77c1e3ccSAndroid Build Coastguard Worker       break;
92*77c1e3ccSAndroid Build Coastguard Worker     case H_ADST:
93*77c1e3ccSAndroid Build Coastguard Worker       *type0 = TYPE_IDTX;
94*77c1e3ccSAndroid Build Coastguard Worker       *type1 = TYPE_ADST;
95*77c1e3ccSAndroid Build Coastguard Worker       break;
96*77c1e3ccSAndroid Build Coastguard Worker     case V_ADST:
97*77c1e3ccSAndroid Build Coastguard Worker       *type0 = TYPE_ADST;
98*77c1e3ccSAndroid Build Coastguard Worker       *type1 = TYPE_IDTX;
99*77c1e3ccSAndroid Build Coastguard Worker       break;
100*77c1e3ccSAndroid Build Coastguard Worker     case H_FLIPADST:
101*77c1e3ccSAndroid Build Coastguard Worker       *type0 = TYPE_IDTX;
102*77c1e3ccSAndroid Build Coastguard Worker       *type1 = TYPE_ADST;
103*77c1e3ccSAndroid Build Coastguard Worker       break;
104*77c1e3ccSAndroid Build Coastguard Worker     case V_FLIPADST:
105*77c1e3ccSAndroid Build Coastguard Worker       *type0 = TYPE_ADST;
106*77c1e3ccSAndroid Build Coastguard Worker       *type1 = TYPE_IDTX;
107*77c1e3ccSAndroid Build Coastguard Worker       break;
108*77c1e3ccSAndroid Build Coastguard Worker     default:
109*77c1e3ccSAndroid Build Coastguard Worker       *type0 = TYPE_DCT;
110*77c1e3ccSAndroid Build Coastguard Worker       *type1 = TYPE_DCT;
111*77c1e3ccSAndroid Build Coastguard Worker       assert(0);
112*77c1e3ccSAndroid Build Coastguard Worker       break;
113*77c1e3ccSAndroid Build Coastguard Worker   }
114*77c1e3ccSAndroid Build Coastguard Worker }
115*77c1e3ccSAndroid Build Coastguard Worker 
116*77c1e3ccSAndroid Build Coastguard Worker double Sqrt2 = pow(2, 0.5);
117*77c1e3ccSAndroid Build Coastguard Worker double invSqrt2 = 1 / pow(2, 0.5);
118*77c1e3ccSAndroid Build Coastguard Worker 
dct_matrix(double n,double k,int size)119*77c1e3ccSAndroid Build Coastguard Worker static double dct_matrix(double n, double k, int size) {
120*77c1e3ccSAndroid Build Coastguard Worker   return cos(PI * (2 * n + 1) * k / (2 * size));
121*77c1e3ccSAndroid Build Coastguard Worker }
122*77c1e3ccSAndroid Build Coastguard Worker 
reference_dct_1d(const double * in,double * out,int size)123*77c1e3ccSAndroid Build Coastguard Worker void reference_dct_1d(const double *in, double *out, int size) {
124*77c1e3ccSAndroid Build Coastguard Worker   for (int k = 0; k < size; ++k) {
125*77c1e3ccSAndroid Build Coastguard Worker     out[k] = 0;
126*77c1e3ccSAndroid Build Coastguard Worker     for (int n = 0; n < size; ++n) {
127*77c1e3ccSAndroid Build Coastguard Worker       out[k] += in[n] * dct_matrix(n, k, size);
128*77c1e3ccSAndroid Build Coastguard Worker     }
129*77c1e3ccSAndroid Build Coastguard Worker     if (k == 0) out[k] = out[k] * invSqrt2;
130*77c1e3ccSAndroid Build Coastguard Worker   }
131*77c1e3ccSAndroid Build Coastguard Worker }
132*77c1e3ccSAndroid Build Coastguard Worker 
reference_idct_1d(const double * in,double * out,int size)133*77c1e3ccSAndroid Build Coastguard Worker void reference_idct_1d(const double *in, double *out, int size) {
134*77c1e3ccSAndroid Build Coastguard Worker   for (int k = 0; k < size; ++k) {
135*77c1e3ccSAndroid Build Coastguard Worker     out[k] = 0;
136*77c1e3ccSAndroid Build Coastguard Worker     for (int n = 0; n < size; ++n) {
137*77c1e3ccSAndroid Build Coastguard Worker       if (n == 0)
138*77c1e3ccSAndroid Build Coastguard Worker         out[k] += invSqrt2 * in[n] * dct_matrix(k, n, size);
139*77c1e3ccSAndroid Build Coastguard Worker       else
140*77c1e3ccSAndroid Build Coastguard Worker         out[k] += in[n] * dct_matrix(k, n, size);
141*77c1e3ccSAndroid Build Coastguard Worker     }
142*77c1e3ccSAndroid Build Coastguard Worker   }
143*77c1e3ccSAndroid Build Coastguard Worker }
144*77c1e3ccSAndroid Build Coastguard Worker 
145*77c1e3ccSAndroid Build Coastguard Worker // TODO(any): Copied from the old 'fadst4' (same as the new 'av1_fadst4'
146*77c1e3ccSAndroid Build Coastguard Worker // function). Should be replaced by a proper reference function that takes
147*77c1e3ccSAndroid Build Coastguard Worker // 'double' input & output.
fadst4_new(const tran_low_t * input,tran_low_t * output)148*77c1e3ccSAndroid Build Coastguard Worker static void fadst4_new(const tran_low_t *input, tran_low_t *output) {
149*77c1e3ccSAndroid Build Coastguard Worker   tran_high_t x0, x1, x2, x3;
150*77c1e3ccSAndroid Build Coastguard Worker   tran_high_t s0, s1, s2, s3, s4, s5, s6, s7;
151*77c1e3ccSAndroid Build Coastguard Worker 
152*77c1e3ccSAndroid Build Coastguard Worker   x0 = input[0];
153*77c1e3ccSAndroid Build Coastguard Worker   x1 = input[1];
154*77c1e3ccSAndroid Build Coastguard Worker   x2 = input[2];
155*77c1e3ccSAndroid Build Coastguard Worker   x3 = input[3];
156*77c1e3ccSAndroid Build Coastguard Worker 
157*77c1e3ccSAndroid Build Coastguard Worker   if (!(x0 | x1 | x2 | x3)) {
158*77c1e3ccSAndroid Build Coastguard Worker     output[0] = output[1] = output[2] = output[3] = 0;
159*77c1e3ccSAndroid Build Coastguard Worker     return;
160*77c1e3ccSAndroid Build Coastguard Worker   }
161*77c1e3ccSAndroid Build Coastguard Worker 
162*77c1e3ccSAndroid Build Coastguard Worker   s0 = sinpi_1_9 * x0;
163*77c1e3ccSAndroid Build Coastguard Worker   s1 = sinpi_4_9 * x0;
164*77c1e3ccSAndroid Build Coastguard Worker   s2 = sinpi_2_9 * x1;
165*77c1e3ccSAndroid Build Coastguard Worker   s3 = sinpi_1_9 * x1;
166*77c1e3ccSAndroid Build Coastguard Worker   s4 = sinpi_3_9 * x2;
167*77c1e3ccSAndroid Build Coastguard Worker   s5 = sinpi_4_9 * x3;
168*77c1e3ccSAndroid Build Coastguard Worker   s6 = sinpi_2_9 * x3;
169*77c1e3ccSAndroid Build Coastguard Worker   s7 = x0 + x1 - x3;
170*77c1e3ccSAndroid Build Coastguard Worker 
171*77c1e3ccSAndroid Build Coastguard Worker   x0 = s0 + s2 + s5;
172*77c1e3ccSAndroid Build Coastguard Worker   x1 = sinpi_3_9 * s7;
173*77c1e3ccSAndroid Build Coastguard Worker   x2 = s1 - s3 + s6;
174*77c1e3ccSAndroid Build Coastguard Worker   x3 = s4;
175*77c1e3ccSAndroid Build Coastguard Worker 
176*77c1e3ccSAndroid Build Coastguard Worker   s0 = x0 + x3;
177*77c1e3ccSAndroid Build Coastguard Worker   s1 = x1;
178*77c1e3ccSAndroid Build Coastguard Worker   s2 = x2 - x3;
179*77c1e3ccSAndroid Build Coastguard Worker   s3 = x2 - x0 + x3;
180*77c1e3ccSAndroid Build Coastguard Worker 
181*77c1e3ccSAndroid Build Coastguard Worker   // 1-D transform scaling factor is sqrt(2).
182*77c1e3ccSAndroid Build Coastguard Worker   output[0] = (tran_low_t)fdct_round_shift(s0);
183*77c1e3ccSAndroid Build Coastguard Worker   output[1] = (tran_low_t)fdct_round_shift(s1);
184*77c1e3ccSAndroid Build Coastguard Worker   output[2] = (tran_low_t)fdct_round_shift(s2);
185*77c1e3ccSAndroid Build Coastguard Worker   output[3] = (tran_low_t)fdct_round_shift(s3);
186*77c1e3ccSAndroid Build Coastguard Worker }
187*77c1e3ccSAndroid Build Coastguard Worker 
reference_adst_1d(const double * in,double * out,int size)188*77c1e3ccSAndroid Build Coastguard Worker void reference_adst_1d(const double *in, double *out, int size) {
189*77c1e3ccSAndroid Build Coastguard Worker   if (size == 4) {  // Special case.
190*77c1e3ccSAndroid Build Coastguard Worker     tran_low_t int_input[4];
191*77c1e3ccSAndroid Build Coastguard Worker     for (int i = 0; i < 4; ++i) {
192*77c1e3ccSAndroid Build Coastguard Worker       int_input[i] = static_cast<tran_low_t>(round(in[i]));
193*77c1e3ccSAndroid Build Coastguard Worker     }
194*77c1e3ccSAndroid Build Coastguard Worker     tran_low_t int_output[4];
195*77c1e3ccSAndroid Build Coastguard Worker     fadst4_new(int_input, int_output);
196*77c1e3ccSAndroid Build Coastguard Worker     for (int i = 0; i < 4; ++i) {
197*77c1e3ccSAndroid Build Coastguard Worker       out[i] = int_output[i];
198*77c1e3ccSAndroid Build Coastguard Worker     }
199*77c1e3ccSAndroid Build Coastguard Worker     return;
200*77c1e3ccSAndroid Build Coastguard Worker   }
201*77c1e3ccSAndroid Build Coastguard Worker 
202*77c1e3ccSAndroid Build Coastguard Worker   for (int k = 0; k < size; ++k) {
203*77c1e3ccSAndroid Build Coastguard Worker     out[k] = 0;
204*77c1e3ccSAndroid Build Coastguard Worker     for (int n = 0; n < size; ++n) {
205*77c1e3ccSAndroid Build Coastguard Worker       out[k] += in[n] * sin(PI * (2 * n + 1) * (2 * k + 1) / (4 * size));
206*77c1e3ccSAndroid Build Coastguard Worker     }
207*77c1e3ccSAndroid Build Coastguard Worker   }
208*77c1e3ccSAndroid Build Coastguard Worker }
209*77c1e3ccSAndroid Build Coastguard Worker 
reference_idtx_1d(const double * in,double * out,int size)210*77c1e3ccSAndroid Build Coastguard Worker static void reference_idtx_1d(const double *in, double *out, int size) {
211*77c1e3ccSAndroid Build Coastguard Worker   double scale = 0;
212*77c1e3ccSAndroid Build Coastguard Worker   if (size == 4)
213*77c1e3ccSAndroid Build Coastguard Worker     scale = Sqrt2;
214*77c1e3ccSAndroid Build Coastguard Worker   else if (size == 8)
215*77c1e3ccSAndroid Build Coastguard Worker     scale = 2;
216*77c1e3ccSAndroid Build Coastguard Worker   else if (size == 16)
217*77c1e3ccSAndroid Build Coastguard Worker     scale = 2 * Sqrt2;
218*77c1e3ccSAndroid Build Coastguard Worker   else if (size == 32)
219*77c1e3ccSAndroid Build Coastguard Worker     scale = 4;
220*77c1e3ccSAndroid Build Coastguard Worker   else if (size == 64)
221*77c1e3ccSAndroid Build Coastguard Worker     scale = 4 * Sqrt2;
222*77c1e3ccSAndroid Build Coastguard Worker   for (int k = 0; k < size; ++k) {
223*77c1e3ccSAndroid Build Coastguard Worker     out[k] = in[k] * scale;
224*77c1e3ccSAndroid Build Coastguard Worker   }
225*77c1e3ccSAndroid Build Coastguard Worker }
226*77c1e3ccSAndroid Build Coastguard Worker 
reference_hybrid_1d(double * in,double * out,int size,int type)227*77c1e3ccSAndroid Build Coastguard Worker void reference_hybrid_1d(double *in, double *out, int size, int type) {
228*77c1e3ccSAndroid Build Coastguard Worker   if (type == TYPE_DCT)
229*77c1e3ccSAndroid Build Coastguard Worker     reference_dct_1d(in, out, size);
230*77c1e3ccSAndroid Build Coastguard Worker   else if (type == TYPE_ADST)
231*77c1e3ccSAndroid Build Coastguard Worker     reference_adst_1d(in, out, size);
232*77c1e3ccSAndroid Build Coastguard Worker   else
233*77c1e3ccSAndroid Build Coastguard Worker     reference_idtx_1d(in, out, size);
234*77c1e3ccSAndroid Build Coastguard Worker }
235*77c1e3ccSAndroid Build Coastguard Worker 
get_amplification_factor(TX_TYPE tx_type,TX_SIZE tx_size)236*77c1e3ccSAndroid Build Coastguard Worker double get_amplification_factor(TX_TYPE tx_type, TX_SIZE tx_size) {
237*77c1e3ccSAndroid Build Coastguard Worker   TXFM_2D_FLIP_CFG fwd_txfm_flip_cfg;
238*77c1e3ccSAndroid Build Coastguard Worker   av1_get_fwd_txfm_cfg(tx_type, tx_size, &fwd_txfm_flip_cfg);
239*77c1e3ccSAndroid Build Coastguard Worker   const int tx_width = tx_size_wide[fwd_txfm_flip_cfg.tx_size];
240*77c1e3ccSAndroid Build Coastguard Worker   const int tx_height = tx_size_high[fwd_txfm_flip_cfg.tx_size];
241*77c1e3ccSAndroid Build Coastguard Worker   const int8_t *shift = fwd_txfm_flip_cfg.shift;
242*77c1e3ccSAndroid Build Coastguard Worker   const int amplify_bit = shift[0] + shift[1] + shift[2];
243*77c1e3ccSAndroid Build Coastguard Worker   double amplify_factor =
244*77c1e3ccSAndroid Build Coastguard Worker       amplify_bit >= 0 ? (1 << amplify_bit) : (1.0 / (1 << -amplify_bit));
245*77c1e3ccSAndroid Build Coastguard Worker 
246*77c1e3ccSAndroid Build Coastguard Worker   // For rectangular transforms, we need to multiply by an extra factor.
247*77c1e3ccSAndroid Build Coastguard Worker   const int rect_type = get_rect_tx_log_ratio(tx_width, tx_height);
248*77c1e3ccSAndroid Build Coastguard Worker   if (abs(rect_type) == 1) {
249*77c1e3ccSAndroid Build Coastguard Worker     amplify_factor *= pow(2, 0.5);
250*77c1e3ccSAndroid Build Coastguard Worker   }
251*77c1e3ccSAndroid Build Coastguard Worker   return amplify_factor;
252*77c1e3ccSAndroid Build Coastguard Worker }
253*77c1e3ccSAndroid Build Coastguard Worker 
reference_hybrid_2d(double * in,double * out,TX_TYPE tx_type,TX_SIZE tx_size)254*77c1e3ccSAndroid Build Coastguard Worker void reference_hybrid_2d(double *in, double *out, TX_TYPE tx_type,
255*77c1e3ccSAndroid Build Coastguard Worker                          TX_SIZE tx_size) {
256*77c1e3ccSAndroid Build Coastguard Worker   // Get transform type and size of each dimension.
257*77c1e3ccSAndroid Build Coastguard Worker   TYPE_TXFM type0;
258*77c1e3ccSAndroid Build Coastguard Worker   TYPE_TXFM type1;
259*77c1e3ccSAndroid Build Coastguard Worker   get_txfm1d_type(tx_type, &type0, &type1);
260*77c1e3ccSAndroid Build Coastguard Worker   const int tx_width = tx_size_wide[tx_size];
261*77c1e3ccSAndroid Build Coastguard Worker   const int tx_height = tx_size_high[tx_size];
262*77c1e3ccSAndroid Build Coastguard Worker 
263*77c1e3ccSAndroid Build Coastguard Worker   std::unique_ptr<double[]> temp_in(
264*77c1e3ccSAndroid Build Coastguard Worker       new (std::nothrow) double[AOMMAX(tx_width, tx_height)]);
265*77c1e3ccSAndroid Build Coastguard Worker   std::unique_ptr<double[]> temp_out(
266*77c1e3ccSAndroid Build Coastguard Worker       new (std::nothrow) double[AOMMAX(tx_width, tx_height)]);
267*77c1e3ccSAndroid Build Coastguard Worker   std::unique_ptr<double[]> out_interm(
268*77c1e3ccSAndroid Build Coastguard Worker       new (std::nothrow) double[tx_width * tx_height]);
269*77c1e3ccSAndroid Build Coastguard Worker   ASSERT_NE(temp_in, nullptr);
270*77c1e3ccSAndroid Build Coastguard Worker   ASSERT_NE(temp_out, nullptr);
271*77c1e3ccSAndroid Build Coastguard Worker   ASSERT_NE(out_interm, nullptr);
272*77c1e3ccSAndroid Build Coastguard Worker 
273*77c1e3ccSAndroid Build Coastguard Worker   // Transform columns.
274*77c1e3ccSAndroid Build Coastguard Worker   for (int c = 0; c < tx_width; ++c) {
275*77c1e3ccSAndroid Build Coastguard Worker     for (int r = 0; r < tx_height; ++r) {
276*77c1e3ccSAndroid Build Coastguard Worker       temp_in[r] = in[r * tx_width + c];
277*77c1e3ccSAndroid Build Coastguard Worker     }
278*77c1e3ccSAndroid Build Coastguard Worker     reference_hybrid_1d(temp_in.get(), temp_out.get(), tx_height, type0);
279*77c1e3ccSAndroid Build Coastguard Worker     for (int r = 0; r < tx_height; ++r) {
280*77c1e3ccSAndroid Build Coastguard Worker       out_interm[r * tx_width + c] = temp_out[r];
281*77c1e3ccSAndroid Build Coastguard Worker     }
282*77c1e3ccSAndroid Build Coastguard Worker   }
283*77c1e3ccSAndroid Build Coastguard Worker 
284*77c1e3ccSAndroid Build Coastguard Worker   // Transform rows.
285*77c1e3ccSAndroid Build Coastguard Worker   for (int r = 0; r < tx_height; ++r) {
286*77c1e3ccSAndroid Build Coastguard Worker     reference_hybrid_1d(out_interm.get() + r * tx_width, temp_out.get(),
287*77c1e3ccSAndroid Build Coastguard Worker                         tx_width, type1);
288*77c1e3ccSAndroid Build Coastguard Worker     for (int c = 0; c < tx_width; ++c) {
289*77c1e3ccSAndroid Build Coastguard Worker       out[c * tx_height + r] = temp_out[c];
290*77c1e3ccSAndroid Build Coastguard Worker     }
291*77c1e3ccSAndroid Build Coastguard Worker   }
292*77c1e3ccSAndroid Build Coastguard Worker 
293*77c1e3ccSAndroid Build Coastguard Worker   // These transforms use an approximate 2D DCT transform, by only keeping the
294*77c1e3ccSAndroid Build Coastguard Worker   // top-left quarter of the coefficients, and repacking them in the first
295*77c1e3ccSAndroid Build Coastguard Worker   // quarter indices.
296*77c1e3ccSAndroid Build Coastguard Worker   // TODO(urvang): Refactor this code.
297*77c1e3ccSAndroid Build Coastguard Worker   if (tx_width == 64 && tx_height == 64) {  // tx_size == TX_64X64
298*77c1e3ccSAndroid Build Coastguard Worker     // Zero out top-right 32x32 area.
299*77c1e3ccSAndroid Build Coastguard Worker     for (int col = 0; col < 32; ++col) {
300*77c1e3ccSAndroid Build Coastguard Worker       memset(out + col * 64 + 32, 0, 32 * sizeof(*out));
301*77c1e3ccSAndroid Build Coastguard Worker     }
302*77c1e3ccSAndroid Build Coastguard Worker     // Zero out the bottom 64x32 area.
303*77c1e3ccSAndroid Build Coastguard Worker     memset(out + 32 * 64, 0, 32 * 64 * sizeof(*out));
304*77c1e3ccSAndroid Build Coastguard Worker     // Re-pack non-zero coeffs in the first 32x32 indices.
305*77c1e3ccSAndroid Build Coastguard Worker     for (int col = 1; col < 32; ++col) {
306*77c1e3ccSAndroid Build Coastguard Worker       memcpy(out + col * 32, out + col * 64, 32 * sizeof(*out));
307*77c1e3ccSAndroid Build Coastguard Worker     }
308*77c1e3ccSAndroid Build Coastguard Worker   } else if (tx_width == 32 && tx_height == 64) {  // tx_size == TX_32X64
309*77c1e3ccSAndroid Build Coastguard Worker     // Zero out right 32x32 area.
310*77c1e3ccSAndroid Build Coastguard Worker     for (int col = 0; col < 32; ++col) {
311*77c1e3ccSAndroid Build Coastguard Worker       memset(out + col * 64 + 32, 0, 32 * sizeof(*out));
312*77c1e3ccSAndroid Build Coastguard Worker     }
313*77c1e3ccSAndroid Build Coastguard Worker     // Re-pack non-zero coeffs in the first 32x32 indices.
314*77c1e3ccSAndroid Build Coastguard Worker     for (int col = 1; col < 32; ++col) {
315*77c1e3ccSAndroid Build Coastguard Worker       memcpy(out + col * 32, out + col * 64, 32 * sizeof(*out));
316*77c1e3ccSAndroid Build Coastguard Worker     }
317*77c1e3ccSAndroid Build Coastguard Worker   } else if (tx_width == 64 && tx_height == 32) {  // tx_size == TX_64X32
318*77c1e3ccSAndroid Build Coastguard Worker     // Zero out the bottom 32x32 area.
319*77c1e3ccSAndroid Build Coastguard Worker     memset(out + 32 * 32, 0, 32 * 32 * sizeof(*out));
320*77c1e3ccSAndroid Build Coastguard Worker     // Note: no repacking needed here.
321*77c1e3ccSAndroid Build Coastguard Worker   } else if (tx_width == 16 && tx_height == 64) {  // tx_size == TX_16X64
322*77c1e3ccSAndroid Build Coastguard Worker     // Note: no repacking needed here.
323*77c1e3ccSAndroid Build Coastguard Worker     // Zero out right 32x16 area.
324*77c1e3ccSAndroid Build Coastguard Worker     for (int col = 0; col < 16; ++col) {
325*77c1e3ccSAndroid Build Coastguard Worker       memset(out + col * 64 + 32, 0, 32 * sizeof(*out));
326*77c1e3ccSAndroid Build Coastguard Worker     }
327*77c1e3ccSAndroid Build Coastguard Worker     // Re-pack non-zero coeffs in the first 32x16 indices.
328*77c1e3ccSAndroid Build Coastguard Worker     for (int col = 1; col < 16; ++col) {
329*77c1e3ccSAndroid Build Coastguard Worker       memcpy(out + col * 32, out + col * 64, 32 * sizeof(*out));
330*77c1e3ccSAndroid Build Coastguard Worker     }
331*77c1e3ccSAndroid Build Coastguard Worker   } else if (tx_width == 64 && tx_height == 16) {  // tx_size == TX_64X16
332*77c1e3ccSAndroid Build Coastguard Worker     // Zero out the bottom 16x32 area.
333*77c1e3ccSAndroid Build Coastguard Worker     memset(out + 16 * 32, 0, 16 * 32 * sizeof(*out));
334*77c1e3ccSAndroid Build Coastguard Worker   }
335*77c1e3ccSAndroid Build Coastguard Worker 
336*77c1e3ccSAndroid Build Coastguard Worker   // Apply appropriate scale.
337*77c1e3ccSAndroid Build Coastguard Worker   const double amplify_factor = get_amplification_factor(tx_type, tx_size);
338*77c1e3ccSAndroid Build Coastguard Worker   for (int c = 0; c < tx_width; ++c) {
339*77c1e3ccSAndroid Build Coastguard Worker     for (int r = 0; r < tx_height; ++r) {
340*77c1e3ccSAndroid Build Coastguard Worker       out[c * tx_height + r] *= amplify_factor;
341*77c1e3ccSAndroid Build Coastguard Worker     }
342*77c1e3ccSAndroid Build Coastguard Worker   }
343*77c1e3ccSAndroid Build Coastguard Worker }
344*77c1e3ccSAndroid Build Coastguard Worker 
345*77c1e3ccSAndroid Build Coastguard Worker template <typename Type>
fliplr(Type * dest,int width,int height,int stride)346*77c1e3ccSAndroid Build Coastguard Worker void fliplr(Type *dest, int width, int height, int stride) {
347*77c1e3ccSAndroid Build Coastguard Worker   for (int r = 0; r < height; ++r) {
348*77c1e3ccSAndroid Build Coastguard Worker     for (int c = 0; c < width / 2; ++c) {
349*77c1e3ccSAndroid Build Coastguard Worker       const Type tmp = dest[r * stride + c];
350*77c1e3ccSAndroid Build Coastguard Worker       dest[r * stride + c] = dest[r * stride + width - 1 - c];
351*77c1e3ccSAndroid Build Coastguard Worker       dest[r * stride + width - 1 - c] = tmp;
352*77c1e3ccSAndroid Build Coastguard Worker     }
353*77c1e3ccSAndroid Build Coastguard Worker   }
354*77c1e3ccSAndroid Build Coastguard Worker }
355*77c1e3ccSAndroid Build Coastguard Worker 
356*77c1e3ccSAndroid Build Coastguard Worker template <typename Type>
flipud(Type * dest,int width,int height,int stride)357*77c1e3ccSAndroid Build Coastguard Worker void flipud(Type *dest, int width, int height, int stride) {
358*77c1e3ccSAndroid Build Coastguard Worker   for (int c = 0; c < width; ++c) {
359*77c1e3ccSAndroid Build Coastguard Worker     for (int r = 0; r < height / 2; ++r) {
360*77c1e3ccSAndroid Build Coastguard Worker       const Type tmp = dest[r * stride + c];
361*77c1e3ccSAndroid Build Coastguard Worker       dest[r * stride + c] = dest[(height - 1 - r) * stride + c];
362*77c1e3ccSAndroid Build Coastguard Worker       dest[(height - 1 - r) * stride + c] = tmp;
363*77c1e3ccSAndroid Build Coastguard Worker     }
364*77c1e3ccSAndroid Build Coastguard Worker   }
365*77c1e3ccSAndroid Build Coastguard Worker }
366*77c1e3ccSAndroid Build Coastguard Worker 
367*77c1e3ccSAndroid Build Coastguard Worker template <typename Type>
fliplrud(Type * dest,int width,int height,int stride)368*77c1e3ccSAndroid Build Coastguard Worker void fliplrud(Type *dest, int width, int height, int stride) {
369*77c1e3ccSAndroid Build Coastguard Worker   for (int r = 0; r < height / 2; ++r) {
370*77c1e3ccSAndroid Build Coastguard Worker     for (int c = 0; c < width; ++c) {
371*77c1e3ccSAndroid Build Coastguard Worker       const Type tmp = dest[r * stride + c];
372*77c1e3ccSAndroid Build Coastguard Worker       dest[r * stride + c] = dest[(height - 1 - r) * stride + width - 1 - c];
373*77c1e3ccSAndroid Build Coastguard Worker       dest[(height - 1 - r) * stride + width - 1 - c] = tmp;
374*77c1e3ccSAndroid Build Coastguard Worker     }
375*77c1e3ccSAndroid Build Coastguard Worker   }
376*77c1e3ccSAndroid Build Coastguard Worker }
377*77c1e3ccSAndroid Build Coastguard Worker 
378*77c1e3ccSAndroid Build Coastguard Worker template void fliplr<double>(double *dest, int width, int height, int stride);
379*77c1e3ccSAndroid Build Coastguard Worker template void flipud<double>(double *dest, int width, int height, int stride);
380*77c1e3ccSAndroid Build Coastguard Worker template void fliplrud<double>(double *dest, int width, int height, int stride);
381*77c1e3ccSAndroid Build Coastguard Worker 
382*77c1e3ccSAndroid Build Coastguard Worker int bd_arr[BD_NUM] = { 8, 10, 12 };
383*77c1e3ccSAndroid Build Coastguard Worker 
384*77c1e3ccSAndroid Build Coastguard Worker int8_t low_range_arr[BD_NUM] = { 18, 32, 32 };
385*77c1e3ccSAndroid Build Coastguard Worker int8_t high_range_arr[BD_NUM] = { 32, 32, 32 };
386*77c1e3ccSAndroid Build Coastguard Worker 
txfm_stage_range_check(const int8_t * stage_range,int stage_num,int8_t cos_bit,int low_range,int high_range)387*77c1e3ccSAndroid Build Coastguard Worker void txfm_stage_range_check(const int8_t *stage_range, int stage_num,
388*77c1e3ccSAndroid Build Coastguard Worker                             int8_t cos_bit, int low_range, int high_range) {
389*77c1e3ccSAndroid Build Coastguard Worker   for (int i = 0; i < stage_num; ++i) {
390*77c1e3ccSAndroid Build Coastguard Worker     EXPECT_LE(stage_range[i], low_range);
391*77c1e3ccSAndroid Build Coastguard Worker     ASSERT_LE(stage_range[i] + cos_bit, high_range) << "stage = " << i;
392*77c1e3ccSAndroid Build Coastguard Worker   }
393*77c1e3ccSAndroid Build Coastguard Worker   for (int i = 0; i < stage_num - 1; ++i) {
394*77c1e3ccSAndroid Build Coastguard Worker     // make sure there is no overflow while doing half_btf()
395*77c1e3ccSAndroid Build Coastguard Worker     ASSERT_LE(stage_range[i + 1] + cos_bit, high_range) << "stage = " << i;
396*77c1e3ccSAndroid Build Coastguard Worker   }
397*77c1e3ccSAndroid Build Coastguard Worker }
398*77c1e3ccSAndroid Build Coastguard Worker }  // namespace libaom_test
399