spla
storage_manager.hpp
Go to the documentation of this file.
1 /**********************************************************************************/
2 /* This file is part of spla project */
3 /* https://github.com/SparseLinearAlgebra/spla */
4 /**********************************************************************************/
5 /* MIT License */
6 /* */
7 /* Copyright (c) 2023 SparseLinearAlgebra */
8 /* */
9 /* Permission is hereby granted, free of charge, to any person obtaining a copy */
10 /* of this software and associated documentation files (the "Software"), to deal */
11 /* in the Software without restriction, including without limitation the rights */
12 /* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
13 /* copies of the Software, and to permit persons to whom the Software is */
14 /* furnished to do so, subject to the following conditions: */
15 /* */
16 /* The above copyright notice and this permission notice shall be included in all */
17 /* copies or substantial portions of the Software. */
18 /* */
19 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
20 /* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
21 /* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
22 /* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
23 /* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
24 /* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */
25 /* SOFTWARE. */
26 /**********************************************************************************/
27 
28 #ifndef SPLA_STORAGE_MANAGER_HPP
29 #define SPLA_STORAGE_MANAGER_HPP
30 
31 #include <spla/config.hpp>
32 
33 #include <core/tdecoration.hpp>
34 
35 #include <algorithm>
36 #include <functional>
37 #include <queue>
38 #include <utility>
39 #include <vector>
40 
41 namespace spla {
42 
56  template<typename T, typename F, int capacity>
57  class StorageManager final {
58  public:
60  typedef std::function<void(Storage& storage)> Function;
61 
62  explicit StorageManager();
63 
64  void register_constructor(F format, Function function);
65  void register_validator(F format, Function function);
66  void register_discard(F format, Function function);
67  void register_validator_discard(F format, Function function);
68  void register_converter(F from, F to, Function function);
69 
70  void validate_ctor(F format, Storage& storage);
71  void validate_rw(F format, Storage& storage);
72  void validate_rwd(F format, Storage& storage);
73  void validate_wd(F format, Storage& storage);
74 
75  private:
76  std::vector<std::vector<std::pair<int, int>>> m_convert_rules;
77  std::vector<Function> m_constructors;
78  std::vector<Function> m_validators;
79  std::vector<Function> m_discards;
80  std::vector<Function> m_converters;
81  };
82 
83  template<typename T, typename F, int capacity>
85  m_convert_rules.resize(capacity);
86  m_constructors.resize(capacity);
87  m_validators.resize(capacity);
88  m_discards.resize(capacity);
89  }
90 
91  template<typename T, typename F, int capacity>
93  const int i = static_cast<int>(format);
94  m_constructors[i] = std::move(function);
95  }
96  template<typename T, typename F, int capacity>
98  const int i = static_cast<int>(format);
99  m_validators[i] = std::move(function);
100  }
101  template<typename T, typename F, int capacity>
103  const int i = static_cast<int>(format);
104  m_discards[i] = std::move(function);
105  }
106  template<typename T, typename F, int capacity>
108  const int i = static_cast<int>(format);
109  m_discards[i] = m_validators[i] = std::move(function);
110  }
111  template<typename T, typename F, int capacity>
113  const int i = static_cast<int>(from);
114  const int j = static_cast<int>(to);
115  const int id = static_cast<int>(m_converters.size());
116  m_convert_rules[i].push_back({j, id});
117  m_converters.push_back(std::move(function));
118  }
119 
120  template<typename T, typename F, int capacity>
122  const int i = static_cast<int>(format);
123  if (!storage.get_ptr_i(i)) {
124  m_constructors[i](storage);
125  }
126  }
127  template<typename T, typename F, int capacity>
129  if (storage.is_valid(format)) {
130  return;
131  }
132  if (!storage.is_valid_any()) {
133  const int i = static_cast<int>(format);
134  if (!storage.get_ptr_i(i)) {
135  if (!m_constructors[i]) {
136  LOG_MSG(Status::NotImplemented, "no such constructor for format " << i);
137  assert(false);
138  return;
139  }
140  m_constructors[i](storage);
141  }
142  if (m_validators[i]) {
143  m_validators[i](storage);
144  }
145  storage.validate(format);
146  return;
147  }
148 
149  const int source = -1;
150  const int infinity = -2;
151  const int target = static_cast<int>(format);
152 
153  std::array<int, capacity> reached;
154  std::queue<int> queue;
155  reached.fill(infinity);
156 
157  assert(storage.is_valid_any());
158 
159  for (int i = 0; i < capacity; ++i) {
160  if (storage.is_valid_i(i)) {
161  reached[i] = source;
162  queue.push(i);
163  }
164  }
165 
166  while (reached[target] == infinity) {
167  if (queue.empty()) {
168  LOG_MSG(Status::NotImplemented, "no conversion path to target format " << target);
169  assert(false);
170  return;
171  }
172 
173  int u = queue.front();
174  queue.pop();
175 
176  for (const auto& target_format : m_convert_rules[u]) {
177  if (reached[target_format.first] == infinity) {
178  reached[target_format.first] = u;
179  queue.push(target_format.first);
180  }
181  }
182  }
183 
184  std::vector<std::pair<int, int>> path;
185  int current = target;
186 
187  while (reached[current] != source) {
188  path.push_back({reached[current], current});
189  current = reached[current];
190  }
191 
192  for (auto iter = path.rbegin(); iter != path.rend(); ++iter) {
193  std::pair<int, int> from_to = *iter;
194  auto search_predicate = [from_to](const std::pair<int, int>& rule) { return rule.first == from_to.second; };
195  auto rule = std::find_if(m_convert_rules[from_to.first].begin(), m_convert_rules[from_to.first].end(), search_predicate);
196 
197  if (storage.get_ref_i(from_to.second).is_null()) {
198  m_constructors[from_to.second](storage);
199  }
200 
201  m_converters[rule->second](storage);
202  storage.validate(static_cast<F>(from_to.second));
203  }
204  }
205  template<typename T, typename F, int capacity>
207  validate_rw(format, storage);
208  storage.invalidate();
209  storage.validate(format);
210  }
211  template<typename T, typename F, int capacity>
213  const int i = static_cast<int>(format);
214  if (!storage.get_ptr_i(i)) {
215  m_constructors[i](storage);
216  }
217  if (m_discards[i]) {
218  m_discards[i](storage);
219  }
220  storage.invalidate();
221  storage.validate(format);
222  }
223 
228 }// namespace spla
229 
230 #endif//SPLA_STORAGE_MANAGER_HPP
General format converter for vector or matrix decoration storage.
Definition: storage_manager.hpp:57
std::function< void(Storage &storage)> Function
Definition: storage_manager.hpp:60
TDecorationStorage< T, F, capacity > Storage
Definition: storage_manager.hpp:59
Storage for decorators with data of a particular vector or matrix object.
Definition: tdecoration.hpp:70
void invalidate()
Definition: tdecoration.hpp:84
void validate(F format)
Definition: tdecoration.hpp:83
bool is_valid(F format) const
Definition: tdecoration.hpp:82
TDecoration< T > * get_ptr_i(int index)
Definition: tdecoration.hpp:73
bool is_valid_any() const
Definition: tdecoration.hpp:80
ref_ptr< TDecoration< T > > & get_ref_i(int index)
Definition: tdecoration.hpp:72
bool is_valid_i(int index) const
Definition: tdecoration.hpp:81
void register_converter(F from, F to, Function function)
Definition: storage_manager.hpp:112
StorageManager()
Definition: storage_manager.hpp:84
void register_discard(F format, Function function)
Definition: storage_manager.hpp:102
void validate_wd(F format, Storage &storage)
Definition: storage_manager.hpp:212
void validate_rw(F format, Storage &storage)
Definition: storage_manager.hpp:128
void validate_ctor(F format, Storage &storage)
Definition: storage_manager.hpp:121
void validate_rwd(F format, Storage &storage)
Definition: storage_manager.hpp:206
void register_validator(F format, Function function)
Definition: storage_manager.hpp:97
void register_validator_discard(F format, Function function)
Definition: storage_manager.hpp:107
void register_constructor(F format, Function function)
Definition: storage_manager.hpp:92
#define LOG_MSG(status, msg)
Definition: logger.hpp:66
Definition: algorithm.hpp:37