-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgaussalgorithm.cpp
More file actions
200 lines (154 loc) · 5.96 KB
/
gaussalgorithm.cpp
File metadata and controls
200 lines (154 loc) · 5.96 KB
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#include "gaussalgorithm.h"
using namespace std;
GaussAlgorithm::GaussAlgorithm(){
_numberOfEquations = 0;
_numberOfVariables = 0;
solution = nullptr;
}
void GaussAlgorithm::readFrom(istream& in){
in >> _numberOfVariables;
in >> _numberOfEquations;
double* currEquation;
for (int i = 0; i < _numberOfEquations; i++){
currEquation = new double[_numberOfVariables + 1];
for(int j = 0; j <= _numberOfVariables; j++)
in >> currEquation[j];
matrix.push_back(currEquation);
}
}
const double* GaussAlgorithm::getSolution () const{
return solution;
}
int GaussAlgorithm::getNumberOfVariables() const{
return _numberOfVariables;
}
void GaussAlgorithm::iterate(vector<double*> matrix, double* currEquation, int position){
int size = matrix.size();
double multiplier = 0.0;
for(int i = 0; i < size; i++){
multiplier = matrix[i][position] / currEquation[position];
for(int j = 0; j <= _numberOfVariables; j++){
matrix[i][j] -= currEquation[j] * multiplier;
}
}
}
void GaussAlgorithm::copyEquation(const double* from, double* to)const{
for (int i = 0; i <= _numberOfVariables; i++)
to[i] = from[i];
}
int GaussAlgorithm::findSolution(int numberOfTreads) throw(invalid_argument) {
if(numberOfTreads <= 0) throw invalid_argument("Incorect number of threads");
if(numberOfTreads > _numberOfEquations) numberOfTreads = _numberOfEquations;
thread threads[numberOfTreads];
vector<double*> Equations[numberOfTreads];
/* Matrix division into small groups beetween the threads.
Every next equation is cyclicaly added to the other group
*/
for(int i = 0; i < _numberOfEquations; i++){
Equations[i % numberOfTreads].push_back(matrix[i]);
}
/*
in "positions[i]" will be stored information
about value of which variable can be found from i-th
equation in matrix.
In the best way (if matrix are square, her lines are linearly independent)
we will get diagonal matrix after iterations, and this information will be redandant.
But when something goes wrong (current line is empty or current element is equal to zero)
we need to change order of lines.
But in this situation it is easier to change current variable, not whole line
(it is also easier to check whether the system has solution at all).
So in this situation we need to save the order of variables.
*/
vector<int>positions (_numberOfEquations);
for(int i = 0; i < _numberOfEquations; i++)
positions[i] = i;
/*
Here is the Gauss' algorithm!
For each iteration every line in the matrix is taken,
checked for being empty and passed
into each thread for further processing.
*/
double* currentEquation = new double[_numberOfVariables + 1]; //copy of current line of matrix
double curr = 0.0; //copy of current element
/* we need a copy, becouse information may be lost during iterations
*/
// these elements are used for checking
// whether the system has solution at all
bool isEmpty = false;
bool hasSolution = true;
int _numberOfEmptyLines = 0;
for(int i = 0; i < _numberOfEquations; i++){
copyEquation( matrix[i], currentEquation);
//here is the current line's checking
//current element cannot be equal to zero,
//so we need to find any other nonzero element
//if it is possible
if(::abs(currentEquation[positions[i]]) < epsilon) {
int j = i + 1;
while(::abs(currentEquation[positions[j]]) < epsilon){
if(j == _numberOfVariables)
break;
j++;
}
if(j == _numberOfVariables){
if(::abs(currentEquation[j]) < epsilon) isEmpty = true;
else hasSolution = false;
}
else std::swap(positions[i], positions[j]);
}
//if system has no solution we can and the algorithm
if(hasSolution == false) {
delete currentEquation;
return 0;
}
//if line is empty (all elements are equal to zero)
//we can miss it. But we need to mark that none of variables can be
//fond from this equation
if(isEmpty){
isEmpty = false;
_numberOfEmptyLines++;
for(int j = _numberOfEquations - 1;j > i; j--)
positions[j] = positions[j - 1];
positions[i] -1;
continue;
}
for(int j = 0; j < numberOfTreads; j++)
threads[j] = thread(&GaussAlgorithm::iterate, this, Equations[j], currentEquation, positions[i]);
for(int j = 0; j < numberOfTreads; j++)
threads[j].join();
//separately convert the current line to the appropriate form
curr = currentEquation[positions[i]];
for(int j = 0; j <=_numberOfVariables; j++){
currentEquation[j] /= curr;
}
copyEquation(currentEquation, matrix[i]);
}
//filling solution's vector
solution = new double[_numberOfVariables];
for(int i = 0; i < _numberOfVariables; i++)
solution[i] = 0.0;
for(int i = 0; i < _numberOfEquations; i++) {
if(positions[i] == -1) continue;
solution[positions[i]] = matrix[i][_numberOfVariables];
}
//function returns the number of solutions
if(_numberOfEquations - _numberOfEmptyLines == _numberOfVariables)
return 1;
return infinity;
}
void GaussAlgorithm::clear(){
int size = matrix.size();
for(int i = 0; i < size; i++)
delete matrix[i];
matrix.clear();
delete solution;
solution = nullptr;
_numberOfEquations = 0;
_numberOfVariables = 0;
}
GaussAlgorithm::~GaussAlgorithm(){
int size = matrix.size();
for(int i = 0; i < size; i++)
delete matrix[i];
delete solution;
}