PhysicsBasedAnimationToolkit 0.0.10
Cross-platform C++20 library of algorithms and data structures commonly used in computer graphics research on physically-based simulation.
Loading...
Searching...
No Matches
LinearOperator.h
Go to the documentation of this file.
1
10
11#ifndef PBAT_MATH_LINEAR_OPERATOR_H
12#define PBAT_MATH_LINEAR_OPERATOR_H
13
14#include <concepts>
15#include <exception>
16#include <pbat/Aliases.h>
18#include <tuple>
19
20namespace pbat {
21namespace math {
22
33template <class T>
34concept CLinearOperator = requires(T t)
35{
36 {
37 t.OutputDimensions()
38 } -> std::convertible_to<int>;
39 {
40 t.InputDimensions()
41 } -> std::convertible_to<int>;
42 {t.Apply(VectorX{}, std::declval<VectorX&>())};
43 {t.Apply(MatrixX{}, std::declval<MatrixX&>())};
44 {
45 t.ToMatrix()
46 } -> std::convertible_to<CSCMatrix>;
47};
48
49template <CLinearOperator... TLinearOperators>
50class LinearOperator;
51
52} // namespace math
53} // namespace pbat
54
55namespace Eigen {
56namespace internal {
57
58template <pbat::math::CLinearOperator... TLinearOperators>
59struct traits<pbat::math::LinearOperator<TLinearOperators...>>
60{
61 using Scalar = pbat::Scalar;
62 using StorageIndex = pbat::CSCMatrix::StorageIndex;
63 using StorageKind = Sparse;
64 using XprKind = MatrixXpr;
65 enum {
66 RowsAtCompileTime = Dynamic,
67 ColsAtCompileTime = Dynamic,
68 MaxRowsAtCompileTime = Dynamic,
69 MaxColsAtCompileTime = Dynamic,
70 Flags = 0
71 };
72};
73
74} // namespace internal
75} // namespace Eigen
76
77namespace pbat {
78namespace math {
79
93template <CLinearOperator... TLinearOperators>
94class LinearOperator : public Eigen::EigenBase<LinearOperator<TLinearOperators...>>
95{
96 public:
97 using SelfType = LinearOperator<TLinearOperators...>;
98 using BaseType = Eigen::EigenBase<SelfType>;
99
102 using StorageIndex = typename CSCMatrix::StorageIndex;
104 enum {
105 ColsAtCompileTime = Eigen::Dynamic,
106 MaxColsAtCompileTime = Eigen::Dynamic,
107 RowsAtCompileTime = Eigen::Dynamic,
108 MaxRowsAtCompileTime = Eigen::Dynamic,
109 IsRowMajor = false
110 };
111
120 LinearOperator(TLinearOperators const&... inOps);
121
122 SelfType& operator=(SelfType const&) = delete;
123
133 template <class TDerivedIn, class TDerivedOut>
134 void Apply(Eigen::MatrixBase<TDerivedIn> const& x, Eigen::DenseBase<TDerivedOut>& y) const;
135
141
152
153 // For Eigen compatibility
154
159 BaseType::Index rows() const { return static_cast<BaseType::Index>(OutputDimensions()); }
164 BaseType::Index cols() const { return static_cast<BaseType::Index>(InputDimensions()); }
165
173 template <class Rhs>
174 Eigen::Product<SelfType, Rhs, Eigen::AliasFreeProduct>
175 operator*(Eigen::MatrixBase<Rhs> const& x) const
176 {
177 return Eigen::Product<SelfType, Rhs, Eigen::AliasFreeProduct>(*this, x.derived());
178 }
179
180 private:
181 std::tuple<TLinearOperators const&...> ops;
182};
183
193template <CLinearOperator... TLinearOperators>
194LinearOperator<TLinearOperators...> ComposeLinearOperators(TLinearOperators const&... inOps)
195{
196 return LinearOperator(inOps...);
197}
198
199template <CLinearOperator... TLinearOperators>
200inline LinearOperator<TLinearOperators...>::LinearOperator(TLinearOperators const&... inOps)
201 : ops(std::make_tuple(std::cref(inOps)...))
202{
203 bool const bInputDimensionsMatch = std::apply(
204 [this](auto... op) -> bool {
205 return ((InputDimensions() == op.InputDimensions()) and ...);
206 },
207 ops);
208 bool const bOutputDimensionsMatch = std::apply(
209 [this](auto... op) -> bool {
210 return ((OutputDimensions() == op.OutputDimensions()) and ...);
211 },
212 ops);
213 if (not(bInputDimensionsMatch and bOutputDimensionsMatch))
214 {
215 throw std::invalid_argument(
216 "Dimensionality mismatch found in CompositeLinearOperator's linear operators.");
217 }
218}
219
220template <CLinearOperator... TLinearOperators>
221template <class TDerivedIn, class TDerivedOut>
223 Eigen::MatrixBase<TDerivedIn> const& x,
224 Eigen::DenseBase<TDerivedOut>& y) const
225{
226 PBAT_PROFILE_NAMED_SCOPE("pbat.math.LinearOperator.Apply");
227 std::apply([&](auto... op) { (op.Apply(x, y), ...); }, ops);
228}
229
230template <CLinearOperator... TLinearOperators>
232{
233 PBAT_PROFILE_NAMED_SCOPE("pbat.math.LinearOperator.ToMatrix");
235 std::apply([&](auto... op) { ((M += op.ToMatrix()), ...); }, ops);
236 return M;
237}
238
239template <CLinearOperator... TLinearOperators>
241{
242 return std::get<0>(ops).OutputDimensions();
243}
244
245template <CLinearOperator... TLinearOperators>
247{
248 return std::get<0>(ops).InputDimensions();
249}
250
251} // namespace math
252} // namespace pbat
253
254namespace Eigen {
255namespace internal {
256
280template <pbat::math::CLinearOperator Lhs, typename Rhs, int ProductType>
281struct generic_product_impl<Lhs, Rhs, SparseShape, DenseShape, ProductType>
282 : generic_product_impl_base<Lhs, Rhs, generic_product_impl<Lhs, Rhs>>
283{
284 typedef typename Product<Lhs, Rhs>::Scalar Scalar;
285
286 template <typename Dst>
287 static void scaleAndAddTo(Dst& dst, Lhs const& lhs, Rhs const& rhs, Scalar const& alpha)
288 {
289 lhs.Apply(alpha * rhs, dst);
290 }
291};
292
293} // namespace internal
294} // namespace Eigen
295
296#endif // PBAT_MATH_LINEAR_OPERATOR_H
Zero-overhead composite type satisfying the CLinearOperator concept.
Definition LinearOperator.h:95
BaseType::Index rows() const
Number of rows (Eigen compatibility)
Definition LinearOperator.h:159
pbat::Index OutputDimensions() const
Number of rows.
Definition LinearOperator.h:240
SelfType NestedExpression
Definition LinearOperator.h:103
Eigen::EigenBase< SelfType > BaseType
Definition LinearOperator.h:98
LinearOperator(TLinearOperators const &... inOps)
Construct a new Linear Operator object from a list of linear operators.
Definition LinearOperator.h:200
pbat::Index InputDimensions() const
Number of columns.
Definition LinearOperator.h:246
pbat::Scalar RealScalar
Definition LinearOperator.h:101
BaseType::Index cols() const
Number of columns (Eigen compatibility)
Definition LinearOperator.h:164
void Apply(Eigen::MatrixBase< TDerivedIn > const &x, Eigen::DenseBase< TDerivedOut > &y) const
Applies all linear operators on x, adding result to y.
Definition LinearOperator.h:222
Eigen::Product< SelfType, Rhs, Eigen::AliasFreeProduct > operator*(Eigen::MatrixBase< Rhs > const &x) const
Lazily left-multiply x by this linear operator.
Definition LinearOperator.h:175
LinearOperator< TLinearOperators... > SelfType
Instance type.
Definition LinearOperator.h:97
CSCMatrix ToMatrix() const
Construct the matrix of all underlying matrices obtained by Lops.
Definition LinearOperator.h:231
pbat::Scalar Scalar
Definition LinearOperator.h:100
typename CSCMatrix::StorageIndex StorageIndex
Definition LinearOperator.h:102
Concept for operator that satisfies linearity in the mathematical sense.
Definition LinearOperator.h:34
Math related functionality.
Definition Concepts.h:19
LinearOperator< TLinearOperators... > ComposeLinearOperators(TLinearOperators const &... inOps)
Compose multiple linear operators into a single linear operator.
Definition LinearOperator.h:194
The main namespace of the library.
Definition Aliases.h:15
Eigen::SparseMatrix< Scalar, Eigen::ColMajor > CSCMatrix
Column-major sparse matrix type.
Definition Aliases.h:52
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic-size matrix type.
Definition Aliases.h:34
Eigen::Vector< Scalar, Eigen::Dynamic > VectorX
Dynamic-size vector type.
Definition Aliases.h:33
std::ptrdiff_t Index
Index type.
Definition Aliases.h:17
double Scalar
Scalar type.
Definition Aliases.h:18
Profiling utilities for the Physics-Based Animation Toolkit (PBAT)