| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <cstddef> // for size_t | ||
| 4 | #include <map> | ||
| 5 | #include <stdexcept> // for std::invalid_argument | ||
| 6 | #include <tuple> | ||
| 7 | #include <utility> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | #include "task/include/task.hpp" | ||
| 11 | |||
| 12 | namespace zavyalov_a_compl_sparse_matr_mult { | ||
| 13 | |||
| 14 | struct Complex { | ||
| 15 | double re; // real | ||
| 16 | double im; // imaginary | ||
| 17 | |||
| 18 |
2/6✓ Branch 0 taken 4704 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2244 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
12356 | explicit Complex(double re = 0.0, double im = 0.0) : re(re), im(im) {} |
| 19 | |||
| 20 | bool operator==(const Complex &other) const { | ||
| 21 |
3/8✓ Branch 0 taken 2352 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2352 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7280 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
9632 | return other.re == re && other.im == im; |
| 22 | } | ||
| 23 | |||
| 24 | bool operator!=(const Complex &other) const { | ||
| 25 | return !(other == *this); | ||
| 26 | } | ||
| 27 | |||
| 28 | Complex operator*(const Complex &other) const { | ||
| 29 |
1/2✓ Branch 1 taken 4728 times.
✗ Branch 2 not taken.
|
16548 | return Complex{(re * other.re) - (im * other.im), (re * other.im) + (im * other.re)}; |
| 30 | } | ||
| 31 | |||
| 32 | Complex operator+(const Complex &other) const { | ||
| 33 | return Complex{re + other.re, im + other.im}; | ||
| 34 | } | ||
| 35 | |||
| 36 | Complex &operator+=(const Complex &other) { | ||
| 37 | 18792 | re += other.re; | |
| 38 | 18792 | im += other.im; | |
| 39 | return *this; | ||
| 40 | } | ||
| 41 | }; | ||
| 42 | |||
| 43 | struct SparseMatrix { | ||
| 44 | std::vector<Complex> val; | ||
| 45 | std::vector<size_t> row_ind; | ||
| 46 | std::vector<size_t> col_ind; | ||
| 47 | size_t height = 0; | ||
| 48 | size_t width = 0; | ||
| 49 | |||
| 50 | SparseMatrix() = default; | ||
| 51 | |||
| 52 | 480 | explicit SparseMatrix(const std::vector<std::vector<Complex>> &matr) | |
| 53 |
1/2✓ Branch 0 taken 480 times.
✗ Branch 1 not taken.
|
480 | : height(matr.size()), width(matr.empty() ? 0 : matr[0].size()) { |
| 54 |
2/4✓ Branch 0 taken 480 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 480 times.
✗ Branch 3 not taken.
|
480 | if (height == 0 || width == 0) { |
| 55 | return; | ||
| 56 | } | ||
| 57 | |||
| 58 |
2/2✓ Branch 0 taken 1808 times.
✓ Branch 1 taken 480 times.
|
2288 | for (size_t col = 0; col < width; ++col) { |
| 59 |
2/2✓ Branch 0 taken 7280 times.
✓ Branch 1 taken 1808 times.
|
9088 | for (size_t row = 0; row < height; ++row) { |
| 60 | if (matr[row][col] != Complex(0.0)) { | ||
| 61 |
2/2✓ Branch 0 taken 4960 times.
✓ Branch 1 taken 2320 times.
|
7280 | val.push_back(matr[row][col]); |
| 62 |
2/2✓ Branch 0 taken 4960 times.
✓ Branch 1 taken 2320 times.
|
7280 | row_ind.push_back(row); |
| 63 |
2/2✓ Branch 0 taken 4960 times.
✓ Branch 1 taken 2320 times.
|
7280 | col_ind.push_back(col); |
| 64 | } | ||
| 65 | } | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | [[nodiscard]] size_t Count() const { | ||
| 70 | return val.size(); | ||
| 71 | } | ||
| 72 | |||
| 73 | 80 | SparseMatrix operator*(const SparseMatrix &matr_b) const { | |
| 74 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
|
80 | if (width != matr_b.height) { |
| 75 | ✗ | throw std::invalid_argument("Incompatible matrix dimensions for multiplication"); | |
| 76 | } | ||
| 77 | |||
| 78 | std::map<std::pair<size_t, size_t>, Complex> mp; // <row, col> -> val | ||
| 79 | |||
| 80 |
2/2✓ Branch 0 taken 1320 times.
✓ Branch 1 taken 80 times.
|
1400 | for (size_t i = 0; i < Count(); ++i) { |
| 81 | 1320 | size_t row_a = row_ind[i]; | |
| 82 | 1320 | size_t col_a = col_ind[i]; | |
| 83 | 1320 | Complex val_a = val[i]; | |
| 84 | |||
| 85 |
2/2✓ Branch 0 taken 21672 times.
✓ Branch 1 taken 1320 times.
|
22992 | for (size_t j = 0; j < matr_b.Count(); ++j) { |
| 86 | 21672 | size_t row_b = matr_b.row_ind[j]; | |
| 87 | 21672 | size_t col_b = matr_b.col_ind[j]; | |
| 88 | 21672 | Complex val_b = matr_b.val[j]; | |
| 89 | |||
| 90 |
2/2✓ Branch 0 taken 4728 times.
✓ Branch 1 taken 16944 times.
|
21672 | if (col_a == row_b) { |
| 91 |
1/2✓ Branch 1 taken 4728 times.
✗ Branch 2 not taken.
|
4728 | mp[{row_a, col_b}] += val_a * val_b; |
| 92 | } | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | 80 | SparseMatrix res; | |
| 97 | 80 | res.width = matr_b.width; | |
| 98 | 80 | res.height = height; | |
| 99 |
2/2✓ Branch 0 taken 1176 times.
✓ Branch 1 taken 80 times.
|
1256 | for (const auto &[key, value] : mp) { |
| 100 |
2/2✓ Branch 0 taken 800 times.
✓ Branch 1 taken 376 times.
|
1176 | res.val.push_back(value); |
| 101 |
2/2✓ Branch 0 taken 800 times.
✓ Branch 1 taken 376 times.
|
1176 | res.row_ind.push_back(key.first); |
| 102 |
2/2✓ Branch 0 taken 800 times.
✓ Branch 1 taken 376 times.
|
1176 | res.col_ind.push_back(key.second); |
| 103 | } | ||
| 104 | |||
| 105 | 80 | return res; | |
| 106 | ✗ | } | |
| 107 | }; | ||
| 108 | |||
| 109 | using InType = std::tuple<SparseMatrix, SparseMatrix>; | ||
| 110 | using OutType = SparseMatrix; | ||
| 111 | using TestType = std::tuple<size_t, size_t, size_t>; // n, m, k. Matrix_1: n*m, Matrix_2: m*k | ||
| 112 | using BaseTask = ppc::task::Task<InType, OutType>; | ||
| 113 | |||
| 114 | } // namespace zavyalov_a_compl_sparse_matr_mult | ||
| 115 |