/*
 *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "modules/audio_processing/utility/pffft_wrapper.h"

#include <algorithm>
#include <cstdlib>
#include <memory>

#include "test/gtest.h"
#include "third_party/pffft/src/pffft.h"

namespace webrtc {
namespace test {
namespace {

constexpr size_t kMaxValidSizeCheck = 1024;

static constexpr int kFftSizes[] = {
    16,  32,      64,  96,  128,  160,  192,  256,  288,  384,   5 * 96, 512,
    576, 5 * 128, 800, 864, 1024, 2048, 2592, 4000, 4096, 12000, 36864};

void CreatePffftWrapper(size_t fft_size, Pffft::FftType fft_type) {
  Pffft pffft_wrapper(fft_size, fft_type);
}

float* AllocateScratchBuffer(size_t fft_size, bool complex_fft) {
  return static_cast<float*>(
      pffft_aligned_malloc(fft_size * (complex_fft ? 2 : 1) * sizeof(float)));
}

double frand() {
  return std::rand() / static_cast<double>(RAND_MAX);
}

void ExpectArrayViewsEquality(rtc::ArrayView<const float> a,
                              rtc::ArrayView<const float> b) {
  ASSERT_EQ(a.size(), b.size());
  for (size_t i = 0; i < a.size(); ++i) {
    SCOPED_TRACE(i);
    EXPECT_EQ(a[i], b[i]);
  }
}

// Compares the output of the PFFFT C++ wrapper to that of the C PFFFT.
// Bit-exactness is expected.
void PffftValidateWrapper(size_t fft_size, bool complex_fft) {
  // Always use the same seed to avoid flakiness.
  std::srand(0);

  // Init PFFFT.
  PFFFT_Setup* pffft_status =
      pffft_new_setup(fft_size, complex_fft ? PFFFT_COMPLEX : PFFFT_REAL);
  ASSERT_TRUE(pffft_status) << "FFT size (" << fft_size << ") not supported.";
  size_t num_floats = fft_size * (complex_fft ? 2 : 1);
  int num_bytes = static_cast<int>(num_floats) * sizeof(float);
  float* in = static_cast<float*>(pffft_aligned_malloc(num_bytes));
  float* out = static_cast<float*>(pffft_aligned_malloc(num_bytes));
  float* scratch = AllocateScratchBuffer(fft_size, complex_fft);

  // Init PFFFT C++ wrapper.
  Pffft::FftType fft_type =
      complex_fft ? Pffft::FftType::kComplex : Pffft::FftType::kReal;
  ASSERT_TRUE(Pffft::IsValidFftSize(fft_size, fft_type));
  Pffft pffft_wrapper(fft_size, fft_type);
  auto in_wrapper = pffft_wrapper.CreateBuffer();
  auto out_wrapper = pffft_wrapper.CreateBuffer();

  // Input and output buffers views.
  rtc::ArrayView<float> in_view(in, num_floats);
  rtc::ArrayView<float> out_view(out, num_floats);
  auto in_wrapper_view = in_wrapper->GetView();
  EXPECT_EQ(in_wrapper_view.size(), num_floats);
  auto out_wrapper_view = out_wrapper->GetConstView();
  EXPECT_EQ(out_wrapper_view.size(), num_floats);

  // Random input data.
  for (size_t i = 0; i < num_floats; ++i) {
    in_wrapper_view[i] = in[i] = static_cast<float>(frand() * 2.0 - 1.0);
  }

  // Forward transform.
  pffft_transform(pffft_status, in, out, scratch, PFFFT_FORWARD);
  pffft_wrapper.ForwardTransform(*in_wrapper, out_wrapper.get(),
                                 /*ordered=*/false);
  ExpectArrayViewsEquality(out_view, out_wrapper_view);

  // Copy the FFT results into the input buffers to compute the backward FFT.
  std::copy(out_view.begin(), out_view.end(), in_view.begin());
  std::copy(out_wrapper_view.begin(), out_wrapper_view.end(),
            in_wrapper_view.begin());

  // Backward transform.
  pffft_transform(pffft_status, in, out, scratch, PFFFT_BACKWARD);
  pffft_wrapper.BackwardTransform(*in_wrapper, out_wrapper.get(),
                                  /*ordered=*/false);
  ExpectArrayViewsEquality(out_view, out_wrapper_view);

  pffft_destroy_setup(pffft_status);
  pffft_aligned_free(in);
  pffft_aligned_free(out);
  pffft_aligned_free(scratch);
}

}  // namespace

TEST(PffftTest, CreateWrapperWithValidSize) {
  for (size_t fft_size = 0; fft_size < kMaxValidSizeCheck; ++fft_size) {
    SCOPED_TRACE(fft_size);
    if (Pffft::IsValidFftSize(fft_size, Pffft::FftType::kReal)) {
      CreatePffftWrapper(fft_size, Pffft::FftType::kReal);
    }
    if (Pffft::IsValidFftSize(fft_size, Pffft::FftType::kComplex)) {
      CreatePffftWrapper(fft_size, Pffft::FftType::kComplex);
    }
  }
}

#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)

class PffftInvalidSizeTest : public ::testing::Test,
                             public ::testing::WithParamInterface<size_t> {};

TEST_P(PffftInvalidSizeTest, DoNotCreateRealWrapper) {
  size_t fft_size = GetParam();
  ASSERT_FALSE(Pffft::IsValidFftSize(fft_size, Pffft::FftType::kReal));
  EXPECT_DEATH(CreatePffftWrapper(fft_size, Pffft::FftType::kReal), "");
}

TEST_P(PffftInvalidSizeTest, DoNotCreateComplexWrapper) {
  size_t fft_size = GetParam();
  ASSERT_FALSE(Pffft::IsValidFftSize(fft_size, Pffft::FftType::kComplex));
  EXPECT_DEATH(CreatePffftWrapper(fft_size, Pffft::FftType::kComplex), "");
}

INSTANTIATE_TEST_SUITE_P(PffftTest,
                         PffftInvalidSizeTest,
                         ::testing::Values(17,
                                           33,
                                           65,
                                           97,
                                           129,
                                           161,
                                           193,
                                           257,
                                           289,
                                           385,
                                           481,
                                           513,
                                           577,
                                           641,
                                           801,
                                           865,
                                           1025));

#endif

// TODO(https://crbug.com/webrtc/9577): Enable once SIMD is always enabled.
TEST(PffftTest, DISABLED_CheckSimd) {
  EXPECT_TRUE(Pffft::IsSimdEnabled());
}

TEST(PffftTest, FftBitExactness) {
  for (int fft_size : kFftSizes) {
    SCOPED_TRACE(fft_size);
    if (fft_size != 16) {
      PffftValidateWrapper(fft_size, /*complex_fft=*/false);
    }
    PffftValidateWrapper(fft_size, /*complex_fft=*/true);
  }
}

}  // namespace test
}  // namespace webrtc
