Eigen-Contrib  5.0.1
 
Loading...
Searching...
No Matches
Vandermonde.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// This Source Code Form is subject to the terms of the Mozilla
5// Public License v. 2.0. If a copy of the MPL was not distributed
6// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
7// SPDX-FileCopyrightText: The Eigen Authors
8// SPDX-License-Identifier: MPL-2.0
9
10// References:
11// [1] N. J. Higham, "Accuracy and Stability of Numerical Algorithms", 2nd ed.,
12// SIAM, 2002, chapter 27. Avoiding spurious overflow by rescaling with
13// powers of two, the technique behind determinant()'s balanced
14// accumulation.
15// [2] P. H. Sterbenz, "Floating-Point Computation", Prentice-Hall, 1974.
16// Scaling by a power of two is exact, the property the balanced
17// accumulation relies on.
18// [3] J. J. Dongarra, J. R. Bunch, C. B. Moler and G. W. Stewart, "LINPACK
19// Users' Guide", SIAM, 1979. determinant()'s balanced accumulation follows
20// the convention of its xGEDI routines, which return determinants as a
21// (fraction, exponent) pair to avoid spurious overflow/underflow.
22// [4] L. Reichel, "Newton Interpolation at Leja Points", BIT 30 (1990),
23// 332--346. Leja ordering controls growth in the Newton representation;
24// BjorckPereyra uses it for genuinely complex node sets.
25
26#ifndef EIGEN_STRUCTURED_VANDERMONDE_H
27#define EIGEN_STRUCTURED_VANDERMONDE_H
28
29// IWYU pragma: private
30#include "./InternalHeaderCheck.h"
31
32namespace Eigen {
33
34template <typename Scalar_, int Rows_ = Dynamic, int Cols_ = Dynamic>
35class Vandermonde;
36
37template <typename Scalar_>
38class BjorckPereyra;
39
40namespace internal {
41
42template <typename Scalar_, int Rows_, int Cols_>
43struct traits<Vandermonde<Scalar_, Rows_, Cols_>> {
44 using Scalar = Scalar_;
45 using StorageKind = Dense;
46 using XprKind = MatrixXpr;
47 using StorageIndex = int;
48 static constexpr int RowsAtCompileTime = Rows_;
49 static constexpr int ColsAtCompileTime = Cols_;
50 static constexpr int MaxRowsAtCompileTime = Rows_;
51 static constexpr int MaxColsAtCompileTime = Cols_;
52 // Deliberately no NestByRefBit: the makeVandermonde() factories (and any
53 // function returning the operator by value) produce owning temporaries, so
54 // Product must nest the operator by value for a delayed-evaluated product
55 // expression to keep its left factor alive. The copy is O(m), negligible
56 // against the O(mn) product evaluation.
57 static constexpr int Flags = Rows_ == 1 && Cols_ != 1 ? RowMajorBit : 0;
58};
59
60template <typename Scalar_, int Rows_, int Cols_>
61struct evaluator_traits<Vandermonde<Scalar_, Rows_, Cols_>> {
62 using Kind = IndexBased;
63 using Shape = StructuredShape;
64};
65
66// Core rewrites alpha * (lhs * rhs) as (alpha * lhs) * rhs. The scaled
67// Vandermonde wrapper needs coefficient and BLAS metadata to participate in
68// that general dense-expression machinery.
69template <typename Scalar_, int Rows_, int Cols_>
70struct evaluator<Vandermonde<Scalar_, Rows_, Cols_>> : evaluator_base<Vandermonde<Scalar_, Rows_, Cols_>> {
71 using XprType = Vandermonde<Scalar_, Rows_, Cols_>;
72 using Scalar = Scalar_;
73 static constexpr int CoeffReadCost = HugeCost;
74 static constexpr int Flags = traits<XprType>::Flags;
75 static constexpr int Alignment = 0;
76
77 EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr) : m_xpr(xpr) {}
78
79 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index row, Index col) const { return m_xpr.coeff(row, col); }
80
81 private:
82 const XprType& m_xpr;
83};
84
85template <typename Scalar_, int Rows_, int Cols_>
86struct blas_traits<Vandermonde<Scalar_, Rows_, Cols_>> {
87 using XprType = Vandermonde<Scalar_, Rows_, Cols_>;
88 using Scalar = Scalar_;
89 using ExtractType = const XprType&;
90 using ExtractType_ = XprType;
91 using DirectLinearAccessType = XprType;
92 static constexpr bool IsComplex = NumTraits<Scalar>::IsComplex;
93 static constexpr bool IsTransposed = false;
94 static constexpr bool NeedToConjugate = false;
95 static constexpr bool HasUsableDirectAccess = false;
96 static constexpr bool HasScalarFactor = false;
97 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE ExtractType extract(const XprType& x) { return x; }
98 static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar extractScalarFactor(const XprType&) { return Scalar(1); }
99};
100
101template <typename Scalar_>
102struct traits<BjorckPereyra<Scalar_>> : traits<Matrix<Scalar_, Dynamic, Dynamic>> {
103 using XprKind = MatrixXpr;
104 using StorageKind = SolverStorage;
105 using StorageIndex = int;
106 using BaseTraits = traits<Matrix<Scalar_, Dynamic, Dynamic>>;
107 static constexpr int Flags = BaseTraits::Flags & RowMajorBit;
108 static constexpr int CoeffReadCost = Dynamic;
109};
110
111} // namespace internal
112
157template <typename Scalar_, int Rows_, int Cols_>
158class Vandermonde : public EigenBase<Vandermonde<Scalar_, Rows_, Cols_>> {
159 public:
160 using Derived = Vandermonde;
161 using StorageBaseType = Vandermonde;
162 using Scalar = Scalar_;
163 using RealScalar = typename NumTraits<Scalar>::Real;
164 using StorageIndex = int;
165 static constexpr int NodeOptions = Rows_ == Dynamic ? AutoAlign : DontAlign;
166 using NodeVector = Matrix<Scalar, Rows_, 1, NodeOptions>;
167 using Nested = Vandermonde;
168
169 static constexpr int RowsAtCompileTime = Rows_;
170 static constexpr int ColsAtCompileTime = Cols_;
171 static constexpr int MaxRowsAtCompileTime = Rows_;
172 static constexpr int MaxColsAtCompileTime = Cols_;
173 static constexpr int SizeAtCompileTime = internal::size_at_compile_time(Rows_, Cols_);
174 static constexpr int MaxSizeAtCompileTime = SizeAtCompileTime;
175 static constexpr int Flags = internal::traits<Vandermonde>::Flags;
176 static constexpr bool IsRowMajor = (Flags & RowMajorBit) != 0;
177 // Deliberately no IsVectorAtCompileTime: Ref<const Vandermonde>'s default
178 // StrideType argument reads it, so its absence makes internal::is_ref_compatible
179 // SFINAE to false and keeps the iterative solvers on their matrix-free path.
180
181 EIGEN_STATIC_ASSERT_NON_INTEGER(RealScalar)
182 EIGEN_MAKE_SCALAR_BINARY_OP_ONTHELEFT(operator*, internal::scalar_product_op)
183
184
185 template <typename Derived>
186 Vandermonde(const MatrixBase<Derived>& nodes, Index cols) : m_x(nodes), m_cols(cols) {
187 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
188 eigen_assert(m_x.size() > 0 && m_cols > 0 && "Vandermonde must be non-empty");
189 eigen_assert((Cols_ == Dynamic || Cols_ == cols) && "cols does not match the compile-time column count");
190 }
191
193 template <typename Derived>
195 EIGEN_STATIC_ASSERT(Rows_ == Dynamic || Cols_ == Dynamic || Rows_ == Cols_, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES)
196 EIGEN_STATIC_ASSERT(
197 Cols_ == Dynamic || Derived::SizeAtCompileTime == Dynamic || Cols_ == Derived::SizeAtCompileTime,
198 YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES)
199 }
200
201 EIGEN_DEVICE_FUNC Index rows() const { return m_x.size(); }
202 EIGEN_DEVICE_FUNC Index cols() const { return m_cols; }
203
205 const NodeVector& nodes() const { return m_x; }
206
208 EIGEN_DEVICE_FUNC Scalar coeff(Index row, Index col) const {
209 Scalar p(1);
210 const Scalar xi = m_x.coeff(row);
211 for (Index t = 0; t < col; ++t) p *= xi;
212 return p;
213 }
214
226 Scalar determinant() const {
227 eigen_assert(rows() == cols() && "Vandermonde::determinant requires a square matrix");
228 const Index n = rows();
229 Scalar det(1);
230 internal::structured_exponent_type exponent = 0;
231 for (Index j = 1; j < n; ++j)
232 for (Index i = 0; i < j; ++i)
233 det = internal::structured_balance(
234 det * internal::structured_balance(Scalar(m_x.coeff(j) - m_x.coeff(i)), exponent), exponent);
235 // ldexp saturates cleanly to zero / infinity once the accumulated exponent
236 // leaves the representable range; the clamp only guards the narrowing to int.
237 return internal::structured_ldexp_clamped(det, exponent);
238 }
239
243 template <typename Dest>
244 void evalTo(Dest& dst) const {
245 dst.col(0).setOnes();
246 for (Index j = 1; j < m_cols; ++j) dst.col(j) = dst.col(j - 1).cwiseProduct(m_x);
247 }
248
250 template <typename Dest>
251 void addTo(Dest& dst) const {
252 NodeVector p = NodeVector::Ones(rows());
253 dst.col(0) += p;
254 for (Index j = 1; j < m_cols; ++j) {
255 p = p.cwiseProduct(m_x);
256 dst.col(j) += p;
257 }
258 }
259
261 template <typename Dest>
262 void subTo(Dest& dst) const {
263 NodeVector p = NodeVector::Ones(rows());
264 dst.col(0) -= p;
265 for (Index j = 1; j < m_cols; ++j) {
266 p = p.cwiseProduct(m_x);
267 dst.col(j) -= p;
268 }
269 }
270
277 template <typename Rhs>
279 EIGEN_STATIC_ASSERT(ColsAtCompileTime == Dynamic || Rhs::RowsAtCompileTime == Dynamic ||
280 int(ColsAtCompileTime) == int(Rhs::RowsAtCompileTime),
281 INVALID_MATRIX_PRODUCT)
282 eigen_assert(a.rows() == cols() && "invalid product: dimensions do not match");
283 return Product<Vandermonde, Rhs>(*this, a.derived());
284 }
285
293 template <typename Dest, typename Rhs, typename ProductScalar>
294 void addProduct(Dest& dst, const Rhs& rhs, const ProductScalar& alpha) const {
295 eigen_assert(rhs.rows() == m_cols && "invalid product: dimensions do not match");
296 // A unit alpha must not multiply: even the identity complex scalar (1,0)
297 // pollutes an (Inf,0) value with NaN through the 0*Inf cross term.
298 const bool unitAlpha = alpha == ProductScalar(1);
299 using SplitComponents =
300 internal::bool_constant<!NumTraits<Scalar>::IsComplex && NumTraits<ProductScalar>::IsComplex>;
301 // Sized like the nodes: a fixed-size Index constructor would be ambiguous.
302 Array<ProductScalar, Rows_, 1> acc = m_x.array().template cast<ProductScalar>();
303 for (Index k = 0; k < rhs.cols(); ++k) {
304 horner(acc, rhs, k, SplitComponents());
305 if (unitAlpha)
306 dst.col(k) += acc.matrix();
307 else
308 dst.col(k) += alpha * acc.matrix();
309 }
310 }
311
312 private:
313 template <typename ProductScalar, typename Rhs>
314 void horner(Array<ProductScalar, Rows_, 1>& acc, const Rhs& rhs, Index k, std::false_type) const {
315 const Index n = m_cols;
316 acc.setConstant(ProductScalar(rhs.coeff(n - 1, k)));
317 for (Index j = n - 2; j >= 0; --j)
318 acc = acc * m_x.array().template cast<ProductScalar>() + ProductScalar(rhs.coeff(j, k));
319 }
320
321 // Complex values at real nodes: (re + i im) x keeps the exact
322 // real-times-complex arithmetic of a dense product, which the
323 // complex-times-complex form would break through 0 * Inf cross terms.
324 template <typename ProductScalar, typename Rhs>
325 void horner(Array<ProductScalar, Rows_, 1>& acc, const Rhs& rhs, Index k, std::true_type) const {
326 using NodeArray = Array<Scalar, Rows_, 1>;
327 const Index n = m_cols;
328 const ProductScalar top(rhs.coeff(n - 1, k));
329 NodeArray re = NodeArray::Constant(rows(), numext::real(top));
330 NodeArray im = NodeArray::Constant(rows(), numext::imag(top));
331 for (Index j = n - 2; j >= 0; --j) {
332 const ProductScalar c(rhs.coeff(j, k));
333 re = re * m_x.array() + numext::real(c);
334 im = im * m_x.array() + numext::imag(c);
335 }
336 acc = re.binaryExpr(im, [](const Scalar& a, const Scalar& b) { return ProductScalar(a, b); });
337 }
338
339 NodeVector m_x;
340 Index m_cols;
341};
342
346template <typename Derived>
351
354template <typename Derived>
359
396template <typename Scalar_>
397class BjorckPereyra : public SolverBase<BjorckPereyra<Scalar_>> {
398 public:
399 using Base = SolverBase<BjorckPereyra>;
400 friend class SolverBase<BjorckPereyra>;
401 EIGEN_GENERIC_PUBLIC_INTERFACE(BjorckPereyra)
402 EIGEN_STATIC_ASSERT_NON_INTEGER(RealScalar)
403 using NodeVector = Matrix<Scalar, Dynamic, 1>;
404
406 BjorckPereyra() : m_isInitialized(false), m_info(InvalidInput) {}
407
409 template <int Rows_, int Cols_>
410 explicit BjorckPereyra(const Vandermonde<Scalar, Rows_, Cols_>& V) : m_isInitialized(false), m_info(InvalidInput) {
411 compute(V);
412 }
413
417 template <int Rows_, int Cols_>
419 EIGEN_STATIC_ASSERT(Rows_ == Dynamic || Cols_ == Dynamic || Rows_ == Cols_, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES)
420 eigen_assert(V.rows() == V.cols() && "BjorckPereyra requires a square Vandermonde matrix");
421 m_x = V.nodes();
422 m_order.clear();
423 m_info = Success;
424 const Index n = m_x.size();
425 if (!m_x.allFinite()) m_info = InvalidInput;
426 for (Index j = 1; j < n && m_info == Success; ++j)
427 for (Index i = 0; i < j; ++i) {
428 if (m_x[i] == m_x[j]) {
429 m_info = NumericalIssue;
430 break;
431 }
432 }
433 if (m_info == Success) initializeNodeOrder(m_x, internal::bool_constant<NumTraits<Scalar>::IsComplex>());
434 m_isInitialized = true;
435 return *this;
436 }
437
438 Index rows() const noexcept { return m_x.size(); }
439 Index cols() const noexcept { return m_x.size(); }
440
445 eigen_assert(m_isInitialized && "BjorckPereyra is not initialized.");
446 return m_info;
447 }
448
449#ifdef EIGEN_PARSED_BY_DOXYGEN
454 template <typename Rhs>
455 inline const Solve<BjorckPereyra, Rhs> solve(const MatrixBase<Rhs>& f) const;
456#endif
457
458#ifndef EIGEN_PARSED_BY_DOXYGEN
461 template <typename RhsType, typename DstType>
462 void _solve_impl(const RhsType& rhs, DstType& dst) const {
463 using RhsScalar = typename RhsType::Scalar;
464 using WorkScalar = typename DstType::Scalar;
465 using ProductOp = internal::scalar_product_op<Scalar, RhsScalar>;
466 EIGEN_CHECK_BINARY_COMPATIBILITY(ProductOp, Scalar, RhsScalar)
467
468 const Index n = m_x.size();
469 dst = rhs;
471 if (!m_order.empty()) permuted.resize(n);
472 for (Index k = 0; k < rhs.cols(); ++k) {
473 auto a = dst.col(k);
474 if (!m_order.empty()) {
475 for (Index i = 0; i < n; ++i) permuted[i] = a[m_order[static_cast<std::size_t>(i)]];
476 a = permuted;
477 }
478 for (Index j = 0; j < n - 1; ++j)
479 for (Index i = n - 1; i > j; --i) a[i] = (a[i] - a[i - 1]) / (m_x[i] - m_x[i - j - 1]);
480 for (Index j = n - 2; j >= 0; --j)
481 for (Index i = j; i < n - 1; ++i) a[i] -= m_x[j] * a[i + 1];
482 }
483 }
484
488 template <bool Conjugate, typename RhsType, typename DstType>
489 void _solve_impl_transposed(const RhsType& rhs, DstType& dst) const {
490 using RhsScalar = typename RhsType::Scalar;
491 using WorkScalar = typename DstType::Scalar;
492 using ProductOp = internal::scalar_product_op<Scalar, RhsScalar>;
493 EIGEN_CHECK_BINARY_COMPATIBILITY(ProductOp, Scalar, RhsScalar)
494
495 const Index n = m_x.size();
496 dst = rhs.template conjugateIf<Conjugate>();
497 Matrix<WorkScalar, Dynamic, 1> permuted;
498 if (!m_order.empty()) permuted.resize(n);
499 for (Index k = 0; k < rhs.cols(); ++k) {
500 auto w = dst.col(k);
501 for (Index j = 0; j < n - 1; ++j)
502 for (Index i = n - 1; i > j; --i) w[i] -= m_x[j] * w[i - 1];
503 for (Index j = n - 2; j >= 0; --j) {
504 w.tail(n - j - 1).array() /= (m_x.tail(n - j - 1) - m_x.head(n - j - 1)).array();
505 for (Index i = j; i < n - 1; ++i) w[i] -= w[i + 1];
506 }
507
508 if (!m_order.empty()) {
509 permuted = w;
510 for (Index i = 0; i < n; ++i) w[m_order[static_cast<std::size_t>(i)]] = permuted[i];
511 }
512 }
513 if (Conjugate) dst = dst.conjugate().eval();
514 }
515#endif
516
517 private:
518 static RealScalar lejaLogAbs(const Scalar& z) { return numext::log(numext::abs(z)); }
519
520 void initializeNodeOrder(const NodeVector&, std::false_type) {}
521
522 void initializeNodeOrder(const NodeVector& nodes, std::true_type) {
523 using Real = typename NumTraits<Scalar>::Real;
524 const Index n = nodes.size();
525 bool genuinelyComplex = false;
526 for (Index i = 0; i < n; ++i) genuinelyComplex = genuinelyComplex || numext::imag(nodes[i]) != Real(0);
527 if (!genuinelyComplex || n < 2) return;
528
529 const NodeVector original = nodes;
530
531 m_order.resize(static_cast<std::size_t>(n));
532 std::vector<char> selected(static_cast<std::size_t>(n), 0);
533 std::vector<RealScalar> scores(static_cast<std::size_t>(n), RealScalar(0));
534 Index next; // the Leja sequence starts at a node of largest modulus
535 original.unaryExpr(&lejaLogAbs).maxCoeff(&next);
536
537 for (Index position = 0; position < n; ++position) {
538 m_order[static_cast<std::size_t>(position)] = next;
539 selected[static_cast<std::size_t>(next)] = 1;
540 if (position + 1 == n) break;
541
542 Index candidate = -1;
543 RealScalar candidateScore = -NumTraits<RealScalar>::infinity();
544 for (Index i = 0; i < n; ++i) {
545 if (selected[static_cast<std::size_t>(i)]) continue;
546 scores[static_cast<std::size_t>(i)] += lejaLogAbs(original[i] - original[next]);
547 if (candidate < 0 || scores[static_cast<std::size_t>(i)] > candidateScore) {
548 candidate = i;
549 candidateScore = scores[static_cast<std::size_t>(i)];
550 }
551 }
552 next = candidate;
553 }
554
555 for (Index i = 0; i < n; ++i) m_x[i] = original[m_order[static_cast<std::size_t>(i)]];
556 }
557
558 NodeVector m_x;
559 std::vector<Index> m_order;
560 bool m_isInitialized;
561 ComputationInfo m_info;
562};
563
564namespace internal {
565
569template <typename SolverScalar, typename RhsScalar,
570 bool Compatible = has_ReturnType<ScalarBinaryOpTraits<SolverScalar, RhsScalar>>::value>
571struct bjorck_pereyra_result_scalar {
572 using type = SolverScalar;
573};
574
575template <typename SolverScalar, typename RhsScalar>
576struct bjorck_pereyra_result_scalar<SolverScalar, RhsScalar, true> {
577 using type = typename ScalarBinaryOpTraits<SolverScalar, RhsScalar>::ReturnType;
578};
579
580template <typename SolverScalar, typename RhsType>
581struct bjorck_pereyra_solve_traits {
582 using ResultScalar = typename bjorck_pereyra_result_scalar<SolverScalar, typename RhsType::Scalar>::type;
583 using PlainObject =
584 typename make_proper_matrix_type<ResultScalar, Dynamic, RhsType::ColsAtCompileTime, RhsType::PlainObject::Options,
585 Dynamic, RhsType::MaxColsAtCompileTime>::type;
586};
587
588template <typename Scalar_, typename RhsType>
589struct solve_traits<BjorckPereyra<Scalar_>, RhsType, Dense> : bjorck_pereyra_solve_traits<Scalar_, RhsType> {};
590
591template <typename Scalar_, typename RhsType>
592struct solve_traits<Transpose<const BjorckPereyra<Scalar_>>, RhsType, Dense>
593 : bjorck_pereyra_solve_traits<Scalar_, RhsType> {};
594
595template <typename Scalar_, typename RhsType>
596struct solve_traits<CwiseUnaryOp<scalar_conjugate_op<Scalar_>, const Transpose<const BjorckPereyra<Scalar_>>>, RhsType,
597 Dense> : bjorck_pereyra_solve_traits<Scalar_, RhsType> {};
598
599template <typename Factor, typename Scalar_, int Rows_, int Cols_, typename Plain, typename Rhs>
600struct scaled_vandermonde_product_impl
601 : generic_product_impl_base<
602 CwiseBinaryOp<scalar_product_op<Factor, Scalar_>, const CwiseNullaryOp<scalar_constant_op<Factor>, Plain>,
603 const Vandermonde<Scalar_, Rows_, Cols_>>,
604 Rhs, scaled_vandermonde_product_impl<Factor, Scalar_, Rows_, Cols_, Plain, Rhs>> {
605 using Op = Vandermonde<Scalar_, Rows_, Cols_>;
606 using ScaledOp = CwiseBinaryOp<scalar_product_op<Factor, Scalar_>,
607 const CwiseNullaryOp<scalar_constant_op<Factor>, Plain>, const Op>;
608 using Scalar = typename Product<ScaledOp, Rhs>::Scalar;
609
610 template <typename Dest>
611 static void scaleAndAddTo(Dest& dst, const ScaledOp& lhs, const Rhs& rhs, const Scalar& alpha) {
612 using RhsNested = typename nested_eval<Rhs, Rows_>::type;
613 RhsNested actualRhs(rhs);
614 lhs.rhs().addProduct(dst, actualRhs, Scalar(alpha * lhs.lhs().functor().m_other));
615 }
616};
617
618// Preserve the Horner kernel after Core introduces the scaled wrapper above;
619// otherwise the wrapper has DenseShape and falls back to a coefficient product.
620#define EIGEN_SCALED_VANDERMONDE_PRODUCT_IMPL(ProductTag) \
621 template <typename Factor, typename Scalar_, int Rows_, int Cols_, typename Plain, typename Rhs> \
622 struct generic_product_impl< \
623 CwiseBinaryOp<scalar_product_op<Factor, Scalar_>, const CwiseNullaryOp<scalar_constant_op<Factor>, Plain>, \
624 const Vandermonde<Scalar_, Rows_, Cols_>>, \
625 Rhs, DenseShape, DenseShape, ProductTag> \
626 : scaled_vandermonde_product_impl<Factor, Scalar_, Rows_, Cols_, Plain, Rhs> {};
627
628EIGEN_SCALED_VANDERMONDE_PRODUCT_IMPL(CoeffBasedProductMode)
629EIGEN_SCALED_VANDERMONDE_PRODUCT_IMPL(LazyCoeffBasedProductMode)
630EIGEN_SCALED_VANDERMONDE_PRODUCT_IMPL(OuterProduct)
631EIGEN_SCALED_VANDERMONDE_PRODUCT_IMPL(InnerProduct)
632EIGEN_SCALED_VANDERMONDE_PRODUCT_IMPL(GemvProduct)
633EIGEN_SCALED_VANDERMONDE_PRODUCT_IMPL(GemmProduct)
634
635#undef EIGEN_SCALED_VANDERMONDE_PRODUCT_IMPL
636
637template <typename Scalar_, int Rows_, int Cols_, typename Rhs, int ProductTag>
638struct generic_product_impl<Vandermonde<Scalar_, Rows_, Cols_>, Rhs, StructuredShape, DenseShape, ProductTag>
639 : structured_product_impl<Vandermonde<Scalar_, Rows_, Cols_>, Rhs> {};
640
641} // namespace internal
642
643} // namespace Eigen
644
645#endif // EIGEN_STRUCTURED_VANDERMONDE_H
Björck-Pereyra O(n^2) solver for square Vandermonde systems.
Definition Vandermonde.h:397
ComputationInfo info() const
Definition Vandermonde.h:444
BjorckPereyra(const Vandermonde< Scalar, Rows_, Cols_ > &V)
Definition Vandermonde.h:410
BjorckPereyra()
Definition Vandermonde.h:406
BjorckPereyra & compute(const Vandermonde< Scalar, Rows_, Cols_ > &V)
Definition Vandermonde.h:418
const Solve< BjorckPereyra, Rhs > solve(const MatrixBase< Rhs > &f) const
constexpr void resize(Index rows, Index cols)
An m x n Vandermonde matrix represented by its node vector.
Definition Vandermonde.h:158
Vandermonde(const MatrixBase< Derived > &nodes, Index cols)
Definition Vandermonde.h:186
Scalar determinant() const
Definition Vandermonde.h:226
const NodeVector & nodes() const
Definition Vandermonde.h:205
Vandermonde(const MatrixBase< Derived > &nodes)
Definition Vandermonde.h:194
Scalar coeff(Index row, Index col) const
Definition Vandermonde.h:208
Product< Vandermonde, Rhs > operator*(const MatrixBase< Rhs > &a) const
Definition Vandermonde.h:278
Vandermonde< typename Derived::Scalar, Derived::SizeAtCompileTime, Dynamic > makeVandermonde(const MatrixBase< Derived > &nodes, Index cols)
Definition Vandermonde.h:347
ComputationInfo
NumericalIssue
constexpr unsigned int RowMajorBit
Namespace containing all symbols from the Eigen library.