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 : };