sokobo
Loading...
Searching...
No Matches
matrix.cpp
1#include <algorithm>
2#include <cmath>
3#include <cstdlib>
4#include <iostream>
5#include <sstream>
6#include <stdexcept>
7#include <string>
8#include <type_traits>
9#include <utility>
10#include <vector>
11
12#include "include/matrix.h"
13
14#include "include/complex_number.h"
15
42template<typename T>
43auto safe_sqrt(T value) ->
44 typename std::conditional_t<std::is_arithmetic_v<T>, T, double>
45{
46 if constexpr (std::is_floating_point_v<T>) {
47 return std::sqrt(value);
48 } else if constexpr (std::is_arithmetic_v<T>) {
49 return static_cast<T>(std::sqrt(static_cast<double>(value)));
50 } else {
51 // For complex types, return the square root of the magnitude as double
52 return std::sqrt(value.magnitude());
53 }
54}
55
85template<typename T>
86auto safe_abs(T value) ->
87 typename std::conditional_t<std::is_arithmetic_v<T>, T, double>
88{
89 if constexpr (std::is_floating_point_v<T>) {
90 return std::abs(value);
91 } else if constexpr (std::is_arithmetic_v<T>) {
92 return static_cast<T>(std::abs(static_cast<double>(value)));
93 } else {
94 // For complex types, return the absolute value of the magnitude as double
95 return std::abs(value.magnitude());
96 }
97}
98
99template<typename T>
100double getAbsoluteValue(const T& value)
101{
102 if constexpr (std::is_arithmetic_v<T>) {
103 // For built-in numeric types
104 return std::abs(static_cast<double>(value));
105 } else {
106 // For custom types like ComplexNumber
107 return value
108 .magnitude(); // or value.abs() depending on your implementation
109 }
110}
111
112template<typename T>
113Matrix<T>::Matrix(const std::vector<std::vector<T>>& mat)
114{
115 if (mat.empty() || mat[0].empty()) {
116 throw std::invalid_argument("Matrix cannot be empty");
117 }
118
119 rows = mat.size();
120 cols = mat[0].size();
121
122 // Check that all rows have the same number of columns
123 for (const auto& row : mat) {
124 if (row.size() != cols) {
125 throw std::invalid_argument(
126 "All matrix rows must have the same number of columns");
127 }
128 }
129
130 data = mat;
131}
132
133template<typename T>
134T& Matrix<T>::operator()(int row, int column)
135{
136 if (row < 0 || row >= rows || column < 0 || column >= cols) {
137 throw std::out_of_range(
138 std::string("Matrix index out of bounds\n") + "[row]: "
139 + std::to_string(row) + " [col]: " + std::to_string(column) + "\n"
140 + "[dimension]: " + std::to_string(rows) + "x" + std::to_string(cols));
141 }
142 return data[row][column];
143}
144
145template<typename T>
146const T& Matrix<T>::operator()(int row, int column) const
147{
148 if (row < 0 || row >= rows || column < 0 || column >= cols) {
149 throw std::out_of_range(
150 std::string("Matrix index out of bounds\n") + "[row]: "
151 + std::to_string(row) + " [col]: " + std::to_string(column) + "\n"
152 + "[dimension]: " + std::to_string(rows) + "x" + std::to_string(cols));
153 }
154 return data[row][column];
155}
156
157template<typename T>
159{
160 if (rows != other.rows || cols != other.cols) {
161 throw std::invalid_argument("Matrix dimensions must match for addition");
162 }
163
164 Matrix<T> result(rows, cols);
165 for (int i = 0; i < rows; ++i) {
166 for (int j = 0; j < cols; ++j) {
167 result(i, j) = data[i][j] + other(i, j);
168 }
169 }
170 return result;
171}
172
173template<typename T>
175{
176 if (rows != other.rows || cols != other.cols) {
177 throw std::invalid_argument("Matrix dimensions must match for subtraction");
178 }
179
180 Matrix<T> result(rows, cols);
181 for (int i = 0; i < rows; ++i) {
182 for (int j = 0; j < cols; ++j) {
183 result(i, j) = data[i][j] - other(i, j);
184 }
185 }
186 return result;
187}
188
189template<typename T>
191{
192 if (cols != other.rows) {
193 throw std::invalid_argument(
194 "Matrix dimensions incompatible for multiplication");
195 }
196
197 Matrix<T> result(rows, other.cols);
198 for (int i = 0; i < rows; ++i) {
199 for (int j = 0; j < other.cols; ++j) {
200 T sum = T {};
201 for (int k = 0; k < cols; ++k) {
202 sum += data[i][k] * other(k, j);
203 }
204 result(i, j) = sum;
205 }
206 }
207 return result;
208}
209
210template<typename T>
211Matrix<T> Matrix<T>::operator*(const T& scalar) const
212{
213 Matrix<T> result(rows, cols);
214 for (int i = 0; i < rows; ++i) {
215 for (int j = 0; j < cols; ++j) {
216 result(i, j) = data[i][j] * scalar;
217 }
218 }
219 return result;
220}
221
222template<typename T>
224{
225 std::vector<std::vector<T>> matrix = data;
226 int n = matrix.size();
227 int m = matrix[0].size();
228 const double EPS = 1E-9;
229 int rank = 0;
230 std::vector<bool> row_selected(n, false);
231
232 for (int i = 0; i < m; ++i) {
233 int j;
234 for (j = 0; j < n; ++j) {
235 if (!row_selected[j] && abs(matrix[j][i]) > EPS) {
236 break;
237 }
238 }
239 if (j != n) {
240 ++rank;
241 row_selected[j] = true;
242 for (int p = i + 1; p < m; ++p) {
243 matrix[j][p] /= matrix[j][i];
244 }
245 for (int k = 0; k < n; ++k) {
246 if (k != j && abs(matrix[k][i]) > EPS) {
247 for (int p = i + 1; p < m; ++p) {
248 matrix[k][p] -= (matrix[j][p] * matrix[k][i]);
249 }
250 }
251 }
252 }
253 }
254 return rank;
255}
256
257template<typename T>
259{
260 if (getRows() != getCols()) {
261 return false;
262 }
263
264 int rows = getRows();
265 for (int i = 0; i < rows; i++) {
266 for (int j = 0; j < i; j++) {
267 if (data[i][j] != data[j][i]) {
268 return false;
269 }
270 }
271 }
272 return true;
273}
274
275template<typename T>
277{
278 if (rows != cols) {
279 throw std::invalid_argument(
280 "Determinant is only defined for square matrices");
281 }
282
283 if (rows == 1) {
284 return data[0][0];
285 }
286
287 if (rows == 2) {
288 return data[0][0] * data[1][1] - data[0][1] * data[1][0];
289 }
290
291 // Use LU decomposition for larger matrices
292 auto [L, U] = LUDecomposition();
293
294 T det = T {1};
295 for (int i = 0; i < rows; ++i) {
296 det *= U(i, i);
297 }
298
299 return det;
300}
301
302template<typename T>
304{
305 if (rows != cols) {
306 throw std::invalid_argument("Inverse is only defined for square matrices");
307 }
308
309 T det = determinant();
310 if (safe_abs(det) < 1e-12) {
311 throw std::runtime_error("Matrix is singular (determinant is zero)");
312 }
313
314 if (rows == 1) {
315 Matrix<T> result(1, 1);
316 result[0][0] = T {1} / data[0][0];
317 return result;
318 }
319
320 if (rows == 2) {
321 Matrix<T> result(2, 2);
322 T invDet = T {1} / det;
323 result(0, 0) = data[1][1] * invDet;
324 result(0, 1) = -data[0][1] * invDet;
325 result(1, 0) = -data[1][0] * invDet;
326 result(1, 1) = data[0][0] * invDet;
327 return result;
328 }
329
330 // Gauss-Jordan elimination for larger matrices
331 Matrix<T> augmented(rows, 2 * cols);
332
333 // Create augmented matrix [A|I]
334 for (int i = 0; i < rows; ++i) {
335 for (int j = 0; j < cols; ++j) {
336 augmented(i, j) = data[i][j];
337 augmented(i, j + cols) = (i == j) ? T {1} : T {};
338 }
339 }
340
341 // Forward elimination
342 for (int i = 0; i < rows; ++i) {
343 // Find pivot
344 int maxRow = i;
345 for (int k = i + 1; k < rows; ++k) {
346 if (safe_abs(augmented(k, i)) > safe_abs(augmented(maxRow, i))) {
347 maxRow = k;
348 }
349 }
350
351 // Swap rows
352 if (maxRow != i) {
353 for (int j = 0; j < 2 * cols; ++j) {
354 std::swap(augmented(i, j), augmented(maxRow, j));
355 }
356 }
357
358 // Scale pivot row
359 T pivot = augmented(i, i);
360 if (safe_abs(pivot) < 1e-12) {
361 throw std::runtime_error("Matrix is singular");
362 }
363
364 for (int j = 0; j < 2 * cols; ++j) {
365 augmented(i, j) /= pivot;
366 }
367
368 // Eliminate column
369 for (int k = 0; k < rows; ++k) {
370 if (k != i) {
371 T factor = augmented(k, i);
372 for (int j = 0; j < 2 * cols; ++j) {
373 augmented(k, j) -= factor * augmented(i, j);
374 }
375 }
376 }
377 }
378
379 // Extract inverse matrix
380 Matrix<T> result(rows, cols);
381 for (int i = 0; i < rows; ++i) {
382 for (int j = 0; j < cols; ++j) {
383 result(i, j) = augmented(i, j + cols);
384 }
385 }
386
387 return result;
388}
389
390template<typename T>
392{
393 Matrix<T> result(cols, rows);
394 for (int i = 0; i < rows; ++i) {
395 for (int j = 0; j < cols; ++j) {
396 result(j, i) = data[i][j];
397 }
398 }
399 return result;
400}
401
402template<typename T>
404{
405 if (rows != cols) {
406 throw std::invalid_argument("Adjoint requires a square matrix.");
407 }
408 Matrix<T> adj(rows, cols);
409
410 if (rows == 1) {
411 adj(0, 0) = T(1);
412 return adj;
413 }
414
415 for (int i = 0; i < rows; i++) {
416 for (int j = 0; j < cols; j++) {
417 Matrix<T> minorMat = getMinor(i, j);
418 T det = minorMat.determinant();
419 T cofactor = ((i + j) % 2 == 0) ? det : (det * (T(-1)));
420 adj(j, i) = cofactor;
421 }
422 }
423 return adj;
424}
425
426template<typename T>
427std::vector<T> Matrix<T>::eigenvalues() const
428{
429 if (rows != cols) {
430 throw std::invalid_argument(
431 "Eigenvalues are only defined for square matrices");
432 }
433
434 // For 2x2 matrices, use analytical solution
435 if (rows == 2) {
436 T trace = data[0][0] + data[1][1];
437 T det = data[0][0] * data[1][1] - data[0][1] * data[1][0];
438 T discriminant = trace * trace - T {4} * det;
439
440 std::vector<T> eigenvals(2);
441 if (discriminant >= 0) {
442 T sqrtDisc = safe_sqrt(discriminant);
443 eigenvals[0] = (trace + sqrtDisc) / T {2};
444 eigenvals[1] = (trace - sqrtDisc) / T {2};
445 } else {
446 // Complex eigenvalues - return real parts only for now
447 eigenvals[0] = trace / T {2};
448 eigenvals[1] = trace / T {2};
449 }
450 return eigenvals;
451 }
452
453 // For larger matrices, use QR algorithm (simplified version)
454 Matrix<T> A = *this;
455 std::vector<T> eigenvals;
456
457 // Power iteration for dominant eigenvalue (simplified approach)
458 const int maxIter = 1000;
459 const double tolerance = 1e-10;
460
461 for (int ev = 0; ev < std::min(rows, 3);
462 ++ev) { // Compute first few eigenvalues
463 std::vector<T> v(rows, T {1});
464
465 for (int iter = 0; iter < maxIter; ++iter) {
466 std::vector<T> Av(rows, T {});
467 for (int i = 0; i < rows; ++i) {
468 for (int j = 0; j < cols; ++j) {
469 Av[i] += A(i, j) * v[j];
470 }
471 }
472
473 // Normalize
474 T norm = T {};
475 for (int i = 0; i < rows; ++i) {
476 norm += Av[i] * Av[i];
477 }
478 norm = safe_sqrt(norm);
479
480 if (norm < tolerance) {
481 break;
482 }
483
484 for (int i = 0; i < rows; ++i) {
485 Av[i] /= norm;
486 }
487
488 // Check convergence
489 T diff = T {};
490 for (int i = 0; i < rows; ++i) {
491 diff += (Av[i] - v[i]) * (Av[i] - v[i]);
492 }
493
494 v = Av;
495
496 if (safe_sqrt(diff) < tolerance) {
497 break;
498 }
499 }
500
501 // Compute eigenvalue
502 T eigenval = T {};
503 T vNorm = T {};
504 for (int i = 0; i < rows; ++i) {
505 for (int j = 0; j < cols; ++j) {
506 eigenval += v[i] * A(i, j) * v[j];
507 }
508 vNorm += v[i] * v[i];
509 }
510 eigenval /= vNorm;
511 eigenvals.push_back(eigenval);
512
513 // Deflate matrix (simplified)
514 for (int i = 0; i < rows; ++i) {
515 for (int j = 0; j < cols; ++j) {
516 A(i, j) -= eigenval * v[i] * v[j];
517 }
518 }
519 }
520
521 return eigenvals;
522}
523
524// template<typename T>
525// Matrix<T> Matrix<T>::eigenvectors() const
526// {
527// // Simplified implementation - returns identity matrix
528// // Full implementation would require more sophisticated algorithms
529// return identity(rows);
530// }
531
532template<typename T>
533std::pair<Matrix<T>, Matrix<T>> Matrix<T>::LUDecomposition() const
534{
535 if (rows != cols) {
536 throw std::invalid_argument("LU decomposition requires a square matrix");
537 }
538
539 Matrix<T> L = identity(rows);
540 Matrix<T> U = *this;
541
542 for (int i = 0; i < rows - 1; ++i) {
543 for (int j = i + 1; j < rows; ++j) {
544 if (safe_abs(U(i, i)) < 1e-12) {
545 throw std::runtime_error(
546 "Matrix is singular - cannot perform LU decomposition");
547 }
548
549 T factor = U(j, i) / U(i, i);
550 L(j, i) = factor;
551
552 for (int k = i; k < cols; ++k) {
553 U(j, k) -= factor * U(i, k);
554 }
555 }
556 }
557
558 return {L, U};
559}
560
561// QR (Gram-Schmidt)
562template<typename T>
563std::pair<Matrix<T>, Matrix<T>> Matrix<T>::QRDecomposition() const
564{
565 Matrix<T> Q(rows, cols); // Start with empty Q
566 Matrix<T> R = zeros(cols, cols);
567
568 // Gram-Schmidt process
569 for (int j = 0; j < cols; ++j) {
570 // Extract column j from ORIGINAL matrix (this)
571 std::vector<T> v(rows);
572 for (int i = 0; i < rows; ++i) {
573 v[i] = (*this)(i, j); // Read from original matrix, not Q
574 }
575
576 // Orthogonalize against previous Q columns
577 for (int k = 0; k < j; ++k) {
578 T dot = T {};
579 for (int i = 0; i < rows; ++i) {
580 dot += Q(i, k) * v[i]; // Use already-computed Q columns
581 }
582 R(k, j) = dot;
583
584 for (int i = 0; i < rows; ++i) {
585 v[i] -= dot * Q(i, k);
586 }
587 }
588
589 // Normalize
590 T norm = T {};
591 for (int i = 0; i < rows; ++i) {
592 norm += v[i] * v[i];
593 }
594 norm = safe_sqrt(norm);
595 R(j, j) = norm;
596
597 if (norm > 1e-12) {
598 for (int i = 0; i < rows; ++i) {
599 Q(i, j) = v[i] / norm; // Write to Q
600 }
601 } else {
602 // Handle zero norm case
603 for (int i = 0; i < rows; ++i) {
604 Q(i, j) = 0;
605 }
606 }
607 }
608
609 return {Q, R};
610}
611
612double abs(const ComplexNumber& c)
613{
614 return c.magnitude();
615}
616
617// Then your original code will work:
618template<typename T>
620{
621 double sum = 0.0;
622 for (int i = 0; i < rows; ++i) {
623 for (int j = 0; j < cols; ++j) {
624 // Better to use:
625 double val = abs(data[i][j]); // Uses ADL to find your overload
626 sum += val * val;
627 }
628 }
629 return std::sqrt(sum);
630}
631
632template<typename T>
634{
635 // Simplified implementation using power method
636 if (rows == 0 || cols == 0) {
637 return 0.0;
638 }
639
640 Matrix<T> AtA = transpose() * (*this);
641 std::vector<T> eigenvals = AtA.eigenvalues();
642
643 double maxEigenval = 0.0;
644 for (const auto& val : eigenvals) {
645 double absVal = getAbsoluteValue(val);
646 if (absVal > maxEigenval) {
647 maxEigenval = absVal;
648 }
649 }
650
651 return std::sqrt(maxEigenval);
652}
653
654template<typename T>
655Matrix<T> Matrix<T>::getMinor(int row, int col) const
656{
657 if (rows <= 1 || cols <= 1) {
658 throw std::invalid_argument("Matrix too small for minor");
659 }
660
661 Matrix<T> minor(rows - 1, cols - 1);
662 int minorRow = 0;
663
664 for (int i = 0; i < rows; ++i) {
665 if (i == row) {
666 continue;
667 }
668
669 int minorCol = 0;
670 for (int j = 0; j < cols; ++j) {
671 if (j == col) {
672 continue;
673 }
674 minor(minorRow, minorCol) = data[i][j];
675 ++minorCol;
676 }
677 ++minorRow;
678 }
679
680 return minor;
681}
682
683template<typename T>
684std::string Matrix<T>::toString() const
685{
686 std::ostringstream oss;
687 oss << "[" << '\n';
688 for (int i = 0; i < rows; ++i) {
689 if (i > 0) {
690 oss << ",";
691 }
692 oss << "[";
693 for (int j = 0; j < cols; ++j) {
694 if (j > 0) {
695 oss << ", ";
696 }
697 oss << data[i][j];
698 }
699 oss << "]" << '\n';
700 }
701 oss << "]";
702 return oss.str();
703}
704
705template<typename T>
707{
708 if (n <= 0) {
709 throw std::invalid_argument("Identity matrix size must be positive");
710 }
711
712 Matrix<T> result(n, n);
713 for (int i = 0; i < n; ++i) {
714 result(i, i) = T {1};
715 }
716 return result;
717}
718
719// Helper
720template<typename T>
721std::vector<T> Matrix<T>::matVec(const std::vector<T>& v) const
722{
723 std::vector<T> r(rows, 0);
724 for (int i = 0; i < rows; ++i) {
725 for (int j = 0; j < cols; ++j) {
726 r[i] += data[i][j] * v[j];
727 }
728 }
729 return r;
730}
731
732template<typename T>
733T Matrix<T>::dot(const std::vector<T>& a, const std::vector<T>& b) const
734{
735 T s = 0;
736 for (int i = 0; i < a.size(); ++i) {
737 s += a[i] * b[i];
738 }
739 return s;
740}
741
742template<typename T>
743double Matrix<T>::norm(const std::vector<T>& v) const
744{
745 return std::sqrt((double)dot(v, v));
746}
747
748template<typename T>
749void Matrix<T>::normalize(std::vector<T>& v) const
750{
751 double n = norm(v);
752 if (n == 0) {
753 return;
754 }
755 for (auto& x : v) {
756 x /= n;
757 }
758}
759
760// Extract a submatrix from (row_start, col_start) to (row_end, col_end)
761// [exclusive]
762template<typename T>
764 int row_end,
765 int col_start,
766 int col_end) const
767{
768 // Validate bounds
769 if (row_start < 0 || row_end > rows || col_start < 0 || col_end > cols) {
770 throw std::out_of_range("Submatrix indices out of bounds");
771 }
772 if (row_start >= row_end || col_start >= col_end) {
773 throw std::invalid_argument("Invalid submatrix range");
774 }
775
776 int sub_rows = row_end - row_start;
777 int sub_cols = col_end - col_start;
778
779 Matrix<T> result(sub_rows, sub_cols);
780
781 for (int i = 0; i < sub_rows; ++i) {
782 for (int j = 0; j < sub_cols; ++j) {
783 result(i, j) = (*this)(row_start + i, col_start + j);
784 }
785 }
786
787 return result;
788}
789
790// Lanczos's algorithm implementation to find eigenvectors
791template<typename T>
793 std::vector<T>& alpha,
794 std::vector<T>& beta,
795 Matrix<T>& Q) const
796{
797 int n = rows;
798 alpha.resize(m);
799 beta.resize(m - 1); // FIX: beta has m-1 elements
800 Q = Matrix<T>(n, m);
801
802 std::vector<T> q(n, 1);
803 normalize(q);
804
805 std::vector<T> q_prev(n, 0);
806
807 for (int j = 0; j < m; ++j) {
808 auto v = matVec(q);
809
810 if (j > 0) {
811 for (int i = 0; i < n; ++i) {
812 v[i] -= beta[j - 1] * q_prev[i];
813 }
814 }
815 alpha[j] = dot(q, v);
816
817 for (int i = 0; i < n; ++i) {
818 v[i] -= alpha[j] * q[i];
819 }
820
821 // FIX: Store current q in column j of Q before computing next q
822 for (int i = 0; i < n; ++i) {
823 Q(i, j) = q[i]; // Store in column j, not row j
824 }
825
826 // FIX: Only compute beta if not last iteration
827 if (j < m - 1) {
828 beta[j] = norm(v);
829 if (beta[j] < 1e-10) {
830 // FIX: Resize arrays to actual size
831 alpha.resize(j + 1);
832 beta.resize(j);
833 Q = Q.submatrix(0, n, 0, j + 1); // Assuming you have submatrix method
834 break;
835 }
836
837 q_prev = q;
838 for (int i = 0; i < n; ++i) {
839 q[i] = v[i] / beta[j];
840 }
841 }
842 }
843}
844
845// Build T
846template<typename T>
847Matrix<T> Matrix<T>::buildTridiagonal(const std::vector<T>& alpha,
848 const std::vector<T>& beta,
849 int m) const
850{
851 Matrix<T> Tm(m, m);
852 for (int i = 0; i < m; ++i) {
853 Tm(i, i) = alpha[i];
854 if (i > 0) {
855 Tm(i, i - 1) = beta[i - 1];
856 }
857 if (i < m - 1) {
858 Tm(i, i + 1) = beta[i];
859 }
860 }
861 return Tm;
862}
863
864template<typename T>
866{
867 int m = std::min(rows, 20);
868 std::vector<T> alpha, beta;
869 Matrix<T> Ql;
870
871 lanczos(m, alpha, beta, Ql);
872
873 // FIX: Use actual size (in case of early termination)
874 int actual_m = alpha.size();
875 Matrix<T> Tm = buildTridiagonal(alpha, beta, actual_m);
876
877 Matrix<T> V = Matrix<T>::identity(actual_m);
878
879 for (int i = 0; i < 100; ++i) {
880 auto [Qk, Rk] = Tm.QRDecomposition();
881 Tm = Rk * Qk;
882 V = V * Qk;
883 }
884
885 Matrix<T> result(rows, actual_m);
886
887 // FIX: Now Ql(i, j) correctly has vectors in columns
888 for (int k = 0; k < actual_m; ++k) {
889 for (int i = 0; i < rows; ++i) {
890 for (int j = 0; j < actual_m; ++j) {
891 result(i, k) += Ql(i, j) * V(j, k);
892 }
893 }
894 }
895 return result;
896}
897
898template<typename T>
900{
901 if (r <= 0 || c <= 0) {
902 throw std::invalid_argument("Matrix dimensions must be positive");
903 }
904
905 return Matrix<T>(r, c); // Default constructor initializes with zeros
906}
907
908template<typename T>
910{
911 if (r <= 0 || c <= 0) {
912 throw std::invalid_argument("Matrix dimensions must be positive");
913 }
914
915 Matrix<T> result(r, c);
916 for (int i = 0; i < r; ++i) {
917 for (int j = 0; j < c; ++j) {
918 result(i, j) = T {1};
919 }
920 }
921 return result;
922}
923
924// Explicit template instantiations
925template class Matrix<double>;
926template class Matrix<float>;
927template class Matrix<int>;
928// template class Matrix<ComplexNumber>;
A templated matrix class supporting various linear algebra operations.
Definition: matrix.h:23
Matrix< T > submatrix(int row_start, int row_end, int col_start, int col_end) const
Extracts a submatrix from specified row and column ranges.
Definition: matrix.cpp:763
Matrix< T > eigenvectors() const
Computes the eigenvectors of the matrix.
Definition: matrix.cpp:865
std::vector< T > matVec(const std::vector< T > &v) const
Performs matrix-vector multiplication.
Definition: matrix.cpp:721
T rank() const
Computes the rank of the matrix.
Definition: matrix.cpp:223
Matrix< T > getMinor(int row, int col) const
Gets the minor matrix by removing a specified row and column.
Definition: matrix.cpp:655
double norm(const std::vector< T > &v) const
Computes the Euclidean (L2) norm of a vector.
Definition: matrix.cpp:743
double spectralNorm() const
Computes the spectral norm (2-norm) of the matrix.
Definition: matrix.cpp:633
Matrix< T > operator*(const Matrix< T > &other) const
Matrix multiplication.
Definition: matrix.cpp:190
std::pair< Matrix< T >, Matrix< T > > QRDecomposition() const
Performs QR decomposition of the matrix using Gram-Schmidt orthogonalization.
Definition: matrix.cpp:563
void lanczos(int m, std::vector< T > &alpha, std::vector< T > &beta, Matrix< T > &Q) const
Performs the Lanczos algorithm for tridiagonalization.
Definition: matrix.cpp:792
Matrix< T > operator-(const Matrix< T > &other) const
Matrix subtraction.
Definition: matrix.cpp:174
std::string toString() const
Converts the matrix to a formatted string representation.
Definition: matrix.cpp:684
Matrix< T > transpose() const
Computes the transpose of the matrix.
Definition: matrix.cpp:391
T dot(const std::vector< T > &a, const std::vector< T > &b) const
Computes the dot product of two vectors.
Definition: matrix.cpp:733
double frobeniusNorm() const
Computes the Frobenius norm of the matrix.
Definition: matrix.cpp:619
Matrix< T > adjoint() const
Computes the adjoint (adjugate) matrix.
Definition: matrix.cpp:403
static Matrix< T > ones(int r, int c)
Creates an r × c matrix filled with ones.
Definition: matrix.cpp:909
void normalize(std::vector< T > &v) const
Normalizes a vector to unit length (in-place).
Definition: matrix.cpp:749
std::pair< Matrix< T >, Matrix< T > > LUDecomposition() const
Performs LU decomposition of the matrix.
Definition: matrix.cpp:533
Matrix()
Default constructor creating an empty 0×0 matrix.
Definition: matrix.h:34
Matrix< T > buildTridiagonal(const std::vector< T > &alpha, const std::vector< T > &beta, int m) const
Constructs a tridiagonal matrix from diagonal and off-diagonal elements.
Definition: matrix.cpp:847
static Matrix< T > zeros(int r, int c)
Creates an r × c matrix filled with zeros.
Definition: matrix.cpp:899
Matrix< T > inverse() const
Computes the inverse of the matrix.
Definition: matrix.cpp:303
std::vector< T > eigenvalues() const
Computes the eigenvalues of the matrix.
Definition: matrix.cpp:427
T & operator()(int row, int column)
Accesses matrix element at specified position (non-const).
Definition: matrix.cpp:134
Matrix< T > operator+(const Matrix< T > &other) const
Matrix addition.
Definition: matrix.cpp:158
static Matrix< T > identity(int n)
Creates an n × n identity matrix.
Definition: matrix.cpp:706
T determinant() const
Computes the determinant of the matrix.
Definition: matrix.cpp:276
bool isSymmetric() const
Checks if the matrix is symmetric.
Definition: matrix.cpp:258