A distributed matrix library for easy use.
Matrix now have first 3 template parameters fixed, may not change in the future:
template<typename Scalar, int Rows, int Cols>
class Matrix;Other parameters are likely to be changed in the future evolution.
Default template parameters is provided in forward declaration, so in the definition of Matrix, full parameters list are required.
Two version of Matrix is provided:
- in the case of
Rows > 0 && Cols > 0, use stack version of Matrix - in the case of
Rows == -1 && Cols == -1, use heap version of Matrix - otherwise, error
For some member functions/member variables, two versions is provided, differed by concept or SFINAE. Here are some examples:
// make a non-template function to a template
// different conditions are provided in various form
template<typename T = Scalar>
requires is_same_v<T, Scalar> && (Rows == -1) && (Cols == -1) // here, conditions for heap version
Matrix(Index rows, Index cols)
: m_storage(rows * cols), m_shape{rows, cols} {}
template<typename T = Scalar>
requires is_same_v<T, Scalar>
constexpr explicit Matrix(InternalStorage storage)
: m_storage{std::move(storage)}
{
if constexpr(!(Rows > 0 && Cols > 0)) { // here, conditions for stack version
static_assert(!is_same_v<T, T>, "Can not initialize the matrix without shape specified!");
}
}Other common functions are shared.
Stack version of Matrix is provided to be constexpr, matrix plus/minus/multiplication are capable of being evaluated at compile time.
- function and variable:
fooBar - private member variable:
foo_,fooBar_ - class name:
MyClass,foo_bar(for template meta programming) - special case
Is_rows_Implemented:rowsis preserved lowercase and separated by_becauserowsrepresents a function namedrows.
details:
In experiment_expr.cpp, x = x + 2 does compile to add eax, 2, but it relies -O2 compiler flag.
conclusion:
It's impossible for operator= to figure out whether *this is the same as the x in x + 2 at compile time on language level. But the optimization does happen on some compilers and with some specific compiler flags.
So, maybe we can write some optimization at run-time and rely on the compiler to optimize out unnecessary codes like in experiment_expr.cpp?
When evaluating expressions that x + x, Eigen return a expression with the type representing the expression and two references as members (m_lhs and m_rhs). When evaluating operator=, Eigen will choose to do no alias assignment or alias assignment depending on the expression. e.g. x = x + x expands to expressions like x[i] = x[i] + x[i], while x = x * x expands to Matrix tmp(x * x); x = tmp.