ECF 1.5
matrice.cpp
1
2// Implementacija razreda Matrica, SLAJ, LUDek
4
5#include "matrice.h"
6#include "check.h"
7
8#define ABS(X) (X>0 ? X : -X)
9//#include <axh.h> // za assert
10
12// razred Matrica
13
14void Matrica::Free(void)
15{
16 static int i;
17 if(data==NULL)
18 return;
19 for(i=0;i<row;i++)
20 delete[] data[i];
21 delete[] data;
22}
23
24void Matrica::Take(void)
25{
26 static int i;
27 CHECK(row>0 && col>0);
28 data=new double*[row];
29 for(i=0;i<row;i++)
30 data[i]=new double[col];
31}
32
33Matrica::Matrica(void)
34{
35 col=row=0;
36 data=NULL;
37}
38
39Matrica::Matrica(int _row,int _col=1)
40{
41 col=_col;
42 row=_row;
43 Take();
44}
45
46void Matrica::Init(int _row, int _col)
47{
48 Free();
49 col=_col;
50 row=_row;
51 Take();
52}
53
54Matrica::Matrica(Matrica &source)
55{
56 static int i;
57 row=source.row;
58 col=source.col;
59 Take();
60 for(i=0;i<row;i++)
61 memcpy(data[i],source.data[i],col*sizeof(double));
62 /*for(int j=0;j<col;j++)
63 data[i][j]=source.data[i][j];*/
64}
65
66Matrica& Matrica::operator =(Matrica& source)
67{
68 static int i;
69 if(data!=NULL) Free();
70 row=source.row;
71 col=source.col;
72 Take();
73 for(i=0;i<row;i++)
74 memcpy(data[i],source.data[i],col*sizeof(double));
75 /*for(int j=0;j<col;j++)
76 data[i][j]=source.data[i][j];*/
77 return *this;
78}
79
80Matrica::~Matrica()
81{
82 Free();
83}
84
85Matrica Matrica::operator +(Matrica &op2)
86{
87 Matrica R(row,col);
88 CHECK(row==op2.row && col==op2.col && row>0);
89 for(int i=0;i<row;i++)
90 for(int j=0;j<col;j++)
91 R.data[i][j]=data[i][j]+op2.data[i][j];
92 return R;
93}
94
95void Matrica::operator +=(Matrica &op2)
96{
97 CHECK(row==op2.row && col==op2.col && row>0);
98 for(int i=0;i<row;i++)
99 for(int j=0;j<col;j++)
100 data[i][j] += op2.data[i][j];
101}
102
103void Matrica::operator -=(Matrica &op2)
104{
105 CHECK(row==op2.row && col==op2.col && row>0);
106 for(int i=0;i<row;i++)
107 for(int j=0;j<col;j++)
108 data[i][j] -= op2.data[i][j];
109}
110
111Matrica Matrica::operator -(const Matrica &op2)
112{
113 Matrica R(row,col);
114 CHECK(row==op2.row && col==op2.col && row>0);
115 for(int i=0;i<row;i++)
116 for(int j=0;j<col;j++)
117 R.data[i][j]=data[i][j]-op2.data[i][j];
118 return R;
119}
120
121Matrica Matrica::operator *(const Matrica &op2)
122{
123 Matrica R(row,op2.col);
124 CHECK(col==op2.row);
125 for(int i=0;i<row;i++)
126 for(int j=0;j<op2.col;j++)
127 { R.data[i][j]=0;
128 for(int k=0;k<col;k++)
129 R.data[i][j]+=data[i][k]*op2.data[k][j];
130 }
131 return R;
132}
133
134Matrica Matrica::operator *(const double &scalar)
135{
136 Matrica R(row,col);
137 for(int i=0;i<row;i++)
138 for(int j=0;j<col;j++)
139 R.data[i][j]=this->data[i][j]*scalar;
140 return R;
141}
142
143// translacija
144Matrica Matrica::operator ~(void)
145{
146 CHECK(data!=NULL);
147 Matrica P(col, row);
148 int i,j;
149 for(i=0;i<row;i++)
150 for(j=0;j<col;j++)
151 P.data[j][i]=data[i][j];
152 return P;
153}
154
155Matrica Matrica::operator /(const double &scalar)
156{
157 Matrica R(row,col);
158 int i,j;
159
160 for (i=0;i<row; i++)
161 for (j=0;j<col; j++)
162 R.Set(i,j,data[i][j]/scalar);
163 return R;
164}
165
166// transponira matricu: ako je parametar 0, transponira samo kopiju, inace sebe samu
167Matrica Matrica::Transpose(int transpose)
168{
169 CHECK(data!=NULL);
170 Matrica P(col, row);
171 int i,j;
172 for(i=0;i<row;i++)
173 for(j=0;j<col;j++)
174 P.data[j][i]=data[i][j];
175 if(!transpose)
176 return P;
177 // ako i this treba transponirati
178 i=row; row=col; col=i;
179 Free(); Take();
180 for(i=0;i<row;i++)
181 for(j=0;j<col;j++)
182 data[i][j]=P.data[i][j];
183 return (*this);
184}
185
186double Matrica::Get(int _row,int _col) const
187{
188 CHECK(data!=NULL && _row>=0 && _row<row && _col>=0 && _col<col);
189 return data[_row][_col];
190}
191
192double Matrica::Get(int _row) const
193{
194 CHECK(data!=NULL && _row>=0 && _row<row);
195 return data[_row][0];
196}
197
198double Matrica::Set(int _row,int _col, double value)
199{
200 CHECK(data!=NULL && _row>=0 && _row<=row && _col>=0 && _col<=col);
201 data[_row][_col]=value;
202 return value;
203}
204
205double Matrica::Set(int _row,double value)
206{
207 CHECK(data!=NULL && _row>=0 && _row<=row);
208 data[_row][0]=value;
209 return value;
210}
211
212int Matrica::Load(const char* fname)
213{
214 double value;
215 FILE *fp;
216 CHECK((fp=fopen(fname,"r"))!=NULL);
217 if(!(fscanf(fp,"%d %d",&row,&col)!=EOF))
218 exit(1);
219 if(data!=NULL)
220 Free();
221 Take();
222 for(int i=0;i<row*col;i++)
223 { if(!(fscanf(fp," %lf ",&value)!=EOF))
224 exit(1);
225 Set(i/col,i%col,value);
226 }
227 fclose(fp);
228 return 1;
229}
230
231void Matrica::Save(const char* fname)
232{
233 FILE *fp;
234 if((fp=fopen(fname,"w+"))==NULL)
235 exit(1);
236 fprintf(fp,"%d %d\n",row,col);
237 for(int i=0;i<row;i++)
238 { for(int j=0;j<col;j++)
239 fprintf(fp," %g ",data[i][j]);
240 fprintf(fp,"\n");
241 }
242 fclose(fp);
243}
244
245void Matrica::SaveLong(const char* fname)
246{
247 FILE *fp;
248 if((fp=fopen(fname,"w+"))==NULL)
249 exit(1);
250 fprintf(fp,"%d %d\n",row,col);
251 for(int i=0;i<row;i++)
252 { for(int j=0;j<col;j++)
253 fprintf(fp," %lf ",data[i][j]);
254 fprintf(fp,"\n");
255 }
256 fclose(fp);
257}
258
259void Matrica::Show(void)
260{
261 int i,j;
262 printf("Rows: %d Cols: %d\n",row,col);
263 for(i=0;i<row;i++)
264 { for(j=0;j<col;j++)
265 printf("%G\t",data[i][j]);
266 printf("\n");
267 }
268}
269
270void Matrica::Reset(int _row,int _col)
271{
272 CHECK(_row>0 && _col>0);
273 Free();
274 row=_row;
275 col=_col;
276 Take();
277 for(int i=0; i<row; i++)
278 for(int j=0; j<col; j++)
279 this->data[i][j] = 0;
280}
281
282int Matrica::CopyColumn(int colnum,Matrica &V)
283{
284 int i;
285 CHECK(colnum>-1 && colnum<col);
286 V.Reset(row,1);
287 for(i=0;i<row;i++)
288 V.Set(i,data[i][colnum]);
289 return 1;
290}
291
292int Matrica::SetColumn(int colnum,Matrica &v)
293{
294 int i;
295 CHECK(v.GetRow()==row);
296 CHECK(colnum>-1 && colnum<col);
297 for(i=0;i<row;i++)
298 data[i][colnum]=v.Get(i);
299 return 1;
300}
301
302double Matrica::Norm(void)
303{
304 double r=0;
305 for(int i=0;i<row;i++)
306 r+= data[i][0]*data[i][0];
307 return r;
308}
309
310Matrica Matrica::operator+ (double broj)
311{ Matrica R(*this);
312 for(int i=0; i<row; i++)
313 for(int j=0; j<col; j++)
314 R[i][j] += broj;
315 return R;
316}
317
318
320// razred SLAJ
321
322void SLAJ::Load_A(char* fname)
323{
324 A.Load(fname);
325}
326
327void SLAJ::Load_b(char* fname)
328{
329 b.Load(fname);
330}
331
332void SLAJ::Save_A(char* fname)
333{
334 A.Save(fname);
335}
336
337void SLAJ::Save_b(char* fname)
338{
339 b.Save(fname);
340}
341
342void SLAJ::Set_A(Matrica &_A)
343{
344 A.Reset(_A.GetRow(),_A.GetCol());
345 A=_A;
346}
347
348void SLAJ::Set_b(Matrica &_b)
349{
350 CHECK(_b.GetCol()==1);
351 b=_b;
352}
353
354void SLAJ::GetSolution(Matrica &X)
355{
356 static int row,i;
357 row=b.GetRow();
358 X.Reset(row,1);
359 for(i=0;i<row;i++)
360 X.data[i][0]=b.data[i][0];
361 //X=b;
362}
363
365// razred LUdek
366
367// za potrebe DASGUPTA6 promijenio sam sve oznaceno sa !!!
368
369
370LUdek::LUdek(void)
371{
372// P=NULL; !!!
373 P=new int[9];
374 for(int i=0;i<9;i++)
375 P[i]=i;
376}
377
378int LUdek::Solve(Matrica &A,Matrica &X,Matrica &b)
379{
380 Set_A(A);
381 Set_b(b);
382 Decompose();
383 ForwardSubst();
384 BackwardSubst();
385 //GetSolution(X);
386 for(int i=0;i<n;i++)
387 X.data[i][0]=b.data[P[i]][0];
388 return 1;
389}
390
391Matrica LUdek::Invert(Matrica &M)
392{
393 // rjesavamo sustav M*M!=I
394 static int i,j,dim,poc=1;
395 static Matrica R(6,6), RR(6,6), I(6,6), c(6,1);
396 //static Matrica R(3,3), RR(3,3), I(3,3), c(3,1);
397 CHECK((dim=M.GetCol()) == M.GetRow());
398// Matrica R(dim,dim), RR(dim,dim), I(dim,dim), c(dim,1); !!!
399 // I jedinicna
400 if(poc==1)
401 { for(i=0;i<dim;i++)
402 { for(j=0;j<dim;j++)
403 I.Set(i,j,0);
404 I.Set(i,i,1);
405 }
406 poc=0;
407 }
408
409 Set_A(M);
410 Decompose();
411
412 for(i=0;i<dim;i++)
413 { I.CopyColumn(i,c);
414 Set_b(c);
415 ForwardSubst();
416 BackwardSubst();
417 GetSolution(c);
418 R.SetColumn(i,c);
419 }
420
421 //vratimo retke ako je bilo pivotiranja
422 for(i=0;i<n;i++)
423 for(j=0;j<n;j++)
424 RR.data[i][j]=R.data[P[i]][j];
425
426 return RR;
427}
428
429
430int LUdek::Decompose(void)
431{
432 static int i,j,k,p;
433 n=A.GetRow();
434/* if(P!=NULL) !!!
435 delete[] P;
436 P=new int[n];
437 for(i=0;i<n;i++)
438 P[i]=i;
439*/
440
441 for(i=0;i<n-1;i++)
442 { if(pivot==1) // pivotiranje
443 { p=i;
444 for(j=i+1;j<n;j++)
445 if(ABS(A.Get(P[j],i))>ABS(A.Get(P[p],i)))
446 p=j;
447 if(A.Get(P[p],i)==0)
448 CHECK(0);
449 k=P[i];
450 P[i]=P[p];
451 P[p]=k;
452 }
453 for(j=i+1;j<n;j++)
454 { //A.Set(P[j],i,A.Get(P[j],i)/A.Get(P[i],i));
455 A.data[P[j]][i]=A.data[P[j]][i]/A.data[P[i]][i];
456 for(k=i+1;k<n;k++)
457 //A.Set(P[j],k,A.Get(P[j],k)-A.Get(P[j],i)*A.Get(P[i],k));
458 A.data[P[j]][k]-= A.data[P[j]][i]*A.data[P[i]][k];
459 }
460 }
461 return 1;
462}
463
464int LUdek::ForwardSubst(void)
465{
466 static int i,j;
467 for(i=0;i<n-1;i++)
468 for(j=i+1;j<n;j++)
469 //b.Set(P[j],0,b.Get(P[j],0)-A.Get(P[j],i)*b.Get(P[i],0));
470 b.data[P[j]][0]-= A.data[P[j]][i]*b.data[P[i]][0];
471 return 1;
472}
473
474int LUdek::BackwardSubst(void)
475{
476 static int i,j;
477 for(i=n-1;i>=0;i--)
478 { //b.Set(P[i],0,b.Get(P[i],0)/A.Get(P[i],i));
479 b.data[P[i]][0] /= A.data[P[i]][i];
480 for(j=0;j<i;j++)
481 //b.Set(P[j],0,b.Get(P[j],0)-A.Get(P[j],i)*b.Get(P[i],0));
482 b.data[P[j]][0] -= A.data[P[j]][i]*b.data[P[i]][0];
483 }
484 return 1;
485}