|
| 1 | +#include <algorithm> |
| 2 | +#include <cassert> |
| 3 | +#include <iostream> |
| 4 | +#include <vector> |
| 5 | + |
| 6 | +void gaussian_elimination(std::vector<double>& a, size_t cols) { |
| 7 | + assert(a.size() % cols == 0); |
| 8 | + auto rows = a.size() / cols; |
| 9 | + |
| 10 | + // Main loop going through all columns |
| 11 | + for (auto k = 0u; k < std::min(rows, cols); ++k) { |
| 12 | + // Step 1: finding the maximum element for each column |
| 13 | + auto max_index = [&]() { |
| 14 | + auto res = k; |
| 15 | + auto max_element = a[k + k * cols]; |
| 16 | + for (auto r = k + 1; r < rows; ++r) |
| 17 | + if (max_element < a[k + r * cols]) { |
| 18 | + max_element = a[k + r * cols]; |
| 19 | + res = r; |
| 20 | + } |
| 21 | + return res; |
| 22 | + }(); |
| 23 | + |
| 24 | + // Check to make sure matrix is good! |
| 25 | + if (a[k + max_index * cols] == 0) { |
| 26 | + std::cout << "matrix is singular! End!\n"; |
| 27 | + return; |
| 28 | + } |
| 29 | + |
| 30 | + // Step 2: swap row with highest value for that column to the top |
| 31 | + for (auto c = 0u; c < cols; ++c) |
| 32 | + std::swap(a[c + k * cols], a[c + max_index * cols]); |
| 33 | + |
| 34 | + // Loop for all remaining rows |
| 35 | + for (auto i = k + 1; i < rows; ++i) { |
| 36 | + |
| 37 | + // Step 3: finding fraction |
| 38 | + auto fraction = a[k + i * cols] / a[k + k * cols]; |
| 39 | + |
| 40 | + // loop through all columns for that row |
| 41 | + for (auto j = k + 1; j < cols; ++j) { |
| 42 | + |
| 43 | + // Step 4: re-evaluate each element |
| 44 | + a[j + i * cols] -= a[j + k * cols] * fraction; |
| 45 | + } |
| 46 | + |
| 47 | + // Step 5: Set lower elements to 0 |
| 48 | + a[k + i * cols] = 0; |
| 49 | + } |
| 50 | + } |
| 51 | +} |
| 52 | + |
| 53 | +std::vector<double> back_substitution(std::vector<double>& a, size_t cols) { |
| 54 | + assert(a.size() % cols == 0); |
| 55 | + auto rows = a.size() / cols; |
| 56 | + |
| 57 | + // Creating the solution Vector |
| 58 | + std::vector<double> soln; |
| 59 | + soln.resize(rows); |
| 60 | + |
| 61 | + // initialize the final element |
| 62 | + soln[rows - 1] = |
| 63 | + a[cols - 1 + (rows - 1) * cols] / a[cols - 1 - 1 + (rows - 1) * cols]; |
| 64 | + |
| 65 | + for (int i = rows - 1; i >= 0; --i) { |
| 66 | + auto sum = 0.0; |
| 67 | + for (int j = cols - 2; j > i; --j) { |
| 68 | + sum += soln[j] * a[j + i * cols]; |
| 69 | + } |
| 70 | + |
| 71 | + soln[i] = (a[cols - 1 + i * cols] - sum) / a[i + i * cols]; |
| 72 | + } |
| 73 | + |
| 74 | + return soln; |
| 75 | +} |
| 76 | + |
| 77 | +int main() { |
| 78 | + std::vector<double> a = {2, 3, 4, 6, |
| 79 | + 1, 2, 3, 4, |
| 80 | + 3, -4, 0, 10}; |
| 81 | + const auto cols = 4u; |
| 82 | + assert(a.size() % cols == 0); |
| 83 | + const auto rows = a.size() / cols; |
| 84 | + |
| 85 | + gaussian_elimination(a, cols); |
| 86 | + |
| 87 | + for (auto i = 0u; i < rows; ++i) { |
| 88 | + std::cout << "["; |
| 89 | + for (auto j = 0u; j < cols; ++j) { |
| 90 | + std::cout << a[j + i * cols] << " "; |
| 91 | + } |
| 92 | + std::cout << "]\n"; |
| 93 | + } |
| 94 | + |
| 95 | + auto soln = back_substitution(a, 4); |
| 96 | + |
| 97 | + for (auto element : soln) |
| 98 | + std::cout << element << std::endl; |
| 99 | +} |
0 commit comments