16fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org/*
26fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
36fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *
46fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *  Use of this source code is governed by a BSD-style license
56fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *  that can be found in the LICENSE file in the root of the source
66fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *  tree. An additional intellectual property rights grant can be found
76fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *  in the file PATENTS.  All contributing project authors may
86fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *  be found in the AUTHORS file in the root of the source tree.
96fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org */
106fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
116fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#include <math.h>
126fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#include <stdlib.h>
136fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#include <string.h>
146fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
156fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#include "third_party/googletest/src/include/gtest/gtest.h"
166fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
17f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org#include "./vp9_rtcd.h"
186fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
19f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org#include "test/acm_random.h"
206fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#include "vpx/vpx_integer.h"
216fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
226fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgusing libvpx_test::ACMRandom;
236fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
246fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgnamespace {
256fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
266fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#ifdef _MSC_VER
276fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgstatic int round(double x) {
28f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org  if (x < 0)
29f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    return static_cast<int>(ceil(x - 0.5));
306fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  else
31f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org    return static_cast<int>(floor(x + 0.5));
326fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}
336fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#endif
346fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
356fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgvoid reference_dct_1d(double input[8], double output[8]) {
366fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  const double kPi = 3.141592653589793238462643383279502884;
376fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  const double kInvSqrt2 = 0.707106781186547524400844362104;
386fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  for (int k = 0; k < 8; k++) {
396fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    output[k] = 0.0;
406fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    for (int n = 0; n < 8; n++)
416fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      output[k] += input[n]*cos(kPi*(2*n+1)*k/16.0);
426fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    if (k == 0)
436fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      output[k] = output[k]*kInvSqrt2;
446fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
456fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}
466fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
476fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgvoid reference_dct_2d(int16_t input[64], double output[64]) {
486fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  // First transform columns
496fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  for (int i = 0; i < 8; ++i) {
506fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    double temp_in[8], temp_out[8];
516fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    for (int j = 0; j < 8; ++j)
526fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      temp_in[j] = input[j*8 + i];
536fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    reference_dct_1d(temp_in, temp_out);
546fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    for (int j = 0; j < 8; ++j)
556fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      output[j*8 + i] = temp_out[j];
566fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
576fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  // Then transform rows
586fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  for (int i = 0; i < 8; ++i) {
596fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    double temp_in[8], temp_out[8];
606fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    for (int j = 0; j < 8; ++j)
616fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      temp_in[j] = output[j + i*8];
626fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    reference_dct_1d(temp_in, temp_out);
636fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    for (int j = 0; j < 8; ++j)
646fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      output[j + i*8] = temp_out[j];
656fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
666fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  // Scale by some magic number
676fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  for (int i = 0; i < 64; ++i)
686fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    output[i] *= 2;
696fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}
706fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
716fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgvoid reference_idct_1d(double input[8], double output[8]) {
726fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  const double kPi = 3.141592653589793238462643383279502884;
736fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  const double kSqrt2 = 1.414213562373095048801688724209698;
746fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  for (int k = 0; k < 8; k++) {
756fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    output[k] = 0.0;
766fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    for (int n = 0; n < 8; n++) {
776fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      output[k] += input[n]*cos(kPi*(2*k+1)*n/16.0);
786fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      if (n == 0)
796fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org        output[k] = output[k]/kSqrt2;
806fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    }
816fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
826fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}
836fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
846fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgvoid reference_idct_2d(double input[64], int16_t output[64]) {
856fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  double out[64], out2[64];
866fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  // First transform rows
876fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  for (int i = 0; i < 8; ++i) {
886fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    double temp_in[8], temp_out[8];
896fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    for (int j = 0; j < 8; ++j)
906fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      temp_in[j] = input[j + i*8];
916fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    reference_idct_1d(temp_in, temp_out);
926fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    for (int j = 0; j < 8; ++j)
936fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      out[j + i*8] = temp_out[j];
946fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
956fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  // Then transform columns
966fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  for (int i = 0; i < 8; ++i) {
976fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    double temp_in[8], temp_out[8];
986fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    for (int j = 0; j < 8; ++j)
996fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      temp_in[j] = out[j*8 + i];
1006fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    reference_idct_1d(temp_in, temp_out);
1016fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    for (int j = 0; j < 8; ++j)
1026fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      out2[j*8 + i] = temp_out[j];
1036fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
1046fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  for (int i = 0; i < 64; ++i)
1056fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    output[i] = round(out2[i]/32);
1066fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}
1076fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
1086fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgTEST(VP9Idct8x8Test, AccuracyCheck) {
1096fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  ACMRandom rnd(ACMRandom::DeterministicSeed());
1106fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  const int count_test_block = 10000;
1116fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  for (int i = 0; i < count_test_block; ++i) {
11287997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org    int16_t input[64];
11387997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org    tran_low_t coeff[64];
1146fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    double output_r[64];
11510a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org    uint8_t dst[64], src[64];
1166fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
11710a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org    for (int j = 0; j < 64; ++j) {
11810a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org      src[j] = rnd.Rand8();
11910a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org      dst[j] = rnd.Rand8();
12010a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org    }
1216fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    // Initialize a test block with input range [-255, 255].
1226fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    for (int j = 0; j < 64; ++j)
12310a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org      input[j] = src[j] - dst[j];
1246fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
1256fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    reference_dct_2d(input, output_r);
1266fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    for (int j = 0; j < 64; ++j)
1276fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      coeff[j] = round(output_r[j]);
1280d106b34dc08439a7c6887d1316a3e1a35f8f0cajohannkoenig@chromium.org    vp9_idct8x8_64_add_c(coeff, dst, 8);
1296fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    for (int j = 0; j < 64; ++j) {
13010a9a0d835561a7f2300c561c514efcf374554d6fgalligan@chromium.org      const int diff = dst[j] - src[j];
1316fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      const int error = diff * diff;
1326fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      EXPECT_GE(1, error)
1336fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org          << "Error: 8x8 FDCT/IDCT has error " << error
1346fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org          << " at index " << j;
1356fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    }
1366fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
1376fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}
1386fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
1396fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}  // namespace
140