| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "ilin_a_gaussian_method_horizontal_band_scheme/seq/include/ops_seq.hpp" | ||
| 2 | |||
| 3 | #include <algorithm> | ||
| 4 | #include <cmath> | ||
| 5 | #include <cstddef> | ||
| 6 | #include <vector> | ||
| 7 | |||
| 8 | #include "ilin_a_gaussian_method_horizontal_band_scheme/common/include/common.hpp" | ||
| 9 | |||
| 10 | namespace ilin_a_gaussian_method_horizontal_band_scheme { | ||
| 11 | |||
| 12 | ✗ | IlinAGaussianMethodSEQ::IlinAGaussianMethodSEQ(const InType &in) { | |
| 13 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 14 | ✗ | GetInput() = in; | |
| 15 | ✗ | GetOutput() = std::vector<double>(); | |
| 16 | ✗ | } | |
| 17 | |||
| 18 | ✗ | bool IlinAGaussianMethodSEQ::ValidationImpl() { | |
| 19 | const auto &input = GetInput(); | ||
| 20 | ✗ | if (input.size() < 4) { | |
| 21 | return false; | ||
| 22 | } | ||
| 23 | |||
| 24 | ✗ | int size = static_cast<int>(input[0]); | |
| 25 | ✗ | int band_width = static_cast<int>(input[1]); | |
| 26 | |||
| 27 | ✗ | if (size <= 0 || band_width <= 0 || band_width > size) { | |
| 28 | return false; | ||
| 29 | } | ||
| 30 | |||
| 31 | ✗ | size_t expected_count = 2 + (size * band_width) + size; | |
| 32 | ✗ | return input.size() == expected_count; | |
| 33 | } | ||
| 34 | |||
| 35 | ✗ | bool IlinAGaussianMethodSEQ::PreProcessingImpl() { | |
| 36 | const auto &input = GetInput(); | ||
| 37 | |||
| 38 | ✗ | data_.size = static_cast<int>(input[0]); | |
| 39 | ✗ | data_.band_width = static_cast<int>(input[1]); | |
| 40 | |||
| 41 | ✗ | auto mat_size = static_cast<size_t>(data_.size) * static_cast<size_t>(data_.band_width); | |
| 42 | auto vec_size = static_cast<size_t>(data_.size); | ||
| 43 | |||
| 44 | ✗ | data_.matrix.resize(mat_size); | |
| 45 | ✗ | data_.vector.resize(vec_size); | |
| 46 | |||
| 47 | ✗ | std::copy(input.begin() + 2, input.begin() + 2 + static_cast<int>(mat_size), data_.matrix.begin()); | |
| 48 | |||
| 49 | ✗ | std::copy(input.begin() + 2 + static_cast<int>(mat_size), input.end(), data_.vector.begin()); | |
| 50 | |||
| 51 | ✗ | solution_.resize(vec_size, 0.0); | |
| 52 | ✗ | GetOutput() = std::vector<double>(vec_size, 0.0); | |
| 53 | |||
| 54 | ✗ | return true; | |
| 55 | } | ||
| 56 | |||
| 57 | ✗ | bool IlinAGaussianMethodSEQ::RunImpl() { | |
| 58 | ✗ | const int n = data_.size; | |
| 59 | ✗ | const int m = data_.band_width; | |
| 60 | |||
| 61 | ✗ | std::vector<double> b = data_.vector; | |
| 62 | ✗ | std::vector<double> matrix = data_.matrix; | |
| 63 | |||
| 64 | ✗ | ForwardElimination(n, m, matrix, b); | |
| 65 | ✗ | BackwardSubstitution(n, m, matrix, b); | |
| 66 | |||
| 67 | ✗ | return true; | |
| 68 | } | ||
| 69 | |||
| 70 | ✗ | void IlinAGaussianMethodSEQ::ForwardElimination(int n, int m, std::vector<double> &matrix, std::vector<double> &b) { | |
| 71 | ✗ | for (int k = 0; k < n; ++k) { | |
| 72 | int max_row = FindPivotRow(k, n, m, matrix); | ||
| 73 | |||
| 74 | ✗ | if (max_row != k) { | |
| 75 | ✗ | SwapRows(k, max_row, m, matrix, b); | |
| 76 | } | ||
| 77 | |||
| 78 | ✗ | int diag_idx = m - 1; | |
| 79 | ✗ | double pivot = matrix[(static_cast<size_t>(k) * static_cast<size_t>(m)) + diag_idx]; | |
| 80 | ✗ | if (std::fabs(pivot) < 1e-12) { | |
| 81 | ✗ | continue; | |
| 82 | } | ||
| 83 | |||
| 84 | ✗ | for (int i = k + 1; i < std::min(n, k + m); ++i) { | |
| 85 | ✗ | EliminateRow(i, k, m, matrix, b, pivot); | |
| 86 | } | ||
| 87 | } | ||
| 88 | ✗ | } | |
| 89 | |||
| 90 | ✗ | int IlinAGaussianMethodSEQ::FindPivotRow(int k, int n, int m, const std::vector<double> &matrix) { | |
| 91 | int max_row = k; | ||
| 92 | double max_val = 0.0; | ||
| 93 | |||
| 94 | ✗ | for (int i = k; i < std::min(n, k + m); ++i) { | |
| 95 | ✗ | int diag_idx = m - 1 - (i - k); | |
| 96 | ✗ | if (diag_idx >= 0) { | |
| 97 | ✗ | double val = std::fabs(matrix[(static_cast<size_t>(i) * static_cast<size_t>(m)) + diag_idx]); | |
| 98 | ✗ | if (val > max_val) { | |
| 99 | max_val = val; | ||
| 100 | max_row = i; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } | ||
| 104 | ✗ | return max_row; | |
| 105 | } | ||
| 106 | |||
| 107 | ✗ | void IlinAGaussianMethodSEQ::SwapRows(int row1, int row2, int m, std::vector<double> &matrix, std::vector<double> &b) { | |
| 108 | ✗ | for (int j = 0; j < m; ++j) { | |
| 109 | ✗ | std::swap(matrix[(static_cast<size_t>(row1) * static_cast<size_t>(m)) + j], | |
| 110 | ✗ | matrix[(static_cast<size_t>(row2) * static_cast<size_t>(m)) + j]); | |
| 111 | } | ||
| 112 | ✗ | std::swap(b[static_cast<size_t>(row1)], b[static_cast<size_t>(row2)]); | |
| 113 | ✗ | } | |
| 114 | |||
| 115 | ✗ | void IlinAGaussianMethodSEQ::EliminateRow(int i, int k, int m, std::vector<double> &matrix, std::vector<double> &b, | |
| 116 | double pivot) { | ||
| 117 | ✗ | int factor_idx = m - 1 - (i - k); | |
| 118 | ✗ | if (factor_idx < 0) { | |
| 119 | return; | ||
| 120 | } | ||
| 121 | |||
| 122 | ✗ | double factor = matrix[(static_cast<size_t>(i) * static_cast<size_t>(m)) + factor_idx] / pivot; | |
| 123 | |||
| 124 | ✗ | for (int j = 0; j < m; ++j) { | |
| 125 | ✗ | int src_idx = j - (i - k); | |
| 126 | ✗ | if (src_idx >= 0 && src_idx < m) { | |
| 127 | ✗ | matrix[(static_cast<size_t>(i) * static_cast<size_t>(m)) + j] -= | |
| 128 | ✗ | factor * matrix[(static_cast<size_t>(k) * static_cast<size_t>(m)) + src_idx]; | |
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | ✗ | b[static_cast<size_t>(i)] -= factor * b[static_cast<size_t>(k)]; | |
| 133 | } | ||
| 134 | |||
| 135 | ✗ | void IlinAGaussianMethodSEQ::BackwardSubstitution(int n, int m, const std::vector<double> &matrix, | |
| 136 | const std::vector<double> &b) { | ||
| 137 | ✗ | for (int i = n - 1; i >= 0; --i) { | |
| 138 | double sum = 0.0; | ||
| 139 | |||
| 140 | ✗ | for (int j = i + 1; j < std::min(n, i + m); ++j) { | |
| 141 | ✗ | int idx = m - 1 + (j - i); | |
| 142 | ✗ | if (idx < m) { | |
| 143 | ✗ | sum += matrix[(static_cast<size_t>(i) * static_cast<size_t>(m)) + idx] * solution_[static_cast<size_t>(j)]; | |
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | ✗ | int diag_idx = m - 1; | |
| 148 | ✗ | double diag = matrix[(static_cast<size_t>(i) * static_cast<size_t>(m)) + diag_idx]; | |
| 149 | ✗ | if (std::fabs(diag) > 1e-12) { | |
| 150 | ✗ | solution_[static_cast<size_t>(i)] = (b[static_cast<size_t>(i)] - sum) / diag; | |
| 151 | } else { | ||
| 152 | ✗ | solution_[static_cast<size_t>(i)] = 0.0; | |
| 153 | } | ||
| 154 | } | ||
| 155 | ✗ | } | |
| 156 | |||
| 157 | ✗ | bool IlinAGaussianMethodSEQ::PostProcessingImpl() { | |
| 158 | ✗ | GetOutput() = solution_; | |
| 159 | ✗ | return true; | |
| 160 | } | ||
| 161 | |||
| 162 | } // namespace ilin_a_gaussian_method_horizontal_band_scheme | ||
| 163 |