81class Toeplitz :
public EigenBase<Toeplitz<Scalar_, Rows_, Cols_>> {
83 using Scalar = Scalar_;
85 using StorageIndex = int;
86 using Complex = std::complex<RealScalar>;
91 static constexpr int RowsAtCompileTime = Rows_;
92 static constexpr int ColsAtCompileTime = Cols_;
93 static constexpr int MaxRowsAtCompileTime = Rows_;
94 static constexpr int MaxColsAtCompileTime = Cols_;
95 static constexpr int SizeAtCompileTime = internal::size_at_compile_time(Rows_, Cols_);
96 static constexpr int MaxSizeAtCompileTime = SizeAtCompileTime;
97 static constexpr bool IsRowMajor =
false;
111 template <
typename ColDerived,
typename RowDerived>
113 EIGEN_STATIC_ASSERT_VECTOR_ONLY(ColDerived)
114 EIGEN_STATIC_ASSERT_VECTOR_ONLY(RowDerived)
115 eigen_assert(m_col.size() > 0 && m_row.size() > 0 &&
"Toeplitz generators must be non-empty");
118 if (rows() > internal::structured_direct_threshold() || cols() > internal::structured_direct_threshold())
119 m_symbol = computeSymbol();
122 EIGEN_DEVICE_FUNC Index rows()
const {
return m_col.size(); }
123 EIGEN_DEVICE_FUNC Index cols()
const {
return m_row.size(); }
126 const ColGeneratorType&
column()
const {
return m_col; }
128 const RowGeneratorType&
row()
const {
return m_row; }
134 ComplexVector
symbol()
const {
return m_symbol.size() > 0 ? m_symbol : computeSymbol(); }
139 return k >= 0 ? m_col.coeff(k) : m_row.coeff(-k);
148 using TransposeType = Toeplitz<Scalar, Cols_, Rows_>;
149 const Index n = cols();
150 typename TransposeType::ColGeneratorType col(n);
152 if (n > 1) col.tail(n - 1) = m_row.tail(n - 1);
153 return TransposeType(col, m_col, internal::structured_reverse_symbol(m_symbol));
160 return Toeplitz(m_col.conjugate(), m_row.conjugate(), internal::structured_reverse_symbol(m_symbol).conjugate());
166 Toeplitz<Scalar, Cols_, Rows_>
adjoint()
const {
167 using AdjointType = Toeplitz<Scalar, Cols_, Rows_>;
168 const Index n = cols();
169 typename AdjointType::ColGeneratorType col(n);
170 col[0] = numext::conj(m_col[0]);
171 if (n > 1) col.tail(n - 1) = m_row.tail(n - 1).conjugate();
172 return AdjointType(col, m_col.conjugate(), m_symbol.conjugate());
179 template <
typename Dest>
180 void evalTo(Dest& dst)
const {
181 const Index m = rows(), n = cols();
182 EIGEN_IF_CONSTEXPR (Dest::IsRowMajor) {
183 for (Index i = 0; i < m; ++i) {
184 const Index h = numext::mini(i + 1, n);
185 dst.row(i).head(h) = m_col.segment(i - h + 1, h).reverse().transpose();
186 if (i + 1 < n) dst.row(i).tail(n - i - 1) = m_row.segment(1, n - i - 1).transpose();
190 for (
Index j = 0; j < n; ++j) {
191 const Index h = numext::mini(j, m);
192 dst.col(j).head(h) = m_row.segment(j - h + 1, h).reverse();
193 if (j < m) dst.col(j).tail(m - j) = m_col.head(m - j);
198 template <
typename Dest>
199 void addTo(Dest& dst)
const {
200 const Index m = rows(), n = cols();
201 EIGEN_IF_CONSTEXPR (Dest::IsRowMajor) {
202 for (
Index i = 0; i < m; ++i) {
203 const Index h = numext::mini(i + 1, n);
204 dst.row(i).head(h) += m_col.segment(i - h + 1, h).reverse().transpose();
205 if (i + 1 < n) dst.row(i).tail(n - i - 1) += m_row.segment(1, n - i - 1).transpose();
209 for (
Index j = 0; j < n; ++j) {
210 const Index h = numext::mini(j, m);
211 dst.col(j).head(h) += m_row.segment(j - h + 1, h).reverse();
212 if (j < m) dst.col(j).tail(m - j) += m_col.head(m - j);
217 template <
typename Dest>
218 void subTo(Dest& dst)
const {
219 const Index m = rows(), n = cols();
220 EIGEN_IF_CONSTEXPR (Dest::IsRowMajor) {
221 for (
Index i = 0; i < m; ++i) {
222 const Index h = numext::mini(i + 1, n);
223 dst.row(i).head(h) -= m_col.segment(i - h + 1, h).reverse().transpose();
224 if (i + 1 < n) dst.row(i).tail(n - i - 1) -= m_row.segment(1, n - i - 1).transpose();
228 for (
Index j = 0; j < n; ++j) {
229 const Index h = numext::mini(j, m);
230 dst.col(j).head(h) -= m_row.segment(j - h + 1, h).reverse();
231 if (j < m) dst.col(j).tail(m - j) -= m_col.head(m - j);
240 template <
typename Rhs>
242 EIGEN_STATIC_ASSERT(ColsAtCompileTime == Dynamic || Rhs::RowsAtCompileTime == Dynamic ||
243 int(ColsAtCompileTime) ==
int(Rhs::RowsAtCompileTime),
244 INVALID_MATRIX_PRODUCT)
245 eigen_assert(x.rows() == cols() &&
"invalid product: dimensions do not match");
252 template <
typename Dest,
typename Rhs,
typename ProductScalar>
253 void addProduct(Dest& dst,
const Rhs& rhs,
const ProductScalar& alpha)
const {
254 const Index m = rows(), n = cols();
255 eigen_assert(rhs.rows() == n &&
"invalid product: dimensions do not match");
256 const bool small = m <= internal::structured_direct_threshold() && n <= internal::structured_direct_threshold();
258 directProduct(dst, rhs, alpha);
260 internal::structured_fft_apply(dst, m_symbol, m, rhs, alpha);
266 template <
typename OtherScalar,
int OtherRows,
int OtherCols>
267 friend class Toeplitz;
273 Toeplitz(
const ColGeneratorType& col,
const RowGeneratorType&
row,
const ComplexVector&
symbol)
274 : m_col(col), m_row(
row), m_symbol(
symbol) {}
279 template <
typename Dest,
typename Rhs,
typename ProductScalar>
280 void directProductColumn(Dest& dst,
const Rhs& rhs,
Index k,
const ProductScalar& alpha)
const {
281 const Index m = rows(), n = cols();
284 const bool unitAlpha = alpha == ProductScalar(1);
285 if (m <= internal::structured_scalar_threshold() && n <= internal::structured_scalar_threshold()) {
288 for (
Index i = 0; i < m; ++i) {
289 ProductScalar acc(0);
290 for (
Index j = 0; j < n; ++j) acc +=
coeff(i, j) * rhs.coeff(j, k);
291 dst.coeffRef(i, k) += unitAlpha ? acc : ProductScalar(alpha * acc);
297 auto dstCol = dst.col(k);
298 for (
Index j = 0; j < n; ++j) {
299 const ProductScalar xj = unitAlpha ? ProductScalar(rhs.coeff(j, k)) : ProductScalar(alpha * rhs.
coeff(j, k));
300 const Index h = numext::mini(j, m);
301 dstCol.head(h) += xj * m_row.segment(j - h + 1, h).reverse();
302 if (j < m) dstCol.tail(m - j) += xj * m_col.head(m - j);
308 template <
typename Dest,
typename Rhs,
typename ProductScalar>
309 void directProduct(Dest& dst,
const Rhs& rhs,
const ProductScalar& alpha)
const {
310 for (
Index k = 0; k < rhs.cols(); ++k) directProductColumn(dst, rhs, k, alpha);
314 ComplexVector computeSymbol()
const {
315 const Index m = rows(), n = cols();
316 const Index p = internal::fft_next_good_size(m + n - 1);
317 ComplexVector embedding = ComplexVector::Zero(p);
318 embedding.head(m) = m_col.template cast<Complex>();
319 embedding.tail(n - 1) = m_row.tail(n - 1).reverse().template cast<Complex>();
320 if (p == 1)
return embedding;
322 auto&& fft = internal::structured_fft_engine<RealScalar>();
323 fft.fwd(
symbol, embedding, p);
327 ColGeneratorType m_col;
328 RowGeneratorType m_row;
329 ComplexVector m_symbol;