23 static_assert(std::is_floating_point_v<T>,
24 "T must be a floating-point type (float or double)");
29 void elimination(
int col);
33 L = std::vector<std::vector<T>>(rows, std::vector<T>(cols, 0));
34 for (
int i = 0; i < rows; i++) {
41 P = std::vector<int>(n);
42 for(
int i=0; i < n; i++){
46 std::vector<int> initInvP()
const {
48 std::vector<int>invP(n,-1);
49 for (
int i = 0; i < n; i++)
52 if (pi < 0 || pi >= n)
throw std::invalid_argument(
"invalid permutation");
57 int pivoting(
int col);
58 void forwardSubstitution(std::vector<T>& y,
const std::vector<T>& b,
int n)
const;
59 void backwardSubstitution(std::vector<T>& x,
const std::vector<T>& y,
int n)
const;
60 std::vector<std::vector<T>> L;
61 std::vector<std::vector<T>> U;
63 static constexpr T eps = std::numeric_limits<T>::epsilon() *
static_cast<T
>(100);
78 const std::vector<std::vector<T>>&
getU()
const{
return U; }
79 const std::vector<std::vector<T>>&
getL()
const{
return L; }
80 const std::vector<int>&
getP()
const{
return P; }
85 int DecomposeLU<T>::pivoting(
int col) {
86 T pivotVal = std::abs(U[col][col]);
88 int rows = matrix.getRows();
89 if (col < 0 || col >= rows) {
90 throw std::runtime_error(
"Invalid column index");
92 for (
int i = col+1; i < rows; i++) {
94 if(std::abs(Ui[col]) > pivotVal) {
95 pivotVal = std::abs(Ui[col]);
99 if (pivotVal <= eps)
throw std::runtime_error(
"Matrix is singular");
108 void DecomposeLU<T>::elimination(
int col) {
109 int rows = matrix.getRows();
110 int cols = matrix.getColumns();
112 if(std::abs(U[col][col]) <= eps)
throw std::runtime_error(
"Pivot is zero");
113 T pivot = U[col][col];
114 for (
int i = col+1; i < rows; i++)
117 T& Li_col = L[i][col];
118 Li_col=Ui[col]/pivot;
119 const auto &Ucol = U[col];
121 for (
int j = col+1; j < cols; j++)
123 Ui[j] -= Li_col * Ucol[j];
125 Ui[col] =
static_cast<T
>(0);
132 void DecomposeLU<T>::decomposition() {
133 if (matrix.getRows() != matrix.getColumns())
134 throw std::runtime_error(
"Matrix must be square for LU decomposition");
135 int n = matrix.getRows();
136 U = matrix.getMatrix();
140 for (
int k = 0; k < n; ++k) {
141 int pivot = pivoting(k);
148 swap_ranges(L[pivot].begin(), L[pivot].begin() + k, L[k].begin());
153 detP = swapCount % 2 == 0 ? 1 : -1;
163 const auto& U = getU();
166 for (
int i = 0; i < rows; i++) det*=U[i][i];
173 for (
int j = 0; j < n; ++j) {
177 for (
int k = 0; k < j; ++k) sum += Lj[k] * y[k];
178 y[j] = (b[j] - sum)/Ljj;
183 void DecomposeLU<T>::backwardSubstitution(std::vector<T>& x,
const std::vector<T>& y,
int n)
const{
184 for (
int k = n-1; k >= 0; --k){
188 for (
int s = k+1; s < n; ++s) sum += Uk[s] * x[s];
189 x[k] = (y[k] - sum)/Ukk;
196 std::vector<std::vector<T>> X(n, std::vector<T>(n));
197 std::vector<int> invP = initInvP();
198 std::vector<T> b(n), y(n), x(n);
201 for(
int i = 0; i < n; ++i) {
209 forwardSubstitution(y, b, n);
210 backwardSubstitution(x, y, n);
212 for (
int k = 0; k < n; ++k) {