linear algebra
Cramer's rule
system of linear equations


Given


 




{





a

1


x
+

b

1


y
+

c

1


z


=



d

1









a

2


x
+

b

2


y
+

c

2


z


=



d

2









a

3


x
+

b

3


y
+

c

3


z


=



d

3












{\displaystyle \left\{{\begin{matrix}a_{1}x+b_{1}y+c_{1}z&={\color {red}d_{1}}\\a_{2}x+b_{2}y+c_{2}z&={\color {red}d_{2}}\\a_{3}x+b_{3}y+c_{3}z&={\color {red}d_{3}}\end{matrix}}\right.}




which in matrix format is



 





[




a

1





b

1





c

1







a

2





b

2





c

2







a

3





b

3





c

3





]




[



x




y




z



]


=


[






d

1











d

2











d

3







]


.


{\displaystyle {\begin{bmatrix}a_{1}&b_{1}&c_{1}\\a_{2}&b_{2}&c_{2}\\a_{3}&b_{3}&c_{3}\end{bmatrix}}{\begin{bmatrix}x\\y\\z\end{bmatrix}}={\begin{bmatrix}{\color {red}d_{1}}\\{\color {red}d_{2}}\\{\color {red}d_{3}}\end{bmatrix}}.}




Then the values of 



x
,
y


{\displaystyle x,y}

 and 



z


{\displaystyle z}

 can be found as follows:







x
=



|






d

1







b

1





c

1









d

2







b

2





c

2









d

3







b

3





c

3





|


|




a

1





b

1





c

1







a

2





b

2





c

2







a

3





b

3





c

3





|



,

y
=



|




a

1







d

1







c

1







a

2







d

2







c

2







a

3







d

3







c

3





|


|




a

1





b

1





c

1







a

2





b

2





c

2







a

3





b

3





c

3





|



,

 and 

z
=



|




a

1





b

1







d

1









a

2





b

2







d

2









a

3





b

3







d

3







|


|




a

1





b

1





c

1







a

2





b

2





c

2







a

3





b

3





c

3





|



.


{\displaystyle x={\frac {\begin{vmatrix}{\color {red}d_{1}}&b_{1}&c_{1}\\{\color {red}d_{2}}&b_{2}&c_{2}\\{\color {red}d_{3}}&b_{3}&c_{3}\end{vmatrix}}{\begin{vmatrix}a_{1}&b_{1}&c_{1}\\a_{2}&b_{2}&c_{2}\\a_{3}&b_{3}&c_{3}\end{vmatrix}}},\quad y={\frac {\begin{vmatrix}a_{1}&{\color {red}d_{1}}&c_{1}\\a_{2}&{\color {red}d_{2}}&c_{2}\\a_{3}&{\color {red}d_{3}}&c_{3}\end{vmatrix}}{\begin{vmatrix}a_{1}&b_{1}&c_{1}\\a_{2}&b_{2}&c_{2}\\a_{3}&b_{3}&c_{3}\end{vmatrix}}},{\text{ and }}z={\frac {\begin{vmatrix}a_{1}&b_{1}&{\color {red}d_{1}}\\a_{2}&b_{2}&{\color {red}d_{2}}\\a_{3}&b_{3}&{\color {red}d_{3}}\end{vmatrix}}{\begin{vmatrix}a_{1}&b_{1}&c_{1}\\a_{2}&b_{2}&c_{2}\\a_{3}&b_{3}&c_{3}\end{vmatrix}}}.}






Task
Given the following system of equations:









{



2
w
−
x
+
5
y
+
z
=
−
3




3
w
+
2
x
+
2
y
−
6
z
=
−
32




w
+
3
x
+
3
y
−
z
=
−
47




5
w
−
2
x
−
3
y
+
3
z
=
49








{\displaystyle {\begin{cases}2w-x+5y+z=-3\\3w+2x+2y-6z=-32\\w+3x+3y-z=-47\\5w-2x-3y+3z=49\\\end{cases}}}




solve for 



w


{\displaystyle w}

, 



x


{\displaystyle x}

, 



y


{\displaystyle y}

 and 



z


{\displaystyle z}

, using Cramer's rule.




#include <math.h>
#include <stdio.h>
#include <stdlib.h>
 
typedef struct {
    int n;
    double **elems;
} SquareMatrix;
 
SquareMatrix init_square_matrix(int n, double elems[n][n]) {
    SquareMatrix A = {
        .n = n,
        .elems = malloc(n * sizeof(double *))
    };
    for(int i = 0; i < n; ++i) {
        A.elems[i] = malloc(n * sizeof(double));
        for(int j = 0; j < n; ++j)
            A.elems[i][j] = elems[i][j];
    }
 
    return A;
}
 
SquareMatrix copy_square_matrix(SquareMatrix src) {
    SquareMatrix dest;
    dest.n = src.n;
    dest.elems = malloc(dest.n * sizeof(double *));
    for(int i = 0; i < dest.n; ++i) {
        dest.elems[i] = malloc(dest.n * sizeof(double));
        for(int j = 0; j < dest.n; ++j)
            dest.elems[i][j] = src.elems[i][j];
    }
 
    return dest;
}
 
double det(SquareMatrix A) {
    double det = 1;
 
    for(int j = 0; j < A.n; ++j) {
        int i_max = j;
        for(int i = j; i < A.n; ++i)
            if(A.elems[i][j] > A.elems[i_max][j])
                i_max = i;
 
        if(i_max != j) {
            for(int k = 0; k < A.n; ++k) {
                double tmp = A.elems[i_max][k];
                A.elems[i_max][k] = A.elems[j][k];
                A.elems[j][k]     = tmp;
            }
 
            det *= -1;
        }
 
        if(abs(A.elems[j][j]) < 1e-12) {
            puts("Singular matrix!");
            return NAN;
        }
 
        for(int i = j + 1; i < A.n; ++i) {
            double mult = -A.elems[i][j] / A.elems[j][j];
            for(int k = 0; k < A.n; ++k)
                A.elems[i][k] += mult * A.elems[j][k];
        }
    }
 
    for(int i = 0; i < A.n; ++i)
        det *= A.elems[i][i];
 
    return det;
}
 
void deinit_square_matrix(SquareMatrix A) {
    for(int i = 0; i < A.n; ++i)
        free(A.elems[i]);
    free(A.elems);
}
 
double cramer_solve(SquareMatrix A, double det_A, double *b, int var) {
    SquareMatrix tmp = copy_square_matrix(A);
    for(int i = 0; i < tmp.n; ++i)
        tmp.elems[i][var] = b[i];
 
    double det_tmp = det(tmp);
    deinit_square_matrix(tmp);
 
    return det_tmp / det_A;
}
 
int main(int argc, char **argv) {
#define N 4
    double elems[N][N] = {
        { 2, -1,  5,  1},
        { 3,  2,  2, -6},
        { 1,  3,  3, -1},
        { 5, -2, -3,  3}
    };
    SquareMatrix A = init_square_matrix(N, elems);
 
    SquareMatrix tmp = copy_square_matrix(A);
    int det_A = det(tmp);
    deinit_square_matrix(tmp);
 
    double b[] = {-3, -32, -47, 49};
 
    for(int i = 0; i < N; ++i)
        printf("%7.3lf\n", cramer_solve(A, det_A, b, i));
 
    deinit_square_matrix(A);
    return EXIT_SUCCESS;
}