Linear Subspace#
Header: <pressio/rom_subspaces.hpp>
Synopsis#
namespace pressio{ namespace rom{
template <class BasisMatrixType>
class LinearSubspace
{
public:
enum class SpanningSet{Columns, Rows};
using basis_matrix_type = /*see description*/;
// constructors
LinearSubspace(const basis_matrix_type & basisMatrix, (1)
SpanningSet spanningSetValue);
LinearSubspace(basis_matrix_type && basisMatrix, (2)
SpanningSet spanningSetValue);
// copy constructor
LinearSubspace(const LinearSubspace &); (3)
// accessors
const basis_matrix_type & basis() const; (4)
std::size_t dimension() const; (5)
bool isColumnSpace() const; (6)
bool isRowSpace() const; (7)
private:
const basis_matrix_type basis_; // exposition-only
};
}} //end namespace
Notes#
the semantics of the class are such that copy and move assignment are implicitly deleted by the compiler, so you cannot copy or move assign an object of the class. The move constructor is guaranteedd to behave as a copy constructor.
the immutability and invariance of this class rely on the assumption that users do not violate const correctness by const_casting the return of (4). Please do not do that!
the design and semantics of the class functions needs a clarification: the intent is to ensure the class always has value semantics because it nees to work even for template arguments with view semantics. Suppose that
basis
were an instance of aTpetra::MultiVector
or aKokkos::View
, which are both classes with view semantics. In such case, if constructor (1) were to simply copy-constructbasis
, it would lead to a shallow copy. This would compromise the immutability and invariant of the class, since any changes to the original object would be reflected in the data member copy-constructed from it. Therefore, in constructor (1) and in (3), we rely onpressio::ops::clone()
, to ensure the correct semantics and achieve the desired immutability.
Important
The class models the VectorSubspace concept.
Example#
int main(){
using basis_t = Eigen::MatrixXd;
using space_t = pressio::rom::LinearSubspace<basis_t>;
basis_t columnBasis1(56,5);
// fill such that columns are linearly independent
space_t space(columnBasis1, space_t::SpanningSet::Columns);
// space.dimension() == 5
basis_t columnBasis2(156,5);
// fill such that columns are linearly independent
space_t space(std::move(columnBasis2), space_t::SpanningSet::Columns);
// space.dimension() == 5
basis_t rowBasis1(3,56);
// fill such that rows are linearly independent
space_t space(rowBasis1, space_t::SpanningSet::Rows);
// space.dimension() == 3
space_t S1(columnBasis1, space_t::SpanningSet::Columns);
space_t S2(columnBasis2, space_t::SpanningSet::Columns);
// S1 = S2; /*illigal*/
// S2 = S1; /*illigal*/
// S1 = std::move(S2); /*illigal*/
lspace_t S3 = S1; // calls copy constructor
lspace_t S4(S1); // calls copy constructor
lspace_t S5(std::move(S1)); // calls copy constructor
}