Flow123d  master-f44eb46
bidirectional_map.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file bidirectional_map.hh
15  * @brief Implementation of bidirectional map.
16  */
17 
18 #ifndef BIDIRECTIONAL_MAP_HH_
19 #define BIDIRECTIONAL_MAP_HH_
20 
21 #include <vector>
22 #include <unordered_map>
23 #include "system/asserts.hh"
24 
25 
26 /**
27  * @brief Bidirectional map templated by <T, unsigned int>.
28  *
29  * Store pairs of value and its position (index) and allow bidirectional search.
30  * Items of both (values, positions) must be unique.
31  */
32 template<typename T>
34 {
35 public:
36  /// Constructor
38 
39  /// Return size of map.
40  unsigned int size() const;
41 
42  /**
43  * Set value of given position.
44  *
45  * Position must be in interval set in \p reinit method <0, init_size-1>.
46  * Element on every position can be set only once.
47  */
48  void set_item(T val, unsigned int pos);
49 
50  /// Add new item at the end position of map.
51  unsigned int add_item(T val);
52 
53  /// Return position of item of given value.
54  int get_position(T val) const;
55 
56  /// Clear the content. Do not release memory.
57  void clear();
58 
59  /// Reset data of map, reserve space for given size.
60  void reserve(unsigned int init_size = 0);
61 
62  /// Resizes to given @p new_size if new size is smaller than the actual.
63  /// The rest of data are thrown away and removed from the map.
64  void resize(unsigned int new_size);
65 
66  /// Return value on given position.
67  T operator[](unsigned int pos) const;
68 
69 private:
70  std::vector<T> vals_vec_; ///< Space to save values.
71  std::unordered_map<T, unsigned int> vals_map_; ///< Maps values to indexes into vals_vec_.
72 };
73 
74 // --------------------------------------------------- BidirectionalMap INLINE implementation -----------
75 template<typename T>
77 {}
78 
79 template<typename T>
80 inline unsigned int BidirectionalMap<T>::size() const {
81  ASSERT_EQ(vals_map_.size(), vals_vec_.size());
82  return vals_map_.size();
83 }
84 
85 template<typename T>
86 inline void BidirectionalMap<T>::set_item(T val, unsigned int pos) {
87  ASSERT_LT( pos, vals_vec_.size() )(pos)(vals_vec_.size()).error("Value id is out of vector size.");
88 
89  auto it = vals_map_.find(vals_vec_[pos]);
90  // possibly erase vals_map[vals_vec_[pos]] if it exists
91  if (it != vals_map_.end()) {
92 
93  // check that the user does not want to duplicate values
94  auto it_dupl = vals_map_.find(val);
95  if(it_dupl != vals_map_.end()){
96  ASSERT(vals_map_[val] == pos)(pos).error("'val' already used in different 'pos'.");
97  }
98  vals_map_.erase(it);
99  }
100 
101  vals_map_[val] = pos;
102  vals_vec_[pos] = val;
103 }
104 
105 template<typename T>
106 inline unsigned int BidirectionalMap<T>::add_item(T val) {
107  ASSERT( vals_map_.find(val) == vals_map_.end() )(val).error("Can not add item since it already exists.");
108  vals_map_[val] = vals_vec_.size();
109  vals_vec_.push_back(val);
110  return vals_map_[val];
111 }
112 
113 template<typename T>
114 inline int BidirectionalMap<T>::get_position(T val) const {
115  typename std::unordered_map<T, unsigned int>::const_iterator iter = vals_map_.find(val);
116  if (iter == vals_map_.end()) return -1;
117  else return iter->second;
118 }
119 
120 template<typename T>
122  vals_map_.clear();
123  vals_vec_.clear();
124 }
125 
126 /// Reset data of map, reserve space for given size.
127 template<typename T>
128 inline void BidirectionalMap<T>::resize(unsigned int new_size)
129 {
130  ASSERT_LT(new_size, vals_vec_.size());
131  for(uint pos = new_size; pos < vals_vec_.size(); pos++){
132  vals_map_.erase(vals_vec_[pos]);
133  }
134  vals_vec_.resize(new_size);
135  ASSERT(vals_vec_.size() == vals_map_.size())(vals_vec_.size())(vals_map_.size());
136 }
137 
138 template<typename T>
139 inline void BidirectionalMap<T>::reserve(unsigned int init_size) {
140  vals_map_.reserve(init_size);
141  vals_vec_.reserve(init_size);
142 }
143 
144 template<typename T>
145 inline T BidirectionalMap<T>::operator[](unsigned int pos) const {
146  ASSERT( pos < vals_vec_.size() )(pos)(vals_vec_.size());
147  return vals_vec_[pos];
148 }
149 
150 
151 #endif // BIDIRECTIONAL_MAP_HH_
Definitions of ASSERTS.
#define ASSERT(expr)
Definition: asserts.hh:351
#define ASSERT_LT(a, b)
Definition of comparative assert macro (Less Than) only for debug mode.
Definition: asserts.hh:301
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Definition: asserts.hh:333
Bidirectional map templated by <T, unsigned int>.
void resize(unsigned int new_size)
Reset data of map, reserve space for given size.
BidirectionalMap()
Constructor.
void clear()
Clear the content. Do not release memory.
std::vector< T > vals_vec_
Space to save values.
unsigned int add_item(T val)
Add new item at the end position of map.
T operator[](unsigned int pos) const
Return value on given position.
int get_position(T val) const
Return position of item of given value.
void reserve(unsigned int init_size=0)
Reset data of map, reserve space for given size.
void set_item(T val, unsigned int pos)
std::unordered_map< T, unsigned int > vals_map_
Maps values to indexes into vals_vec_.
unsigned int size() const
Return size of map.
unsigned int uint