NANA
matrix.cpp
浏览该文件的文档.
1
15#include "..\include\core\matrix.h"
16#include "..\include\core\safememory.hpp"
17
18#include <iostream>
19namespace NANA {
20
21Matrix::Matrix() :
22 m_rows(0),
23 m_cols(0),
24 m_step(0),
25 m_data(nullptr),
26 m_val(nullptr) {
27
28}
29
30Matrix::Matrix(int rows, int cols)
31{
32 this->create(rows, cols);
33}
34
35Matrix::Matrix(const Matrix& M) {
36 this->create(M.m_rows, M.m_cols);
37 for (int i = 0; i < M.m_rows; i++)
38 memcpy(m_val[i], M.m_val[i], M.m_cols * sizeof(NAFLOAT));
39}
40Matrix::Matrix(int m, int n, NAFLOAT const* val) {
41 this->create(m, n);
42 int32_t k = 0;
43 for (int32_t i = 0; i < m; i++)
44 for (int32_t j = 0; j < n; j++)
45 m_val[i][j] = val[k++];
46}
47
48Matrix::~Matrix()
49{
50 this->release();
51}
52
53
54int Matrix::cols() const {
55 return m_cols;
56}
57
58int Matrix::rows() const {
59 return m_rows;
60}
61
62
63Matrix Matrix::getMat(int i1, int j1, int i2, int j2 ) {
64
65 if (i2 == -1) i2 = m_rows - 1;
66 if (j2 == -1) j2 = m_cols - 1;
67 if (i1 < 0 || i2 >= m_rows || j1 < 0 || j2 >= m_cols || i2 < i1 || j2 < j1) {
68 std::cerr << "ERROR: Cannot get submatrix [" << i1 << ".." << i2 <<
69 "] x [" << j1 << ".." << j2 << "]" <<
70 " of a (" << m_rows << "x" << m_cols << ") matrix." << std::endl;
71 exit(0);
72 }
73 Matrix M(i2 - i1 + 1, j2 - j1 + 1);
74 for (int32_t i = 0; i < M.m_rows; i++)
75 for (int32_t j = 0; j < M.m_cols; j++)
76 M.m_val[i][j] = m_val[i1 + i][j1 + j];
77 return M;
78}
79
80
81void Matrix::setMat(const Matrix& M, int i1, int j1) {
82 if (i1<0 || j1<0 || i1 + M.m_rows>m_rows || j1 + M.m_cols>m_cols) {
83 std::cerr << "ERROR: Cannot set submatrix [" << i1 << ".." << i1 + M.m_rows - 1 <<
84 "] x [" << j1 << ".." << j1 + M.m_cols - 1 << "]" <<
85 " of a (" << m_rows << "x" << m_cols << ") matrix." << std::endl;
86 exit(0);
87 }
88 for (int32_t i = 0; i < M.m_rows; i++)
89 for (int32_t j = 0; j < M.m_cols; j++)
90 m_val[i1 + i][j1 + j] = M.m_val[i][j];
91}
92
93void Matrix::setMatrixEye(Matrix& mat, const int m) {
94 mat.release();
95 mat.create(m, m);
96 mat.fill(0.0);
97 for (int i = 0; i < m; i++)
98 mat.m_val[i][i] = 1.0;
99}
100
101
102
103void Matrix::LU(const Matrix& A, Matrix& L, Matrix& U) {
104 int rows = A.rows();
105 int cols = A.cols();
106 NA_Assert(rows == cols);
107 Matrix Q = A;
108 L.release();
109 L.create(rows, cols);
110 U.release();
111 U.create(rows, cols);
112 NAFLOAT** q = Q.getValPtr();
113 NAFLOAT** l = L.getValPtr();
114 NAFLOAT** u = U.getValPtr();
115
116 int i, j, k;
117 for (k = 0; k < rows - 1; ++k) {
118 NA_Assert(std::fabs(q[k][k]) > NA_EPS);
119 for (i = k + 1; i < rows; ++i) {
120 q[i][k] /= q[k][k];
121 for (j = k + 1; j < cols; ++j) {
122 q[i][j] -= (q[i][k] * q[k][j]);
123 }
124
125 }
126 }
127
128 for (i = 0; i < rows; ++i) {
129 for (j = 0; j < i; ++j) {
130 l[i][j] = q[i][j];
131 u[i][j] = 0.0;
132 }
133 l[i][i] = 1.0;
134 u[i][i] = q[i][i];
135 for (j = i + 1; j < cols; ++j) {
136 l[i][j] = 0.0;
137 u[i][j] = q[i][j];
138 }
139 }
140}
141
142void Matrix::QR(const Matrix& A, Matrix& Q, Matrix& R) {
143 int rows = A.rows();
144 int cols = A.cols();
145 R = A;
146 NA_Assert(rows >= cols);
147 setMatrixEye(Q, rows);
148 int ncols, i, j, k;
149 if (rows == cols)
150 ncols = rows - 1;
151 else
152 ncols = cols;
153 double u, alpha, w, t;
154 NAFLOAT** a = R.getValPtr();
155 NAFLOAT** q = Q.getValPtr();
156 for (k = 0; k < ncols; ++k) {
157 u = 0.0;
158 for (i = k; i < rows; ++i) {
159 w = std::fabs(a[i][k]);
160 if (w > u)
161 u = w;
162 }
163 NA_Assert(u >= NA_EPS);
164 alpha = 0.0;
165 for (i = k; i < rows; ++i) {
166 t = a[i][k] / u;
167 alpha += (t * t);
168 }
169 if (a[k][k] > 0.0)
170 u = -u;
171 alpha = u * std::sqrtf(alpha);
172 NA_Assert(std::fabs(alpha) >= NA_EPS);
173 u = std::sqrtf(2.0 * alpha * (alpha - a[k][k]));
174 NA_Assert(!isNan(u));
175 a[k][k] = (a[k][k] - alpha) / u;
176
177 for (i = k + 1; i < rows; ++i)
178 a[i][k] /= u;
179
180 for (j = 0; j < rows; ++j) {
181 t = 0.0;
182 for (i = k; i < rows; ++i)
183 t += a[i][k] * q[i][j];
184 for (i = k; i < rows; ++i)
185 q[i][j] -= 2.0 * t * a[i][k];
186 }
187 for (j = k + 1; j < cols; ++j) {
188 t = 0.0;
189 for (i = k; i < rows; ++i)
190 t += a[i][k] * a[i][j];
191 for (i = k; i < rows; ++i)
192 a[i][j] -= 2.0 * t * a[i][k];
193 }
194 a[k][k] = alpha;
195 for (i = k + 1; i < rows; ++i)
196 a[i][k] = 0.0;
197 }
198 for (i = 0; i < ncols; ++i) {
199 for (j = i + 1; j < rows; ++j) {
200 t = q[i][j];
201 q[i][j] = q[j][i];
202 q[j][i] = t;
203 }
204 }
205}
206
207static NAFLOAT SIGN(NAFLOAT a, NAFLOAT b) {
208 if (b >= 0.0)
209 return std::fabs(a);
210 return -std::fabs(a);
211}
212
213static NAFLOAT SQR(NAFLOAT a) {
214 if (a == 0.0)
215 return 0.0;
216 return a * a;
217}
218
219NAFLOAT pythag(NAFLOAT a, NAFLOAT b) {
220 NAFLOAT absa, absb;
221 absa = fabs(a);
222 absb = fabs(b);
223 if (absa > absb)
224 return absa * std::sqrt(1.0 + SQR(absb / absa));
225 else
226 return (absb == 0.0 ? 0.0 : absb * sqrt(1.0 + SQR(absa / absb)));
227}
228
236void Matrix::SVD( const Matrix & A, Matrix& U2, Matrix& W, Matrix& V) {
237 Matrix U = A;
238 int m = A.rows();
239 int n = A.cols();
240 U2 = Matrix(m, m);
241 V = Matrix(n, n);
242
243 NAFLOAT* w = (NAFLOAT*)malloc(n * sizeof(NAFLOAT));
244 NAFLOAT* rv1 = (NAFLOAT*)malloc(n * sizeof(NAFLOAT));
245
246 int32_t flag, i, its, j, jj, k, l, nm;
247 NAFLOAT anorm, c, f, g, h, s, scale, x, y, z;
248
249 g = scale = anorm = 0.0;
250 for (i = 0; i < n; i++) {
251 l = i + 1;
252 rv1[i] = scale * g;
253 g = s = scale = 0.0;
254 if (i < m) {
255 for (k = i; k < m; k++) scale += fabs(U.m_val[k][i]);
256 if (scale) {
257 for (k = i; k < m; k++) {
258 U.m_val[k][i] /= scale;
259 s += U.m_val[k][i] * U.m_val[k][i];
260 }
261 f = U.m_val[i][i];
262 g = -SIGN(sqrt(s), f);
263 h = f * g - s;
264 U.m_val[i][i] = f - g;
265 for (j = l; j < n; j++) {
266 for (s = 0.0, k = i; k < m; k++) s += U.m_val[k][i] * U.m_val[k][j];
267 f = s / h;
268 for (k = i; k < m; k++) U.m_val[k][j] += f * U.m_val[k][i];
269 }
270 for (k = i; k < m; k++) U.m_val[k][i] *= scale;
271 }
272 }
273 w[i] = scale * g;
274 g = s = scale = 0.0;
275 if (i < m && i != n - 1) {
276 for (k = l; k < n; k++) scale += fabs(U.m_val[i][k]);
277 if (scale) {
278 for (k = l; k < n; k++) {
279 U.m_val[i][k] /= scale;
280 s += U.m_val[i][k] * U.m_val[i][k];
281 }
282 f = U.m_val[i][l];
283 g = -SIGN(sqrt(s), f);
284 h = f * g - s;
285 U.m_val[i][l] = f - g;
286 for (k = l; k < n; k++) rv1[k] = U.m_val[i][k] / h;
287 for (j = l; j < m; j++) {
288 for (s = 0.0, k = l; k < n; k++) s += U.m_val[j][k] * U.m_val[i][k];
289 for (k = l; k < n; k++) U.m_val[j][k] += s * rv1[k];
290 }
291 for (k = l; k < n; k++) U.m_val[i][k] *= scale;
292 }
293 }
294 anorm = std::max(anorm, (std::fabs(w[i]) + std::fabs(rv1[i])));
295 }
296 for (i = n - 1; i >= 0; i--) { // Accumulation of right-hand transformations.
297 if (i < n - 1) {
298 if (g) {
299 for (j = l; j < n; j++) // Double division to avoid possible underflow.
300 V.m_val[j][i] = (U.m_val[i][j] / U.m_val[i][l]) / g;
301 for (j = l; j < n; j++) {
302 for (s = 0.0, k = l; k < n; k++) s += U.m_val[i][k] * V.m_val[k][j];
303 for (k = l; k < n; k++) V.m_val[k][j] += s * V.m_val[k][i];
304 }
305 }
306 for (j = l; j < n; j++) V.m_val[i][j] = V.m_val[j][i] = 0.0;
307 }
308 V.m_val[i][i] = 1.0;
309 g = rv1[i];
310 l = i;
311 }
312 for (i = std::min(m, n) - 1; i >= 0; --i) { // Accumulation of left-hand transformations.
313 l = i + 1;
314 g = w[i];
315 for (j = l; j < n; j++) U.m_val[i][j] = 0.0;
316 if (g) {
317 g = 1.0 / g;
318 for (j = l; j < n; j++) {
319 for (s = 0.0, k = l; k < m; k++) s += U.m_val[k][i] * U.m_val[k][j];
320 f = (s / U.m_val[i][i]) * g;
321 for (k = i; k < m; k++) U.m_val[k][j] += f * U.m_val[k][i];
322 }
323 for (j = i; j < m; j++) U.m_val[j][i] *= g;
324 }
325 else for (j = i; j < m; j++) U.m_val[j][i] = 0.0;
326 ++U.m_val[i][i];
327 }
328 for (k = n - 1; k >= 0; k--) { // Diagonalization of the bidiagonal form: Loop over singular values,
329 for (its = 0; its < 30; its++) { // and over allowed iterations.
330 flag = 1;
331 for (l = k; l >= 0; l--) { // Test for splitting.
332 nm = l - 1;
333 if ((NAFLOAT)(fabs(rv1[l]) + anorm) == anorm) { flag = 0; break; }
334 if ((NAFLOAT)(fabs(w[nm]) + anorm) == anorm) { break; }
335 }
336 if (flag) {
337 c = 0.0; // Cancellation of rv1[l], if l > 1.
338 s = 1.0;
339 for (i = l; i <= k; i++) {
340 f = s * rv1[i];
341 rv1[i] = c * rv1[i];
342 if ((NAFLOAT)(fabs(f) + anorm) == anorm) break;
343 g = w[i];
344 h = pythag(f, g);
345 w[i] = h;
346 h = 1.0 / h;
347 c = g * h;
348 s = -f * h;
349 for (j = 0; j < m; j++) {
350 y = U.m_val[j][nm];
351 z = U.m_val[j][i];
352 U.m_val[j][nm] = y * c + z * s;
353 U.m_val[j][i] = z * c - y * s;
354 }
355 }
356 }
357 z = w[k];
358 if (l == k) { // Convergence.
359 if (z < 0.0) { // Singular value is made nonnegative.
360 w[k] = -z;
361 for (j = 0; j < n; j++) V.m_val[j][k] = -V.m_val[j][k];
362 }
363 break;
364 }
365
366 NA_Assert(its != 29,"ERROR in SVD: No convergence in 30 iterations");
367 x = w[l]; // Shift from bottom 2-by-2 minor.
368 nm = k - 1;
369 y = w[nm];
370 g = rv1[nm];
371 h = rv1[k];
372 f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y);
373 g = pythag(f, 1.0);
374 f = ((x - z) * (x + z) + h * ((y / (f + SIGN(g, f))) - h)) / x;
375 c = s = 1.0; // Next QR transformation:
376 for (j = l; j <= nm; j++) {
377 i = j + 1;
378 g = rv1[i];
379 y = w[i];
380 h = s * g;
381 g = c * g;
382 z = pythag(f, h);
383 rv1[j] = z;
384 c = f / z;
385 s = h / z;
386 f = x * c + g * s;
387 g = g * c - x * s;
388 h = y * s;
389 y *= c;
390 for (jj = 0; jj < n; jj++) {
391 x = V.m_val[jj][j];
392 z = V.m_val[jj][i];
393 V.m_val[jj][j] = x * c + z * s;
394 V.m_val[jj][i] = z * c - x * s;
395 }
396 z = pythag(f, h);
397 w[j] = z; // Rotation can be arbitrary if z = 0.
398 if (z) {
399 z = 1.0 / z;
400 c = f * z;
401 s = h * z;
402 }
403 f = c * g + s * y;
404 x = c * y - s * g;
405 for (jj = 0; jj < m; jj++) {
406 y = U.m_val[jj][j];
407 z = U.m_val[jj][i];
408 U.m_val[jj][j] = y * c + z * s;
409 U.m_val[jj][i] = z * c - y * s;
410 }
411 }
412 rv1[l] = 0.0;
413 rv1[k] = f;
414 w[k] = x;
415 }
416 }
417
418 // sort singular values and corresponding columns of u and v
419 // by decreasing magnitude. Also, signs of corresponding columns are
420 // flipped so as to maximize the number of positive elements.
421 int32_t s2, inc = 1;
422 NAFLOAT sw;
423 NAFLOAT* su = (NAFLOAT*)malloc(m * sizeof(NAFLOAT));
424 NAFLOAT* sv = (NAFLOAT*)malloc(n * sizeof(NAFLOAT));
425 do { inc *= 3; inc++; } while (inc <= n);
426 do {
427 inc /= 3;
428 for (i = inc; i < n; i++) {
429 sw = w[i];
430 for (k = 0; k < m; k++) su[k] = U.m_val[k][i];
431 for (k = 0; k < n; k++) sv[k] = V.m_val[k][i];
432 j = i;
433 while (w[j - inc] < sw) {
434 w[j] = w[j - inc];
435 for (k = 0; k < m; k++) U.m_val[k][j] = U.m_val[k][j - inc];
436 for (k = 0; k < n; k++) V.m_val[k][j] = V.m_val[k][j - inc];
437 j -= inc;
438 if (j < inc) break;
439 }
440 w[j] = sw;
441 for (k = 0; k < m; k++) U.m_val[k][j] = su[k];
442 for (k = 0; k < n; k++) V.m_val[k][j] = sv[k];
443 }
444 } while (inc > 1);
445 for (k = 0; k < n; k++) { // flip signs
446 s2 = 0;
447 for (i = 0; i < m; i++) if (U.m_val[i][k] < 0.0) s2++;
448 for (j = 0; j < n; j++) if (V.m_val[j][k] < 0.0) s2++;
449 if (s2 > (m + n) / 2) {
450 for (i = 0; i < m; i++) U.m_val[i][k] = -U.m_val[i][k];
451 for (j = 0; j < n; j++) V.m_val[j][k] = -V.m_val[j][k];
452 }
453 }
454
455 // create vector and copy singular values
456 W = Matrix(std::min(m, n), 1, w);
457
458 // extract mxm submatrix U
459 U2.setMat(U.getMat(0, 0, m - 1, std::min(m - 1, n - 1)), 0, 0);
460
461 // release temporary memory
462 free(w);
463 free(rv1);
464 free(su);
465 free(sv);
466}
467
468
469
470
471void Matrix::solve(const Matrix& A, const Matrix& b, Matrix& x, int flag) {
472 if (DecompositionMethod::GaussiaJordan == flag) {
473 x = A.inv(DecompositionMethod::GaussiaJordan) * b;
474 }
475}
476
477Matrix Matrix::zeros(int rows, int cols) {
478 Matrix mat(rows, cols);
479 mat.fill(0.0);
480 return mat;
481}
482
483void Matrix::create(int rows, int cols)
484{
485#ifdef NANA_DEBUG
486 std::cout << "内存申请\n";
487#endif
488 m_rows = rows;
489 m_cols = cols;
490 int temp = m_cols % 32;
491 if (0 == temp)
492 m_step = m_cols;
493 else
494 m_step = m_cols + 32 - temp;
495 size_t nSize = static_cast<size_t> (m_rows) * m_step;
496 m_data = new NAFLOAT[nSize];
497 m_val = new NAFLOAT * [m_rows];
498 m_val[0] = m_data;
499 for (int i = 1; i < m_rows; i++)
500 m_val[i] = m_val[i - 1] + m_step;
501}
502
503void Matrix::release()
504{
505#ifdef NANA_DEBUG
506 std::cout << "内存释放\n";
507#endif
508 deleteArraySafe(m_data);
509 deleteArraySafe(m_val);
510 m_rows = m_cols = 0;
511}
512
513void Matrix::fill(const NAFLOAT& value)
514{
515 int i;
516 for (i = 0; i < m_cols; ++i) {
517 m_val[0][i] = value;
518 }
519 size_t nLen = static_cast<size_t>(m_cols * sizeof(NAFLOAT));
520 for (i = 1; i < m_rows; ++i) {
521 memcpy(m_val[i], m_val[i - 1], nLen);
522 }
523
524}
525
526NAFLOAT** Matrix::getValPtr() const
527{
528 return m_val;
529}
530
531const NAFLOAT** Matrix::getConstValPtr() const {
532 return const_cast<const NAFLOAT**>(m_val);
533}
534
535Matrix Matrix::T() const {
536 Matrix C(m_cols, m_rows);
537 for (int i = 0; i < m_rows; i++)
538 for (int32_t j = 0; j < m_cols; j++)
539 C.m_val[j][i] = m_val[i][j];
540 return C;
541}
542
543Matrix& Matrix::operator=(const Matrix& M)
544{
545 if (this != &M) {
546 if (M.m_cols != m_cols || M.m_rows != m_rows) {
547 this->release();
548 this->create(M.m_rows, M.m_cols);
549 }
550 if (M.m_cols > 0)
551 for (int i = 0; i < M.m_rows; i++)
552 memcpy(m_val[i], M.m_val[i], m_step * sizeof(NAFLOAT));
553 }
554 return *this;
555}
556
557
558const NAFLOAT* Matrix::operator[](int row) const {
559 return const_cast<const NAFLOAT*>(m_val[row]);
560}
561
562Matrix Matrix::operator+ (const Matrix& B) {
563 Matrix& A = *this;
564 NA_Assert(A.m_cols == B.m_cols || A.m_rows == B.m_rows);
565
566 Matrix C(A.m_rows, A.m_cols);
567 for (int i = 0; i < m_rows; i++)
568 for (int j = 0; j < m_cols; j++)
569 C.m_val[i][j] = A.m_val[i][j] + B.m_val[i][j];
570 return C;
571}
572
573
574Matrix Matrix::operator-(const Matrix& B) {
575 Matrix& A = *this;
576 NA_Assert(A.m_cols == B.m_cols || A.m_rows == B.m_rows);
577
578 Matrix C(A.m_rows, A.m_cols);
579 for (int i = 0; i < m_rows; i++)
580 for (int j = 0; j < m_cols; j++)
581 C.m_val[i][j] = A.m_val[i][j] - B.m_val[i][j];
582 return C;
583}
584
585
586Matrix Matrix::operator*(const Matrix& B) {
587 Matrix& A = *this;
588 NA_Assert(A.m_cols == B.m_rows);
589
590 Matrix C(A.m_rows, B.m_cols);
591 C.fill(0.0);
592 for (int i = 0; i < A.m_rows; i++)
593 for (int j = 0; j < B.m_cols; j++)
594 for (int k = 0; k < A.m_cols; k++)
595 C.m_val[i][j] += A.m_val[i][k] * B.m_val[k][j];
596 return C;
597}
598
599Matrix Matrix::dot(const Matrix& B) const {
600
601 NA_Assert((m_cols == B.m_cols) && (m_rows == B.m_rows));
602
603 Matrix C(m_rows, m_cols);
604 for (int i = 0; i < m_rows; i++)
605 for (int j = 0; j < m_cols; j++)
606 C.m_val[i][j] = m_val[i][j] * B.m_val[i][j];
607 return C;
608}
609
610Matrix Matrix::dot(NAFLOAT b) const {
611 Matrix C(m_rows, m_cols);
612 for (int i = 0; i < m_rows; i++)
613 for (int j = 0; j < m_cols; j++)
614 C.m_val[i][j] = m_val[i][j] * b;
615 return C;
616}
617
624static int GaussiaJordanInv(const Matrix& src, Matrix& dst) {
625 int rows = src.rows();
626 int cols = src.cols();
627 NA_Assert(rows == cols);
629 dst = src;
630 int i, j, k, temp;
631 NAFLOAT** data = dst.getValPtr();
632
633 std::vector<int> is(rows);
634 std::vector<int> js(cols);
636 double d, p;
637 for (k = 0; k < rows; ++k) {
638 d = 0.0;
639 for (i = k; i < rows; ++i) {
640 for (j = k; j < cols; ++j) {
641 p = std::fabs(data[i][j]);
642 if (p > d) {
643 d = p;
644 is[k] = i;
645 js[k] = j;
646 }
647 }
648 }
649 NA_Assert(d >= NA_EPS);
650 temp = is[k];
651 if (temp != k) {
652 for (j = 0; j < cols; ++j) {
653 p = data[k][j];
654 data[k][j] = data[temp][j];
655 data[temp][j] = p;
656 }
657 }
658 temp = js[k];
659 if (temp != k) {
660 for (i = 0; i < rows; ++i) {
661 p = data[i][k];
662 data[i][k] = data[i][temp];
663 data[i][temp] = p;
664 }
665 }
667 data[k][k] = 1.0 / data[k][k];
668
669 for (j = 0; j < cols; ++j) {
670 if (k == j)
671 continue;
672 data[k][j] *= data[k][k];
673 }
675 for (i = 0; i < rows; ++i) {
676 if (i == k)
677 continue;
678 for (j = 0; j < cols; ++j) {
679 if (j == k)
680 continue;
681 data[i][j] -= data[i][k] * data[k][j];
682 }
683 }
684 for (i = 0; i < rows; ++i) {
685 if (i == k)
686 continue;
687 data[i][k] *= (-data[k][k]);
688 }
689 }
690
691
692 for (k = rows - 1; k >= 0; --k) {
693 temp = js[k];
694 if (k != temp) {
695 for (j = 0; j < cols; ++j) {
696 p = data[k][j];
697 data[k][j] = data[temp][j];
698 data[temp][j] = p;
699 }
700 }
701 temp = is[k];
702 if (k != temp) {
703 for (i = 0; i < rows; ++i) {
704 p = data[i][k];
705 data[i][k] = data[i][temp];
706 data[i][temp] = p;
707 }
708 }
709 }
710
711
712 return RET_OK;
713}
714
715
716Matrix Matrix::inv(int flag) const {
717 Matrix invMat;
718 if (GaussiaJordan == flag) {
719 GaussiaJordanInv(*this, invMat);
720 }
721
722
723 return invMat;
724}
725
726NAFLOAT Matrix::det() const {
728 NA_Assert(m_rows == m_cols);
729 double f, detVal, q, d;
730 int i, j, k, is, js;
731 int n = m_rows;
732 f = 1.0;
733 detVal = 1.0;
734 Matrix A = *this;
735 double** a = A.getValPtr();
736 for (k = 0; k < n - 1; ++k) {
737 q = 0.0;
738 for (i = k; i < n; ++i) {
739 for (j = k; j < n; ++j) {
740 d = std::fabs(a[i][j]);
741 if (d > q) {
742 q = d;
743 is = i;
744 js = j;
745 }
746 }
747 }
748
749 if (q < NA_EPS) {
750 return 0.0;
751 }
752 if (is != k) {
753 f = -f;
754 for (j = k; j < n; ++j) {
755 d = a[k][j];
756 a[k][j] = a[is][j];
757 a[is][j] = d;
758 }
759 }
760
761 if (js != k) {
762 f = -f;
763 for (i = k; i < n; ++i) {
764 d = a[i][js];
765 a[i][js] = a[i][k];
766 a[i][k] = d;
767 }
768 }
769
770 detVal *= a[k][k];
771 for (i = k + 1; i < n; ++i) {
772 d = a[i][k] / a[k][k];
773 for (j = k + 1; j < n; ++j) {
774 a[i][j] -= d * a[k][j];
775 }
776 }
777 }
778 detVal *= f * a[n - 1][n - 1];
779 return detVal;
780}
781
782
783int Matrix::rank() const {
784 int i, j, k, nn, is, js, cycle;
785 double q, d;
787 Matrix A = *this;
788 double** a = A.getValPtr();
789 nn = std::min(m_rows, m_cols);
790 k = 0;
791 for (cycle = 0; cycle < nn; ++cycle) {
792 q = 0.0;
793 for (i = 1; i < m_rows; ++i) {
794 for (j = 1; j < m_cols; ++j) {
795 d = std::fabs(a[i][j]);
796 if (d > q) {
797 q = d;
798 is = i;
799 js = j;
800 }
801 }
802 }
803
804 if (q < NA_EPS)
805 return k;
806
807 ++k;
808 if (is != cycle) {
809 for (j = 1; j < m_cols; ++j) {
810 d = a[cycle][j];
811 a[cycle][j] = a[is][j];
812 a[is][j] = d;
813 }
814 }
815 if (js != cycle) {
816 for (i = 1; i < m_rows; ++i) {
817 d = a[i][js];
818 a[i][js] = a[i][cycle];
819 a[i][cycle] = d;
820 }
821 }
822 for (i = cycle + 1; i < m_rows; ++i) {
823 d = a[i][cycle] / a[cycle][cycle];
824 for (j = cycle + 1; j < m_cols; ++j) {
825 a[i][j] -= d * a[cycle][j];
826 }
827 }
828
829
830 }
831
832 return k;
833
834}
835
836std::istream& operator>>(std::istream& is, Matrix& m)
837{
838 NAFLOAT** val = m.getValPtr();
839 for (int i = 0; i < m.rows(); i++) {
840 for (int j = 0; j < m.cols(); j++) {
841 is >> val[i][j];
842 }
843 }
844 return is;
845}
846
847std::ostream& operator<< (std::ostream& out, const Matrix& M){
848 if (M.m_cols == 0 || M.m_rows == 0) {
849 out << "[empty matrix]";
850 }
851 else {
852 char buffer[1024];
853 for (int i = 0; i < M.m_rows; i++) {
854 for (int j = 0; j < M.m_cols; j++) {
855 sprintf_s(buffer, "%12.7f ", M.m_val[i][j]);
856 out << buffer;
857 }
858 out << std::endl;
859 }
860 }
861 return out;
862}
863
864
865
866
867
868
869
870
872CMatrix::CMatrix() {
873 m_redata = nullptr;
874 m_imdata = nullptr;
875 m_reval = nullptr;
876 m_imval = nullptr;
877 m_rows = 0;
878 m_cols = 0;
879}
880
881CMatrix::~CMatrix() {
882 this->release();
883}
884
885void CMatrix::create(int rows, int cols) {
886 m_rows = rows;
887 m_cols = cols;
888 int temp = m_cols % 32;
889 if (0 == temp)
890 m_step = m_cols;
891 else
892 m_step = m_cols + 32 - temp;
893 size_t nSize = static_cast<size_t> (m_rows) * m_step;
895 m_redata = new NAFLOAT[nSize];
896 m_reval = new NAFLOAT * [m_rows];
897 m_reval[0] = m_redata;
898 for (int i = 1; i < m_rows; i++)
899 m_reval[i] = m_reval[i - 1] + m_step;
900 m_imdata = new NAFLOAT[nSize];
901 m_imval = new NAFLOAT * [m_rows];
902 m_imval[0] = m_imdata;
903 for (int i = 1; i < m_rows; i++)
904 m_imval[i] = m_imval[i - 1] + m_step;
905}
906
907
908
913void CMatrix::release() {
914 deleteArraySafe(m_redata);
915 deleteArraySafe(m_reval);
916 deleteArraySafe(m_imdata);
917 deleteArraySafe(m_imval);
918 m_rows = m_cols = 0;
919}
920
921
922
923
924}
简单矩阵类
Definition: matrix.h:31
NAFLOAT ** m_val
矩阵的数据
Definition: matrix.h:286
int m_rows
行数
Definition: matrix.h:290
Matrix getMat(int i1, int j1, int i2=-1, int j2=-1)
获取当前矩阵的子矩阵
Definition: matrix.cpp:63
int m_cols
列数
Definition: matrix.h:292
int rows() const
获取矩阵的行数
Definition: matrix.cpp:58
int cols() const
获取矩阵的列数
Definition: matrix.cpp:54
void create(int rows, int cols)
申请内存
Definition: matrix.cpp:483
Matrix inv(int flag=GaussiaJordan) const
实现矩阵的求逆
Definition: matrix.cpp:716
void setMat(const Matrix &M, int i, int j)
设置当前矩阵
Definition: matrix.cpp:81
NAFLOAT ** getValPtr() const
获取值的指针
Definition: matrix.cpp:526
void fill(const NAFLOAT &value)
用value填充Matrix的全部内容
Definition: matrix.cpp:513
void release()
释放已申请的内存
Definition: matrix.cpp:503
@ RET_OK
0表示返回值正常
Definition: core_global.h:36
#define NA_Assert(expr)
当表达式非法,抛出异常
Definition: error.h:56
std::istream & operator>>(std::istream &is, Matrix &m)
Definition: matrix.cpp:836
#define NA_EPS
定义一个极小的正数 smallest such that 1.0+DBL_EPSILON != 1.0
Definition: nadef.hpp:40
bool isNan(_Tp x)
判断一个数是否是Not a number
Definition: nadef.hpp:89
void deleteArraySafe(_T *&p)
deleteArraySafe 安全释放 xxx * a = new xxx[num];申请的内存
Definition: safememory.hpp:55