-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsistema_linear.c
153 lines (125 loc) · 3.85 KB
/
sistema_linear.c
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "sistema_linear.h"
/* Global local Variables */
long double EPSILON = 1e-9;
matrix_t init_matriz(size_t m, size_t n)
{
matrix_t A = (matrix_t)malloc(sizeof(vector_t) * m);
if (!A)
{
printf("\n[ERROR] Memory allocation failure for matrix, init_matriz()\n\n");
exit(EXIT_FAILURE);
}
for (size_t i = 0; i < m; i++)
if (!(A[i] = (vector_t)calloc(n, sizeof(double))))
{
printf("\n[ERROR] Memory allocation failure for matrix, init_matriz()\n\n");
exit(EXIT_FAILURE);
}
return A;
}
matrix_t solver_LU(matrix_t LU, size_t *vpermut, matrix_t x, matrix_t b, size_t n)
{
/*
Ax = b, Solve the system using LU decomposition
LUx = b (Lines of b adjusted with those permuted during construction of the LU, vector vpermut)
Note: Using x and b as matrices for the convenience of operations between matrices, without the need for operations
between matrices and vectors, a vector of i elements is a matrix with index [i][0] (column vector)
*/
double b_permut[n];
for (size_t i = 0; i < n; i++)
b_permut[i] = b[vpermut[i]][0];
double y[n];
for (size_t i = 0; i < n; i++)
{
double sum = 0;
for (int j = 0; j <= (int)i - 1; j++)
sum += LU[i][j] * y[j];
y[i] = b_permut[i] - sum;
}
for (size_t i = 0; i < n; i++)
x[i][0] = 0;
for (int i = (n - 1); i >= 0; i--)
{
double sum = 0;
for (size_t j = (i + 1); j < n; j++)
sum += LU[i][j] * x[j][0];
x[i][0] = (y[i] - sum) / LU[i][i];
}
return x;
}
matrix_t LU_decomposition(matrix_t A, matrix_t LU, size_t *vpermut, size_t n)
{
/*
Decompose A into LU.
vpermut vector of indices at which rows were permuted during decomposition.
*/
for (size_t i = 0; i < n; i++)
{
memcpy(LU[i], A[i], sizeof(double) * n);
vpermut[i] = i;
}
for (size_t k = 0; k < (n - 1); k++)
{
double pivo = LU[k][k];
size_t l_pivo = k;
for (size_t i = (k + 1); i < n; i++)
if (fabs(LU[i][k]) > fabs(pivo))
{
pivo = LU[i][k];
l_pivo = i;
}
if (fabsl((long double)pivo) < EPSILON)
{
printf("[ERROR] Constraint matrix A is singular, system not possible! (Try smaller values for EPSILON, -e <value>)\n\n");
exit(EXIT_FAILURE);
}
if (l_pivo != k)
{
size_t aux = vpermut[k];
vpermut[k] = vpermut[l_pivo];
vpermut[l_pivo] = aux;
for (size_t j = 0; j < n; j++)
{
double aux = LU[k][j];
LU[k][j] = LU[l_pivo][j];
LU[l_pivo][j] = aux;
}
}
for (size_t i = (k + 1); i < n; i++)
{
double escalar = LU[i][k] / LU[k][k];
LU[i][k] = escalar;
for (size_t j = (k + 1); j < n; j++)
LU[i][j] -= (escalar * LU[k][j]);
}
}
return LU;
}
matrix_t matrix_multi(matrix_t A, matrix_t B, matrix_t dest, size_t m, size_t n, size_t r)
{
for (size_t i = 0; i < m; i++)
for (size_t k = 0; k < r; k++)
{
dest[i][k] = 0;
for (size_t j = 0; j < n; j++)
dest[i][k] += A[i][j] * B[j][k];
}
return dest;
}
matrix_t scala_multi(matrix_t src, double escalar, matrix_t dest, size_t m, size_t n)
{
for (size_t i = 0; i < m; i++)
for (size_t j = 0; j < n; j++)
dest[i][j] = escalar * src[i][j];
return dest;
}
matrix_t transpose(matrix_t src, matrix_t dest, size_t m, size_t n)
{
for (size_t i = 0; i < m; i++)
for (size_t j = 0; j < n; j++)
dest[j][i] = src[i][j];
return dest;
}