1#include <Eigen/Core>
2#include <iostream>
3
4using namespace Eigen;
5
6// [circulant_func]
7template<class ArgType>
8class circulant_functor {
9  const ArgType &m_vec;
10public:
11  circulant_functor(const ArgType& arg) : m_vec(arg) {}
12
13  const typename ArgType::Scalar& operator() (Index row, Index col) const {
14    Index index = row - col;
15    if (index < 0) index += m_vec.size();
16    return m_vec(index);
17  }
18};
19// [circulant_func]
20
21// [square]
22template<class ArgType>
23struct circulant_helper {
24  typedef Matrix<typename ArgType::Scalar,
25                 ArgType::SizeAtCompileTime,
26                 ArgType::SizeAtCompileTime,
27                 ColMajor,
28                 ArgType::MaxSizeAtCompileTime,
29                 ArgType::MaxSizeAtCompileTime> MatrixType;
30};
31// [square]
32
33// [makeCirculant]
34template <class ArgType>
35CwiseNullaryOp<circulant_functor<ArgType>, typename circulant_helper<ArgType>::MatrixType>
36makeCirculant(const Eigen::MatrixBase<ArgType>& arg)
37{
38  typedef typename circulant_helper<ArgType>::MatrixType MatrixType;
39  return MatrixType::NullaryExpr(arg.size(), arg.size(), circulant_functor<ArgType>(arg.derived()));
40}
41// [makeCirculant]
42
43// [main]
44int main()
45{
46  Eigen::VectorXd vec(4);
47  vec << 1, 2, 4, 8;
48  Eigen::MatrixXd mat;
49  mat = makeCirculant(vec);
50  std::cout << mat << std::endl;
51}
52// [main]
53