CLRX  1
An unofficial OpenCL extensions designed for Radeon GPUs
Containers.h
Go to the documentation of this file.
1 /*
2  * CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3  * Copyright (C) 2014-2018 Mateusz Szpakowski
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
23 #ifndef __CLRX_CONTAINERS_H__
24 #define __CLRX_CONTAINERS_H__
25 
26 #include <CLRX/Config.h>
27 #include <cstddef>
28 #include <iterator>
29 #include <algorithm>
30 #include <vector>
31 #include <utility>
32 #include <unordered_map>
33 #include <initializer_list>
34 
36 namespace CLRX
37 {
38 
40 template<typename T>
41 class Array
42 {
43 public:
44  typedef T* iterator;
45  typedef const T* const_iterator;
46  typedef T element_type;
47 private:
48  T* ptr, *ptrEnd;
49 public:
51  Array(): ptr(nullptr), ptrEnd(nullptr)
52  { }
53 
55  explicit Array(size_t N)
56  {
57  ptr = nullptr;
58  if (N != 0)
59  ptr = new T[N];
60  ptrEnd = ptr+N;
61  }
62 
64  template<typename It>
65  Array(It b, It e)
66  {
67  try
68  {
69  ptr = nullptr;
70  const size_t N = e-b;
71  if (N != 0)
72  ptr = new T[N];
73  ptrEnd = ptr+N;
74  std::copy(b, e, ptr);
75  }
76  catch(...)
77  {
78  delete[] ptr;
79  throw;
80  }
81  }
82 
84  Array(const Array& cp)
85  {
86  try
87  {
88  ptr = ptrEnd = nullptr;
89  const size_t N = cp.size();
90  if (N != 0)
91  ptr = new T[N];
92  ptrEnd = ptr+N;
93  std::copy(cp.ptr, cp.ptrEnd, ptr);
94  }
95  catch(...)
96  {
97  delete[] ptr;
98  throw;
99  }
100  }
101 
103  Array(Array&& cp) noexcept
104  {
105  ptr = cp.ptr;
106  ptrEnd = cp.ptrEnd;
107  cp.ptr = cp.ptrEnd = nullptr;
108  }
109 
111  Array(std::initializer_list<T> list)
112  {
113  try
114  {
115  ptr = nullptr;
116  const size_t N = list.size();
117  if (N != 0)
118  ptr = new T[N];
119  ptrEnd = ptr+N;
120  std::copy(list.begin(), list.end(), ptr);
121  }
122  catch(...)
123  {
124  delete[] ptr;
125  throw;
126  }
127  }
128 
131  { delete[] ptr; }
132 
134  Array& operator=(const Array& cp)
135  {
136  if (this == &cp)
137  return *this;
138  assign(cp.begin(), cp.end());
139  return *this;
140  }
142  Array& operator=(Array&& cp) noexcept
143  {
144  if (this == &cp)
145  return *this;
146  delete[] ptr;
147  ptr = cp.ptr;
148  ptrEnd = cp.ptrEnd;
149  cp.ptr = cp.ptrEnd = nullptr;
150  return *this;
151  }
152 
154  Array& operator=(std::initializer_list<T> list)
155  {
156  assign(list.begin(), list.end());
157  return *this;
158  }
159 
161  const T& operator[] (size_t i) const
162  { return ptr[i]; }
164  T& operator[] (size_t i)
165  { return ptr[i]; }
166 
168  bool empty() const
169  { return ptrEnd==ptr; }
170 
172  size_t size() const
173  { return ptrEnd-ptr; }
174 
176  void allocate(size_t N)
177  {
178  if (N == size())
179  return;
180  delete[] ptr;
181  ptr = nullptr;
182  if (N != 0)
183  ptr = new T[N];
184  ptrEnd = ptr + N;
185  }
186 
188  void resize(size_t N)
189  {
190  if (N == size())
191  return;
192  T* newPtr = nullptr;
193  if (N != 0)
194  newPtr = new T[N];
195  try
196  {
197  /* move only if move constructor doesn't throw exceptions */
198  const size_t toMove = std::min(N, size());
199  for (size_t k = 0; k < toMove; k++)
200  newPtr[k] = std::move_if_noexcept(ptr[k]);
201  }
202  catch(...)
203  {
204  delete[] newPtr;
205  throw;
206  }
207  delete[] ptr;
208  ptr = newPtr;
209  ptrEnd = ptr + N;
210  }
211 
213  void clear()
214  {
215  delete[] ptr;
216  ptr = ptrEnd = nullptr;
217  }
218 
220  template<typename It>
221  Array& assign(It b, It e)
222  {
223  const size_t N = e-b;
224  if (N != size())
225  {
226  T* newPtr = nullptr;
227  if (N != 0)
228  newPtr = new T[N];
229  try
230  { std::copy(b, e, newPtr); }
231  catch(...)
232  {
233  delete[] newPtr;
234  throw;
235  }
236  delete[] ptr;
237  ptr = newPtr;
238  ptrEnd = ptr+N;
239  }
240  else // no size changed only copy
241  std::copy(b, e, ptr);
242  return *this;
243  }
244 
246  const T* data() const
247  { return ptr; }
249  T* data()
250  { return ptr; }
251 
253  const T* begin() const
254  { return ptr; }
256  T* begin()
257  { return ptr; }
258 
260  const T* end() const
261  { return ptrEnd; }
263  T* end()
264  { return ptrEnd; }
265 
267  const T& front() const
268  { return *ptr; }
270  T& front()
271  { return *ptr; }
273  const T& back() const
274  { return ptrEnd[-1]; }
276  T& back()
277  { return ptrEnd[-1]; }
278 
280  void swap(Array& array)
281  {
282  std::swap(ptr, array.ptr);
283  std::swap(ptrEnd, array.ptrEnd);
284  }
285 };
286 
288 template<typename T>
289 class VectorSet: public std::vector<T>
290 {
291 public:
294  { }
295 
297  explicit VectorSet(size_t n) : std::vector<T>(n)
298  { }
299 
301  VectorSet(size_t n, const T& v) : std::vector<T>(n, v)
302  { }
303 
305  template<typename It>
306  VectorSet(It first, It last) : std::vector<T>(first, last)
307  { }
308 
310  VectorSet(std::initializer_list<T> l): std::vector<T>(l)
311  { }
312 
314  void insertValue(const T& v)
315  {
316  auto fit = std::find(std::vector<T>::begin(), std::vector<T>::end(), v);
317  if (fit == std::vector<T>::end())
318  std::vector<T>::push_back(v);
319  }
320 
322  void eraseValue(const T& v)
323  {
324  auto fit = std::find(std::vector<T>::begin(), std::vector<T>::end(), v);
325  if (fit != std::vector<T>::end())
326  std::vector<T>::erase(fit);
327  }
328 
330  bool hasValue(const T& v) const
331  {
332  return std::find(std::vector<T>::begin(), std::vector<T>::end(), v) !=
333  std::vector<T>::end();
334  }
335 };
336 
337 
339 
345 template<typename Iter>
346 Iter binaryFind(Iter begin, Iter end, const
347  typename std::iterator_traits<Iter>::value_type& v);
348 
350 
357 template<typename Iter, typename Comp =
358  std::less<typename std::iterator_traits<Iter>::value_type> >
359 Iter binaryFind(Iter begin, Iter end, const
360  typename std::iterator_traits<Iter>::value_type& v, Comp comp);
361 
363 
369 template<typename Iter>
370 Iter binaryMapFind(Iter begin, Iter end, const
371  typename std::iterator_traits<Iter>::value_type::first_type& k);
372 
374 
381 template<typename Iter, typename Comp =
382  std::less<typename std::iterator_traits<Iter>::value_type::first_type> >
383 Iter binaryMapFind(Iter begin, Iter end, const
384  typename std::iterator_traits<Iter>::value_type::first_type& k, Comp comp);
385 
387 
391 template<typename Iter>
392 void mapSort(Iter begin, Iter end);
393 
395 
399 template<typename Iter, typename Comp =
400  std::less<typename std::iterator_traits<Iter>::value_type::first_type> >
401 void mapSort(Iter begin, Iter end, Comp comp);
402 
404 
410 template<typename Iter>
411 Iter binaryFind(Iter begin, Iter end,
412  const typename std::iterator_traits<Iter>::value_type& v)
413 {
414  auto it = std::lower_bound(begin, end, v);
415  if (it == end || v < *it)
416  return end;
417  return it;
418 }
419 
421 
428 template<typename Iter, typename Comp>
429 Iter binaryFind(Iter begin, Iter end,
430  const typename std::iterator_traits<Iter>::value_type& v, Comp comp)
431 {
432  auto it = std::lower_bound(begin, end, v, comp);
433  if (it == end || comp(v, *it))
434  return end;
435  return it;
436 }
437 
439 template<typename Iter>
440 Iter binaryMapFind(Iter begin, Iter end, const
441  typename std::iterator_traits<Iter>::value_type::first_type& k)
442 {
443  typedef typename std::iterator_traits<Iter>::value_type::first_type K;
444  typedef typename std::iterator_traits<Iter>::value_type::second_type V;
445  auto it = std::lower_bound(begin, end, std::make_pair(k, V()),
446  [](const std::pair<K,V>& e1, const std::pair<K,V>& e2) {
447  return e1.first < e2.first; });
448  if (it == end || k < it->first)
449  return end;
450  return it;
451 }
452 
454 template<typename Iter, typename Comp>
455 Iter binaryMapFind(Iter begin, Iter end, const
456  typename std::iterator_traits<Iter>::value_type::first_type& k, Comp comp)
457 {
458  typedef typename std::iterator_traits<Iter>::value_type::first_type K;
459  typedef typename std::iterator_traits<Iter>::value_type::second_type V;
460  auto it = std::lower_bound(begin, end, std::make_pair(k, V()),
461  [&comp](const std::pair<K,V>& e1, const std::pair<K,V>& e2) {
462  return comp(e1.first, e2.first); });
463  if (it == end || comp(k, it->first))
464  return end;
465  return it;
466 }
467 
469 
473 template<typename Iter>
474 void mapSort(Iter begin, Iter end)
475 {
476  typedef typename std::iterator_traits<Iter>::value_type::first_type K;
477  typedef typename std::iterator_traits<Iter>::value_type::second_type V;
478  std::sort(begin, end, [](const std::pair<K,V>& e1, const std::pair<K,V>& e2) {
479  return e1.first < e2.first; });
480 }
481 
483 
488 template<typename Iter, typename Comp>
489 void mapSort(Iter begin, Iter end, Comp comp)
490 {
491  typedef typename std::iterator_traits<Iter>::value_type::first_type K;
492  typedef typename std::iterator_traits<Iter>::value_type::second_type V;
493  std::sort(begin, end, [&comp](const std::pair<K,V>& e1, const std::pair<K,V>& e2) {
494  return comp(e1.first, e2.first); });
495 }
496 
499 template<typename K, typename V>
502 {
503 private:
504  struct Entry
505  {
506  size_t sortedPos;
507  size_t usage;
508  V value;
509  };
510 
511  size_t totalWeight;
512  size_t maxWeight;
513 
514  typedef typename std::unordered_map<K, Entry>::iterator EntryMapIt;
515  // sorted entries - sorted by usage
516  std::vector<EntryMapIt> sortedEntries;
517  std::unordered_map<K, Entry> entryMap;
518 
519  void updateInSortedEntries(EntryMapIt it)
520  {
521  const size_t curPos = it->second.sortedPos;
522  if (curPos == 0)
523  return; // first position
524  if (sortedEntries[curPos-1]->second.usage < it->second.usage &&
525  (curPos==1 || sortedEntries[curPos-2]->second.usage >= it->second.usage))
526  {
527  //std::cout << "fast path" << std::endl;
528  std::swap(sortedEntries[curPos-1]->second.sortedPos, it->second.sortedPos);
529  std::swap(sortedEntries[curPos-1], sortedEntries[curPos]);
530  return;
531  }
532  //std::cout << "slow path" << std::endl;
533  auto fit = std::upper_bound(sortedEntries.begin(),
534  sortedEntries.begin()+it->second.sortedPos, it,
535  [](EntryMapIt it1, EntryMapIt it2)
536  { return it1->second.usage > it2->second.usage; });
537  if (fit != sortedEntries.begin()+it->second.sortedPos)
538  {
539  const size_t curPos = it->second.sortedPos;
540  std::swap((*fit)->second.sortedPos, it->second.sortedPos);
541  std::swap(*fit, sortedEntries[curPos]);
542  }
543  }
544 
545  void insertToSortedEntries(EntryMapIt it)
546  {
547  it->second.sortedPos = sortedEntries.size();
548  sortedEntries.push_back(it);
549  }
550 
551  void removeFromSortedEntries(size_t pos)
552  {
553  // update later element positioning
554  for (size_t i = pos+1; i < sortedEntries.size(); i++)
555  (sortedEntries[i]->second.sortedPos)--;
556  sortedEntries.erase(sortedEntries.begin() + pos);
557  }
558 
559 public:
561  explicit SimpleCache(size_t _maxWeight) : totalWeight(0), maxWeight(_maxWeight)
562  { }
563 
565  V* use(const K& key)
566  {
567  auto it = entryMap.find(key);
568  if (it != entryMap.end())
569  {
570  it->second.usage++;
571  updateInSortedEntries(it);
572  return &(it->second.value);
573  }
574  return nullptr;
575  }
576 
578  bool hasKey(const K& key)
579  { return entryMap.find(key) != entryMap.end(); }
580 
582  void put(const K& key, const V& value)
583  {
584  auto res = entryMap.insert({ key, Entry{ 0, 0, value } });
585  if (!res.second)
586  {
587  removeFromSortedEntries(res.first->second.sortedPos); // remove old value
588  // update value
589  totalWeight -= res.first->second.value.weight();
590  res.first->second = Entry{ 0, 0, value };
591  }
592  const size_t elemWeight = value.weight();
593 
594  // correct max weight if element have greater weight
595  if (elemWeight > maxWeight)
596  maxWeight = elemWeight<<1;
597 
598  while (totalWeight+elemWeight > maxWeight)
599  {
600  // remove min usage element
601  auto minUsageIt = sortedEntries.back();
602  sortedEntries.pop_back();
603  totalWeight -= minUsageIt->second.value.weight();
604  entryMap.erase(minUsageIt);
605  }
606 
607  insertToSortedEntries(res.first); // new entry in sorted entries
608 
609  totalWeight += elemWeight;
610  }
611 };
612 
613 };
614 
615 namespace std
616 {
617 
619 template<typename T>
621 { a1.swap(a2); }
622 
623 }
624 
625 #endif
const T * begin() const
get iterator to first element
Definition: Containers.h:253
T element_type
element type
Definition: Containers.h:46
Iter binaryMapFind(Iter begin, Iter end, const typename std::iterator_traits< Iter >::value_type::first_type &k)
binary find helper for array-map
Definition: Containers.h:440
void swap(Array &array)
swap two arrays
Definition: Containers.h:280
void allocate(size_t N)
only allocating space without keeping previous content
Definition: Containers.h:176
bool hasKey(const K &key)
return true if key exists
Definition: Containers.h:578
const T & operator[](size_t i) const
operator of indexing
Definition: Containers.h:161
VectorSet(size_t n, const T &v)
constructor
Definition: Containers.h:301
const T & front() const
get first element
Definition: Containers.h:267
STL namespace.
an array class
Definition: Containers.h:41
VectorSet.
Definition: Containers.h:289
void resize(size_t N)
resize space with keeping old content
Definition: Containers.h:188
Configuration header.
const T * const_iterator
type of constant iterator
Definition: Containers.h:45
Array()
empty constructor
Definition: Containers.h:51
Array(size_t N)
construct array of N elements
Definition: Containers.h:55
Array & operator=(Array &&cp) noexcept
move assignment
Definition: Containers.h:142
T & back()
get last element
Definition: Containers.h:276
VectorSet(It first, It last)
constructor
Definition: Containers.h:306
Array & operator=(std::initializer_list< T > list)
assignment from initializer list
Definition: Containers.h:154
Array(std::initializer_list< T > list)
constructor with initializer list
Definition: Containers.h:111
T * end()
get iterator to after last element
Definition: Containers.h:263
Array & operator=(const Array &cp)
copy assignment
Definition: Containers.h:134
void insertValue(const T &v)
insert new value if doesn&#39;t exists
Definition: Containers.h:314
T * data()
get data
Definition: Containers.h:249
T & front()
get first element
Definition: Containers.h:270
void put(const K &key, const V &value)
put value
Definition: Containers.h:582
void mapSort(Iter begin, Iter end)
map range of iterators
Definition: Containers.h:474
main namespace
Definition: AsmDefs.h:38
Array & assign(It b, It e)
assign from range of iterators
Definition: Containers.h:221
T * iterator
type of iterator
Definition: Containers.h:44
~Array()
destructor
Definition: Containers.h:130
Array(It b, It e)
construct array of elements in begin and end
Definition: Containers.h:65
T * begin()
get iterator to first element
Definition: Containers.h:256
SimpleCache(size_t _maxWeight)
constructor
Definition: Containers.h:561
Array(const Array &cp)
copy constructor
Definition: Containers.h:84
void eraseValue(const T &v)
erase value if exists
Definition: Containers.h:322
VectorSet(std::initializer_list< T > l)
constructor
Definition: Containers.h:310
V * use(const K &key)
use key - get value
Definition: Containers.h:565
Iter binaryFind(Iter begin, Iter end, const typename std::iterator_traits< Iter >::value_type &v)
binary find helper
Definition: Containers.h:411
bool hasValue(const T &v) const
return true if value present in vector set
Definition: Containers.h:330
size_t size() const
returns number of elements
Definition: Containers.h:172
const T * data() const
get data
Definition: Containers.h:246
void clear()
clear array
Definition: Containers.h:213
bool empty() const
returns true if empty
Definition: Containers.h:168
Array(Array &&cp) noexcept
move constructor
Definition: Containers.h:103
const T & back() const
get last element
Definition: Containers.h:273
const T * end() const
get iterator to after last element
Definition: Containers.h:260
VectorSet(size_t n)
constructor
Definition: Containers.h:297
Simple cache for object. object class should have a weight method.
Definition: Containers.h:501
VectorSet()
constructor
Definition: Containers.h:293