Hermes2D  3.0
hash.cpp
1 // This file is part of Hermes2D.
2 //
3 // Hermes2D is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 2 of the License, or
6 // (at your option) any later version.
7 //
8 // Hermes2D is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Hermes2D. If not, see <http://www.gnu.org/licenses/>.
15 
16 #include "global.h"
17 #include "mesh.h"
18 #include "hash.h"
19 
20 namespace Hermes
21 {
22  namespace Hermes2D
23  {
24  HashTable::HashTable()
25  {
26  v_table = nullptr; e_table = nullptr;
27  }
28 
29  HashTable::~HashTable()
30  {
31  free();
32  }
33 
34  void HashTable::init(int size)
35  {
36  v_table = e_table = nullptr;
37 
38  mask = size - 1;
39  if (size & mask) throw Hermes::Exceptions::Exception("Parameter 'size' must be a power of two.");
40 
41  // allocate and initialize the hash tables
42  v_table = new Node*[size];
43  e_table = new Node*[size];
44 
45  memset(v_table, 0, size * sizeof(Node*));
46  memset(e_table, 0, size * sizeof(Node*));
47  }
48 
49  void HashTable::copy_list(Node** ptr, Node* node)
50  {
51  while (node != nullptr)
52  {
53  *ptr = &nodes[node->id];
54  ptr = &((*ptr)->next_hash);
55  node = node->next_hash;
56  }
57  *ptr = nullptr;
58  }
59 
60  Node* HashTable::get_node(int id) const
61  {
62  return &(nodes[id]);
63  }
64 
66  {
67  return nodes.get_num_items();
68  }
69 
71  {
72  return nodes.get_size();
73  }
74 
75  void HashTable::copy(const HashTable* ht)
76  {
77  free();
78  nodes.copy(ht->nodes);
79  mask = ht->mask;
80 
81  v_table = new Node*[mask + 1];
82  e_table = new Node*[mask + 1];
83  for (int i = 0; i <= mask; i++)
84  {
85  copy_list(v_table + i, ht->v_table[i]);
86  copy_list(e_table + i, ht->e_table[i]);
87  }
88  }
89 
91  {
92  memset(v_table, 0, (mask + 1) * sizeof(Node*));
93  memset(e_table, 0, (mask + 1) * sizeof(Node*));
94 
95  Node* node;
96  for_all_nodes(node, this)
97  {
98  int p1 = node->p1, p2 = node->p2;
99  if (p1 > p2) std::swap(p1, p2);
100  int idx = hash(p1, p2);
101 
102  if (node->type == HERMES_TYPE_VERTEX)
103  {
104  node->next_hash = v_table[idx];
105  v_table[idx] = node;
106  }
107  else
108  {
109  node->next_hash = e_table[idx];
110  e_table[idx] = node;
111  }
112  }
113  }
114 
116  {
117  nodes.free();
118  if (v_table != nullptr)
119  {
120  delete[] v_table;
121  v_table = nullptr;
122  }
123  if (e_table != nullptr)
124  {
125  delete[] e_table;
126  e_table = nullptr;
127  }
128  }
129 
130  inline Node* HashTable::search_list(Node* node, int p1, int p2) const
131  {
132  while (node != nullptr)
133  {
134  if (node->p1 == p1 && node->p2 == p2)
135  return node;
136  node = node->next_hash;
137  }
138  return nullptr;
139  }
140 
142  {
143  // search for the node in the vertex hashtable
144  if (p1 > p2) std::swap(p1, p2);
145  int i = hash(p1, p2);
146  Node* node = search_list(v_table[i], p1, p2);
147  if (node != nullptr)
148  return node;
149 
150  // not found - create a new_ one
151  Node* newnode = nodes.add();
152 
153  // initialize the new_ Node
154  newnode->type = HERMES_TYPE_VERTEX;
155  newnode->ref = 0;
156  newnode->bnd = 0;
157  newnode->p1 = p1;
158  newnode->p2 = p2;
159  assert(nodes[p1].type == HERMES_TYPE_VERTEX && nodes[p2].type == HERMES_TYPE_VERTEX);
160  newnode->x = (nodes[p1].x + nodes[p2].x) * 0.5;
161  newnode->y = (nodes[p1].y + nodes[p2].y) * 0.5;
162 
163  // insert into hashtable
164  newnode->next_hash = v_table[i];
165  v_table[i] = newnode;
166 
167  return newnode;
168  }
169 
171  {
172  // search for the node in the edge hashtable
173  if (p1 > p2) std::swap(p1, p2);
174  int i = hash(p1, p2);
175  Node* node = search_list(e_table[i], p1, p2);
176  if (node != nullptr) return node;
177 
178  // not found - create a new_ one
179  Node* newnode = nodes.add();
180 
181  // initialize the new_ node
182  newnode->type = HERMES_TYPE_EDGE;
183  newnode->ref = 0;
184  newnode->bnd = 0;
185  newnode->p1 = p1;
186  newnode->p2 = p2;
187  newnode->marker = 0;
188  newnode->elem[0] = newnode->elem[1] = nullptr;
189 
190  // insert into hashtable
191  newnode->next_hash = e_table[i];
192  e_table[i] = newnode;
193 
194  return newnode;
195  }
196 
197  Node* HashTable::peek_vertex_node(int p1, int p2) const
198  {
199  if (p1 > p2) std::swap(p1, p2);
200  return search_list(v_table[hash(p1, p2)], p1, p2);
201  }
202 
203  Node* HashTable::peek_edge_node(int p1, int p2) const
204  {
205  if (p1 > p2) std::swap(p1, p2);
206  return search_list(e_table[hash(p1, p2)], p1, p2);
207  }
208 
210  {
211  // remove the node from the hash table
212  int i = hash(nodes[id].p1, nodes[id].p2);
213  Node** ptr = v_table + i;
214  Node* node = *ptr;
215  while (node != nullptr)
216  {
217  if (node->id == id)
218  {
219  *ptr = node->next_hash;
220  break;
221  }
222  ptr = &node->next_hash;
223  node = *ptr;
224  }
225 
226  // remove node from the array
227  nodes.remove(id);
228  }
229 
231  {
232  // remove the node from the hash table
233  int i = hash(nodes[id].p1, nodes[id].p2);
234  Node** ptr = e_table + i;
235  Node* node = *ptr;
236  while (node != nullptr)
237  {
238  if (node->id == id)
239  {
240  *ptr = node->next_hash;
241  break;
242  }
243  ptr = &node->next_hash;
244  node = *ptr;
245  }
246 
247  // remove node from the array
248  nodes.remove(id);
249  }
250  }
251 }
::xsd::cxx::tree::id< char, ncname > id
C++ type corresponding to the ID XML Schema built-in type.
double x
vertex node coordinates
Definition: element.h:63
Node * peek_edge_node(int p1, int p2) const
Returns an edge node with parent id's p1 and p2 if it exists, nullptr otherwise.
Definition: hash.cpp:203
unsigned type
0 = vertex node; 1 = edge node
Definition: element.h:52
int id
node id number
Definition: element.h:48
Definition: adapt.h:24
Node * get_vertex_node(int p1, int p2)
Definition: hash.cpp:141
void init(int size=H2D_DEFAULT_HASH_SIZE)
Definition: hash.cpp:34
Node * get_edge_node(int p1, int p2)
Definition: hash.cpp:170
Node * next_hash
next node in hash synonym list
Definition: element.h:77
Element * elem[2]
elements sharing the edge node
Definition: element.h:70
void remove_edge_node(int id)
Removes an edge node with parent id's p1 and p2.
Definition: hash.cpp:230
Node * get_node(int id) const
Retrieves a node by its id number.
Definition: hash.cpp:60
void remove_vertex_node(int id)
Removes a vertex node with parent id's p1 and p2.
Definition: hash.cpp:209
void rebuild()
Reconstructs the hashtable, after, e.g., the nodes have been loaded from a file.
Definition: hash.cpp:90
Common definitions for Hermes2D.
Stores one node of a mesh.
Definition: element.h:45
::xsd::cxx::tree::type type
C++ type corresponding to the anyType XML Schema built-in type.
void free()
Frees all memory used by the instance.
Definition: hash.cpp:115
Node * peek_vertex_node(int p1, int p2) const
Returns a vertex node with parent id's p1 and p2 if it exists, nullptr otherwise. ...
Definition: hash.cpp:197
int get_num_nodes() const
Returns the total number of nodes stored.
Definition: hash.cpp:65
Array< Node > nodes
Array storing all nodes.
Definition: hash.h:77
int p1
parent id numbers
Definition: element.h:75
unsigned bnd
1 = boundary node; 0 = inner node
Definition: element.h:54
unsigned ref
the number of elements using the node
Definition: element.h:50
void copy(const HashTable *ht)
Copies another hash table contents.
Definition: hash.cpp:75
int marker
edge marker
Definition: element.h:68
Stores and searches node tables.
Definition: hash.h:39
int get_max_node_id() const
Returns the maximum node id number plus one.
Definition: hash.cpp:70