You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

unordered_set.h 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * Frozen
  3. * Copyright 2016 QuarksLab
  4. *
  5. * Licensed to the Apache Software Foundation (ASF) under one
  6. * or more contributor license agreements. See the NOTICE file
  7. * distributed with this work for additional information
  8. * regarding copyright ownership. The ASF licenses this file
  9. * to you under the Apache License, Version 2.0 (the
  10. * "License"); you may not use this file except in compliance
  11. * with the License. You may obtain a copy of the License at
  12. *
  13. * http://www.apache.org/licenses/LICENSE-2.0
  14. *
  15. * Unless required by applicable law or agreed to in writing,
  16. * software distributed under the License is distributed on an
  17. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  18. * KIND, either express or implied. See the License for the
  19. * specific language governing permissions and limitations
  20. * under the License.
  21. */
  22. #ifndef FROZEN_LETITGO_UNORDERED_SET_H
  23. #define FROZEN_LETITGO_UNORDERED_SET_H
  24. #include "frozen/bits/basic_types.h"
  25. #include "frozen/bits/constexpr_assert.h"
  26. #include "frozen/bits/elsa.h"
  27. #include "frozen/bits/pmh.h"
  28. #include "frozen/bits/version.h"
  29. #include "frozen/random.h"
  30. #include <utility>
  31. namespace frozen {
  32. namespace bits {
  33. struct Get {
  34. template <class T> constexpr T const &operator()(T const &key) const {
  35. return key;
  36. }
  37. };
  38. } // namespace bits
  39. template <class Key, std::size_t N, typename Hash = elsa<Key>,
  40. class KeyEqual = std::equal_to<Key>>
  41. class unordered_set {
  42. static constexpr std::size_t storage_size =
  43. bits::next_highest_power_of_two(N) * (N < 32 ? 2 : 1); // size adjustment to prevent high collision rate for small sets
  44. using container_type = bits::carray<Key, N>;
  45. using tables_type = bits::pmh_tables<storage_size, Hash>;
  46. KeyEqual const equal_;
  47. container_type keys_;
  48. tables_type tables_;
  49. public:
  50. /* typedefs */
  51. using key_type = Key;
  52. using value_type = Key;
  53. using size_type = typename container_type::size_type;
  54. using difference_type = typename container_type::difference_type;
  55. using hasher = Hash;
  56. using key_equal = KeyEqual;
  57. using const_reference = typename container_type::const_reference;
  58. using reference = const_reference;
  59. using const_pointer = typename container_type::const_pointer;
  60. using pointer = const_pointer;
  61. using const_iterator = const_pointer;
  62. using iterator = const_iterator;
  63. public:
  64. /* constructors */
  65. unordered_set(unordered_set const &) = default;
  66. constexpr unordered_set(container_type keys, Hash const &hash,
  67. KeyEqual const &equal)
  68. : equal_{equal}
  69. , keys_{keys}
  70. , tables_{bits::make_pmh_tables<storage_size>(
  71. keys_, hash, bits::Get{}, default_prg_t{})} {}
  72. explicit constexpr unordered_set(container_type keys)
  73. : unordered_set{keys, Hash{}, KeyEqual{}} {}
  74. constexpr unordered_set(std::initializer_list<Key> keys)
  75. : unordered_set{keys, Hash{}, KeyEqual{}} {}
  76. constexpr unordered_set(std::initializer_list<Key> keys, Hash const & hash, KeyEqual const & equal)
  77. : unordered_set{container_type{keys}, hash, equal} {
  78. constexpr_assert(keys.size() == N, "Inconsistent initializer_list size and type size argument");
  79. }
  80. /* iterators */
  81. constexpr const_iterator begin() const { return keys_.begin(); }
  82. constexpr const_iterator end() const { return keys_.end(); }
  83. constexpr const_iterator cbegin() const { return keys_.cbegin(); }
  84. constexpr const_iterator cend() const { return keys_.cend(); }
  85. /* capacity */
  86. constexpr bool empty() const { return !N; }
  87. constexpr size_type size() const { return N; }
  88. constexpr size_type max_size() const { return N; }
  89. /* lookup */
  90. constexpr std::size_t count(Key const &key) const {
  91. auto const k = lookup(key);
  92. return equal_(k, key);
  93. }
  94. constexpr const_iterator find(Key const &key) const {
  95. auto const &k = lookup(key);
  96. if (equal_(k, key))
  97. return &k;
  98. else
  99. return keys_.end();
  100. }
  101. constexpr std::pair<const_iterator, const_iterator> equal_range(Key const &key) const {
  102. auto const &k = lookup(key);
  103. if (equal_(k, key))
  104. return {&k, &k + 1};
  105. else
  106. return {keys_.end(), keys_.end()};
  107. }
  108. /* bucket interface */
  109. constexpr std::size_t bucket_count() const { return storage_size; }
  110. constexpr std::size_t max_bucket_count() const { return storage_size; }
  111. /* observers*/
  112. constexpr hasher hash_function() const { return tables_.hash_; }
  113. constexpr key_equal key_eq() const { return equal_; }
  114. private:
  115. constexpr auto const &lookup(Key const &key) const {
  116. return keys_[tables_.lookup(key)];
  117. }
  118. };
  119. template <typename T, std::size_t N>
  120. constexpr auto make_unordered_set(T const (&keys)[N]) {
  121. return unordered_set<T, N>{keys};
  122. }
  123. } // namespace frozen
  124. #endif