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.

algorithms.h 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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_BITS_ALGORITHMS_H
  23. #define FROZEN_LETITGO_BITS_ALGORITHMS_H
  24. #include "frozen/bits/basic_types.h"
  25. #include <limits>
  26. #include <tuple>
  27. namespace frozen {
  28. namespace bits {
  29. auto constexpr next_highest_power_of_two(std::size_t v) {
  30. // https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
  31. constexpr auto trip_count = std::numeric_limits<decltype(v)>::digits;
  32. v--;
  33. for(std::size_t i = 1; i < trip_count; i <<= 1)
  34. v |= v >> i;
  35. v++;
  36. return v;
  37. }
  38. template<class T>
  39. auto constexpr log(T v) {
  40. std::size_t n = 0;
  41. while (v > 1) {
  42. n += 1;
  43. v >>= 1;
  44. }
  45. return n;
  46. }
  47. constexpr std::size_t bit_weight(std::size_t n) {
  48. return (n <= 8*sizeof(unsigned int))
  49. + (n <= 8*sizeof(unsigned long))
  50. + (n <= 8*sizeof(unsigned long long))
  51. + (n <= 128);
  52. }
  53. unsigned int select_uint_least(std::integral_constant<std::size_t, 4>);
  54. unsigned long select_uint_least(std::integral_constant<std::size_t, 3>);
  55. unsigned long long select_uint_least(std::integral_constant<std::size_t, 2>);
  56. template<std::size_t N>
  57. unsigned long long select_uint_least(std::integral_constant<std::size_t, N>) {
  58. static_assert(N < 2, "unsupported type size");
  59. return {};
  60. }
  61. template<std::size_t N>
  62. using select_uint_least_t = decltype(select_uint_least(std::integral_constant<std::size_t, bit_weight(N)>()));
  63. template <typename Iter, typename Compare>
  64. constexpr auto min_element(Iter begin, const Iter end,
  65. Compare const &compare) {
  66. auto result = begin;
  67. while (begin != end) {
  68. if (compare(*begin, *result)) {
  69. result = begin;
  70. }
  71. ++begin;
  72. }
  73. return result;
  74. }
  75. template <class T>
  76. constexpr void cswap(T &a, T &b) {
  77. auto tmp = a;
  78. a = b;
  79. b = tmp;
  80. }
  81. template <class T, class U>
  82. constexpr void cswap(std::pair<T, U> & a, std::pair<T, U> & b) {
  83. cswap(a.first, b.first);
  84. cswap(a.second, b.second);
  85. }
  86. template <class... Tys, std::size_t... Is>
  87. constexpr void cswap(std::tuple<Tys...> &a, std::tuple<Tys...> &b, std::index_sequence<Is...>) {
  88. using swallow = int[];
  89. (void) swallow{(cswap(std::get<Is>(a), std::get<Is>(b)), 0)...};
  90. }
  91. template <class... Tys>
  92. constexpr void cswap(std::tuple<Tys...> &a, std::tuple<Tys...> &b) {
  93. cswap(a, b, std::make_index_sequence<sizeof...(Tys)>());
  94. }
  95. template <typename Iterator, class Compare>
  96. constexpr Iterator partition(Iterator left, Iterator right, Compare const &compare) {
  97. auto pivot = left + (right - left) / 2;
  98. auto value = *pivot;
  99. cswap(*right, *pivot);
  100. for (auto it = left; 0 < right - it; ++it) {
  101. if (compare(*it, value)) {
  102. cswap(*it, *left);
  103. left++;
  104. }
  105. }
  106. cswap(*right, *left);
  107. return left;
  108. }
  109. template <typename Iterator, class Compare>
  110. constexpr void quicksort(Iterator left, Iterator right, Compare const &compare) {
  111. while (0 < right - left) {
  112. auto new_pivot = bits::partition(left, right, compare);
  113. quicksort(left, new_pivot, compare);
  114. left = new_pivot + 1;
  115. }
  116. }
  117. template <typename T, std::size_t N, class Compare>
  118. constexpr bits::carray<T, N> quicksort(bits::carray<T, N> const &array,
  119. Compare const &compare) {
  120. bits::carray<T, N> res = array;
  121. quicksort(res.begin(), res.end() - 1, compare);
  122. return res;
  123. }
  124. template <class T, class Compare> struct LowerBound {
  125. T const &value_;
  126. Compare const &compare_;
  127. constexpr LowerBound(T const &value, Compare const &compare)
  128. : value_(value), compare_(compare) {}
  129. template <class ForwardIt>
  130. inline constexpr ForwardIt doit_fast(ForwardIt first,
  131. std::integral_constant<std::size_t, 0>) {
  132. return first;
  133. }
  134. template <class ForwardIt, std::size_t N>
  135. inline constexpr ForwardIt doit_fast(ForwardIt first,
  136. std::integral_constant<std::size_t, N>) {
  137. auto constexpr step = N / 2;
  138. static_assert(N/2 == N - N / 2 - 1, "power of two minus 1");
  139. auto it = first + step;
  140. auto next_it = compare_(*it, value_) ? it + 1 : first;
  141. return doit_fast(next_it, std::integral_constant<std::size_t, N / 2>{});
  142. }
  143. template <class ForwardIt, std::size_t N>
  144. inline constexpr ForwardIt doitfirst(ForwardIt first, std::integral_constant<std::size_t, N>, std::integral_constant<bool, true>) {
  145. return doit_fast(first, std::integral_constant<std::size_t, N>{});
  146. }
  147. template <class ForwardIt, std::size_t N>
  148. inline constexpr ForwardIt doitfirst(ForwardIt first, std::integral_constant<std::size_t, N>, std::integral_constant<bool, false>) {
  149. auto constexpr next_power = next_highest_power_of_two(N);
  150. auto constexpr next_start = next_power / 2 - 1;
  151. auto it = first + next_start;
  152. if (compare_(*it, value_)) {
  153. auto constexpr next = N - next_start - 1;
  154. return doitfirst(it + 1, std::integral_constant<std::size_t, next>{}, std::integral_constant<bool, next_highest_power_of_two(next) - 1 == next>{});
  155. }
  156. else
  157. return doit_fast(first, std::integral_constant<std::size_t, next_start>{});
  158. }
  159. template <class ForwardIt>
  160. inline constexpr ForwardIt doitfirst(ForwardIt first, std::integral_constant<std::size_t, 1>, std::integral_constant<bool, false>) {
  161. return doit_fast(first, std::integral_constant<std::size_t, 1>{});
  162. }
  163. };
  164. template <std::size_t N, class ForwardIt, class T, class Compare>
  165. constexpr ForwardIt lower_bound(ForwardIt first, const T &value, Compare const &compare) {
  166. return LowerBound<T, Compare>{value, compare}.doitfirst(first, std::integral_constant<std::size_t, N>{}, std::integral_constant<bool, next_highest_power_of_two(N) - 1 == N>{});
  167. }
  168. template <std::size_t N, class Compare, class ForwardIt, class T>
  169. constexpr bool binary_search(ForwardIt first, const T &value,
  170. Compare const &compare) {
  171. ForwardIt where = lower_bound<N>(first, value, compare);
  172. return (!(where == first + N) && !(compare(value, *where)));
  173. }
  174. template<class InputIt1, class InputIt2>
  175. constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
  176. {
  177. for (; first1 != last1; ++first1, ++first2) {
  178. if (!(*first1 == *first2)) {
  179. return false;
  180. }
  181. }
  182. return true;
  183. }
  184. template<class InputIt1, class InputIt2>
  185. constexpr bool lexicographical_compare(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
  186. {
  187. for (; (first1 != last1) && (first2 != last2); ++first1, ++first2) {
  188. if (*first1 < *first2)
  189. return true;
  190. if (*first2 < *first1)
  191. return false;
  192. }
  193. return (first1 == last1) && (first2 != last2);
  194. }
  195. } // namespace bits
  196. } // namespace frozen
  197. #endif