diff options
Diffstat (limited to 'third_party/aom/test/fft_test.cc')
-rw-r--r-- | third_party/aom/test/fft_test.cc | 256 |
1 files changed, 0 insertions, 256 deletions
diff --git a/third_party/aom/test/fft_test.cc b/third_party/aom/test/fft_test.cc deleted file mode 100644 index e24e451a3..000000000 --- a/third_party/aom/test/fft_test.cc +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (c) 2018, Alliance for Open Media. All rights reserved - * - * This source code is subject to the terms of the BSD 2 Clause License and - * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License - * was not distributed with this source code in the LICENSE file, you can - * obtain it at www.aomedia.org/license/software. If the Alliance for Open - * Media Patent License 1.0 was not distributed with this source code in the - * PATENTS file, you can obtain it at www.aomedia.org/license/patent. - */ - -#include <math.h> - -#include <algorithm> -#include <complex> -#include <vector> - -#include "aom_dsp/fft_common.h" -#include "aom_mem/aom_mem.h" -#include "av1/common/common.h" -#include "config/aom_dsp_rtcd.h" -#include "test/acm_random.h" -#include "third_party/googletest/src/googletest/include/gtest/gtest.h" - -namespace { - -typedef void (*tform_fun_t)(const float *input, float *temp, float *output); - -// Simple 1D FFT implementation -template <typename InputType> -void fft(const InputType *data, std::complex<float> *result, int n) { - if (n == 1) { - result[0] = data[0]; - return; - } - std::vector<InputType> temp(n); - for (int k = 0; k < n / 2; ++k) { - temp[k] = data[2 * k]; - temp[n / 2 + k] = data[2 * k + 1]; - } - fft(&temp[0], result, n / 2); - fft(&temp[n / 2], result + n / 2, n / 2); - for (int k = 0; k < n / 2; ++k) { - std::complex<float> w = std::complex<float>((float)cos(2. * PI * k / n), - (float)-sin(2. * PI * k / n)); - std::complex<float> a = result[k]; - std::complex<float> b = result[n / 2 + k]; - result[k] = a + w * b; - result[n / 2 + k] = a - w * b; - } -} - -void transpose(std::vector<std::complex<float> > *data, int n) { - for (int y = 0; y < n; ++y) { - for (int x = y + 1; x < n; ++x) { - std::swap((*data)[y * n + x], (*data)[x * n + y]); - } - } -} - -// Simple 2D FFT implementation -template <class InputType> -std::vector<std::complex<float> > fft2d(const InputType *input, int n) { - std::vector<std::complex<float> > rowfft(n * n); - std::vector<std::complex<float> > result(n * n); - for (int y = 0; y < n; ++y) { - fft(input + y * n, &rowfft[y * n], n); - } - transpose(&rowfft, n); - for (int y = 0; y < n; ++y) { - fft(&rowfft[y * n], &result[y * n], n); - } - transpose(&result, n); - return result; -} - -struct FFTTestArg { - int n; - void (*fft)(const float *input, float *temp, float *output); - FFTTestArg(int n_in, tform_fun_t fft_in) : n(n_in), fft(fft_in) {} -}; - -std::ostream &operator<<(std::ostream &os, const FFTTestArg &test_arg) { - return os << "fft_arg { n:" << test_arg.n << " fft:" << test_arg.fft << " }"; -} - -class FFT2DTest : public ::testing::TestWithParam<FFTTestArg> { - protected: - void SetUp() { - int n = GetParam().n; - input_ = (float *)aom_memalign(32, sizeof(*input_) * n * n); - temp_ = (float *)aom_memalign(32, sizeof(*temp_) * n * n); - output_ = (float *)aom_memalign(32, sizeof(*output_) * n * n * 2); - memset(input_, 0, sizeof(*input_) * n * n); - memset(temp_, 0, sizeof(*temp_) * n * n); - memset(output_, 0, sizeof(*output_) * n * n * 2); - } - void TearDown() { - aom_free(input_); - aom_free(temp_); - aom_free(output_); - } - float *input_; - float *temp_; - float *output_; -}; - -TEST_P(FFT2DTest, Correct) { - int n = GetParam().n; - for (int i = 0; i < n * n; ++i) { - input_[i] = 1; - std::vector<std::complex<float> > expected = fft2d<float>(&input_[0], n); - GetParam().fft(&input_[0], &temp_[0], &output_[0]); - for (int y = 0; y < n; ++y) { - for (int x = 0; x < (n / 2) + 1; ++x) { - EXPECT_NEAR(expected[y * n + x].real(), output_[2 * (y * n + x)], 1e-5); - EXPECT_NEAR(expected[y * n + x].imag(), output_[2 * (y * n + x) + 1], - 1e-5); - } - } - input_[i] = 0; - } -} - -TEST_P(FFT2DTest, Benchmark) { - int n = GetParam().n; - float sum = 0; - for (int i = 0; i < 1000 * (64 - n); ++i) { - input_[i % (n * n)] = 1; - GetParam().fft(&input_[0], &temp_[0], &output_[0]); - sum += output_[0]; - input_[i % (n * n)] = 0; - } -} - -INSTANTIATE_TEST_CASE_P(C, FFT2DTest, - ::testing::Values(FFTTestArg(2, aom_fft2x2_float_c), - FFTTestArg(4, aom_fft4x4_float_c), - FFTTestArg(8, aom_fft8x8_float_c), - FFTTestArg(16, aom_fft16x16_float_c), - FFTTestArg(32, - aom_fft32x32_float_c))); -#if ARCH_X86 || ARCH_X86_64 -#if HAVE_SSE2 -INSTANTIATE_TEST_CASE_P( - SSE2, FFT2DTest, - ::testing::Values(FFTTestArg(4, aom_fft4x4_float_sse2), - FFTTestArg(8, aom_fft8x8_float_sse2), - FFTTestArg(16, aom_fft16x16_float_sse2), - FFTTestArg(32, aom_fft32x32_float_sse2))); -#endif // HAVE_SSE2 -#if HAVE_AVX2 -INSTANTIATE_TEST_CASE_P( - AVX2, FFT2DTest, - ::testing::Values(FFTTestArg(8, aom_fft8x8_float_avx2), - FFTTestArg(16, aom_fft16x16_float_avx2), - FFTTestArg(32, aom_fft32x32_float_avx2))); -#endif // HAVE_AVX2 -#endif // ARCH_X86 || ARCH_X86_64 - -struct IFFTTestArg { - int n; - tform_fun_t ifft; - IFFTTestArg(int n_in, tform_fun_t ifft_in) : n(n_in), ifft(ifft_in) {} -}; - -std::ostream &operator<<(std::ostream &os, const IFFTTestArg &test_arg) { - return os << "ifft_arg { n:" << test_arg.n << " fft:" << test_arg.ifft - << " }"; -} - -class IFFT2DTest : public ::testing::TestWithParam<IFFTTestArg> { - protected: - void SetUp() { - int n = GetParam().n; - input_ = (float *)aom_memalign(32, sizeof(*input_) * n * n * 2); - temp_ = (float *)aom_memalign(32, sizeof(*temp_) * n * n * 2); - output_ = (float *)aom_memalign(32, sizeof(*output_) * n * n); - memset(input_, 0, sizeof(*input_) * n * n * 2); - memset(temp_, 0, sizeof(*temp_) * n * n * 2); - memset(output_, 0, sizeof(*output_) * n * n); - } - void TearDown() { - aom_free(input_); - aom_free(temp_); - aom_free(output_); - } - float *input_; - float *temp_; - float *output_; -}; - -TEST_P(IFFT2DTest, Correctness) { - int n = GetParam().n; - ASSERT_GE(n, 2); - std::vector<float> expected(n * n); - std::vector<float> actual(n * n); - // Do forward transform then invert to make sure we get back expected - for (int y = 0; y < n; ++y) { - for (int x = 0; x < n; ++x) { - expected[y * n + x] = 1; - std::vector<std::complex<float> > input_c = fft2d(&expected[0], n); - for (int i = 0; i < n * n; ++i) { - input_[2 * i + 0] = input_c[i].real(); - input_[2 * i + 1] = input_c[i].imag(); - } - GetParam().ifft(&input_[0], &temp_[0], &output_[0]); - - for (int yy = 0; yy < n; ++yy) { - for (int xx = 0; xx < n; ++xx) { - EXPECT_NEAR(expected[yy * n + xx], output_[yy * n + xx] / (n * n), - 1e-5); - } - } - expected[y * n + x] = 0; - } - } -}; - -TEST_P(IFFT2DTest, Benchmark) { - int n = GetParam().n; - float sum = 0; - for (int i = 0; i < 1000 * (64 - n); ++i) { - input_[i % (n * n)] = 1; - GetParam().ifft(&input_[0], &temp_[0], &output_[0]); - sum += output_[0]; - input_[i % (n * n)] = 0; - } -} -INSTANTIATE_TEST_CASE_P( - C, IFFT2DTest, - ::testing::Values(IFFTTestArg(2, aom_ifft2x2_float_c), - IFFTTestArg(4, aom_ifft4x4_float_c), - IFFTTestArg(8, aom_ifft8x8_float_c), - IFFTTestArg(16, aom_ifft16x16_float_c), - IFFTTestArg(32, aom_ifft32x32_float_c))); -#if ARCH_X86 || ARCH_X86_64 -#if HAVE_SSE2 -INSTANTIATE_TEST_CASE_P( - SSE2, IFFT2DTest, - ::testing::Values(IFFTTestArg(4, aom_ifft4x4_float_sse2), - IFFTTestArg(8, aom_ifft8x8_float_sse2), - IFFTTestArg(16, aom_ifft16x16_float_sse2), - IFFTTestArg(32, aom_ifft32x32_float_sse2))); -#endif // HAVE_SSE2 - -#if HAVE_AVX2 -INSTANTIATE_TEST_CASE_P( - AVX2, IFFT2DTest, - ::testing::Values(IFFTTestArg(8, aom_ifft8x8_float_avx2), - IFFTTestArg(16, aom_ifft16x16_float_avx2), - IFFTTestArg(32, aom_ifft32x32_float_avx2))); -#endif // HAVE_AVX2 -#endif // ARCH_X86 || ARCH_X86_64 - -} // namespace |