rsvs3D  0.0.0
Codes for the c++ implementation of the 3D RSVS
arraystructures_incl.cpp
1 /*
2 File for the implementation of the class template ArrayStruct
3 this .cpp file is INCLUDED as part of arraystructures.hpp and cannot be
4 compiled on its own.
5 
6 */
7 #ifndef ARRAYSTRUCTS_INCL_H_INCLUDED
8 #define ARRAYSTRUCTS_INCL_H_INCLUDED
9 
10 #include "arraystructures.hpp"
11 #include "warning.hpp"
12 
13 template <class T> void ConcatenateVector(std::vector<T> &vecRoot, const std::vector<T> &vecConcat)
14 {
15  vecRoot.insert(vecRoot.end(), vecConcat.begin(), vecConcat.end());
16 }
17 
18 template <class T> bool CompareDisp(T &mesh1, T &mesh2)
19 {
20  bool compFlag;
21  std::stringstream ss1, ss2;
22  auto old_buf = std::cout.rdbuf(ss1.rdbuf());
23 
24  mesh1.disp();
25  std::cout.rdbuf(ss2.rdbuf());
26  mesh2.disp();
27  std::cout.rdbuf(old_buf);
28 
29  compFlag = ss1.str().compare(ss2.str()) == 0;
30  return (compFlag);
31 }
32 
33 template <class T> void DisplayVector(std::vector<T> vec)
34 {
35  PrintVector(vec, std::cout);
36 }
37 template <class T> void PrintVector(std::vector<T> vec, std::ostream &streamout)
38 {
39  streamout << int(vec.size()) << " - ";
40  for (int i = 0; i < int(vec.size()); ++i)
41  {
42  streamout << vec[i] << " ";
43  }
44  streamout << " | ";
45 }
46 
47 template <class T> void DisplayVectorStatistics(std::vector<T> vec)
48 {
49  std::cout << int(vec.size()) << " - ";
50  std::cout << *min_element(vec.begin(), vec.end()) << " " << *max_element(vec.begin(), vec.end()) << " ";
51  T s = 0;
52  for (auto &n : vec)
53  {
54  s += n;
55  }
56  std::cout << s << " " << double(s) / double(vec.size());
57  std::cout << " | ";
58 }
59 
60 template <class T, class R>
61 R ConcatenateVectorField(const ArrayStruct<T> &arrayIn, R T::*mp, const std::vector<int> &subList)
62 {
63  R surfInds;
64  int ii;
65  auto itVecInt = surfInds.begin();
66 
67  for (ii = 0; ii < int(subList.size()); ++ii)
68  {
69  surfInds.insert(itVecInt, (arrayIn(subList[ii])->*mp).begin(), (arrayIn(subList[ii])->*mp).end());
70  itVecInt = surfInds.end();
71  // vDisplayVector(arrayIn(subList[ii])->*mp);std::cout << std::endl;
72  }
73  return (surfInds);
74 }
75 
76 template <class T, class R>
77 std::vector<R> ConcatenateScalarField(const ArrayStruct<T> &arrayIn, R T::*mp, const std::vector<int> &subList)
78 {
79  std::vector<R> surfInds;
80  int ii;
81  surfInds.reserve(subList.size());
82  for (ii = 0; ii < int(subList.size()); ++ii)
83  {
84  surfInds.push_back((arrayIn(subList[ii])->*mp));
85  // vDisplayVector(arrayIn(subList[ii])->*mp);std::cout << std::endl;
86  }
87  return (surfInds);
88 }
89 
90 template <class T, class R> R ConcatenateVectorField(const ArrayStruct<T> &arrayIn, R T::*mp, int rStart, int rEnd)
91 {
92  R surfInds;
93  int ii;
94  auto itVecInt = surfInds.begin();
95 
96  for (ii = rStart; ii < rEnd; ++ii)
97  {
98  surfInds.insert(itVecInt, (arrayIn(ii)->*mp).begin(), (arrayIn(ii)->*mp).end());
99  itVecInt = surfInds.end();
100  // vDisplayVector(arrayIn(subList[ii])->*mp);std::cout << std::endl;
101  }
102  return (surfInds);
103 }
104 
105 template <class T, class R>
106 std::vector<R> ConcatenateScalarField(const ArrayStruct<T> &arrayIn, R T::*mp, int rStart, int rEnd)
107 {
108  std::vector<R> surfInds;
109  int ii;
110  surfInds.reserve((rStart - rEnd) > 0 ? (rStart - rEnd) : 0);
111  for (ii = rStart; ii < rEnd; ++ii)
112  {
113  surfInds.push_back((arrayIn(ii)->*mp));
114  // vDisplayVector(arrayIn(subList[ii])->*mp);std::cout << std::endl;
115  }
116  return (surfInds);
117 }
118 
119 template <class T, class R, class U, class V>
120 void OperArrayStructMethod(const ArrayStruct<T> &arrayIn, const std::vector<int> &subList, R T::*mp, U &out, V oper)
121 {
122  int ii;
123 
124  for (ii = 0; ii < int(subList.size()); ++ii)
125  {
126  out = oper(out, (arrayIn(subList[ii])->*mp)());
127 
128  // vDisplayVector(arrayIn(subList[ii])->*mp);std::cout << std::endl;
129  }
130 }
131 template <class T, class R> std::vector<R> ReturnDataEqualRange(T key, const std::unordered_multimap<T, R> &hashTable)
132 {
133  std::vector<R> subList;
134 
135  subList.reserve(5);
136  auto range = hashTable.equal_range(key);
137  for (auto it = range.first; it != range.second; ++it)
138  {
139  subList.push_back(it->second);
140  }
141 
142  return (subList);
143 }
144 template <class T, class R>
145 void ReturnDataEqualRange(T key, const std::unordered_multimap<T, R> &hashTable, std::vector<R> &subList)
146 {
147  subList.clear();
148  subList.reserve(5);
149  auto range = hashTable.equal_range(key);
150  for (auto it = range.first; it != range.second; ++it)
151  {
152  subList.push_back(it->second);
153  }
154 }
155 template <typename T> inline void sort(std::vector<T> &vec)
156 {
157  sort(vec.begin(), vec.end());
158 }
159 template <typename T> inline void unique(std::vector<T> &vec)
160 {
161  auto itVecInt = std::unique(vec.begin(), vec.end());
162  vec.resize(std::distance(vec.begin(), itVecInt));
163 }
164 // template <typename T> inline void set_intersection(std::vector<T>
165 // &targVec,std::vector<T> &vec1,std::vector<T> &vec2,bool isSort)
166 // {
167 // T tempType;
168 // typename std::vector<T>::iterator it;
169 // targVec.assign(vec1.size(),tempType);
170 // if(!isSort){
171 // sort(vec1);
172 // sort(vec2);
173 // }
174 // it
175 // =set_intersection(vec1.begin(),vec1.end(),vec2.begin(),vec2.end(),targVec.begin());
176 
177 // targVec.resize(it-targVec.begin());
178 // }
179 
180 template <typename T>
181 inline void set_intersection(std::vector<T> &targVec, const std::vector<T> &vec1, const std::vector<T> &vec2,
182  bool isSort)
183 {
184  T tempType;
185  typename std::vector<T>::iterator it;
186  targVec.assign(vec1.size(), tempType);
187  if (!isSort)
188  {
189  RSVS3D_ERROR_ARGUMENT("Constant vectors are unsorted cannot intersect");
190  }
191  it = set_intersection(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), targVec.begin());
192 
193  targVec.resize(it - targVec.begin());
194 }
195 
196 // Find option for vectors
197 
198 // Templated test for all types that need to be derived from ArrayStruct<T>
199 
200 //
201 
202 template <class T> int TestTemplate_ArrayStruct()
203 {
204  ArrayStruct<T> stackT, stackT2, stackT3;
205  T singleT;
206  std::vector<int> testSub = {2, 5, 10, 7};
207  std::vector<int> delInd = {1, 2};
208  FILE *fidw, *fidr;
209  int i = 0, j = 0;
210  int errFlag = 0;
211  bool errTest;
212 
213  try
214  {
215  // Test Initialisation
216  stackT.assign(5, singleT);
217  stackT.PopulateIndices();
218  stackT2.Init(5);
219  stackT2.PopulateIndices();
220 
221  errTest = CompareDisp(stackT, stackT2);
222  if (!errTest)
223  {
224  std::cerr << "Error Displays were not the same (Stage 1)" << std::endl;
225  errFlag++;
226  }
227  // Test ASsignement
228  singleT.index = 10;
229  stackT[2] = singleT;
230  errTest = CompareDisp(stackT, stackT2);
231  if (errTest)
232  {
233  std::cerr << "Error Displays were not the same - assignement not "
234  "working (Stage 2)"
235  << std::endl;
236  errFlag++;
237  }
238  errFlag += TestReadiness(stackT, " after assignement", false, false);
239 
240  // Test prepare
241  stackT.PrepareForUse();
242  stackT2.PrepareForUse();
243  errFlag += TestReadiness(stackT, " after PrepareForUse", true, true);
244 
245  // Test Find
246  i = stackT.find(10);
247  j = stackT.find(7);
248  testSub = stackT.find_list(testSub);
249  errFlag += TestReadiness(stackT, " after find", true, true);
250 
251  if (i != 2 || j != rsvs3d::constants::__notfound)
252  {
253  std::cerr << "FIND did not Succesfully identify the indices" << std::endl;
254  errFlag++;
255  }
256  if (testSub[2] != 2 || testSub[3] != rsvs3d::constants::__notfound)
257  {
258  std::cerr << "FIND_LISTS did not Succesfully identify the "
259  "indices"
260  << std::endl;
261  errFlag++;
262  }
263 
264  try
265  {
266  stackT[2].index = 7;
267  errFlag += TestReadiness(stackT, " after [] assignement", false, false);
268 
269  i = stackT.find(10);
270 // If this does not throw an error with have an issue
271 #ifdef SAFE_ACCESS
272  std::cerr << "FIND did not throw an error at the unsafe access" << std::endl;
273  errFlag++;
274 #endif // SAFE_ACCESS
275  }
276  catch (std::exception const &ex)
277  {
278  std::cout << "Previous Call should have thrown the following "
279  "warning:"
280  << std::endl;
281  std::cout << "Warning: reading from potentially obsolete unordered_map" << std::endl;
282  i = -1;
283  }
284  // Test Concatenation of arrays
285 
286  stackT.PrepareForUse();
287  errFlag += TestReadiness(stackT, " after PrepareForUse (2nd Time Time)", true, true);
288 
289  stackT.Concatenate(stackT2);
290  errFlag += TestReadiness(stackT, " after Concatenate", false, false);
291 
292  stackT.PrepareForUse();
293  errFlag += TestReadiness(stackT, " after PrepareForUse (3nd Time Time)", true, true);
294 
295  stackT.PopulateIndices();
296  errFlag += TestReadiness(stackT, " after PopulateIndices", false, true);
297 
298  stackT.PrepareForUse();
299  errFlag += TestReadiness(stackT, " after PrepareForUse (4th Time Time)", true, true);
300 
301  // Test Read write:
302  fidw = fopen("../TESTOUT/testarray.dat", "w");
303  if (fidw != NULL)
304  {
305  stackT.write(fidw);
306  errFlag += TestReadiness(stackT, " Write out", true, true);
307  fclose(fidw);
308  fidr = fopen("../TESTOUT/testarray.dat", "r");
309  if (fidr != NULL)
310  {
311  stackT3.read(fidr);
312  fclose(fidr);
313  stackT3.PrepareForUse();
314  errTest = CompareDisp(stackT, stackT3);
315  if (!errTest)
316  {
317  std::cerr << "Error Displays were not the same after write read" << std::endl;
318  errFlag++;
319  }
320  }
321  else
322  {
323  std::cout << "Error: Could not open file to read test arraystructures." << std::endl;
324  errFlag++;
325  }
326  }
327  else
328  {
329  std::cout << "Error: Could not open file to write test arraystructures." << std::endl;
330  errFlag++;
331  }
332 
333  stackT2 = stackT;
334  errTest = CompareDisp(stackT, stackT2);
335  if (!errTest)
336  {
337  std::cerr << "Error Displays were not the same after full assignement" << std::endl;
338  errFlag++;
339  }
340  stackT.disp();
341  errFlag += TestReadiness(stackT, " Disp", true, true);
342 
343  stackT.elems.erase(stackT.elems.begin(), ++(++stackT.elems.begin()));
344  stackT.isHash = 0;
345  stackT.isSetMI = 0;
346  stackT2.remove(delInd);
347 
348  errTest = CompareDisp(stackT, stackT2);
349  if (!errTest)
350  {
351  stackT.disp();
352  stackT2.disp();
353  std::cerr << "Error Displays were not the same erase" << std::endl;
354  errFlag++;
355  }
356  }
357  catch (std::exception const &ex)
358  {
359  std::cerr << "Exception: " << ex.what() << std::endl;
360  return -1;
361  }
362  return (errFlag);
363 }
364 
365 template <class T> int TestReadiness(T &stackT, const char *txt, bool errTarg, bool errTargCheck)
366 {
367  // Test if the behaviour of the readyness test is as expected
368  // stackT is the class to be tested
369  // txt is a string to be displayed telling the user where the error is
370  // occuring errTarg is
371  bool errTest;
372  int errFlag = 0;
373  errTest = stackT.isready();
374  if (!(errTest == errTarg))
375  {
376  std::cerr << "stackT wrongly marked as " << (errTarg ? "not" : "") << " ready (isready()) " << txt << std::endl;
377  errFlag++;
378  }
379  errTest = stackT.checkready();
380  if (!(errTest == errTargCheck))
381  {
382  std::cerr << "stackT wrongly marked as " << (errTarg ? "not" : "") << " ready (checkready())" << txt
383  << std::endl;
384  errFlag++;
385  }
386  return (errFlag);
387 }
388 
389 // member function definition template <class T> : "ArrayStruct"
390 
391 template <class T> inline int ArrayStruct<T>::GetMaxIndex() const
392 {
393 #ifdef SAFE_ACCESS
394  if (!isSetMI)
395  {
396  std::cerr << "warning: Potentially unsafe reading of max index"
397  " - execute PrepareForUse() before access"
398  << std::endl;
399  std::cerr << " in " << __PRETTY_FUNCTION__ << std::endl;
400  }
401 #endif // SAFE_ACCESS
402  return (maxIndex);
403 }
404 
405 template <class T> int ArrayStruct<T>::find(int key, bool noWarn) const
406 {
407  if (isHash == 0 && !noWarn)
408  {
409  std::cerr << "Warning: reading from potentially obsolete unordered_map ";
410  std::cerr << std::endl << " in " << __PRETTY_FUNCTION__ << std::endl;
411  std::cerr << " To avoid this message perform read operations on"
412  " ArrayStruct<T> using the () operator"
413  << std::endl;
414  }
415  auto search = hashTable.find(key);
416 
417  if (search == hashTable.end())
418  {
419  return (rsvs3d::constants::__notfound);
420  }
421 #ifdef SAFE_ACCESS
422  int key2;
423  key2 = elems[search->second].index;
424  if (key2 != key)
425  {
426  std::cerr << " Error in " << __PRETTY_FUNCTION__ << std::endl;
427  RSVS3D_ERROR_ARGUMENT("FIND returned an invalid output ");
428  }
429 #endif // SAFE_ACCESS
430  return (search->second);
431 }
432 
433 template <class T> std::vector<int> ArrayStruct<T>::find_list(const std::vector<int> &key, bool noWarn) const
434 {
435  std::vector<int> returnSub = key;
436  int ii;
437  for (ii = 0; ii < int(key.size()); ++ii)
438  {
439  returnSub[ii] = this->find(key[ii], noWarn);
440  }
441  return (returnSub);
442 }
443 
444 template <class T> void ArrayStruct<T>::write(FILE *fid) const
445 {
446  int ii;
447  fprintf(fid, "%i %i \n", int(this->size()), int(isInMesh));
448  for (ii = 0; ii < int(this->size()); ++ii)
449  {
450  elems[ii].write(fid);
451  }
452 }
453 template <class T> void ArrayStruct<T>::read(FILE *fid)
454 {
455  int ii, n;
456  fscanf(fid, "%i %i ", &n, &ii);
457  isInMesh = bool(ii);
458  this->Init(n);
459  for (ii = 0; ii < n; ++ii)
460  {
461  elems[ii].read(fid);
462  }
463 }
464 
465 template <class T> bool ArrayStruct<T>::checkready()
466 {
467  readyforuse = true;
468  int i = 0;
469  readyforuse = ((isHash == 1) & (isSetMI == 1));
470  if (readyforuse)
471  {
472  while ((i < this->size()) & readyforuse)
473  {
474  readyforuse = readyforuse & elems[i].isready(isInMesh);
475  ++i;
476  }
477  }
478 
479  return (readyforuse);
480 }
481 template <class T> void ArrayStruct<T>::ForceArrayReady()
482 {
483  isHash = 1;
484  isSetMI = 1;
485  readyforuse = true;
486 }
487 
488 template <class T> void ArrayStruct<T>::disp() const
489 {
490  std::cout << "Array of size " << this->size() << std::endl;
491  for (int ii = 0; unsigned_int(ii) < elems.size(); ii++)
492  {
493  std::cout << "Array " << ii << " ";
494  elems[ii].disp();
495  }
496  std::cout << "Array Dat: isHash " << isHash << "; isSetMI " << isSetMI << "; isInMesh " << isInMesh << std::endl;
497 }
498 template <class T> void ArrayStruct<T>::disp(int iStart, int iEnd) const
499 {
500  std::cout << "Array of size " << this->size() << std::endl;
501  for (int ii = iStart; iEnd < elems.size(); ii++)
502  {
503  std::cout << "Array " << ii << " ";
504  elems[ii].disp();
505  }
506  std::cout << "Array Dat: isHash " << isHash << "; isSetMI " << isSetMI << "; isInMesh " << isInMesh << std::endl;
507 }
508 template <class T> void ArrayStruct<T>::disp(const std::vector<int> &subs) const
509 {
510  int ii;
511  std::cout << "Array of size " << this->size() << " displaying subset of size " << subs.size() << std::endl;
512  for (ii = 0; unsigned_int(ii) < subs.size(); ii++)
513  {
514  std::cout << "Array " << subs[ii] << " ";
515  elems[subs[ii]].disp();
516  }
517 }
518 
519 template <class T> inline void ArrayStruct<T>::Init(int n)
520 {
521  T sT;
522  this->clear();
523  this->reserve(n);
524  this->assign(n, sT);
525 }
526 
527 template <class T> void ArrayStruct<T>::HashArray()
528 {
529  // Generates a valid unordered_map for the current ArrayStruct
530  // Function should not be called repeatedly
531  if (!hashTable.empty())
532  {
533  hashTable.clear();
534  }
535  hashTable.reserve(elems.size());
536  for (int i = 0; i < int(elems.size()); ++i)
537  {
538  hashTable.emplace(elems[i].Key(), i);
539  }
540  isHash = 1;
541 
542  // std::cout << "Array Struct Succesfully Hashed" << std::endl;
543 }
544 
545 template <class T> void ArrayStruct<T>::TightenConnectivity()
546 {
547  for (int i = 0; i < int(elems.size()); ++i)
548  {
549  elems[i].TightenConnectivity();
550  }
551 
552  // std::cout << "Array Struct Succesfully Hashed" << std::endl;
553 }
554 
555 template <class T> void ArrayStruct<T>::SetMaxIndex()
556 {
557  // Sets the correct value of maxIndex
558  int n = elems.size();
559  maxIndex = 0;
560  for (int ii = n - 1; - 1 < ii; --ii)
561  {
562  if (maxIndex < this->elems[ii].index)
563  {
564  maxIndex = elems[ii].index;
565  }
566  }
567  isSetMI = 1;
568 }
569 /*template<class T> void ArrayStruct <T>::SetMaxIndex()
570 {
571  // Sets the correct value of maxIndex
572  int n=elems.size();
573  maxIndex=0;
574  for(int ii=0;ii<n;++ii){
575  maxIndex= (maxIndex<this->elems[ii].index) ? elems[ii].index :
576 maxIndex;
577  }
578  isSetMI=1;
579 }*/
580 template <class T> void ArrayStruct<T>::Concatenate(const ArrayStruct<T> &other)
581 {
582  int nCurr, nNew, nTot, ii;
583  nCurr = this->size();
584  nNew = other.size();
585  nTot = nCurr + nNew;
586  elems.reserve(nTot);
587 
588  for (ii = 0; ii < nNew; ii++)
589  {
590  elems.push_back(other.elems[ii]);
591  }
592  // this->HashArray();
593  // this->SetMaxIndex();
594  isHash = 0;
595  isSetMI = 0;
596  readyforuse = false;
597 }
598 
599 template <class T> void ArrayStruct<T>::PopulateIndices()
600 {
601  int n = elems.size();
602  maxIndex = -1;
603  for (int ii = 0; ii < n; ++ii)
604  {
605  elems[ii].index = ii + 1;
606  }
607  maxIndex = n;
608  isSetMI = 1;
609  isHash = 0;
610  readyforuse = false;
611  this->HashArray();
612 }
613 template <class T> void ArrayStruct<T>::ChangeIndices(int nVert, int nEdge, int nSurf, int nVolu)
614 {
615  int n = elems.size();
616  for (int ii = 0; ii < n; ++ii)
617  {
618  elems[ii].ChangeIndices(nVert, nEdge, nSurf, nVolu);
619  }
620 
621  isSetMI = 0;
622  isHash = 0;
623  readyforuse = false;
624 }
625 template <class T> void ArrayStruct<T>::PrepareForUse()
626 {
627  for (int ii = 0; ii < this->size(); ++ii)
628  {
629  this->elems[ii].PrepareForUse();
630  }
631  if (isSetMI == 0)
632  {
633  this->SetMaxIndex();
634  }
635  if (isHash == 0)
636  {
637  this->HashArray();
638  }
639  readyforuse = true;
640 }
641 
642 template <class T> void ArrayStruct<T>::remove(std::vector<int> delInd)
643 {
644  HashedVector<int, T> delHash;
645  // int isHashCurr=isHash;
646 
647  delHash.vec = delInd;
648  delHash.GenerateHash();
649 
650  elems.erase(std::remove_if(elems.begin(), elems.end(), delHash), elems.end());
651 
652  isHash = 0;
653  isSetMI = 0;
654  // This part of the code lets remove maintain the hashTable up to date.
655  /*for (int i = 0; i < int(delInd.size()); ++i)
656  {
657  this->hashTable.erase(delInd[i]);
658  }
659  isHash=isHashCurr;*/
660 }
661 
662 // Implementation of std::vector member functions into the base class
663 
664 template <class T> inline int ArrayStruct<T>::size() const
665 {
666  return (int(elems.size()));
667 }
668 template <class T> inline int ArrayStruct<T>::capacity() const
669 {
670  return (int(elems.capacity()));
671 }
672 template <class T> inline void ArrayStruct<T>::assign(int n, T &newelem)
673 {
674  elems.assign(n, newelem);
675  isHash = 0;
676  isSetMI = 0;
677  readyforuse = false;
678 }
679 template <class T> inline void ArrayStruct<T>::push_back(T &newelem)
680 {
681  elems.push_back(newelem);
682 
683  maxIndex = newelem.index > maxIndex ? newelem.index : maxIndex;
684  hashTable.emplace(newelem.Key(), elems.size() - 1);
685 }
686 template <class T> inline void ArrayStruct<T>::reserve(int n)
687 {
688  elems.reserve(n);
689 }
690 template <class T> inline void ArrayStruct<T>::clear()
691 {
692  elems.clear();
693  hashTable.clear();
694  // isHash=0;
695  maxIndex = 0;
696  // readyforuse=false;
697 }
698 // Hashed Vector Template class implementations
699 
700 template <class T, class Q, class R> inline void HashedVector<T, Q, R>::GenerateHash()
701 {
702  hashTable.clear();
703  HashVector(vec, hashTable);
704  isHash = true;
705 }
706 template <class T, class Q, class R> inline int HashedVector<T, Q, R>::find(const T key) const
707 {
708  return (FindSub(key, hashTable));
709 }
710 template <class T, class Q, class R> inline std::vector<int> HashedVector<T, Q, R>::findall(const T key) const
711 {
712  return (ReturnDataEqualRange(key, hashTable));
713 }
714 
715 template <class T, class Q, class R> inline int HashedVector<T, Q, R>::count(const T key) const
716 {
717  return (hashTable.count(key));
718 }
719 
720 template <class T, class Q, class R> std::vector<int> HashedVector<T, Q, R>::count(const std::vector<T> &key) const
721 {
722  std::vector<int> subOut;
723  subOut.reserve(key.size());
724  for (int i = 0; i < int(key.size()); ++i)
725  {
726  subOut.push_back(hashTable.count(key[i]));
727  }
728 
729  return (subOut);
730 }
731 
732 template <class T, class Q, class R>
733 inline std::vector<int> HashedVector<T, Q, R>::find_list(const std::vector<T> &key) const
734 {
735  return (FindSubList(key, vec, hashTable));
736 }
737 
738 template <class T, class Q, class R> inline bool HashedVector<T, Q, R>::IsInVec(const Q &key) const
739 {
740  return (FindSub(key.Key(), hashTable) != rsvs3d::constants::__notfound);
741 }
742 
743 template <class T, class Q, class R> bool HashedVector<T, Q, R>::operator()(const Q &key) const
744 {
745  return (FindSub(key.Key(), hashTable) != rsvs3d::constants::__notfound);
746 }
747 
748 template <class T, class Q, class R> inline void HashedMap<T, Q, R>::GenerateHash()
749 {
750  hashTable.clear();
751  HashVector(vec, hashTable, targ);
752  isHash = true;
753 }
754 
755 template <class T> int FindSub(const T &key, const std::unordered_multimap<T, int> &hashTable)
756 {
757  auto search = hashTable.find(key);
758 
759  if (search == hashTable.end())
760  {
761  return (rsvs3d::constants::__notfound);
762  }
763 
764  return (search->second);
765 }
766 
767 template <class T>
768 std::vector<int> FindSubList(const std::vector<T> &keyFind, const std::vector<T> &keyList,
769  std::unordered_multimap<T, int> &hashTable)
770 {
771  std::vector<int> returnSub;
772  int ii;
773 
774  returnSub.reserve(int(keyFind.size()));
775 
776  if (hashTable.empty())
777  {
778  HashVector(keyList, hashTable);
779  }
780 
781  for (ii = 0; ii < int(keyFind.size()); ++ii)
782  {
783  returnSub.push_back(FindSub(keyFind[ii], hashTable));
784 #ifdef SAFE_ACCESS
785  if (returnSub[ii] >= 0)
786  {
787  if (keyList[returnSub[ii]] != keyFind[ii])
788  {
789  RSVS3D_ERROR_ARGUMENT("FIND returned an invalid output ");
790  }
791  }
792 #endif // SAFE_ACCESS
793  }
794  return (returnSub);
795 }
796 
797 template <class T>
798 std::vector<int> FindSubList(const std::vector<T> &keyFind, const std::vector<T> &keyList,
799  const std::unordered_multimap<T, int> &hashTable)
800 {
801  std::vector<int> returnSub;
802  int ii;
803 
804  returnSub.reserve(int(keyFind.size()));
805 
806  if (hashTable.empty() && keyList.size() > 0 && keyFind.size() > 0)
807  {
808  RSVS3D_ERROR_ARGUMENT("Hash table needs to be full to find list");
809  }
810 
811  for (ii = 0; ii < int(keyFind.size()); ++ii)
812  {
813  returnSub.push_back(FindSub(keyFind[ii], hashTable));
814 #ifdef SAFE_ACCESS
815  if (returnSub[ii] >= 0)
816  {
817  if (keyList[returnSub[ii]] != keyFind[ii])
818  {
819  RSVS3D_ERROR_ARGUMENT("FIND returned an invalid output ");
820  }
821  }
822 #endif // SAFE_ACCESS
823  }
824  return (returnSub);
825 }
826 
827 template <class T, class Q>
828 void HashVector(const std::vector<T> &elems, std::unordered_multimap<T, Q> &hashTable, const std::vector<Q> &targElems)
829 {
830  // Generates a valid unordered_map for the current ArrayStruct
831  // Function should not be called repeatedly
832 
833  hashTable.reserve(elems.size());
834  if (targElems.size() == 0)
835  {
836  for (int i = 0; i < int(elems.size()); ++i)
837  {
838  hashTable.emplace(elems[i], i);
839  }
840  }
841  else if (targElems.size() == elems.size())
842  {
843  for (int i = 0; i < int(elems.size()); ++i)
844  {
845  hashTable.emplace(elems[i], targElems[i]);
846  }
847  }
848  else
849  {
850  RSVS3D_ERROR_ARGUMENT("HashVector failed as input vectors are of "
851  "different sizes");
852  }
853 }
854 
855 template <template <class Q, class R> class T, class Q, class R> void EraseKeyPair(T<Q, R> hashTable, Q key, R pos)
856 {
857  typename T<Q, R>::iterator it;
858  it = hashTable.find(key);
859  while (it->second != pos && it->first == key)
860  {
861  ++it;
862  }
863 
864  if (it->second == pos && it->first == key)
865  {
866  hashTable.erase(it);
867  }
868  else
869  {
870  std::cerr << "Error: Key value std::pair not found and could not be removed " << std::endl;
871  std::cerr << " key " << key << " pos " << pos << std::endl;
872  std::cerr << " in function:" << __PRETTY_FUNCTION__ << std::endl;
873  RSVS3D_ERROR_ARGUMENT("Key value std::pair not found and could not be removed");
874  }
875 }
876 
877 #endif // ARRAYSTRUCTS_INCL_H_INCLUDED
Provide std::vector container with hashed index mapping.
Provides the error and warning system used by the RSVS3D project.
#define RSVS3D_ERROR_ARGUMENT(M)
Throw a invalid_argument.
Definition: warning.hpp:148