algorithm.hpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. // Boost.Geometry
  2. // Copyright (c) 2021, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  4. // Licensed under the Boost Software License version 1.0.
  5. // http://www.boost.org/users/license.html
  6. #ifndef BOOST_GEOMETRY_UTIL_ALGORITHM_HPP
  7. #define BOOST_GEOMETRY_UTIL_ALGORITHM_HPP
  8. #include <boost/geometry/core/coordinate_dimension.hpp>
  9. #include <boost/geometry/util/type_traits_std.hpp>
  10. namespace boost { namespace geometry
  11. {
  12. #ifndef DOXYGEN_NO_DETAIL
  13. namespace detail
  14. {
  15. // Other implementations can be found in the history of this file.
  16. // The discussion and benchmarks can be found here:
  17. // https://github.com/boostorg/geometry/pull/827
  18. // O(logN) version 2
  19. template <std::size_t N>
  20. struct for_each_index_impl2
  21. {
  22. static const std::size_t N1 = N / 2;
  23. static const std::size_t N2 = N - N1;
  24. template <std::size_t Offset, typename UnaryFunction>
  25. constexpr static inline void apply(UnaryFunction& function)
  26. {
  27. for_each_index_impl2<N1>::template apply<Offset>(function);
  28. for_each_index_impl2<N2>::template apply<Offset + N1>(function);
  29. }
  30. };
  31. template <>
  32. struct for_each_index_impl2<3>
  33. {
  34. template <std::size_t Offset, typename UnaryFunction>
  35. constexpr static inline void apply(UnaryFunction& function)
  36. {
  37. function(util::index_constant<Offset>());
  38. function(util::index_constant<Offset + 1>());
  39. function(util::index_constant<Offset + 2>());
  40. }
  41. };
  42. template <>
  43. struct for_each_index_impl2<2>
  44. {
  45. template <std::size_t Offset, typename UnaryFunction>
  46. constexpr static inline void apply(UnaryFunction& function)
  47. {
  48. function(util::index_constant<Offset>());
  49. function(util::index_constant<Offset + 1>());
  50. }
  51. };
  52. template <>
  53. struct for_each_index_impl2<1>
  54. {
  55. template <std::size_t Offset, typename UnaryFunction>
  56. constexpr static inline void apply(UnaryFunction& function)
  57. {
  58. function(util::index_constant<Offset>());
  59. }
  60. };
  61. template <>
  62. struct for_each_index_impl2<0>
  63. {
  64. template <std::size_t Offset, typename UnaryFunction>
  65. constexpr static inline void apply(UnaryFunction& )
  66. {}
  67. };
  68. // Interface
  69. template <std::size_t N, typename UnaryFunction>
  70. constexpr inline UnaryFunction for_each_index(UnaryFunction function)
  71. {
  72. for_each_index_impl2
  73. <
  74. N
  75. >::template apply<0>(function);
  76. return function;
  77. }
  78. template <typename Geometry, typename UnaryFunction>
  79. constexpr inline UnaryFunction for_each_dimension(UnaryFunction function)
  80. {
  81. for_each_index_impl2
  82. <
  83. geometry::dimension<Geometry>::value
  84. >::template apply<0>(function);
  85. return function;
  86. }
  87. // ----------------------------------------------------------------------------
  88. // O(logN) version 2
  89. template <std::size_t N>
  90. struct all_indexes_of_impl2
  91. {
  92. static const std::size_t N1 = N / 2;
  93. static const std::size_t N2 = N - N1;
  94. template <std::size_t Offset, typename UnaryPredicate>
  95. constexpr static inline bool apply(UnaryPredicate& predicate)
  96. {
  97. return all_indexes_of_impl2<N1>::template apply<Offset>(predicate)
  98. && all_indexes_of_impl2<N2>::template apply<Offset + N1>(predicate);
  99. }
  100. };
  101. template <>
  102. struct all_indexes_of_impl2<3>
  103. {
  104. template <std::size_t Offset, typename UnaryPredicate>
  105. constexpr static inline bool apply(UnaryPredicate& predicate)
  106. {
  107. return predicate(util::index_constant<Offset>())
  108. && predicate(util::index_constant<Offset + 1>())
  109. && predicate(util::index_constant<Offset + 2>());
  110. }
  111. };
  112. template <>
  113. struct all_indexes_of_impl2<2>
  114. {
  115. template <std::size_t Offset, typename UnaryPredicate>
  116. constexpr static inline bool apply(UnaryPredicate& predicate)
  117. {
  118. return predicate(util::index_constant<Offset>())
  119. && predicate(util::index_constant<Offset + 1>());
  120. }
  121. };
  122. template <>
  123. struct all_indexes_of_impl2<1>
  124. {
  125. template <std::size_t Offset, typename UnaryPredicate>
  126. constexpr static inline bool apply(UnaryPredicate& predicate)
  127. {
  128. return predicate(util::index_constant<Offset>());
  129. }
  130. };
  131. template <>
  132. struct all_indexes_of_impl2<0>
  133. {
  134. template <std::size_t Offset, typename UnaryPredicate>
  135. constexpr static inline bool apply(UnaryPredicate& )
  136. {
  137. return true;
  138. }
  139. };
  140. // Interface
  141. template <std::size_t N, typename UnaryPredicate>
  142. constexpr inline bool all_indexes_of(UnaryPredicate predicate)
  143. {
  144. return all_indexes_of_impl2<N>::template apply<0>(predicate);
  145. }
  146. template <typename Geometry, typename UnaryPredicate>
  147. constexpr inline bool all_dimensions_of(UnaryPredicate predicate)
  148. {
  149. return all_indexes_of_impl2
  150. <
  151. geometry::dimension<Geometry>::value
  152. >::template apply<0>(predicate);
  153. }
  154. // ----------------------------------------------------------------------------
  155. // O(logN) version 2
  156. template <std::size_t N>
  157. struct any_index_of_impl2
  158. {
  159. static const std::size_t N1 = N / 2;
  160. static const std::size_t N2 = N - N1;
  161. template <std::size_t Offset, typename UnaryPredicate>
  162. constexpr static inline bool apply(UnaryPredicate& predicate)
  163. {
  164. return any_index_of_impl2<N1>::template apply<Offset>(predicate)
  165. || any_index_of_impl2<N2>::template apply<Offset + N1>(predicate);
  166. }
  167. };
  168. template <>
  169. struct any_index_of_impl2<3>
  170. {
  171. template <std::size_t Offset, typename UnaryPredicate>
  172. constexpr static inline bool apply(UnaryPredicate& predicate)
  173. {
  174. return predicate(util::index_constant<Offset>())
  175. || predicate(util::index_constant<Offset + 1>())
  176. || predicate(util::index_constant<Offset + 2>());
  177. }
  178. };
  179. template <>
  180. struct any_index_of_impl2<2>
  181. {
  182. template <std::size_t Offset, typename UnaryPredicate>
  183. constexpr static inline bool apply(UnaryPredicate& predicate)
  184. {
  185. return predicate(util::index_constant<Offset>())
  186. || predicate(util::index_constant<Offset + 1>());
  187. }
  188. };
  189. template <>
  190. struct any_index_of_impl2<1>
  191. {
  192. template <std::size_t Offset, typename UnaryPredicate>
  193. constexpr static inline bool apply(UnaryPredicate& predicate)
  194. {
  195. return predicate(util::index_constant<Offset>());
  196. }
  197. };
  198. template <>
  199. struct any_index_of_impl2<0>
  200. {
  201. template <std::size_t Offset, typename UnaryPredicate>
  202. constexpr static inline bool apply(UnaryPredicate& )
  203. {
  204. return false;
  205. }
  206. };
  207. // Interface
  208. template <std::size_t N, typename UnaryPredicate>
  209. constexpr inline bool any_index_of(UnaryPredicate predicate)
  210. {
  211. return any_index_of_impl2<N>::template apply<0>(predicate);
  212. }
  213. template <typename Geometry, typename UnaryPredicate>
  214. constexpr inline bool any_dimension_of(UnaryPredicate predicate)
  215. {
  216. return any_index_of_impl2
  217. <
  218. geometry::dimension<Geometry>::value
  219. >::template apply<0>(predicate);
  220. }
  221. template <std::size_t N, typename UnaryPredicate>
  222. constexpr inline bool none_index_of(UnaryPredicate predicate)
  223. {
  224. return ! any_index_of_impl2<N>::template apply<0>(predicate);
  225. }
  226. template <typename Geometry, typename UnaryPredicate>
  227. constexpr inline bool none_dimension_of(UnaryPredicate predicate)
  228. {
  229. return ! any_index_of_impl2
  230. <
  231. geometry::dimension<Geometry>::value
  232. >::template apply<0>(predicate);
  233. }
  234. // ----------------------------------------------------------------------------
  235. } // namespace detail
  236. #endif // DOXYGEN_NO_DETAIL
  237. }} // namespace boost::geometry
  238. #endif // BOOST_GEOMETRY_UTIL_ALGORITHM_HPP