C++: Transpose of Matrix, using SINGLE DIMENSION dynamic array to save elements - c++

Dear Friends I am having problem to transpose a matrix. The transposed matrix has elements that are undefined. Not sure what is wrong. Thank you for your time!
entries[i] is the dynamic array storing the elements in the matrix. Elements are stored row by row, from left to right. i.e. in a 3X3 matrix, entries[2] is 3rd element on the 1st row, entries[3] is 1st element on the 2nd row
n is the number of rows of matrix
m is the number of columns of matrix
Matrix Matrix::Transpose() const {
double* temp;
temp = new double[n * m];
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
temp[(j - 1) * m + i - 1] = entries[(i - 1) * m + j - 1];
}
Matrix Result(m, n, temp);
delete temp;
return Result;
}
When the original matrix is a square, all elements of the transposed matrix are defined. When the original matrix is 1x3, then the resulting transposed 3x1 matrix has undefined elements for the 2nd and 3rd elements. I.e. (1 1 3) after transposed returns (1 -3452346326236 -12351251515)
The Matrix Print out function is below. The error likely comes from here too.
void Matrix::Print() const
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
cout << setw(13) << entries[(i - 1) * m + j - 1];
cout << endl;
}
}

When the matrix is not square, the line
temp[(j - 1) * m + i - 1] = entries[(i - 1) * m + j - 1];
is not right. It needs to be:
temp[(j - 1) * n + i - 1] = entries[(i - 1) * m + j - 1];
// ^^ needs to be n, not m.
Think of the 2D analogue. You want to use:
temp[j][i] = entries[i][j];
entries is a n x m matrix. For it, the 2D indices [i][j] are translated as [i*m + j] for the 1D index.
temp is a m x n matrix. For it, the 2D indices [j][i] are translated as [j*n + i] for the 1D index.
Suggestion for improved readability
Instead of n and m, use num_rows, and num_columns. You will find your code a lot more readable.

Related

C++: Matrix Gauss Elimination Does Not Work: Using SINGLE DIMENSION Array to store elements

my codes does not work for Gauss Elimination for Matrix. The core code is ok, but it seems to be missing some final touch which I honestly dont know. Would be great if someone can point out the mistake.
Basically when I input a square 3x3 Matrix filled with 3s, I get back (3, 3, 3, 0, -3, -3, 0, 0, 3) but it should be (3, 3, 3, 0, 0, 0, 0, 0, 0)
n is number of rows of matrix and m is number of columns.
All elements of matrix are stored in a SINGLE DIMENSION array called entries[i]
My code below for GaussElimination basically starts with placing the row with the largest first element on the top row. Then after that I just delete the elements right below the top elements.
Matrix Matrix::GaussElim() const {
double maxEle;
int maxRow;
for (int i = 1; i <= m; i++) {
maxEle = fabs(entries[i-1]);
maxRow = i;
for (int k = i+1; k <= m; k++) {
if (fabs(entries[(k - 1) * n + i - 1]) > maxEle) {
maxEle = entries[(k - 1) * n + i - 1];
maxRow = k;
}
}
for (int a = 1; a <= m; a++) {
swap(entries[(i - 1) * m + a - 1], entries[(maxRow - 1) * m + a - 1]);
}
for (int b = i + 1; b <= n; b++) {
double c = -(entries[(b - 1) * m + i - 1]) / entries[(i - 1) * m + i - 1];
for (int d = i; d <= n; d++) {
if (i == d) {
entries[(b - 1) * m + d - 1] = 0;
}
else {
entries[(b - 1) * m + d - 1] = c * entries[(i - 1) * m + d - 1];
}
}
}
}
Matrix Result(n, m, entries);
return Result;
}
For starters, I'd suggest to drop the habit of starting the loops at 1 instead of the more idiomatic 0, it would simplify all of the formulas.
That said, this statement
else {
entries[(b - 1) * m + d - 1] = c * entries[(i - 1) * m + d - 1];
// ^^^
}
Looks suspicious. There should be a += (or a -=, depending on how you choose the sign of the pivot).
Another source of unexpected results is the way chosen to calculate the constant c:
double c = -(entries[(b - 1) * m + i - 1]) / entries[(i - 1) * m + i - 1];
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Even in case of partial pivoting, that value could be zero (or too small), due to the nature of the starting matrix, like in the posted example, or to numerical errors. In those cases, it would be preferable to just zero out all the remaining elements of the matrix.

Symmetric matrix, value into c++ vector

I am trying to solve the following problem. Let's say I have a symmetric matrix with size n. I want to take all the "important values", and store them into a vector. Let me give an example to explain it better.
Let's say I have the following matrix A = [1, 2, 3 // 2, 5, 6 // 3, 6, 9]. I want to define vector of size n*(n+1)/2 such that:
V = [A(0,0), A(0,1), A(0,2), A(1,1), A(1,2), A(2,2) ]
I want to find a function that receives as input two integer i and j, and outputs the corresponding value of the matrix. The catch is that I do not want to access the matrix directly, instead I want to access the vector.
This is my reasoning so far. If I have an input with j < i, I just swap them since the matrix is symmetric. If I have that i == 0, the position in the array is just j. If that is not the case, I think I need to do something like this. (n is the dimension of the matrix, and position is the integer that I need when for the array.)
int position = 0;
for(int k = 0; k < i; k++){
position = position + (n-k);
}
position = position + j % i;
However, this code fails. I think I'm close to the solution but I am missing something. Any help?
The last j % i should be j - i.
In addition, the loop is essentially doing
position = n + (n - 1) + ... + (n - i + 1);
which can be simplified to
position = (n * 2 - i + 1) * i / 2;
So you can simply write
position = (n * 2 - i + 1) * i / 2 + j - i;
or
position = (n * 2 - i - 1) * i / 2 + j;
You can do simply this:
int myvector[matrix.size()];
int pos = 0;
for(int i = 0; i < matrix.size(); i++){
for(int j = 0; j < matrix.size(); j++){
if(j > i) myvector[pos++] = matrix[i][j];
else myvector[pos++] = matrix[j][i];
}
}

2D isometric engine - Math problems - Cube selection - diamond shape map

I calculate my coordinates when i create a layer with a std::vector, filled with cube objects(wich is a class of mine):
for(int J = 0; J < mapSize; J++)
{
for(int I = 0; I < mapSize; I++)
{
x = (J - I) * (cubeSize/2);
y = (J + I) * (cubeSize/4);
c = new cube(cubeSize, x, y, z, I, J);
cs.push_back(*c);
}
}
I wanna do this : cs[getCubeByID(mouseX, mouseY)].setTexture(...);
Example of use: The cube in I-J [0, 0] have the number 0 in the cubes array. if i click on 0,0 i got this number.
EDIT:
We gave me the formula to get a J or a I with a pair of x,y in the comments, thanks a lot. I only need to convert this pair of I-J to the entry number of my array like the example i gave.
I tried : int entry = (J - 1) * size + (I - 1); and the selected cube is not so far from the one i want but still not the right formula. Modular arithmetic can fix my problem but i don't understand how it's working.
So you have
x = (J - I) * (cubeSize/2);
y = (J + I) * (cubeSize/4);
and you want to compute I and J (and therefore the index which is I + J*mapSize) from that, right? It's a linear system of two equations.
J - I = x * 2 / cubeSize
J + I = y * 4 / cubeSize
I = (y * 2 - x) / cubeSize
J = (y * 2 + x) / cubeSize

Multiplying 2D Arrays in C++

I overloaded operator * which multiplying 2D arrays. I have some problems with multiplying, don't understand exactly an indexes when I am multiplying.
Here's some declarations:
int *const e; //pointer to the memory storing all integer elements of A
const int row, column; //r and c are the numbers of rows and columns respectively
And some code:
A A::operator*(const A& matrix)const
{
MAT result(matrix.row, matrix.column);
if (column == matrix.row)
{
for (int i = 0; i < row; ++i)
{
for (int j = 0; j < matrix.column; j++)
{
result.e[j*row + i] = 0;
for (int k = 0; k < column; k++)
{
result.e[j*row + i] += e[j*row + k] * matrix.e[k*row + column];
}
}
}
}
return result;
}
I know that I need 3 loops, I think I have some problems in
result.e[j*row + i] += e[j*row + k] * matrix.e[k*row + column];
Do you have any clue ? You can write me some ideas how can I figure out it myself, because I want to understand it. Thanks
Your line
result.e[j*row + i] += e[j*row + k] * matrix.e[k*row + column];
is broken. The product P of two matrices A (dim M,N) and B (dim N,P) has it's coefficient in position (i,j) defined by the following :
Pi,j = sum(k = 1..N, ai,k . bk,j).
Thus the line mentioned above should be :
result.e[j*row + i] += e[j*row + k] * matrix.e[k*row + i];

matrix multiplication as column major

I am trying to multiply as column major and I can't seem to find the right formula!
I want to have the matrices as 1D.
Let's say I have these matrices:
A=
1 3
2 4
and B=
5 2 1
6 3 7
The above matrices are assumed that are stored already in column major order.
I am trying:
int main(int argc, const char* argv[]) {
int rows=2;
int cols=3;
int A[rows*rows];
int B[rows*cols];
int res[rows*cols];
A[0]=1;
A[1]=3;
A[2]=2;
A[3]=4;
B[0]=5;
B[1]=2;
B[2]=1;
B[3]=6;
B[4]=3;
B[5]=7;
/*A[0]=1;
A[1]=2;
A[2]=3;
A[3]=4;
B[0]=5;
B[1]=6;
B[2]=2;
B[3]=3;
B[4]=1;
B[5]=7;
*/
//multiplication as column major
for (int i=0;i<rows;i++){
for (int j=0;j<cols;j++){
res[i+j*rows]=0;
for (int k=0;k<rows;k++){
res[i+j*rows]+=A[i+k*rows]*B[k+j*cols];
}
}
}
for (int i=0;i<rows*cols;i++){
printf("\n\nB[%d]=%d\t",i,res[i]);
}
return 0;
}
I am not getting the correct results.
Also,I can't understand (in the case where the matrices are stored in column major already) ,how to index the matrices A and B.
A[0]=1;
A[1]=3;
...
or
A[0]=1;
A[1]=2;
...
I don't want to transpose the matrices and then use row major.
I want to handle the data as column major.
Because the indices ,if stored as column major,will be different (hence,will matter in order to do the multiplication).
There are two things that lead to your confusion here.
First, the data in your contiguous one-dimensional vector is not in column-major order as you say, but in row-major order, as is the usual layout of two-dimensional contiguous arrays in C. The linear one-dimensional indices of row i and column j in a matrix with M rows and N columns (MxN) are:
A[i*N + j] // row major
A[i + M*j] // column major
The "major" refers to the dimension of the outer loop when traversing the array sequentially with two nested loops:
n = 0;
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++) {
printf("%8d", A[n++]);
}
printf("\n");
}
Second, you use the two dimensions rows and columns which are the dimensions of the resulting matrix, which is confusing, because the number of columns in A is rows.
In fact, there are three different dimensions involved in matrix multiplication when you multiply an MxL matrix A with an LxN matrix B to get an MxN matrix C. In your case, M and L happen to be both 2:
L (k) | N (j)
|
| 5 2 1
L (k) |
| 6 3 7
|
-----------------+-------------
|
1 3 | 23 11 22
M (i) |
2 4 | 34 16 30
|
The letters in parentheses are the variables the code below uses to iterate over the respective dimension.
Now you can multiply your matrices in row-major format:
#define M 2
#define N 3
#define L 2
int A[M * L] = {1, 3, 2, 4};
int B[L * N] = {5, 2, 1, 6, 3, 7};
int res[M * N];
int i, j, k;
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++) {
res[j + i * N] = 0;
for (k = 0; k < L; k++) {
res[j + i * N] += A[k + i * L] * B[j + k * N];
}
}
}
for (i = 0; i < M * N; i++) printf("[%d] = %d\n", i, res[i]);
or in column-major format:
#define M 2
#define N 3
#define L 2
int A[M * L] = {1, 2, 3, 4};
int B[L * N] = {5, 6, 2, 3, 1, 7};
int res[M * N];
int i, j, k;
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++) {
res[j * M + i] = 0;
for (k = 0; k < L; k++) {
res[j * M + i] += A[k * M + i] * B[j * L + k];
}
}
}
for (i = 0; i < M * N; i++) printf("[%d] = %d\n", i, res[i]);
Both input and output are in the respective matrix representation and differ in the two cases, of course.
What do you think about
res[i+j*rows]+=A[i+k*rows]*B[k+j*cols];
what it will do?
It will access array res, A and B out of bound when i and k becomes 1 and j becomes 2.
res[1+2*2]+=A[1+1*2]*B[1+2*3] = res[5]+=A[4]*B[7];
This will invoke undefined behavior and you may get either expected or unexpected result.
I think you need this:
res[i*rows+j] += A[i*rows + k] * B[j + k*cols];