<commit_before>/******************************************************************************
 * Copyright © 2012-2013 Institut für Nachrichtentechnik, Universität Rostock *
 * Copyright © 2006-2012 Quality & Usability Lab,                             *
 *                       Telekom Innovation Laboratories, TU Berlin           *
 *                                                                            *
 * This file is part of the Audio Processing Framework (APF).                 *
 *                                                                            *
 * The APF is free software:  you can redistribute it and/or modify it  under *
 * the terms of the  GNU  General  Public  License  as published by the  Free *
 * Software Foundation, either version 3 of the License,  or (at your option) *
 * any later version.                                                         *
 *                                                                            *
 * The APF is distributed in the hope that it will be useful, but WITHOUT ANY *
 * WARRANTY;  without even the implied warranty of MERCHANTABILITY or FITNESS *
 * FOR A PARTICULAR PURPOSE.                                                  *
 * See the GNU General Public License for more details.                       *
 *                                                                            *
 * You should  have received a copy  of the GNU General Public License  along *
 * with this program.  If not, see <http://www.gnu.org/licenses/>.            *
 *                                                                            *
 *                                 http://AudioProcessingFramework.github.com *
 ******************************************************************************/

/// @file
/// Convolution engine.

#ifndef APF_CONVOLVER_H
#define APF_CONVOLVER_H

#include <algorithm>  // for std::transform()
#include <cassert>

#ifdef __SSE__
#include <xmmintrin.h>  // for SSE instrinsics
#endif

#include "apf/math.h"
#include "apf/fftwtools.h"  // for fftw_allocator and fftw traits
#include "apf/container.h"  // for fixed_vector, fixed_list
#include "apf/iterator.h"  // for make_*_iterator()

namespace apf
{

/** Convolution engine.
 * A convolution engine normally consists of an Input, a Filter and
 * an Output / StaticOutput.
 * There are also combinations:
 * Input + Output = Convolver; Input + StaticOutput = StaticConvolver
 *
 * Uses (uniformly) partitioned convolution.
 *
 * TODO: describe thread (un)safety
 **/
namespace conv
{

/// Calculate necessary number of partitions for a given filter length
static size_t min_partitions(size_t block_size, size_t filter_size)
{
  return (filter_size + block_size - 1) / block_size;
}

/// Two blocks of time-domain or FFT (half-complex) data.
struct fft_node : fixed_vector<float, fftw_allocator<float>>
{
  explicit fft_node(size_t n)
    : fixed_vector<float, fftw_allocator<float>>(n)
    , zero(true)
  {}

  fft_node(const fft_node&) = delete;
  fft_node(fft_node&&) = default;

  fft_node& operator=(const fft_node& rhs)
  {
    assert(this->size() == rhs.size());

    if (rhs.zero)
    {
      this->zero = true;
    }
    else
    {
      std::copy(rhs.begin(), rhs.end(), this->begin());
      this->zero = false;
    }
    return *this;
  }

  // WARNING: The 'zero' flag allows saving computation power, but it also
  // raises the risk of programming errors! Handle with care!

  /// To avoid unnecessary FFTs and filling buffers with zeros.
  /// @note If zero == true, the buffer itself is not necessarily all zeros!
  bool zero;
};

/// Container holding a number of FFT blocks.
struct Filter : fixed_vector<fft_node>
{
  /// Constructor; create empty filter.
  Filter(size_t block_size_, size_t partitions_)
    : fixed_vector<fft_node>(partitions_, block_size_ * 2)
  {
    assert(this->partitions() > 0);
  }

  /// Constructor from time domain coefficients.
  template<typename In>
  Filter(size_t block_size_, In first, In last, size_t partitions_ = 0);
  // Implementation below, after definition of Transform

  size_t block_size() const { return front().size() / 2; }
  size_t partition_size() const { return front().size(); }
  size_t partitions() const { return this->size(); }
};

/// Forward-FFT-related functions
class TransformBase
{
  public:
    template<typename In>
    void prepare_filter(In first, In last, Filter& filter) const;

    size_t block_size() const { return _block_size; }
    size_t partition_size() const { return _partition_size; }

    template<typename In>
    In prepare_partition(In first, In last, fft_node& partition) const;

  protected:
    explicit TransformBase(size_t block_size_);

    ~TransformBase() = default;  ///< Protected destructor

    using scoped_plan = fftw<float>::scoped_plan;
    using plan_ptr = std::unique_ptr<scoped_plan>;

    plan_ptr _create_plan(float* array) const;

    /// In-place FFT
    void _fft(float* first) const
    {
      fftw<float>::execute_r2r(*_fft_plan, first, first);
      _sort_coefficients(first);
    }

    plan_ptr _fft_plan;

  private:
    void _sort_coefficients(float* first) const;

    const size_t _block_size;
    const size_t _partition_size;<commit_msg>Make apf::conv::TransformBase move-constructible<commit_after>/******************************************************************************
 * Copyright © 2012-2013 Institut für Nachrichtentechnik, Universität Rostock *
 * Copyright © 2006-2012 Quality & Usability Lab,                             *
 *                       Telekom Innovation Laboratories, TU Berlin           *
 *                                                                            *
 * This file is part of the Audio Processing Framework (APF).                 *
 *                                                                            *
 * The APF is free software:  you can redistribute it and/or modify it  under *
 * the terms of the  GNU  General  Public  License  as published by the  Free *
 * Software Foundation, either version 3 of the License,  or (at your option) *
 * any later version.                                                         *
 *                                                                            *
 * The APF is distributed in the hope that it will be useful, but WITHOUT ANY *
 * WARRANTY;  without even the implied warranty of MERCHANTABILITY or FITNESS *
 * FOR A PARTICULAR PURPOSE.                                                  *
 * See the GNU General Public License for more details.                       *
 *                                                                            *
 * You should  have received a copy  of the GNU General Public License  along *
 * with this program.  If not, see <http://www.gnu.org/licenses/>.            *
 *                                                                            *
 *                                 http://AudioProcessingFramework.github.com *
 ******************************************************************************/

/// @file
/// Convolution engine.

#ifndef APF_CONVOLVER_H
#define APF_CONVOLVER_H

#include <algorithm>  // for std::transform()
#include <cassert>

#ifdef __SSE__
#include <xmmintrin.h>  // for SSE instrinsics
#endif

#include "apf/math.h"
#include "apf/fftwtools.h"  // for fftw_allocator and fftw traits
#include "apf/container.h"  // for fixed_vector, fixed_list
#include "apf/iterator.h"  // for make_*_iterator()

namespace apf
{

/** Convolution engine.
 * A convolution engine normally consists of an Input, a Filter and
 * an Output / StaticOutput.
 * There are also combinations:
 * Input + Output = Convolver; Input + StaticOutput = StaticConvolver
 *
 * Uses (uniformly) partitioned convolution.
 *
 * TODO: describe thread (un)safety
 **/
namespace conv
{

/// Calculate necessary number of partitions for a given filter length
static size_t min_partitions(size_t block_size, size_t filter_size)
{
  return (filter_size + block_size - 1) / block_size;
}

/// Two blocks of time-domain or FFT (half-complex) data.
struct fft_node : fixed_vector<float, fftw_allocator<float>>
{
  explicit fft_node(size_t n)
    : fixed_vector<float, fftw_allocator<float>>(n)
    , zero(true)
  {}

  fft_node(const fft_node&) = delete;
  fft_node(fft_node&&) = default;

  fft_node& operator=(const fft_node& rhs)
  {
    assert(this->size() == rhs.size());

    if (rhs.zero)
    {
      this->zero = true;
    }
    else
    {
      std::copy(rhs.begin(), rhs.end(), this->begin());
      this->zero = false;
    }
    return *this;
  }

  // WARNING: The 'zero' flag allows saving computation power, but it also
  // raises the risk of programming errors! Handle with care!

  /// To avoid unnecessary FFTs and filling buffers with zeros.
  /// @note If zero == true, the buffer itself is not necessarily all zeros!
  bool zero;
};

/// Container holding a number of FFT blocks.
struct Filter : fixed_vector<fft_node>
{
  /// Constructor; create empty filter.
  Filter(size_t block_size_, size_t partitions_)
    : fixed_vector<fft_node>(partitions_, block_size_ * 2)
  {
    assert(this->partitions() > 0);
  }

  /// Constructor from time domain coefficients.
  template<typename In>
  Filter(size_t block_size_, In first, In last, size_t partitions_ = 0);
  // Implementation below, after definition of Transform

  size_t block_size() const { return front().size() / 2; }
  size_t partition_size() const { return front().size(); }
  size_t partitions() const { return this->size(); }
};

/// Forward-FFT-related functions
class TransformBase
{
  public:
    template<typename In>
    void prepare_filter(In first, In last, Filter& filter) const;

    size_t block_size() const { return _block_size; }
    size_t partition_size() const { return _partition_size; }

    template<typename In>
    In prepare_partition(In first, In last, fft_node& partition) const;

  protected:
    explicit TransformBase(size_t block_size_);

    TransformBase(TransformBase&&) = default;
    ~TransformBase() = default;

    using scoped_plan = fftw<float>::scoped_plan;
    using plan_ptr = std::unique_ptr<scoped_plan>;

    plan_ptr _create_plan(float* array) const;

    /// In-place FFT
    void _fft(float* first) const
    {
      fftw<float>::execute_r2r(*_fft_plan, first, first);
      _sort_coefficients(first);
    }

    plan_ptr _fft_plan;

  private:
    void _sort_coefficients(float* first) const;

    const size_t _block_size;
    const size_t _partition_size;
{'fraction_non_alphanumeric': 0.12188865665969979, 'fraction_numerical': 0.004370131103933118, 'mean_word_length': 2.2917448405253285, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 40, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7008381', 'n_tokens_mistral': 2968, 'n_tokens_neox': 2829, 'n_words': 899}