Row Operations

This code is a functioning for most matrix inversions, but it does not work if a[j][j]=0. What I think I need to do is create an else statement that reads through all the rows with the same column and if it finds a non zero value to switch the entire rows in both matrix a and b. How would I go about implementing that?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

int main()
{
double a[8][8]={2.0000,-2.0000,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
-1.0000,0.0,0.0,0.0,0.0,0.0,1.1111,0.0,0.0,-1.1111,0.0,0.0,0.0,0.0,0.0,
1.3333,0.0,0.0,-1.3333,0.0,0.0,0.0,0.0,0.0,1.1111,-1.1111,0.0,0.0,0.0,0.0,
0.0,0.0,-1.2500,0.0,0.0,2.6786,-1.4286,0.0,0.0,0.0,0.0,-1.3333,0.0,
-1.4286,4.4286,-1.6667,0.0,0.0,0.0,0.0,-1.0000,0.0,-1.6667,2.6667};
double b[8][8]={1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0};
int i,j,k,l;
float t;


for (j = 0; j<8; j++){
    for (i=j; i<8; i++){
        if (a[i][j] != 0){
            t = 1.0/a[j][j];
            for (k = 0; k<8; k++){
                a[j][k] *= t;
                b[j][k] *= t;
            }
            for (l = 0; l<8; l++){
                if (l != j){
                    t = -a[l][j];
                    for (k = 0; k<8; k++){
                        a[l][k] = a[l][k] + t*a[j][k];
                        b[l][k] = b[l][k] + t*b[j][k];
                    }
                }
           }           
        }
    }
}

}


edit: In my compiler the matrices are in one row, but I just made them a few different lines so that it's easier to see the question.
Last edited on
closed account (D80DSL3A)
I got it to work for your given 8x8 example by inserting this code between lines 18 and 19:
1
2
3
4
5
6
7
8
if( a[j][j] == 0.0 )		
	for(k=j+1; k<8; ++k)			
		if( a[k][j] != 0.0 )
		{
			swapRows(a, j, k);// swap rows j and k
			swapRows(b, j, k);
			break;// because the needed case has been found
		}	

This may be coincidence that it works though. If you test it please let me know if you find any cases for which this simple approach fails.
It will clearly fail if no row k below row j can be found such that a[k][j] != 0, but maybe this can't happen for a matrix with a non-vanishing determinant? Presumably you have tested that determinant(a) != 0 before seeking the inverse.
I'm writing it to put on a MCU, so there is no swapRows identifier. How would I swap the rows otherwise?
closed account (D80DSL3A)
Sorry, swapRows() is a function I wrote myself. I didn't include the function definition because it's very simple. I thought you might just write it yourself.
Here's my version:
1
2
3
4
5
6
7
8
9
10
11
void swapRows(double m[][N], int r1, int r2)
{	
	double temp;
	for(int c=0; c<N; ++c)
	{
	        temp = m[r1][c];
		m[r1][c] = m[r2][c];
		m[r2][c] = temp;
	}
	return;
}

EDIT: substitute the value 8 for N in the function.
I adapted your code to work for any NxN matrix, not just for 8x8.
Last edited on
Sorry, I'm still getting a few errors.

"Non-void function "main" should return a value" in file "/main.cpp" at line 24
"Statement is unreachable" in file "/main.cpp"
"Expression must have pointer-to-object type"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "mbed.h"
#include "math.h"
Serial pc(USBTX, USBRX);

int main()
{
double a[8][8]={2,-2,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,1.111,0,0,-1.111,0,0,0,0,0,1.333,0,0,-1.333,0,0,0,0,0,1.111,-1.111,0,0,0,0,0,0,-1.25,0,0,2.6786,-1.428,0,0,0,0,-1.333,0,-1.4286,4.4286,-1.6667,0,0,0,0,-1,0,-1.6667,2.667};
double b[8][8]={1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1};

float mult[8][8];
int i,j,k,l;
float t;
int r1,r2,c;

void swapRows(double m[][8],int r1,int r2);
{	
	double temp;
	for(c=0; c<8; ++c)
	{
	    temp = a[r1][c];
		a[r1][c] = a[r2][c];
		a[r2][c] = temp;
	}
	return;
}


pc.printf("Input matrix\n\r");

for (i=0;i<8;i++){
    pc.printf("\n\r");
    for(j=0;j<8;j++){
        pc.printf("%f\t",a[i][j]);
        }
    }

for (j = 0; j<8; j++){
    for (i=j; i<8; i++){
        if( a[j][j] == 0.0 ){		
	        for(k=j+1; k<8; ++k){			
		        if( a[k][j] != 0.0 ){
			        swapRows(a, j, k);// swap rows j and k
			        swapRows(b, j, k);
			        break;// because the needed case has been found
		        }
		    }
		}	
        if (a[i][j] != 0){
            t = 1.0/a[j][j];
            for (k = 0; k<8; k++){
                a[j][k] *= t;
                b[j][k] *= t;
            }
            for (l = 0; l<8; l++){
                if (l != j){
                    t = -a[l][j];
                    for (k = 0; k<8; k++){
                        a[l][k] = a[l][k] + t*a[j][k];
                        b[l][k] = b[l][k] + t*b[j][k];
                    }
                }
           }           
        }
    }
}


pc.printf("\r\n\r\nInverse matrix\n\r");

for(l=0;l<8;l++){
    pc.printf("\r\n");
    for(k=0;k<8;k++){
        pc.printf("%f\t", b[l][k]);
        }
    }
//Matrix multiplication

pc.printf("\r\n\r\nMatrix x Inverse to Create Identity Matrix\n\r\n");
for(i=0;i<8;i++){
    for(j=0;j<8;j++){
        mult[i][j]=0;
        for(k=0;k<8;k++){
            mult[i][j]+=b[i][k]*c[k][j];
        }
     pc.printf("%f\t",mult[i][j]);
    }
            printf("\r\n");
}


}
Last edited on
closed account (D80DSL3A)
You put that inside the main() ??? That won't work.
Also, the rest of the program appears to be written to handle a 5x5 matrix, not an 8x8.

I don't wish to troubleshoot every detail of your code. You need to know what you're doing.
Perhaps someone else can help. Good luck with your project.

EDIT: I see your code is now set up for an 8x8 matrix throughout.
Try placing lines 15-25 ( the swapRows() definition ) above main(). Maybe that's the only error.
Last edited on
Ah you were correct about the int main, my mistake. And I thought I fixed the 5x5 before posting, my apologies.. It works, though! Thank you so much! Your efforts are so incredibly appreciated!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "mbed.h"
#include "math.h"
Serial pc(USBTX, USBRX);

void swapRows(double m[][8], int r1, int r2)
{	
	double temp;
	for(int c=0; c<8; ++c)
	{
	        temp = m[r1][c];
		m[r1][c] = m[r2][c];
		m[r2][c] = temp;
	}
	return;
}

int main()
{
double a[8][8]={2.0000,-2.0000,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1.0000,0.0,0.0,0.0,0.0,0.0,1.1111,0.0,0.0,-1.1111,0.0,0.0,0.0,0.0,0.0,1.3333,0.0,0.0,-1.3333,0.0,0.0,0.0,0.0,0.0,1.1111,-1.1111,0.0,0.0,0.0,0.0,0.0,0.0,-1.2500,0.0,0.0,2.6786,-1.4286,0.0,0.0,0.0,0.0,-1.3333,0.0,-1.4286,4.4286,-1.6667,0.0,0.0,0.0,0.0,-1.0000,0.0,-1.6667,2.6667};
double b[8][8]={1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0};
float mult[8][8];
float c[8][8]={2.0000,-2.0000,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1.0000,0.0,0.0,0.0,0.0,0.0,1.1111,0.0,0.0,-1.1111,0.0,0.0,0.0,0.0,0.0,1.3333,0.0,0.0,-1.3333,0.0,0.0,0.0,0.0,0.0,1.1111,-1.1111,0.0,0.0,0.0,0.0,0.0,0.0,-1.2500,0.0,0.0,2.6786,-1.4286,0.0,0.0,0.0,0.0,-1.3333,0.0,-1.4286,4.4286,-1.6667,0.0,0.0,0.0,0.0,-1.0000,0.0,-1.6667,2.6667};
int i,j,k,l;
float t;


pc.printf("Input matrix\n\r");

for (i=0;i<8;i++){
    pc.printf("\n\r");
    for(j=0;j<8;j++){
        pc.printf("%f\t",a[i][j]);
        }
    }

for (j = 0; j<8; j++){
    for (i=j; i<8; i++){
        if( a[j][j] == 0.0 ){		
	        for(k=j+1; k<8; ++k){			
		        if( a[k][j] != 0.0 ){
			        swapRows(a, j, k);
			        swapRows(b, j, k);
			        break;
		        }
		    }
		}
		if (a[i][j] != 0.0){
            t = 1.0/a[j][j];
            for (k = 0; k<8; k++){
                a[j][k] *= t;
                b[j][k] *= t;
            }
            for (l = 0; l<8; l++){
                if (l != j){
                    t = -a[l][j];
                    for (k = 0; k<8; k++){
                        a[l][k] = a[l][k] + t*a[j][k];
                        b[l][k] = b[l][k] + t*b[j][k];
                    }
                }
           }           
        }
    }
}

pc.printf("\r\n\r\nInverse matrix\n\r");

for(l=0;l<8;l++){
    pc.printf("\r\n");
    for(k=0;k<8;k++){
        pc.printf("%f\t", b[l][k]);
        }
    }
//Matrix multiplication

pc.printf("\r\n\r\nMatrix x Inverse to Create Identity Matrix\n\r\n");
for(i=0;i<8;i++){
    for(j=0;j<8;j++){
        mult[i][j]=0;
        for(k=0;k<8;k++){
            mult[i][j]+=b[i][k]*c[k][j];
        }
     pc.printf("%f\t",mult[i][j]);
    }
            printf("\r\n");
}

}
Last edited on
closed account (D80DSL3A)
You're welcome.
I had wanted to have an inverse() function for my Matrix class based on a row reduction method anyways. Now I have it - so thank you!
My existing method was based on finding the adjoint of the matrix (M). Then:
M-1 = adjoint(M)/determinant(M)

The row reduction method is way more efficient (in terms of # of operations).
Sorry for the snarky reply back there, I thought it was gonna get bad.
Yes, my original code did it that way too. Since I'm using an MCU though, we ran into serious program memory problems, so we decided to go with the row method as well. Best of luck!
Topic archived. No new replies allowed.