integer_sequence_algorithm.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. // Ceres Solver - A fast non-linear least squares minimizer
  2. // Copyright 2023 Google Inc. All rights reserved.
  3. // http://ceres-solver.org/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are met:
  7. //
  8. // * Redistributions of source code must retain the above copyright notice,
  9. // this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above copyright notice,
  11. // this list of conditions and the following disclaimer in the documentation
  12. // and/or other materials provided with the distribution.
  13. // * Neither the name of Google Inc. nor the names of its contributors may be
  14. // used to endorse or promote products derived from this software without
  15. // specific prior written permission.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  18. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  21. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  24. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  25. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  26. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. // POSSIBILITY OF SUCH DAMAGE.
  28. //
  29. // Author: jodebo_beck@gmx.de (Johannes Beck)
  30. // sergiu.deitsch@gmail.com (Sergiu Deitsch)
  31. //
  32. // Algorithms to be used together with integer_sequence, like computing the sum
  33. // or the exclusive scan (sometimes called exclusive prefix sum) at compile
  34. // time.
  35. #ifndef CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
  36. #define CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
  37. #include <utility>
  38. #include "ceres/jet_fwd.h"
  39. namespace ceres::internal {
  40. // Implementation of calculating an exclusive scan (exclusive prefix sum) of an
  41. // integer sequence. Exclusive means that the i-th input element is not included
  42. // in the i-th sum. Calculating the exclusive scan for an input array I results
  43. // in the following output R:
  44. //
  45. // R[0] = 0
  46. // R[1] = I[0];
  47. // R[2] = I[0] + I[1];
  48. // R[3] = I[0] + I[1] + I[2];
  49. // ...
  50. //
  51. // In C++17 std::exclusive_scan does the same operation at runtime (but
  52. // cannot be used to calculate the prefix sum at compile time). See
  53. // https://en.cppreference.com/w/cpp/algorithm/exclusive_scan for a more
  54. // detailed description.
  55. //
  56. // Example for integer_sequence<int, 1, 4, 3> (seq := integer_sequence):
  57. // T , Sum, Ns... , Rs...
  58. // ExclusiveScanImpl<int, 0, seq<int, 1, 4, 3>, seq<int >>
  59. // ExclusiveScanImpl<int, 1, seq<int, 4, 3>, seq<int, 0 >>
  60. // ExclusiveScanImpl<int, 5, seq<int, 3>, seq<int, 0, 1 >>
  61. // ExclusiveScanImpl<int, 8, seq<int >, seq<int, 0, 1, 5>>
  62. // ^^^^^^^^^^^^^^^^^
  63. // resulting sequence
  64. template <typename T, T Sum, typename SeqIn, typename SeqOut>
  65. struct ExclusiveScanImpl;
  66. template <typename T, T Sum, T N, T... Ns, T... Rs>
  67. struct ExclusiveScanImpl<T,
  68. Sum,
  69. std::integer_sequence<T, N, Ns...>,
  70. std::integer_sequence<T, Rs...>> {
  71. using Type =
  72. typename ExclusiveScanImpl<T,
  73. Sum + N,
  74. std::integer_sequence<T, Ns...>,
  75. std::integer_sequence<T, Rs..., Sum>>::Type;
  76. };
  77. // End of 'recursion'. The resulting type is SeqOut.
  78. template <typename T, T Sum, typename SeqOut>
  79. struct ExclusiveScanImpl<T, Sum, std::integer_sequence<T>, SeqOut> {
  80. using Type = SeqOut;
  81. };
  82. // Calculates the exclusive scan of the specified integer sequence. The last
  83. // element (the total) is not included in the resulting sequence so they have
  84. // same length. This means the exclusive scan of integer_sequence<int, 1, 2, 3>
  85. // will be integer_sequence<int, 0, 1, 3>.
  86. template <typename Seq>
  87. class ExclusiveScanT {
  88. using T = typename Seq::value_type;
  89. public:
  90. using Type =
  91. typename ExclusiveScanImpl<T, T(0), Seq, std::integer_sequence<T>>::Type;
  92. };
  93. // Helper to use exclusive scan without typename.
  94. template <typename Seq>
  95. using ExclusiveScan = typename ExclusiveScanT<Seq>::Type;
  96. // Removes all elements from a integer sequence corresponding to specified
  97. // ValueToRemove.
  98. //
  99. // This type should not be used directly but instead RemoveValue.
  100. template <typename T, T ValueToRemove, typename... Sequence>
  101. struct RemoveValueImpl;
  102. // Final filtered sequence
  103. template <typename T, T ValueToRemove, T... Values>
  104. struct RemoveValueImpl<T,
  105. ValueToRemove,
  106. std::integer_sequence<T, Values...>,
  107. std::integer_sequence<T>> {
  108. using type = std::integer_sequence<T, Values...>;
  109. };
  110. // Found a matching value
  111. template <typename T, T ValueToRemove, T... Head, T... Tail>
  112. struct RemoveValueImpl<T,
  113. ValueToRemove,
  114. std::integer_sequence<T, Head...>,
  115. std::integer_sequence<T, ValueToRemove, Tail...>>
  116. : RemoveValueImpl<T,
  117. ValueToRemove,
  118. std::integer_sequence<T, Head...>,
  119. std::integer_sequence<T, Tail...>> {};
  120. // Move one element from the tail to the head
  121. template <typename T, T ValueToRemove, T... Head, T MiddleValue, T... Tail>
  122. struct RemoveValueImpl<T,
  123. ValueToRemove,
  124. std::integer_sequence<T, Head...>,
  125. std::integer_sequence<T, MiddleValue, Tail...>>
  126. : RemoveValueImpl<T,
  127. ValueToRemove,
  128. std::integer_sequence<T, Head..., MiddleValue>,
  129. std::integer_sequence<T, Tail...>> {};
  130. // Start recursion by splitting the integer sequence into two separate ones
  131. template <typename T, T ValueToRemove, T... Tail>
  132. struct RemoveValueImpl<T, ValueToRemove, std::integer_sequence<T, Tail...>>
  133. : RemoveValueImpl<T,
  134. ValueToRemove,
  135. std::integer_sequence<T>,
  136. std::integer_sequence<T, Tail...>> {};
  137. // RemoveValue takes an integer Sequence of arbitrary type and removes all
  138. // elements matching ValueToRemove.
  139. //
  140. // In contrast to RemoveValueImpl, this implementation deduces the value type
  141. // eliminating the need to specify it explicitly.
  142. //
  143. // As an example, RemoveValue<std::integer_sequence<int, 1, 2, 3>, 4>::type will
  144. // not transform the type of the original sequence. However,
  145. // RemoveValue<std::integer_sequence<int, 0, 0, 2>, 2>::type will generate a new
  146. // sequence of type std::integer_sequence<int, 0, 0> by removing the value 2.
  147. template <typename Sequence, typename Sequence::value_type ValueToRemove>
  148. struct RemoveValue
  149. : RemoveValueImpl<typename Sequence::value_type, ValueToRemove, Sequence> {
  150. };
  151. // Convenience template alias for RemoveValue.
  152. template <typename Sequence, typename Sequence::value_type ValueToRemove>
  153. using RemoveValue_t = typename RemoveValue<Sequence, ValueToRemove>::type;
  154. // Returns true if all elements of Values are equal to HeadValue.
  155. //
  156. // Returns true if Values is empty.
  157. template <typename T, T HeadValue, T... Values>
  158. inline constexpr bool AreAllEqual_v = ((HeadValue == Values) && ...);
  159. // Predicate determining whether an integer sequence is either empty or all
  160. // values are equal.
  161. template <typename Sequence>
  162. struct IsEmptyOrAreAllEqual;
  163. // Empty case.
  164. template <typename T>
  165. struct IsEmptyOrAreAllEqual<std::integer_sequence<T>> : std::true_type {};
  166. // General case for sequences containing at least one value.
  167. template <typename T, T HeadValue, T... Values>
  168. struct IsEmptyOrAreAllEqual<std::integer_sequence<T, HeadValue, Values...>>
  169. : std::integral_constant<bool, AreAllEqual_v<T, HeadValue, Values...>> {};
  170. // Convenience variable template for IsEmptyOrAreAllEqual.
  171. template <class Sequence>
  172. inline constexpr bool IsEmptyOrAreAllEqual_v =
  173. IsEmptyOrAreAllEqual<Sequence>::value;
  174. } // namespace ceres::internal
  175. #endif // CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_