Line data Source code
1 1 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : /// \file
5 : /// `blaze::CompressedMatrix` is a general-purpose sparse matrix type. This file
6 : /// implements interoperability of `blaze::CompressedMatrix` with our data
7 : /// structures.
8 :
9 : #pragma once
10 :
11 : #include <blaze/math/CompressedMatrix.h>
12 : #include <cstddef>
13 : #include <pup.h>
14 : #include <vector>
15 :
16 : #include "Options/Options.hpp"
17 : #include "Options/ParseError.hpp"
18 : #include "Utilities/Gsl.hpp"
19 :
20 : namespace PUP {
21 : /// @{
22 : /// Serialization of blaze::CompressedMatrix
23 : template <typename Type, bool SO, typename Tag>
24 : void pup(er& p, blaze::CompressedMatrix<Type, SO, Tag>& t) {
25 : size_t rows = t.rows();
26 : size_t columns = t.columns();
27 : p | rows;
28 : p | columns;
29 : const size_t first_dimension = (SO == blaze::rowMajor) ? rows : columns;
30 : size_t num_non_zeros = t.nonZeros();
31 : p | num_non_zeros;
32 : // blaze::CompressedMatrix has no `.data()` access, so we use the low-level
33 : // `append` mechanism for serialization instead of `PUParray`. Maybe there's
34 : // an even faster way using PUPbytes.
35 : size_t index;
36 : if (p.isUnpacking()) {
37 : t.resize(rows, columns);
38 : t.reserve(num_non_zeros);
39 : Type value;
40 : for (size_t i = 0; i < first_dimension; ++i) {
41 : p | num_non_zeros;
42 : for (size_t j = 0; j < num_non_zeros; ++j) {
43 : p | index;
44 : p | value;
45 : if constexpr (SO == blaze::rowMajor) {
46 : t.append(i, index, value);
47 : } else {
48 : t.append(index, i, value);
49 : }
50 : }
51 : t.finalize(i);
52 : }
53 : } else {
54 : for (size_t i = 0; i < first_dimension; ++i) {
55 : num_non_zeros = t.nonZeros(i);
56 : p | num_non_zeros;
57 : for (auto it = t.begin(i); it != t.end(i); ++it) {
58 : index = it->index();
59 : p | index;
60 : p | it->value();
61 : }
62 : }
63 : }
64 : }
65 : template <typename Type, bool SO, typename Tag>
66 : void operator|(er& p, blaze::CompressedMatrix<Type, SO, Tag>& t) {
67 : pup(p, t);
68 : }
69 : /// @}
70 : } // namespace PUP
71 :
72 : namespace CompressedMatrix_detail {
73 : template <typename Type>
74 : std::vector<std::vector<Type>> parse_to_vectors(const Options::Option& options);
75 : } // namespace CompressedMatrix_detail
76 :
77 : template <typename Type, bool SO, typename Tag>
78 0 : struct Options::create_from_yaml<blaze::CompressedMatrix<Type, SO, Tag>> {
79 : template <typename Metavariables>
80 0 : static blaze::CompressedMatrix<Type, SO, Tag> create(
81 : const Options::Option& options) {
82 : const auto data = CompressedMatrix_detail::parse_to_vectors<Type>(options);
83 : const size_t num_rows = data.size();
84 : size_t num_cols = 0;
85 : if (num_rows > 0) {
86 : num_cols = data[0].size();
87 : }
88 : blaze::CompressedMatrix<Type, SO, Tag> result(num_rows, num_cols);
89 : for (size_t i = 0; i < num_rows; i++) {
90 : const auto& row = gsl::at(data, i);
91 : if (row.size() != num_cols) {
92 : PARSE_ERROR(options.context(),
93 : "All matrix rows must have the same size.");
94 : }
95 : for (size_t j = 0; j < num_cols; j++) {
96 : if (gsl::at(row, j) != 0.) {
97 : result(i, j) = gsl::at(row, j);
98 : }
99 : }
100 : }
101 : return result;
102 : }
103 : };
|