GLM: assign 3x3 sub matrix of 4x4 matrix - c++

Let's say I have a 4x4 matrix M and a 3x3 matrix R.
How can write the 3x3 submatrix of M with R?
The naive way would be using two loops:
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
M[i][j] = R[i][j];
}
}
But I would like to know if there is a shorthand for this in GLM.
EDIT:
Someone pointed out there is a similar question: Simplest way to convert mat3 to mat4
But it's not the same because, in that question, the 4th row&col are filled with the pattern of the identity matrix. But I need to preserve the original contents of the 4th row&col of M

Related

I'm new to c++, is there an algorithm to find the distance to nearest 0 in a 3d array?

In a 3D array, the diagonal elements are 0 i.e. a[k][k][k]=0 for k=1 to 10. I need to fill the remaining matrix with distance to the nearest 0.
I came across the breadth first search, but can i do it without using data structures? (not familiar with data structures)
unsigned short d = 10, r = 10, c = 10;
double*** a = new double** [d];
for (int i = 0; i < d; ++i) {
a[i] = new double* [r];
for (int j = 0; j < r; ++j)
a[i][j] = new double[c];
}
for (int i = 0; i < 10; i++) {
a[i][i][i] = 0;
}
return a 3d distance array.
you can find all zeros and find the closest by calculating the manhattan distance.
another efficient way to this will be to use bfs algorithm. the first zero found in bfs is the closest zero from source.
here is a tutorial for 2d array sortest distance
Just fill your matrix with this formula for all i, j, k :
a[i][j][k] = MAX(i,j,k) - MIN(i,j,k)
The Manhattan distance to the diagonal is indeed the difference between the highest index and the lowest one.
This formula is so simple that it seems somewhat magical, but it works !

Mapping the "lower diagonal" of a tensor to a matrix, as a generalization of the extraction of the lower triangular part of a matrix into a vector

Given a rank-4 tensor (each rank with dimension K), for example T(p,q,r,s), we can 1-to-1 map all the tensor elements into a matrix of dimension K^2 x K^2, for example M(i,j) in which the two first tensor indices p,q and the last two indices r,s are combined in a column major way:
i = p + K * q
j = r + K * s
Exploiting some (anti-)symmetries of the given tensor, for example T(p,q,r,s) = -T(q,p,r,s) = -T(p,q,s,r) = T(q,p,s,r) and T(p,q,r,s) = T(r,s,p,q), we would like to be able to construct a matrix H(m,n) that only contains the unique elements (i.e. those not related by the previously defined symmetries), such that p>q and r>s into the matrix H(m,n), which would then be of dimension K(K-1)/2 x K(K-1)/2.
How could we find an algorithm (or even better: how can we use the C++ library Eigen) to accomplish these index transformations? Furthermore, can we write down m and n algebraically in terms of p,q and r,s, like we can do in the case where we would want to extract the strict lower triangular matrix (no diagonal) into a vector?
For reference, given a square matrix Eigen::MatrixXd M (K,K), here is an algorithm that extracts the strict lower triangle of a given square matrix M into a vector m of size, using the C++ Eigen library:
Eigen::VectorXd strictLowerTriangle(const Eigen::MatrixXd& M) {
auto K = static_cast<size_t>(M.cols()); // the dimension of the matrix
Eigen::VectorXd m = Eigen::VectorXd::Zero((K*(K-1)/2)); // strictly lower triangle has K(K-1)/2 parameters
size_t vector_index = 0;
for (size_t q = 0; q < K; q++) { // "column major" ordering for, so we do p first, then q
for (size_t p = q+1; p < K; p++) {
m(vector_index) = M(p,q);
vector_index++;
}
}
return m;
}
We are able to extend this algorithm to the requested general case:
Eigen::MatrixXd strictLowerTriangle(const Eigen::Tensor<double, 4>& T) {
auto K = static_cast<size_t> (dims[0]);
Eigen::MatrixXd M (K*(K-1)/2, K*(K-1)/2);
size_t row_index = 0;
for (size_t j = 0; j < K; j++) { // "column major" ordering for row_index<-i,j so we do j first, then i
for (size_t i = j+1; i < K; i++) { // in column major indices, columns are contiguous, so the first of two indices changes more rapidly
// require i > j
size_t column_index = 0;
for (size_t l = 0; l < K; l++) { // "column major" ordering for column_index<-k,l so we do l first, then k
for (size_t k = l+1; k < K; k++) { // in column major indices, columns are contiguous, so the first of two indices changes more rapidly
// require l > k
M(row_index,column_index) = T(i,j,k,l);
column_index++;
}
}
row_index++;
}
}
return M;
}

Creating a function in C++ that performs the Matlab operation [z;z] where z is a matrix or vector

I am trying to create a function that basically copy's the matlab command: [z;-z] where z = randn(m,n) which returns an m-by-n matrix of random entries. I was able to create a function in C++ for the randn function which is below:
MatrixXd generateGaussianNoise(int n, int m){
MatrixXd M(n,m);
normal_distribution<double> nd(0.0, 1.0);
random_device rd;
mt19937 gen(rd());
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
M(i,j) = nd(gen);
}
}
return M;
}
Now I need to create the [z;-z] function. For example let's say z = randn(2,2) then the output will be:
-2.2588 0.3188
0.8622 -1.3077
Now when I write [z;-z] we get:
-2.2588 0.3188
0.8622 -1.3077
2.2588 -0.3188
-0.8622 1.3077
What I am thinking is creating a function that taken in the matrix or vector z store those entries in another matrix or vector and then create a new matrix or vector that is doubled in size to place the associated entries in the correct (i,j) positions.
I am not sure if this is how I should proceed. Any comments or suggestions are greatly appreciated. As a side note, I am still a bit of a novice in C++.
You should first initialize your output matrix to the correct size by using the rows and cols in your matrix. You can then use the comma initializer syntax to fill this matrix by vertically concatenating one matrix with the negative of the same matrix
MatrixXd A(n, m);
normal_distribution<double> nd(0.0, 1.0);
random_device rd;
mt19937 gen(rd());
// Fill up the matrix
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
A(i, j) = nd(gen);
}
}
// Vertically concatenate the matrix with the negative version
MatrixXd B(A.rows() * 2, A.cols());
B << A, -A;
return B;
I think this should be enough?
MatrixXd generateGaussianNoise(int n, int m){
MatrixXd M(2*n,m);
normal_distribution<double> nd(0.0, 1.0);
random_device rd;
mt19937 gen(rd());
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
double r = nd(gen);
M(i,j) = r;
M(n+i,j) = -r;
}
}
return M;
You could use your code that fills a m-by-n matrix, and add another piece of code that "doubles" this matrix into a 2m-by-n matrix.
However, in C++ you are usually supposed to allocate the proper dimensions immediately, and do it only once.
That is:
MatrixXd M(2 * n, m);
(as a side-note, please decide whether your matrix is m-by-n or n-by-m; this is very important to prevent confusion)
Then, while filling your matrix, write two elements at each iteration:
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
double element = nd(gen);
M(i, j) = element;
M(i + n, j) = -element;
}
}
If you are going to work with large matrices, you should remember that elements are stored in memory in column-major order (unless you decide to override this choice). This order is also used by Matlab. So, for better performance with large matrices, you should fill them so each column is filled before the other column. So you should switch the nesting order of your loops:
for(int j = 0; j < m; j++){
for(int i = 0; i < n; i++){
double element = nd(gen);
M(i, j) = element;
M(i + n, j) = -element;
}
}
Here, two successive iterations will write to neighboring addresses in memory, which will most likely have better performance.

Trouble calculating product of upper triangular matrix using 1-D array (c++)

I'm trying to multiply two upper triangular matrices together. The matrices are stored in single dimensional arrays instead of the usual 2-D arrays by omitting the zeros that would be under the diagonal (to conserve space). I've figured out how to map elements given a pair of indices to the index for the single array. but I'm having trouble with the actual calculation (The calculation works for smaller n x n square matrices, but for some reason gives incorrect results for larger n x n matrices). I believe that I might be passing in incorrect parameters to the getValue() function, but I think they should be right considering the general formula for matrix multiplication. Any help will be appreciated!
Here's my relevant code:
// mat is an array containing the upper triangle data for a square matrix of size n
// returns element at (i,j), or 0 for the lower triangle
int val(int *mat, int n, int i, int j)
{
if (i > j) {
return 0; // lower triangle
} else {
return mat[j + (i*n) - i*(i+1)/2];
}
}
user101263,
You might not want to map your 2D array into a 1D array for simplification, beacuse in reality, it just complicates the simple matrix-multiplication algorithm.
Here is an implementation of the MM algorithm:
int main()
{
int[5][5] result;
/* omitted: create your 2 2D arrays a & b */
matrixMulitplcation(a,b, result)
}
int** matrixMultiplcation(int a[5][5], int b[5][5], result[5][5])
{
for(int R=0;R<5;R++)
{
for(int C=0;C<5;C++)
{
result[R][C]=0;
for(int T=0;T<5;T++)
result[R][C]+=a[R][T]*b[T][C];
}
}
return result;
}
Please let me know if you have any questions!
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
for(int k = 0;k < n; k++)
{
C[ij_to_k(i,j,n)] += A[ij_to_k(i,k,n)] * B[ij_to_k(k,j,n)];
}
}
}
Just create the ij_to_k() function and you are good to go.

Multiplication of matrices

I ve got two matrices W2 and hiddenLayer and i want to proceed the multiplication of those. W2 size's 12x50 and hiddenLayer size's 50x1. The proper code for the above calculation:
for(int h=0; h<50; h++){
for(int k=0; k<12; k++){
outputLayer += W2[k][h]*HiddenLayer[h];
}
}
or i ve got to put at first k-for??
Matrix multiplication is defined as:
C = AB ⇔ Ci,j = Σk=1..n Ai,k Bk,j for i,j = 1...n (in case of square matrices).
Thus outputLayer is a vector. Since HiddenLayer is a vector too, this isn't really a matrix multiplication but a matrix vector multiplication, which simplifies the formula above:
b = Ax ⇔ bi = Σk=1..m Ai,k xk for i = 1...n (A is an n x m matrix).
So all in all your code should be something like
for(int row = 0; row < 12; row++){
outputLayer[row] = 0;
for(int column = 0; column < 50; column++){
outputLayer[row] += W2[row][column]*HiddenLayer[column];
}
}