| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "tsyplakov_k_mul_double_crs_matrix/seq/include/ops_seq.hpp" | ||
| 2 | |||
| 3 | #include <cmath> | ||
| 4 | #include <cstdlib> | ||
| 5 | #include <limits> | ||
| 6 | #include <map> | ||
| 7 | #include <vector> | ||
| 8 | |||
| 9 | #include "tsyplakov_k_mul_double_crs_matrix/common/include/common.hpp" | ||
| 10 | |||
| 11 | namespace tsyplakov_k_mul_double_crs_matrix { | ||
| 12 | |||
| 13 | ✗ | TsyplakovKTestTaskSEQ::TsyplakovKTestTaskSEQ(const InType &in) { | |
| 14 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 15 | GetInput() = in; | ||
| 16 | ✗ | } | |
| 17 | |||
| 18 | ✗ | bool TsyplakovKTestTaskSEQ::ValidationImpl() { | |
| 19 | ✗ | return (GetInput().a.cols == GetInput().b.rows) && (GetInput().a.rows > 0) && (GetInput().a.cols > 0) && | |
| 20 | ✗ | (GetInput().b.rows > 0) && (GetInput().b.cols > 0); | |
| 21 | } | ||
| 22 | |||
| 23 | ✗ | bool TsyplakovKTestTaskSEQ::PreProcessingImpl() { | |
| 24 | ✗ | GetOutput() = SparseMatrixCRS(GetInput().a.rows, GetInput().b.cols); | |
| 25 | ✗ | return true; | |
| 26 | } | ||
| 27 | |||
| 28 | ✗ | std::vector<double> TsyplakovKTestTaskSEQ::MultiplyRowByMatrix(const std::vector<double> &row_values, | |
| 29 | const std::vector<int> &row_cols, | ||
| 30 | const SparseMatrixCRS &b, int &result_nnz) { | ||
| 31 | std::map<int, double> temp_result; | ||
| 32 | ✗ | for (size_t i = 0; i < row_cols.size(); ++i) { | |
| 33 | ✗ | int col_a = row_cols[i]; | |
| 34 | ✗ | double val_a = row_values[i]; | |
| 35 | |||
| 36 | ✗ | int start = b.row_ptr[col_a]; | |
| 37 | ✗ | int end = b.row_ptr[col_a + 1]; | |
| 38 | |||
| 39 | ✗ | for (int j = start; j < end; ++j) { | |
| 40 | ✗ | int col_b = b.col_index[j]; | |
| 41 | ✗ | double val_b = b.values[j]; | |
| 42 | |||
| 43 | ✗ | temp_result[col_b] += val_a * val_b; | |
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | const double eps = std::numeric_limits<double>::epsilon() * 100; | ||
| 48 | ✗ | std::vector<double> result_values; | |
| 49 | ✗ | result_nnz = 0; | |
| 50 | |||
| 51 | ✗ | for (auto it = temp_result.begin(); it != temp_result.end();) { | |
| 52 | ✗ | if (std::abs(it->second) < eps) { | |
| 53 | it = temp_result.erase(it); | ||
| 54 | } else { | ||
| 55 | ✗ | result_values.push_back(it->second); | |
| 56 | ++it; | ||
| 57 | ✗ | ++result_nnz; | |
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | ✗ | return result_values; | |
| 62 | } | ||
| 63 | |||
| 64 | ✗ | bool TsyplakovKTestTaskSEQ::RunImpl() { | |
| 65 | const SparseMatrixCRS &a = GetInput().a; | ||
| 66 | ✗ | const SparseMatrixCRS &b = GetInput().b; | |
| 67 | SparseMatrixCRS &c = GetOutput(); | ||
| 68 | |||
| 69 | c.values.clear(); | ||
| 70 | c.col_index.clear(); | ||
| 71 | ✗ | c.row_ptr.assign(a.rows + 1, 0); | |
| 72 | |||
| 73 | ✗ | for (int i = 0; i < a.rows; ++i) { | |
| 74 | ✗ | int start_a = a.row_ptr[i]; | |
| 75 | ✗ | int end_a = a.row_ptr[i + 1]; | |
| 76 | |||
| 77 | ✗ | std::vector<double> row_values(a.values.begin() + start_a, a.values.begin() + end_a); | |
| 78 | ✗ | std::vector<int> row_cols(a.col_index.begin() + start_a, a.col_index.begin() + end_a); | |
| 79 | |||
| 80 | ✗ | int row_nnz = 0; | |
| 81 | ✗ | std::vector<double> row_result = MultiplyRowByMatrix(row_values, row_cols, b, row_nnz); | |
| 82 | |||
| 83 | ✗ | c.row_ptr[i + 1] = c.row_ptr[i] + row_nnz; | |
| 84 | } | ||
| 85 | |||
| 86 | c.values.clear(); | ||
| 87 | c.col_index.clear(); | ||
| 88 | ✗ | c.row_ptr.assign(a.rows + 1, 0); | |
| 89 | |||
| 90 | ✗ | for (int i = 0; i < a.rows; ++i) { | |
| 91 | ✗ | int start_a = a.row_ptr[i]; | |
| 92 | ✗ | int end_a = a.row_ptr[i + 1]; | |
| 93 | |||
| 94 | std::map<int, double> temp_result; | ||
| 95 | |||
| 96 | ✗ | for (int k_idx = start_a; k_idx < end_a; ++k_idx) { | |
| 97 | ✗ | int k = a.col_index[k_idx]; | |
| 98 | ✗ | double a_ik = a.values[k_idx]; | |
| 99 | |||
| 100 | ✗ | int start_b = b.row_ptr[k]; | |
| 101 | ✗ | int end_b = b.row_ptr[k + 1]; | |
| 102 | |||
| 103 | ✗ | for (int j_idx = start_b; j_idx < end_b; ++j_idx) { | |
| 104 | ✗ | int j = b.col_index[j_idx]; | |
| 105 | ✗ | double b_kj = b.values[j_idx]; | |
| 106 | ✗ | temp_result[j] += a_ik * b_kj; | |
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | const double eps = std::numeric_limits<double>::epsilon() * 100; | ||
| 111 | ✗ | c.row_ptr[i] = static_cast<int>(c.values.size()); | |
| 112 | |||
| 113 | ✗ | for (const auto &[col, val] : temp_result) { | |
| 114 | ✗ | if (std::abs(val) > eps) { | |
| 115 | ✗ | c.col_index.push_back(col); | |
| 116 | ✗ | c.values.push_back(val); | |
| 117 | } | ||
| 118 | } | ||
| 119 | } | ||
| 120 | ✗ | c.row_ptr[a.rows] = static_cast<int>(c.values.size()); | |
| 121 | |||
| 122 | ✗ | return true; | |
| 123 | } | ||
| 124 | |||
| 125 | ✗ | bool TsyplakovKTestTaskSEQ::PostProcessingImpl() { | |
| 126 | ✗ | return true; | |
| 127 | } | ||
| 128 | |||
| 129 | } // namespace tsyplakov_k_mul_double_crs_matrix | ||
| 130 |