flat_map.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. //---------------------------------------------------------------------------//
  2. // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
  3. //
  4. // Distributed under the Boost Software License, Version 1.0
  5. // See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt
  7. //
  8. // See http://boostorg.github.com/compute for more information.
  9. //---------------------------------------------------------------------------//
  10. #ifndef BOOST_COMPUTE_CONTAINER_FLAT_MAP_HPP
  11. #define BOOST_COMPUTE_CONTAINER_FLAT_MAP_HPP
  12. #include <cstddef>
  13. #include <utility>
  14. #include <exception>
  15. #include <boost/config.hpp>
  16. #include <boost/throw_exception.hpp>
  17. #include <boost/compute/exception.hpp>
  18. #include <boost/compute/algorithm/find.hpp>
  19. #include <boost/compute/algorithm/lower_bound.hpp>
  20. #include <boost/compute/algorithm/upper_bound.hpp>
  21. #include <boost/compute/container/vector.hpp>
  22. #include <boost/compute/functional/get.hpp>
  23. #include <boost/compute/iterator/transform_iterator.hpp>
  24. #include <boost/compute/types/pair.hpp>
  25. #include <boost/compute/detail/buffer_value.hpp>
  26. namespace boost {
  27. namespace compute {
  28. template<class Key, class T>
  29. class flat_map
  30. {
  31. public:
  32. typedef Key key_type;
  33. typedef T mapped_type;
  34. typedef typename ::boost::compute::vector<std::pair<Key, T> > vector_type;
  35. typedef typename vector_type::value_type value_type;
  36. typedef typename vector_type::size_type size_type;
  37. typedef typename vector_type::difference_type difference_type;
  38. typedef typename vector_type::reference reference;
  39. typedef typename vector_type::const_reference const_reference;
  40. typedef typename vector_type::pointer pointer;
  41. typedef typename vector_type::const_pointer const_pointer;
  42. typedef typename vector_type::iterator iterator;
  43. typedef typename vector_type::const_iterator const_iterator;
  44. typedef typename vector_type::reverse_iterator reverse_iterator;
  45. typedef typename vector_type::const_reverse_iterator const_reverse_iterator;
  46. explicit flat_map(const context &context = system::default_context())
  47. : m_vector(context)
  48. {
  49. }
  50. flat_map(const flat_map<Key, T> &other)
  51. : m_vector(other.m_vector)
  52. {
  53. }
  54. flat_map<Key, T>& operator=(const flat_map<Key, T> &other)
  55. {
  56. if(this != &other){
  57. m_vector = other.m_vector;
  58. }
  59. return *this;
  60. }
  61. ~flat_map()
  62. {
  63. }
  64. iterator begin()
  65. {
  66. return m_vector.begin();
  67. }
  68. const_iterator begin() const
  69. {
  70. return m_vector.begin();
  71. }
  72. const_iterator cbegin() const
  73. {
  74. return m_vector.cbegin();
  75. }
  76. iterator end()
  77. {
  78. return m_vector.end();
  79. }
  80. const_iterator end() const
  81. {
  82. return m_vector.end();
  83. }
  84. const_iterator cend() const
  85. {
  86. return m_vector.cend();
  87. }
  88. reverse_iterator rbegin()
  89. {
  90. return m_vector.rbegin();
  91. }
  92. const_reverse_iterator rbegin() const
  93. {
  94. return m_vector.rbegin();
  95. }
  96. const_reverse_iterator crbegin() const
  97. {
  98. return m_vector.crbegin();
  99. }
  100. reverse_iterator rend()
  101. {
  102. return m_vector.rend();
  103. }
  104. const_reverse_iterator rend() const
  105. {
  106. return m_vector.rend();
  107. }
  108. const_reverse_iterator crend() const
  109. {
  110. return m_vector.crend();
  111. }
  112. size_type size() const
  113. {
  114. return m_vector.size();
  115. }
  116. size_type max_size() const
  117. {
  118. return m_vector.max_size();
  119. }
  120. bool empty() const
  121. {
  122. return m_vector.empty();
  123. }
  124. size_type capacity() const
  125. {
  126. return m_vector.capacity();
  127. }
  128. void reserve(size_type size, command_queue &queue)
  129. {
  130. m_vector.reserve(size, queue);
  131. }
  132. void reserve(size_type size)
  133. {
  134. command_queue queue = m_vector.default_queue();
  135. reserve(size, queue);
  136. queue.finish();
  137. }
  138. void shrink_to_fit()
  139. {
  140. m_vector.shrink_to_fit();
  141. }
  142. void clear()
  143. {
  144. m_vector.clear();
  145. }
  146. std::pair<iterator, bool>
  147. insert(const value_type &value, command_queue &queue)
  148. {
  149. iterator location = upper_bound(value.first, queue);
  150. if(location != begin()){
  151. value_type current_value;
  152. ::boost::compute::copy_n(location - 1, 1, &current_value, queue);
  153. if(value.first == current_value.first){
  154. return std::make_pair(location - 1, false);
  155. }
  156. }
  157. m_vector.insert(location, value);
  158. return std::make_pair(location, true);
  159. }
  160. std::pair<iterator, bool> insert(const value_type &value)
  161. {
  162. command_queue queue = m_vector.default_queue();
  163. std::pair<iterator, bool> result = insert(value, queue);
  164. queue.finish();
  165. return result;
  166. }
  167. iterator erase(const const_iterator &position, command_queue &queue)
  168. {
  169. return erase(position, position + 1, queue);
  170. }
  171. iterator erase(const const_iterator &position)
  172. {
  173. command_queue queue = m_vector.default_queue();
  174. iterator iter = erase(position, queue);
  175. queue.finish();
  176. return iter;
  177. }
  178. iterator erase(const const_iterator &first,
  179. const const_iterator &last,
  180. command_queue &queue)
  181. {
  182. return m_vector.erase(first, last, queue);
  183. }
  184. iterator erase(const const_iterator &first, const const_iterator &last)
  185. {
  186. command_queue queue = m_vector.default_queue();
  187. iterator iter = erase(first, last, queue);
  188. queue.finish();
  189. return iter;
  190. }
  191. size_type erase(const key_type &value, command_queue &queue)
  192. {
  193. iterator position = find(value, queue);
  194. if(position == end()){
  195. return 0;
  196. }
  197. else {
  198. erase(position, queue);
  199. return 1;
  200. }
  201. }
  202. iterator find(const key_type &value, command_queue &queue)
  203. {
  204. ::boost::compute::get<0> get_key;
  205. return ::boost::compute::find(
  206. ::boost::compute::make_transform_iterator(begin(), get_key),
  207. ::boost::compute::make_transform_iterator(end(), get_key),
  208. value,
  209. queue
  210. ).base();
  211. }
  212. iterator find(const key_type &value)
  213. {
  214. command_queue queue = m_vector.default_queue();
  215. iterator iter = find(value, queue);
  216. queue.finish();
  217. return iter;
  218. }
  219. const_iterator find(const key_type &value, command_queue &queue) const
  220. {
  221. ::boost::compute::get<0> get_key;
  222. return ::boost::compute::find(
  223. ::boost::compute::make_transform_iterator(begin(), get_key),
  224. ::boost::compute::make_transform_iterator(end(), get_key),
  225. value,
  226. queue
  227. ).base();
  228. }
  229. const_iterator find(const key_type &value) const
  230. {
  231. command_queue queue = m_vector.default_queue();
  232. const_iterator iter = find(value, queue);
  233. queue.finish();
  234. return iter;
  235. }
  236. size_type count(const key_type &value, command_queue &queue) const
  237. {
  238. return find(value, queue) != end() ? 1 : 0;
  239. }
  240. size_type count(const key_type &value) const
  241. {
  242. command_queue queue = m_vector.default_queue();
  243. size_type result = count(value, queue);
  244. queue.finish();
  245. return result;
  246. }
  247. iterator lower_bound(const key_type &value, command_queue &queue)
  248. {
  249. ::boost::compute::get<0> get_key;
  250. return ::boost::compute::lower_bound(
  251. ::boost::compute::make_transform_iterator(begin(), get_key),
  252. ::boost::compute::make_transform_iterator(end(), get_key),
  253. value,
  254. queue
  255. ).base();
  256. }
  257. iterator lower_bound(const key_type &value)
  258. {
  259. command_queue queue = m_vector.default_queue();
  260. iterator iter = lower_bound(value, queue);
  261. queue.finish();
  262. return iter;
  263. }
  264. const_iterator lower_bound(const key_type &value, command_queue &queue) const
  265. {
  266. ::boost::compute::get<0> get_key;
  267. return ::boost::compute::lower_bound(
  268. ::boost::compute::make_transform_iterator(begin(), get_key),
  269. ::boost::compute::make_transform_iterator(end(), get_key),
  270. value,
  271. queue
  272. ).base();
  273. }
  274. const_iterator lower_bound(const key_type &value) const
  275. {
  276. command_queue queue = m_vector.default_queue();
  277. const_iterator iter = lower_bound(value, queue);
  278. queue.finish();
  279. return iter;
  280. }
  281. iterator upper_bound(const key_type &value, command_queue &queue)
  282. {
  283. ::boost::compute::get<0> get_key;
  284. return ::boost::compute::upper_bound(
  285. ::boost::compute::make_transform_iterator(begin(), get_key),
  286. ::boost::compute::make_transform_iterator(end(), get_key),
  287. value,
  288. queue
  289. ).base();
  290. }
  291. iterator upper_bound(const key_type &value)
  292. {
  293. command_queue queue = m_vector.default_queue();
  294. iterator iter = upper_bound(value, queue);
  295. queue.finish();
  296. return iter;
  297. }
  298. const_iterator upper_bound(const key_type &value, command_queue &queue) const
  299. {
  300. ::boost::compute::get<0> get_key;
  301. return ::boost::compute::upper_bound(
  302. ::boost::compute::make_transform_iterator(begin(), get_key),
  303. ::boost::compute::make_transform_iterator(end(), get_key),
  304. value,
  305. queue
  306. ).base();
  307. }
  308. const_iterator upper_bound(const key_type &value) const
  309. {
  310. command_queue queue = m_vector.default_queue();
  311. const_iterator iter = upper_bound(value, queue);
  312. queue.finish();
  313. return iter;
  314. }
  315. const mapped_type at(const key_type &key) const
  316. {
  317. const_iterator iter = find(key);
  318. if(iter == end()){
  319. BOOST_THROW_EXCEPTION(std::out_of_range("key not found"));
  320. }
  321. return value_type(*iter).second;
  322. }
  323. detail::buffer_value<mapped_type> operator[](const key_type &key)
  324. {
  325. iterator iter = find(key);
  326. if(iter == end()){
  327. iter = insert(std::make_pair(key, mapped_type())).first;
  328. }
  329. size_t index = iter.get_index() * sizeof(value_type) + sizeof(key_type);
  330. return detail::buffer_value<mapped_type>(m_vector.get_buffer(), index);
  331. }
  332. private:
  333. ::boost::compute::vector<std::pair<Key, T> > m_vector;
  334. };
  335. } // end compute namespace
  336. } // end boost namespace
  337. #endif // BOOST_COMPUTE_CONTAINER_FLAT_MAP_HPP