I would like to use data stored into an Eigen (https://eigen.tuxfamily.org) vector
Eigen::Vector<double, 6> vec({1,2,3,4,5,6});
as if they were a triangular matrix
1 2 3
0 4 5
0 0 6
I know how to do it for a full matrix using Eigen's Map
Eigen::Vector<double, 9> vec({1,2,3,4,5,6,7,8,9});
std::cout << Eigen::Map<Eigen::Matrix<double, 3, 3, RowMajor>>(vec.data());
which produces
1 2 3
4 5 6
7 8 9
However I do not know how to make a Map to a triangular matrix.
Is it possible? Thanks!
[Edited for clarity]
CodePudding user response:
This is not a direct solution to your problem but a way how to calculate the std::vector
to fill in the 0
at the correct place. I think it is also possible to calculate it as a std::array
if needed. I am not sure if that helps, but I guess you could use the calculated vector to fill the Eigen::Map
#include <array>
#include <cstddef>
#include <iostream>
#include <vector>
template<typename T, size_t N>
class EigenVector
{
static constexpr int CalculateRowColSize(size_t n)
{
size_t i = 1;
size_t inc = 1;
do
{
if (inc == n)
{
return static_cast<int>(i);
}
i ;
inc = i;
} while (i < n);
return -1;
}
static constexpr bool IsValid(size_t n)
{
if(CalculateRowColSize(n) == -1)
{
return false;
}
return true;
}
static_assert(IsValid(N));
public:
EigenVector() = delete;
static std::vector<T> Calculate(std::array<T, N> values)
{
constexpr size_t mRowColSize = CalculateRowColSize(N);
std::vector<T> ret;
auto count = 0;
auto valueCounter = 0;
for (size_t i = 0; i < mRowColSize; i )
{
for (auto j = 0; j < count; j )
{
ret.push_back(T());
}
for (size_t j = 0; j < mRowColSize - count; j )
{
ret.push_back(values[valueCounter]);
valueCounter ;
}
count ;
}
return ret;
}
};
int main()
{
{
const std::array<int, 6> arr{ 1,2,3,4,5,6 };
const auto values = EigenVector<int, 6>::Calculate(arr);
for (auto& val : values)
{
std::cout << val << " ";
}
}
std::cout << std::endl << std::endl;
{
const std::array<int, 10> arr{ 1,2,3,4,5,6,7,8,9,10 };
const auto values = EigenVector<int, 10>::Calculate(arr);
for (auto& val : values)
{
std::cout << val << " ";
}
}
return 0;
}
Output:
1 2 3 0 4 5 0 0 6
1 2 3 4 0 5 6 7 0 0 8 9 0 0 0 10
Note that the algorithm is written that only possible matrix sizes are valid as input
CodePudding user response:
In my opinion this cannot be done using Map only: The implementation of Map as it is relies on stride sizes that remain constant no matter their index positions, see https://eigen.tuxfamily.org/dox/classEigen_1_1Stride.html. To implement a triangular matrix map you would have to have a Map that changes its inner stride depending on the actual column number. The interfaces in Eigen do not allow that at the moment, see https://eigen.tuxfamily.org/dox/Map_8h_source.html.
But if you are just concerned about the extra memory you can just use Eigen's sparse matrix representation:
https://eigen.tuxfamily.org/dox/group__TutorialSparse.html
(Refer to section "Filling a sparse matrix".)