-
Notifications
You must be signed in to change notification settings - Fork 0
/
matrix.hpp
337 lines (299 loc) · 8.48 KB
/
matrix.hpp
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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
#pragma once
#include "nodetype.h"
#include<iostream>
#include <math.h>
using namespace std;
class vectorNode : public BasicNode
{
private:
unsigned int l;
public:
//SCMath兼容
virtual int getType() {return Vector;}
virtual void addNode(BasicNode*) {throw addSonExcep(Vector);}
virtual BasicNode* eval() {return this;}
//原生功能
double *v;
vectorNode(unsigned int l)
{
this->l = l;
this->v = new double[l];
for (unsigned int i = 0; i < l; i++)
this->v[i] = 0;
}
vectorNode(const vectorNode& m2) : BasicNode(m2)
{
this->l = m2.l;
this->v = new double[l];
for (unsigned int i = 0; i < l; i++)
this->v[i] = m2.v[i];
}
double dot(vectorNode &v2)
{
if (v2.l != this->l)
throw string("两个向量维度不对不能相乘");
else
{
double result = 0;
for (unsigned int i = 0; i < l; i++)
result += this->v[i] * v2.v[i];
return result;
}
}
vectorNode mul(double n)
{
vectorNode result(this->l);
for (unsigned int i = 0; i < l; i++)
result.v[i]=this->v[i]*n;
return result;
}
vectorNode add(vectorNode v2)
{
if(v2.l!=this->l)
throw string("两个向量维度不对不能相加");
else
{
vectorNode result(this->l);
for (unsigned int i = 0; i < l; i++)
result.v[i]=this->v[i]+v2.v[i];
return result;
}
}
void output(ostream &os)
{
for (unsigned int i = 0; i < l; i++)
{
os << v[i];
}
os << endl;
}
~vectorNode() { delete[]v; }
unsigned int getl() const { return l; }
};
class matrixNode : public BasicNode
{
private:
unsigned int r;
unsigned int c;
void malloc()
{
this->m = new double*[r]; //给第一维分配空间
for (unsigned int i = 0; i < r; i++)
this->m[i] = new double[c]; //给第二维分配空间
}
public:
//SCMath兼容
virtual int getType() {return Matrix;}
virtual void addNode(BasicNode*) {throw addSonExcep(Matrix);}
virtual BasicNode* eval() {return this;}
//原生功能
double **m;
matrixNode(unsigned int r, unsigned int c)
{
this->r = r;
this->c = c;
this->malloc();
//初始化为零矩阵
for (unsigned int i = 0; i < r; i++)
{
for (unsigned int j = 0; j < c; j++)
this->m[i][j] = 0;
}
}
matrixNode(const matrixNode& m2) : BasicNode(m2)
{
this->r = m2.r;
this->c = m2.c;
this->malloc();
for (unsigned int i = 0; i < r; i++)
{
for (unsigned int j = 0; j < c; j++)
this->m[i][j] = m2.m[i][j];
}
}
~matrixNode()
{
for (unsigned int i = 0; i < r; i++)
delete[] m[i];
delete[] m;
}
unsigned int getr() const { return r; }
unsigned int getc() const { return c; }
vectorNode getRVector(unsigned int rn)
{
vectorNode result = vectorNode(this->c);
for (unsigned int i = 0; i < this->c; i++)
result.v[i] = this->m[rn][i];
return result;
}
vectorNode getCVector(unsigned int cn)
{
vectorNode result = vectorNode(this->r);
for (unsigned int i = 0; i < this->r; i++)
result.v[i] = this->m[i][cn];
return result;
}
void setRVector(vectorNode v, unsigned int rn)
{
if(v.getl()!=this->c)
throw string("赋值的向量维度与矩阵行列长度不匹配");
else
{
for (unsigned int i = 0; i < this->c; i++)
this->m[rn][i]=v.v[i];
}
}
void setCVector(vectorNode v, unsigned int cn)
{
if(v.getl()!=this->r)
throw string("赋值的向量维度与矩阵行列长度不匹配");
else
{
for (unsigned int i = 0; i < this->r; i++)
this->m[i][cn]=v.v[i];
}
}
double algCofactor(unsigned int i,unsigned int j)
{
matrixNode mb = matrixNode(r - 1, r - 1);
for (unsigned int r = 0; r < this->r; r++)
{
for (unsigned int c = 0; c < this->c; c++)
{
if(c==j || r==i)
continue;
int subR,subC;
if (c > j)
subC = c - 1;
else
subC = c;
if(r > i)
subR = r-1;
else
subR = r;
mb.m[subR][subC] = this->m[r][c];
}
}
return pow(-1, i + j) * mb.det();
}
double det()
{
if (this->r != this->c)
throw string("只有方阵才能求行列式");
else if (this->r == 1)
return this->m[0][0];
else
{
double result = 0;
//得到从当前矩阵中划去第0行和第j列的所有元素后得到的矩阵
for (unsigned int j = 0; j < this->r; j++)
{
result += this->algCofactor(0,j) * this->m[0][j];
}
return result;
}
}
matrixNode adjoint()
{
if (this->r != this->c)
throw string("只有方阵才能求伴随矩阵");
else
{
matrixNode result = matrixNode(this->r,this->c);
for (unsigned int i = 0; i < this->r; i++)
{
for (unsigned int j = 0; j < this->c; j++)
result.m[i][j]=this->algCofactor(j,i);
}
return result;
}
}
matrixNode inv()
{
double d=this->det();
return this->adjoint().mul(1/d);
}
matrixNode dot(matrixNode &m2)
{
if (this->c != m2.r) //如果矩阵A的列数不等于矩阵B的行数……
throw string("两个矩阵的维度不能相乘");
else
{
matrixNode result = matrixNode(this->r, m2.c);
for (unsigned int i = 0; i < this->r; i++)
{
vectorNode v1 = this->getRVector(i);
for (unsigned int j = 0; j < m2.c; j++)
{
vectorNode v2 = m2.getCVector(j);
result.m[i][j] = v1.dot(v2);
}
}
return result;
}
}
matrixNode mul(double n)
{
matrixNode result(this->r,this->c);
for (unsigned int i = 0; i < this->r; i++)
for (unsigned int j = 0; j < this->c; j++)
result.m[i][j]=this->m[i][j]*n;
return result;
}
matrixNode add(matrixNode m2)
{
if(m2.c==this->c&&m2.r==this->r)
{
matrixNode result(this->r,this->c);
for (unsigned int i = 0; i < this->r; i++)
for (unsigned int j = 0; j < this->c; j++)
result.m[i][j]=this->m[i][j]+m2.m[i][j];
return result;
}
else
throw string("两个矩阵维度不对不能相加");
}
void rsub(unsigned int r1,unsigned int r2,double m)
{
vectorNode vr1=this->getRVector(r1);
vectorNode vr2=this->getRVector(r2);
vectorNode vr22=vr2.mul(-1*m);
this->setRVector(vr1.add(vr22),r1);
}
void rmul(unsigned int r,double m)
{
vectorNode vr=this->getRVector(r);
this->setRVector(vr.mul(m),r);
}
void rswap(unsigned int r1,unsigned int r2)
{
vectorNode vr1=this->getRVector(r1);
vectorNode vr2=this->getRVector(r2);
this->setRVector(vr1,r2);
this->setRVector(vr2,r1);
}
void output(ostream &os = cout)
{
for (unsigned int i = 0; i < r; i++)
{
for (unsigned int j = 0; j < c; j++)
{
os << m[i][j];
}
os << "\n\t";
}
}
static vectorNode solve(matrixNode m, vectorNode v) //克拉默法则求解
{
double D = m.det();
vectorNode result = vectorNode(v.getl());
for (unsigned int i = 0; i < v.getl(); i++) //逐行替换并计算行列式,目前替换第i列
{
matrixNode mb = matrixNode(m);
for (unsigned int j = 0; j < v.getl(); j++) //替换第i列的第j个元素
mb.m[j][i] = v.v[j];
result.v[i] = mb.det() / D;
}
return result;
}
};