autoppl  v0.8
A C++ template library for probabilistic programming
autocorrelation.hpp
Go to the documentation of this file.
1 #pragma once
2 #include <Eigen/Dense>
3 #include <unsupported/Eigen/FFT>
4 
5 namespace ppl {
6 namespace math {
7 
8 inline size_t padded_length(size_t N)
9 {
10  return std::pow(2, std::ceil(std::log(N)/std::log(2.)));
11 }
12 
25 template <class T>
26 inline auto autocorrelation(const Eigen::MatrixBase<T>& x)
27 {
28  using scalar_t = typename T::Scalar;
29  using complex_t = std::complex<scalar_t>;
30 
31  size_t n_rows = x.rows();
32  size_t padded_len = 2*padded_length(n_rows);
33 
34  Eigen::Matrix<scalar_t, Eigen::Dynamic, Eigen::Dynamic> out(x.rows(), x.cols());
35 
36  Eigen::FFT<scalar_t> fft;
37 
38  for (int i = 0; i < x.cols(); ++i) {
39 
40  // create centered copy of x
41  Eigen::Matrix<scalar_t, Eigen::Dynamic, 1> x_cent(padded_len);
42  x_cent.setZero();
43  x_cent.head(n_rows) = x.col(i).array() - x.col(i).mean();
44 
45  // FFT
46  Eigen::Matrix<complex_t, Eigen::Dynamic, 1> freq(padded_len);
47  fft.fwd(freq, x_cent);
48 
49  // compute complex-norm element-wise
50  freq = freq.array().abs2();
51 
52  // inverse FFT and trim to shape of x
53  Eigen::Matrix<complex_t, Eigen::Dynamic, 1> ifreq(padded_len);
54  fft.inv(ifreq, freq);
55 
56  // get autocorrelation by normalizing by variance
57  out.col(i) = ifreq.head(n_rows).real() / (n_rows * n_rows * 2.);
58  out.col(i) /= out(0,i);
59 
60  }
61 
62  return out;
63 }
64 
65 } // namespace math
66 } // namespace ppl
ppl::math::autocorrelation
auto autocorrelation(const Eigen::MatrixBase< T > &x)
Definition: autocorrelation.hpp:26
ppl
Definition: bounded.hpp:11
ppl::math::padded_length
size_t padded_length(size_t N)
Definition: autocorrelation.hpp:8