Morpheus 1.0.0
Dynamic matrix type and algorithms for sparse matrices
Loading...
Searching...
No Matches
Dia/Serial/Morpheus_Convert_Impl.hpp
1
24#ifndef MORPHEUS_DIA_SERIAL_CONVERT_IMPL_HPP
25#define MORPHEUS_DIA_SERIAL_CONVERT_IMPL_HPP
26
27#include <Morpheus_Macros.hpp>
28#if defined(MORPHEUS_ENABLE_SERIAL)
29
30#include <Morpheus_Exceptions.hpp>
31#include <Morpheus_SpaceTraits.hpp>
32#include <Morpheus_FormatTraits.hpp>
33#include <Morpheus_FormatTags.hpp>
34#include <Morpheus_Spaces.hpp>
35
36#include <impl/Coo/Serial/Morpheus_Sort_Impl.hpp>
37
38// TODO: Remove use of set during Coo to Dia Conversion
39#include <set>
40
41namespace Morpheus {
42namespace Impl {
43
44template <typename ExecSpace, typename SourceType, typename DestinationType>
45void convert(
46 const SourceType& src, DestinationType& dst,
47 typename std::enable_if<
48 Morpheus::is_dia_matrix_format_container_v<SourceType> &&
49 Morpheus::is_dia_matrix_format_container_v<DestinationType> &&
50 Morpheus::has_custom_backend_v<ExecSpace> &&
51 Morpheus::has_serial_execution_space_v<ExecSpace> &&
52 Morpheus::has_access_v<ExecSpace, SourceType, DestinationType>>::type* =
53 nullptr) {
54 using size_type = typename SourceType::size_type;
55
56 dst.resize(src.nrows(), src.ncols(), src.nnnz(),
57 src.cdiagonal_offsets().size());
58
59 // element-wise copy of indices and values
60 for (size_type n = 0; n < src.cdiagonal_offsets().size(); n++) {
61 dst.diagonal_offsets(n) = src.cdiagonal_offsets(n);
62 }
63
64 for (size_type j = 0; j < src.cvalues().ncols(); j++) {
65 for (size_type i = 0; i < src.cvalues().nrows(); i++) {
66 dst.values(i, j) = src.cvalues(i, j);
67 }
68 }
69}
70
71template <typename ExecSpace, typename SourceType, typename DestinationType>
72void convert(
73 const SourceType& src, DestinationType& dst,
74 typename std::enable_if<
75 Morpheus::is_dia_matrix_format_container_v<SourceType> &&
76 Morpheus::is_coo_matrix_format_container_v<DestinationType> &&
77 Morpheus::has_custom_backend_v<ExecSpace> &&
78 Morpheus::has_serial_execution_space_v<ExecSpace> &&
79 Morpheus::has_access_v<ExecSpace, SourceType, DestinationType>>::type* =
80 nullptr) {
81 using index_type = typename SourceType::index_type;
82 using size_type = typename SourceType::size_type;
83 using value_type = typename SourceType::value_type;
84
85 dst.resize(src.nrows(), src.ncols(), src.nnnz());
86
87 const size_type ndiag = src.cvalues().ncols();
88
89 for (size_type i = 0, nnzid = 0; i < ndiag; i++) {
90 const index_type k = src.cdiagonal_offsets(i);
91
92 const size_type i_start = std::max<index_type>(0, -k);
93 const size_type j_start = std::max<index_type>(0, k);
94
95 // number of elements to process in this diagonal
96 const size_type N = std::min(src.nrows() - i_start, src.ncols() - j_start);
97
98 for (size_type n = 0; n < N; n++) {
99 const value_type temp = src.cvalues(i_start + n, i);
100
101 if (temp != value_type(0)) {
102 dst.row_indices(nnzid) = i_start + n;
103 dst.column_indices(nnzid) = j_start + n;
104 dst.values(nnzid) = temp;
105 nnzid = nnzid + 1;
106 }
107 }
108 }
109
110 if (!Impl::is_sorted<ExecSpace>(dst)) {
111 Impl::sort_by_row_and_column<ExecSpace>(dst);
112 // dst.sort();
113 }
114}
115
116template <typename ExecSpace, typename SourceType, typename DestinationType>
117void convert(
118 const SourceType& src, DestinationType& dst,
119 typename std::enable_if<
120 Morpheus::is_coo_matrix_format_container_v<SourceType> &&
121 Morpheus::is_dia_matrix_format_container_v<DestinationType> &&
122 Morpheus::has_custom_backend_v<ExecSpace> &&
123 Morpheus::has_serial_execution_space_v<ExecSpace> &&
124 Morpheus::has_access_v<ExecSpace, SourceType, DestinationType>>::type* =
125 nullptr) {
126 using index_type = typename SourceType::index_type;
127 using size_type = typename SourceType::size_type;
128
129 if (src.nnnz() == 0) {
130 dst.resize(src.nrows(), src.ncols(), src.nnnz(), 0);
131 return;
132 }
133
134 std::vector<index_type> diag_map(src.nnnz(), 0);
135
136 // Find on which diagonal each entry sits on
137 for (size_type n = 0; n < src.nnnz(); n++) {
138 diag_map[n] = src.ccolumn_indices(n) - src.crow_indices(n);
139 }
140
141 // Create unique diagonal set
142 std::set<index_type> diag_set(diag_map.begin(), diag_map.end());
143 size_type ndiags = diag_set.size();
144
145 if (Impl::exceeds_tolerance(src.nrows(), src.nnnz(), ndiags)) {
147 "DiaMatrix fill-in would exceed maximum tolerance");
148 }
149
150 dst.resize(src.nrows(), src.ncols(), src.nnnz(), ndiags);
151
152 for (auto it = diag_set.cbegin(); it != diag_set.cend(); ++it) {
153 auto i = std::distance(diag_set.cbegin(), it);
154 dst.diagonal_offsets(i) = *it;
155 }
156
157 for (size_type n = 0; n < src.nnnz(); n++) {
158 for (size_type i = 0; i < ndiags; i++) {
159 if (diag_map[n] == dst.diagonal_offsets(i)) {
160 dst.values(src.crow_indices(n), i) = src.cvalues(n);
161 break;
162 }
163 }
164 }
165}
166
167} // namespace Impl
168} // namespace Morpheus
169
170#endif // MORPHEUS_ENABLE_SERIAL
171#endif // MORPHEUS_DIA_SERIAL_CONVERT_IMPL_HPP
Definition: Morpheus_Exceptions.hpp:69
Generic Morpheus interfaces.
Definition: dummy.cpp:24