Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

RegisteredMultiArray.h
Go to the documentation of this file.
1 
31 #pragma once
32 
33 
34 #include <ogdf/basic/basic.h>
36 
37 #include <cstddef>
38 #include <cstdint>
39 #include <stdexcept>
40 #include <tuple>
41 #include <unordered_map>
42 #include <utility>
43 
44 namespace ogdf {
45 
47 
51 template<typename Key2, typename Value, int array_max>
53  using ValuePairType = std::pair<Key2, Value>;
54  using ValueArrayType = std::array<ValuePairType, array_max>;
55  using ValueMapType = std::unordered_map<Key2, Value>;
56 
57  uint8_t m_size = 0;
58  void* m_value = nullptr;
59 
60 
61  UsuallySmallMap() = default;
62 
64  if (m_value != nullptr) {
65  if (m_size <= 0) {
66  delete (ValueMapType*)m_value;
67  } else if (m_size == 1) {
68  delete (ValuePairType*)m_value;
69  } else {
70  delete (ValueArrayType*)m_value;
71  }
72  }
73  }
74 
76  if (copy.m_value == nullptr) {
77  m_value = nullptr;
78  } else if (m_size <= 0) {
79  m_value = new ValueMapType(copy.getValueMap());
80  } else if (m_size == 1) {
81  m_value = new ValuePairType(copy.getValueScalar());
82  } else {
83  m_value = new ValueArrayType(copy.getValueArray());
84  }
85  }
86 
88 
90  using std::swap;
91  swap(first.m_size, second.m_size);
92  swap(first.m_value, second.m_value);
93  }
94 
95  void unset(const Key2& key) {
96  if (!contains(key)) {
97  return;
98  }
99  if (m_size <= 0) {
100  ValueMapType& map = getValueMap();
101  int cnt = map.erase(key);
102  OGDF_ASSERT(cnt == 1);
103  } else if (m_size == 1) {
104  delete (ValuePairType*)m_value;
105  m_value = nullptr;
106  m_size = 0;
107  } else {
108  ValueArrayType& array = getValueArray();
109  for (int i = 0; i < m_size; ++i) {
110  if (array[i].first == key) {
111  if (i != m_size - 1) {
112  using std::swap;
113  swap(array[i], array[m_size - 1]);
114  }
115  m_size--;
116  break;
117  }
118  }
119  }
120  }
121 
122  Value& get_or_create(const Key2& key, const Value& def = Value()) {
123  if (m_value == nullptr) {
124  // create scalar value
125  m_size = 1;
126  ValuePairType* pair = new ValuePairType(key, def);
127  m_value = pair;
128  return pair->second;
129  } else if (m_size <= 0) {
130  ValueMapType& map = getValueMap();
131  auto it = map.find(key);
132  if (it != map.end()) {
133  return it->second;
134  }
135 
136  // insert into map
137  auto ins = map.insert({key, def});
138  OGDF_ASSERT(ins.second);
139  return ins.first->second;
140  } else if (m_size == 1) {
141  ValuePairType& pair = getValueScalar();
142  if (pair.first == key) {
143  return pair.second;
144  }
145 
146  // convert to array
147  m_size = 2;
148  ValueArrayType* array = new ValueArrayType {std::move(pair), ValuePairType(key, def)};
149  delete (ValuePairType*)m_value;
150  m_value = array;
151  return (*array)[1].second;
152  } else {
153  ValueArrayType& array = getValueArray();
154  for (int i = 0; i < m_size; ++i) {
155  if (array[i].first == key) {
156  return array[i].second;
157  }
158  }
159 
160  if (m_size < array_max) {
161  // insert into array
162  int i = m_size;
163  m_size++;
164  array[i] = ValuePairType(key, def);
165  return array[i].second;
166  } else {
167  // convert to map
168  ValueMapType* map = new ValueMapType();
169  for (int i = 0; i < array_max; ++i) {
170  map->insert(std::move(array[i]));
171  }
172  delete (ValueArrayType*)m_value;
173  m_value = map;
174  m_size = 0;
175  return get_or_create(key);
176  }
177  }
178  }
179 
180  Value& get_or_raise(const Key2& key) const {
181  if (m_value == nullptr) {
182  throw std::out_of_range("no keys stored");
183  } else if (m_size <= 0) {
184  ValueMapType& map = getValueMap();
185  auto it = map.find(key);
186  if (it == map.end()) {
187  throw std::out_of_range("key not in map");
188  }
189  return it->second;
190  } else if (m_size == 1) {
191  ValuePairType& pair = getValueScalar();
192  if (pair.first == key) {
193  return pair.second;
194  } else {
195  throw std::out_of_range("key not in scalar");
196  }
197  } else {
198  ValueArrayType& array = getValueArray();
199  for (int i = 0; i < m_size; ++i) {
200  if (array[i].first == key) {
201  return array[i].second;
202  }
203  }
204  throw std::out_of_range("key not in array");
205  }
206  }
207 
208  bool contains(const Key2& key) const {
209  if (m_value == nullptr) {
210  return false;
211  } else if (m_size <= 0) {
212  return getValueMap().count(key);
213  } else if (m_size == 1) {
214  return getValueScalar().first == key;
215  } else {
216  ValueArrayType& array = getValueArray();
217  for (int i = 0; i < m_size; ++i) {
218  if (array[i].first == key) {
219  return true;
220  }
221  }
222  return false;
223  }
224  }
225 
226  bool empty() const { return m_value == nullptr; }
227 
228  size_t size() const {
229  if (m_value == nullptr) {
230  return 0;
231  } else if (m_size > 0) {
232  return m_size;
233  } else {
234  return getValueMap().size();
235  }
236  }
237 
238  bool usesMap() const { return m_size == 0 && m_value != nullptr; }
239 
241  OGDF_ASSERT(m_size == 1);
242  OGDF_ASSERT(m_value != nullptr);
243  return *((ValuePairType*)m_value);
244  }
245 
247  OGDF_ASSERT(m_size > 1);
248  OGDF_ASSERT(m_value != nullptr);
249  return *((ValueArrayType*)m_value);
250  }
251 
253  OGDF_ASSERT(m_size == 0);
254  OGDF_ASSERT(m_value != nullptr);
255  return *((ValueMapType*)m_value);
256  }
257 };
258 
259 template<typename Key1, typename Key2, typename Value, template<typename...> class BaseArray,
260  int array_max = 64>
262 
270 public:
272 
273  RegisteredMultiArray() = default;
274 
277 
278  template<class... T>
279  explicit RegisteredMultiArray(T&&... t) : m_array(std::forward<T>(t)...) {};
280 
281  Value& operator()(const Key1& k1, const Key2& k2) { return m_array[k1].get_or_create(k2); }
282 
283  Value& get_or_create(const Key1& k1, const Key2& k2) { return m_array[k1].get_or_create(k2); }
284 
285  Value& get_or_raise(const Key1& k1, const Key2& k2) { return m_array[k1].get_or_raise(k2); }
286 
287  const Value& get_or_raise(const Key1& k1, const Key2& k2) const {
288  return m_array[k1].get_or_raise(k2);
289  }
290 
291  EntryType& get_all(const Key1& k1) { return m_array[k1]; }
292 
293  const EntryType& get_all(const Key1& k1) const { return m_array[k1]; }
294 
295  void remove(const Key1& k1, const Key2& k2) { return m_array[k1].unset(k2); }
296 
297  bool contains(const Key1& k1, const Key2& k2) const { return m_array[k1].contains(k2); }
298 
299  size_t count(const Key1& k1) const { return m_array[k1].size(k1); }
300 
301  bool has(const Key1& k1) const { return !m_array[k1].empty(k1); }
302 
303 private:
304  BaseArray<EntryType> m_array;
305 };
306 
307 }
ogdf
The namespace for all OGDF objects.
Definition: multilevelmixer.cpp:39
ogdf::UsuallySmallMap::getValueArray
ValueArrayType & getValueArray() const
Definition: RegisteredMultiArray.h:246
ogdf::RegisteredMultiArray::remove
void remove(const Key1 &k1, const Key2 &k2)
Definition: RegisteredMultiArray.h:295
ogdf::UsuallySmallMap::get_or_raise
Value & get_or_raise(const Key2 &key) const
Definition: RegisteredMultiArray.h:180
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:66
ogdf::UsuallySmallMap::swap
friend void swap(UsuallySmallMap &first, UsuallySmallMap &second) noexcept
Definition: RegisteredMultiArray.h:89
copy_move.h
Utility macros for declaring copy and move constructors and assignment operations.
ogdf::UsuallySmallMap::getValueScalar
ValuePairType & getValueScalar() const
Definition: RegisteredMultiArray.h:240
OGDF_DEFAULT_MOVE
#define OGDF_DEFAULT_MOVE(cls)
Explicitly provides default move construction and assignment for class cls.
Definition: copy_move.h:52
ogdf::UsuallySmallMap::empty
bool empty() const
Definition: RegisteredMultiArray.h:226
ogdf::RegisteredMultiArray::RegisteredMultiArray
RegisteredMultiArray(T &&... t)
Definition: RegisteredMultiArray.h:279
ogdf::RegisteredMultiArray::operator()
Value & operator()(const Key1 &k1, const Key2 &k2)
Definition: RegisteredMultiArray.h:281
ogdf::UsuallySmallMap::usesMap
bool usesMap() const
Definition: RegisteredMultiArray.h:238
ogdf::UsuallySmallMap::ValueArrayType
std::array< ValuePairType, array_max > ValueArrayType
Definition: RegisteredMultiArray.h:54
ogdf::RegisteredMultiArray::m_array
BaseArray< EntryType > m_array
Definition: RegisteredMultiArray.h:304
ogdf::UsuallySmallMap
A wrapper around std::map that uses a constant-size array (or only a single value) plus linear search...
Definition: RegisteredMultiArray.h:52
ogdf::UsuallySmallMap::m_size
uint8_t m_size
Definition: RegisteredMultiArray.h:57
ogdf::UsuallySmallMap::UsuallySmallMap
UsuallySmallMap()=default
ogdf::UsuallySmallMap::unset
void unset(const Key2 &key)
Definition: RegisteredMultiArray.h:95
Minisat::Internal::copy
static void copy(const T &from, T &to)
Definition: Alg.h:61
ogdf::RegisteredMultiArray
Data structure for two-dimensional mappings that are sparse in the second dimension.
Definition: RegisteredMultiArray.h:269
backward::details::move
const T & move(const T &v)
Definition: backward.hpp:243
ogdf::UsuallySmallMap::get_or_create
Value & get_or_create(const Key2 &key, const Value &def=Value())
Definition: RegisteredMultiArray.h:122
ogdf::RegisteredMultiArray::get_or_raise
Value & get_or_raise(const Key1 &k1, const Key2 &k2)
Definition: RegisteredMultiArray.h:285
ogdf::RegisteredMultiArray::get_or_raise
const Value & get_or_raise(const Key1 &k1, const Key2 &k2) const
Definition: RegisteredMultiArray.h:287
ogdf::UsuallySmallMap::contains
bool contains(const Key2 &key) const
Definition: RegisteredMultiArray.h:208
ogdf::UsuallySmallMap::getValueMap
ValueMapType & getValueMap() const
Definition: RegisteredMultiArray.h:252
ogdf::RegisteredMultiArray::count
size_t count(const Key1 &k1) const
Definition: RegisteredMultiArray.h:299
ogdf::RegisteredMultiArray::get_all
const EntryType & get_all(const Key1 &k1) const
Definition: RegisteredMultiArray.h:293
ogdf::UsuallySmallMap::size
size_t size() const
Definition: RegisteredMultiArray.h:228
OGDF_COPY_MOVE_BY_SWAP
#define OGDF_COPY_MOVE_BY_SWAP(cls)
Provide move construct/assign and copy assign given there is a copy constructor and swap.
Definition: copy_move.h:76
ogdf::RegisteredMultiArray::get_all
EntryType & get_all(const Key1 &k1)
Definition: RegisteredMultiArray.h:291
ogdf::RegisteredMultiArray::has
bool has(const Key1 &k1) const
Definition: RegisteredMultiArray.h:301
basic.h
Basic declarations, included by all source files.
std
Definition: GML.h:111
ogdf::RegisteredMultiArray::contains
bool contains(const Key1 &k1, const Key2 &k2) const
Definition: RegisteredMultiArray.h:297
ogdf::UsuallySmallMap::~UsuallySmallMap
~UsuallySmallMap()
Definition: RegisteredMultiArray.h:63
ogdf::UsuallySmallMap::UsuallySmallMap
UsuallySmallMap(const UsuallySmallMap &copy)
Definition: RegisteredMultiArray.h:75
ogdf::UsuallySmallMap::ValuePairType
std::pair< Key2, Value > ValuePairType
Definition: RegisteredMultiArray.h:53
ogdf::RegisteredMultiArray::get_or_create
Value & get_or_create(const Key1 &k1, const Key2 &k2)
Definition: RegisteredMultiArray.h:283
ogdf::UsuallySmallMap::ValueMapType
std::unordered_map< Key2, Value > ValueMapType
Definition: RegisteredMultiArray.h:55
OGDF_DEFAULT_COPY
#define OGDF_DEFAULT_COPY(cls)
Explicitly provides default copy construction and assignment for class cls.
Definition: copy_move.h:47
ogdf::RegisteredMultiArray::RegisteredMultiArray
RegisteredMultiArray()=default
ogdf::UsuallySmallMap::m_value
void * m_value
Definition: RegisteredMultiArray.h:58
OGDF_SWAP_OP
#define OGDF_SWAP_OP(cls)
Declares the swap function for class cls.
Definition: copy_move.h:65