Eigen matrix rowwise addition - c++

I have an Nx3 Eigen matrix representing a bunch of locations of vertices in 3d space.
I'm trying to add a 1x3 matrix to each row in the Nx3 to move every point a given direction and distance.
#include <Eigen/Dense>
int N = 20; //for example
MatrixXf N3(N, 3);
N3.fill(2);
MatrixXf origin(1, 3);
origin << 1, 2, 3;
Now I want to add origin to each row in N3 so N3 becomes 3, 4, 5 in each row. (The values in N3 are all different 3d vertex locations in the real code.)
3, 4, 5
3, 4, 5
3, 4, 5 etc...

you may just write
N3 += origin.replicate(N,1);
note that no temporary matrix is created, replicate() returns an expression.

Try this (untested)
for (int i = 0 ; i < 3 ; i++)
N3.block(i, 0, 1, 3) = N3.block(i, 0, 1, 3) + origin
I do not remember if += is supported

MatrixXf result = N3 + MatrixXf::Constant(1, N, 1) * origin;
Should be simple as that.

Related

How to roll the rows of a Eigen:Matrix?

I want to reindex a Eigen:Matrix by rolling N∈ℤ rows like this (here N=+1):
1 4 7 -> 3 6 9
2 5 8 1 4 7
3 6 9 2 5 8
Is there a simple way, or do I have to create a new matrix and copy over the data?
I suggest setting up a new matrix and copying the data. Eigen's block operations allow doing this in an efficient way. Here is how a shift by n rows can be done for the example above.
MatrixXi A(3,3);
A << 1, 2, 3, 4, 5, 6, 7, 8, 9;
A.transposeInPlace();
int n = 1; // number of shifts
n = n % A.rows();
MatrixXi B(A.rows(), A.cols());
B.bottomRows(A.rows() - n) = A.topRows(A.rows() - n);
B.topRows(n) = A.bottomRows(n);
std::cout << "B = " << B << std::endl;
If you are interested in a matlab-like syntax you can also use
MatrixXd A;
//... fill A
VectorXi indices = {{2,0,1}};
A(indices, Eigen::all);
I don't know, whether this internally makes a copy.
Note: This does not work for Sparse matrices, see Subset columns of sparse eigen matrix

How sparse matrix-indexing can be done for a matrix stored as "Compressed Sparse Row"?

I have my large sparse symmetric matrix stored as Compressed Sparse Row (CSR) using Intel MKL. For the sake of example, let's assume my symmetric sparse matrix is a 5x5:
A =
1 -1 0 -3 0
-1 5 0 0 0
0 0 4 6 4
-3 0 6 7 0
0 0 4 0 -5
values = {1, -1, -3, 5, 4, 6, 4, 7, -5}; // symmetric sparse matrix
columns = {0, 1, 3, 1, 2, 3, 4, 3, 4}; // zero-based
rowIndex = {0, 3, 4, 7, 8, 9}; // zero-based
I am trying to find a submatrix of A given the rows and columns, e.g., A(1:3, 2:4):
A(1:3,2:4) =
0 0 0
4 6 4
6 7 0
values = {4, 6, 4, 6, 7}; // General sparse matrix (sub-matrix is not necessarily symmetric)
columns = {0, 1, 2, 0, 1}; // zero-based
rowIndex = {0, 0, 3, 5}; // zero-based
I would be grateful to know how matrix-indexing can be done. One way I can think of is to convert CSR to coordinate format COO and apply matrix-indexing and then converting it back to CSR, which I don't think it is an efficient way.
Could someone let me know of an efficient or a common way of sparse matrix-indexing?
The trick is to look up values in the lower triangle by the output column (which is their row). You can keep an index into the data for each row, since you visit the entries in column order as you progress in row order for the output.
With the expositional type
struct CSR { // sometimes implicitly symmetric
std::vector<...> vals;
std::vector<int> cols,rowStart;
};
we have
// Return the [r0,r1) by [c0,c1) submatrix, never
// using any symmetry it might have.
CSR submatrix(const CSR &sym,int r0,int r1,int c0,int c1) {
const int m=r1-r0,n=c1-c0;
std::vector<int> finger(sym.rowStart.begin()+c0,sym.rowStart.begin()+c1);
CSR ret;
ret.rowStart.reserve(m+1);
ret.rowStart.push_back(0);
for(int r=0,rs=r0;r<m;++r,++rs) {
// (Strictly) lower triangle:
for(int cs=c0,c=0;cs<rs;++cs,++c)
for(int &f=finger[c],f1=sym.rowStart[cs+1];f<f1;++f) {
const int cf=sym.cols[f];
if(cf>rs) break;
if(cf==rs) {
ret.vals.push_back(sym.vals[f]);
ret.cols.push_back(c);
}
}
// Copy the relevant subsequence of the upper triangle:
for(int f=sym.rowStart[rs],f1=sym.rowStart[rs+1];f<f1;++f) {
const int c=sym.cols[f]-c0;
if(c<0) continue;
if(c>=n) break;
ret.vals.push_back(sym.vals[f]);
ret.cols.push_back(c);
}
ret.rowStart.push_back(ret.vals.size());
}
return ret;
}
For large matrices, the upper triangle loop could be optimized by using a binary search to find the relevant range of f.

How to rotate a dynamic array to the right?

I have a custom array object. It has two main variables:
m_array = Pointer to dynamic array.
m_size - The size of the array. The size for this array is 10.
When I rotate to the left, this works fine:
std::rotate(m_array + 0, m_array + 1, m_array + m_size);
This is equivalent to:
// simple rotation to the left
std::rotate(v.begin(), v.begin() + 1, v.end());
When I try rotating to the right, I'm getting a runtime error.
I need the equivalent of this:
// simple rotation to the right
std::rotate(v.rbegin(), v.rbegin() + 1, v.rend());
I tried this:
std::rotate(m_array + m_size, m_array + m_size + 1, m_array + 0);
I get the error: Invalid iterator range
So, I thought this was m_size, so I tried this:
std::rotate(m_array + m_size - 1, m_array + (m_size - 1) + 1, m_array + 0);
And I get the same error.
Thoughts are welcomed.
The source I tried to follow:
http://en.cppreference.com/w/cpp/algorithm/rotate
To do a right rotation (to borrow your phrase), you want the range to be everything but the last element in the array. I'll leave it to you to adapt this code to work on variable-sized arrays.
#include <algorithm>
#include <iostream>
int main() {
int data[10] = { 0, 1, 2, 3, 4,
5, 6, 7, 8, 9 };
auto print_all = [&data]() {
for(auto v: data) {
std::cout << v << ' ';
}
std::cout << '\n';
};
print_all();
// rotate elements to the left
std::rotate(data, data + 1, data + 10);
print_all();
// rotate element to the right, back to the original position
std::rotate(data, data + 9, data + 10);
print_all();
return 0;
}
My output looks like this:
./rotate
0 1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 0
0 1 2 3 4 5 6 7 8 9
The reason std::rotate(v.rbegin(), v.rbegin() + 1, v.rend()) works is that it uses reverse iterators. That means that v.rbegin() + 1 is actually decrementing the position in the array and is equal to v.begin() + v.size() - 1.
When using raw pointer arithmetic, there is no way to get the same reverse iterating behavior. You will have to manually translate the left rotation to a right rotation. This can easily be done by flipping the rotate position about the center of the array and performing a left rotate.
Left or right rotation can be boiled down to dividing an array into 2 sections and then swapping them. Whether it is a left rotation or right rotation just dictates where the division is made. For a left rotate by k, the rotation point is at k mod N. For a right rotate, the rotation point is at -k mod N where N is the total length of the array. This selects the index in the original array you would like to be at index 0 of the newly rotated array.
So the following right rotate by 1,
std::rotate(v.rbegin(), v.rbegin() + 1, v.rend())
is equivalent to using raw pointers in the following way:
int* p = &v[0];
int n = v.size();
int k = -1;
std::rotate(p, p + mod(k, n), p + n);
where mod() is the modulo operation (basically the % operator that always wraps to a positive number):
int mod(int x, int y) { return ((x % y) + y) % y; }

Multiplication of each matrix column by each vector element using Eigen C++ Library

I need to multiply each matrix column by each vector element using Eigen C++ library. I tried colwise without success.
Sample data:
Eigen::Matrix3Xf A(3,2); //3x2
A << 1 2,
2 2,
3 5;
Eigen::Vector3f V = Eigen::Vector3f(2, 3);
//Expected result
C = A.colwise()*V;
//C
//2 6,
//4 6,
//6 15
//this means C 1st col by V first element and C 2nd col by V 2nd element.
Matrix A can have 3xN and V Nx1. Meaning (cols x rowls).
This is what I would do:
Code
Eigen::Matrix3Xf A(3, 2); // 3x2
A << 1, 2, 2, 2, 3, 5;
Eigen::Vector3f V = Eigen::Vector3f(1, 2, 3);
const Eigen::Matrix3Xf C = A.array().colwise() * V.array();
std::cout << C << std::endl;
Example output:
1 2
4 4
9 15
Explanation
You were close, the trick is to use .array() to do broadcasting multiplications.
colwiseReturnType doesn't have a .array() method, so we have to do our colwise shenanigans on the array view of A.
If you want to compute the element-wise product of two vectors (The coolest of cool cats call this the Hadamard Product), you can do
Eigen::Vector3f a = ...;
Eigen::Vector3f b = ...;
Eigen::Vector3f elementwise_product = a.array() * b.array();
Which is what the above code is doing, in a columnwise fashion.
Edit:
To address the row case, you can use .rowwise(), and you'll need an extra transpose() to make things fit
Eigen::Matrix<float, 3, 2> A; // 3x2
A << 1, 2, 2, 2, 3, 5;
Eigen::Vector2f V = Eigen::Vector2f(2, 3);
// Expected result
Eigen::Matrix<float, 3, 2> C = A.array().rowwise() * V.transpose().array();
std::cout << C << std::endl;
Example output:
2 6
4 6
6 15
In other words, you want to scale each column by a different factor, that is, apply a non uniform scaling. Scaling are best represented as a diagonal matrix, thus:
C = A * V.asDiagonal();
Since Eigen is based on expression template, this does not create any temporary and amount to a code similar to Jacob's answer:
C = A.array().rowwise() * V.transpose().array();

Elegant way the find the Vertices of a Cube

Nearly every OpenGL tutorial lets you implement drawing a cube. Therefore the vertices of the cube are needed. In the example code I saw a long list defining every vertex. But I would like to compute the vertices of a cube rather that using a overlong list of precomputed coordinates.
A cube is made of eight vertices and twelve triangles. Vertices are defined by x, y, and z. Triangles are defined each by the indexes of three vertices.
Is there an elegant way to compute the vertices and the element indexes of a cube?
When i was "porting" the csg.js project to Java I've found some cute code which generated cube with selected center point and radius. (I know it's JS, but anyway)
// Construct an axis-aligned solid cuboid. Optional parameters are `center` and
// `radius`, which default to `[0, 0, 0]` and `[1, 1, 1]`. The radius can be
// specified using a single number or a list of three numbers, one for each axis.
//
// Example code:
//
// var cube = CSG.cube({
// center: [0, 0, 0],
// radius: 1
// });
CSG.cube = function(options) {
options = options || {};
var c = new CSG.Vector(options.center || [0, 0, 0]);
var r = !options.radius ? [1, 1, 1] : options.radius.length ?
options.radius : [options.radius, options.radius, options.radius];
return CSG.fromPolygons([
[[0, 4, 6, 2], [-1, 0, 0]],
[[1, 3, 7, 5], [+1, 0, 0]],
[[0, 1, 5, 4], [0, -1, 0]],
[[2, 6, 7, 3], [0, +1, 0]],
[[0, 2, 3, 1], [0, 0, -1]],
[[4, 5, 7, 6], [0, 0, +1]]
].map(function(info) {
return new CSG.Polygon(info[0].map(function(i) {
var pos = new CSG.Vector(
c.x + r[0] * (2 * !!(i & 1) - 1),
c.y + r[1] * (2 * !!(i & 2) - 1),
c.z + r[2] * (2 * !!(i & 4) - 1)
);
return new CSG.Vertex(pos, new CSG.Vector(info[1]));
}));
}));
};
I solved this problem with this piece code (C#):
public CubeShape(Coord3 startPos, int size) {
int l = size / 2;
verts = new Coord3[8];
for (int i = 0; i < 8; i++) {
verts[i] = new Coord3(
(i & 4) != 0 ? l : -l,
(i & 2) != 0 ? l : -l,
(i & 1) != 0 ? l : -l) + startPos;
}
tris = new Tris[12];
int vertCount = 0;
void AddVert(int one, int two, int three) =>
tris[vertCount++] = new Tris(verts[one], verts[two], verts[three]);
for (int i = 0; i < 3; i++) {
int v1 = 1 << i;
int v2 = v1 == 4 ? 1 : v1 << 1;
AddVert(0, v1, v2);
AddVert(v1 + v2, v2, v1);
AddVert(7, 7 - v2, 7 - v1);
AddVert(7 - (v1 + v2), 7 - v1, 7 - v2);
}
}
If you want to understand more of what is going on, you can check out the github page I wrote that explains it.