SHOGUN  v3.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Map.h
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 3 of the License, or
5  * (at your option) any later version.
6  *
7  * Written (W) 2012 Evgeniy Andreev (gsomix)
8  *
9  * Copyright (C) 2012 Evgeniy Andreev (gsomix)
10  */
11 
12 #ifndef _MAP_H_
13 #define _MAP_H_
14 
15 #include <shogun/base/SGObject.h>
16 #include <shogun/lib/common.h>
17 #include <shogun/lib/Hash.h>
18 #include <shogun/base/DynArray.h>
19 
20 #include <cstdio>
21 
22 #include <shogun/io/SGIO.h>
23 #include <shogun/lib/Lock.h>
24 
25 
26 namespace shogun
27 {
28 
29 #define IGNORE_IN_CLASSLIST
30 
31 #define MapNode CMapNode<K, T>
32 
33 #ifndef DOXYGEN_SHOULD_SKIP_THIS
34 
35 IGNORE_IN_CLASSLIST template<class K, class T> struct CMapNode
36 {
38  int32_t index;
39 
41  bool free;
42 
44  K key;
45 
47  T data;
48 
50  CMapNode *left;
51 
53  CMapNode *right;
54 };
55 #endif
56 
60 IGNORE_IN_CLASSLIST template<class K, class T> class CMap: public CSGObject
61 {
62 public:
64  CMap(int32_t size=41, int32_t reserved=128, bool tracable=true)
65  {
66  hash_size=size;
67  free_index=0;
68  num_elements=0;
69  use_sg_mallocs=tracable;
70 
71  if (use_sg_mallocs)
72  hash_array=SG_CALLOC(MapNode*, size);
73  else
74  hash_array=(CMapNode<K, T>**) calloc(size, sizeof(CMapNode<K, T>*));
75 
76  for (int32_t i=0; i<size; i++)
77  {
78  hash_array[i]=NULL;
79  }
80 
81  array=new DynArray<CMapNode<K, T>*>(reserved, tracable);
82  }
83 
85  virtual ~CMap()
86  {
87  destroy_map();
88  }
89 
91  virtual const char* get_name() const { return "Map"; }
92 
99  int32_t add(const K& key, const T& data)
100  {
101  int32_t index=hash(key);
102  if (chain_search(index, key)==NULL)
103  {
104  lock.lock();
105  int32_t added_index=insert_key(index, key, data);
106  num_elements++;
107  lock.unlock();
108 
109  return added_index;
110  }
111 
112  return -1;
113  }
114 
120  bool contains(const K& key)
121  {
122  int32_t index=hash(key);
123  if (chain_search(index, key)!=NULL)
124  return true;
125 
126  return false;
127  }
128 
133  void remove(const K& key)
134  {
135  int32_t index=hash(key);
136  CMapNode<K, T>* result=chain_search(index, key);
137 
138  if (result!=NULL)
139  {
140  lock.lock();
141  delete_key(index, result);
142  num_elements--;
143  lock.unlock();
144  }
145  }
146 
152  int32_t index_of(const K& key)
153  {
154  int32_t index=hash(key);
155  CMapNode<K ,T>* result=chain_search(index, key);
156 
157  if (result!=NULL)
158  return result->index;
159 
160  return -1;
161  }
162 
169  T get_element(const K& key)
170  {
171  int32_t index=hash(key);
172  CMapNode<K, T>* result=chain_search(index, key);
173 
174  if (result!=NULL)
175  return result->data;
176  else
177  {
178  int32_t added_index=add(key, T());
179  result=get_node_ptr(added_index);
180 
181  return result->data;
182  }
183  }
184 
190  void set_element(const K& key, const T& data)
191  {
192  int32_t index=hash(key);
193  CMapNode<K, T>* result=chain_search(index, key);
194 
195  lock.lock();
196 
197  if (result!=NULL)
198  result->data=data;
199  else
200  add(key, data);
201 
202  lock.unlock();
203  }
204 
209  int32_t get_num_elements() const
210  {
211  return num_elements;
212  }
213 
218  int32_t get_array_size() const
219  {
220  return array->get_num_elements();
221  }
222 
230  T* get_element_ptr(int32_t index)
231  {
232  CMapNode<K, T>* result=array->get_element(index);
233  if (result!=NULL && !is_free(result))
234  return &(array->get_element(index)->data);
235  return NULL;
236  }
237 
245  CMapNode<K, T>* get_node_ptr(int32_t index)
246  {
247  return array->get_element(index);
248  }
249 
251  CMapNode<K, T>** get_array()
252  {
253  return array->get_array();
254  }
255 
257  CMap& operator =(const CMap& orig)
258  {
259 
260  destroy_map();
262 
263  hash_size = orig.hash_size;
264 
265  if (use_sg_mallocs)
266  hash_array = SG_CALLOC(MapNode*, hash_size);
267  else
268  hash_array = (CMapNode<K, T>**) calloc(hash_size,
269  sizeof(CMapNode<K, T>*));
270 
271  for (int32_t i = 0; i<hash_size; i++)
272  {
273  hash_array[i] = NULL;
274  }
275 
277 
278  for (int i = 0; i < orig.num_elements; i++)
279  {
280  CMapNode<K, T>* node = orig.array->get_element(i);
281  add(node->key, node->data);
282  }
283 
284  return *this;
285  }
286 
287 private:
291  int32_t hash(const K& key)
292  {
293  return CHash::MurmurHash3((uint8_t*)(&key), sizeof(key), 0xDEADBEEF) % hash_size;
294  }
295 
297  bool is_free(CMapNode<K, T>* node)
298  {
299  if (node->free==true)
300  return true;
301 
302  return false;
303  }
304 
306  CMapNode<K, T>* chain_search(int32_t index, const K& key)
307  {
308  if (hash_array[index]==NULL)
309  {
310  return NULL;
311  }
312  else
313  {
314  CMapNode<K, T>* current=hash_array[index];
315 
316  do // iterating all items in the list
317  {
318  if (current->key==key)
319  return current; // it's a search key
320 
321  current=current->right;
322 
323  } while (current!=NULL);
324 
325  return NULL;
326  }
327  }
328 
330  int32_t insert_key(int32_t index, const K& key, const T& data)
331  {
332  int32_t new_index;
333  CMapNode<K, T>* new_node;
334 
336  {
337  // init new node
338  if (use_sg_mallocs)
339  new_node=SG_CALLOC(MapNode, 1);
340  else
341  new_node=(CMapNode<K, T>*) calloc(1, sizeof(CMapNode<K, T>));
342 
343  new (&new_node->key) K();
344  new (&new_node->data) T();
345 
346  array->append_element(new_node);
347 
348  new_index=free_index;
349  free_index++;
350  }
351  else
352  {
353  new_node=array->get_element(free_index);
354  ASSERT(is_free(new_node))
355 
356  new_index=free_index;
357  free_index=new_node->index;
358  }
359 
360  new_node->index=new_index;
361  new_node->free=false;
362  new_node->key=key;
363  new_node->data=data;
364  new_node->left=NULL;
365  new_node->right=NULL;
366 
367  // add new node in start of list
368  if (hash_array[index]==NULL)
369  {
370  hash_array[index]=new_node;
371  }
372  else
373  {
374  hash_array[index]->left=new_node;
375  new_node->right=hash_array[index];
376 
377  hash_array[index]=new_node;
378  }
379 
380  return new_index;
381  }
382 
384  void delete_key(int32_t index, CMapNode<K, T>* node)
385  {
386  int32_t temp=0;
387 
388  if (node==NULL)
389  return;
390 
391  if (node->right!=NULL)
392  node->right->left = node->left;
393 
394  if (node->left!=NULL)
395  node->left->right = node->right;
396  else
397  hash_array[index] = node->right;
398 
399  temp=node->index;
400 
401  node->index=free_index;
402  node->free=true;
403  node->left=NULL;
404  node->right=NULL;
405 
406  free_index=temp;
407  }
408 
409  /*cleans up map*/
410  void destroy_map()
411  {
412  if (array!=NULL)
413  {
414  for(int32_t i=0; i<array->get_num_elements(); i++)
415  {
416  CMapNode<K, T>* element = array->get_element(i);
417  if (element!=NULL)
418  {
419  element->key.~K();
420  element->data.~T();
421 
422  if (use_sg_mallocs)
423  SG_FREE(element);
424  else
425  free(element);
426  }
427  }
428  delete array;
429  }
430 
431  if (hash_array!=NULL)
432  {
433  if (use_sg_mallocs)
434  SG_FREE(hash_array);
435  else
436  free(hash_array);
437  }
438 
439  }
440 
441 protected:
444 
446  int32_t hash_size;
447 
449  int32_t free_index;
450 
452  int32_t num_elements;
453 
455  CMapNode<K, T>** hash_array;
456 
459 
462 };
463 
464 }
465 
466 #endif /* _MAP_H_ */

SHOGUN Machine Learning Toolbox - Documentation