123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- // Ceres Solver - A fast non-linear least squares minimizer
- // Copyright 2023 Google Inc. All rights reserved.
- // http://ceres-solver.org/
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are met:
- //
- // * Redistributions of source code must retain the above copyright notice,
- // this list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above copyright notice,
- // this list of conditions and the following disclaimer in the documentation
- // and/or other materials provided with the distribution.
- // * Neither the name of Google Inc. nor the names of its contributors may be
- // used to endorse or promote products derived from this software without
- // specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- // POSSIBILITY OF SUCH DAMAGE.
- //
- // Author: jodebo_beck@gmx.de (Johannes Beck)
- // sergiu.deitsch@gmail.com (Sergiu Deitsch)
- //
- // Algorithms to be used together with integer_sequence, like computing the sum
- // or the exclusive scan (sometimes called exclusive prefix sum) at compile
- // time.
- #ifndef CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
- #define CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
- #include <utility>
- #include "ceres/jet_fwd.h"
- namespace ceres::internal {
- // Implementation of calculating an exclusive scan (exclusive prefix sum) of an
- // integer sequence. Exclusive means that the i-th input element is not included
- // in the i-th sum. Calculating the exclusive scan for an input array I results
- // in the following output R:
- //
- // R[0] = 0
- // R[1] = I[0];
- // R[2] = I[0] + I[1];
- // R[3] = I[0] + I[1] + I[2];
- // ...
- //
- // In C++17 std::exclusive_scan does the same operation at runtime (but
- // cannot be used to calculate the prefix sum at compile time). See
- // https://en.cppreference.com/w/cpp/algorithm/exclusive_scan for a more
- // detailed description.
- //
- // Example for integer_sequence<int, 1, 4, 3> (seq := integer_sequence):
- // T , Sum, Ns... , Rs...
- // ExclusiveScanImpl<int, 0, seq<int, 1, 4, 3>, seq<int >>
- // ExclusiveScanImpl<int, 1, seq<int, 4, 3>, seq<int, 0 >>
- // ExclusiveScanImpl<int, 5, seq<int, 3>, seq<int, 0, 1 >>
- // ExclusiveScanImpl<int, 8, seq<int >, seq<int, 0, 1, 5>>
- // ^^^^^^^^^^^^^^^^^
- // resulting sequence
- template <typename T, T Sum, typename SeqIn, typename SeqOut>
- struct ExclusiveScanImpl;
- template <typename T, T Sum, T N, T... Ns, T... Rs>
- struct ExclusiveScanImpl<T,
- Sum,
- std::integer_sequence<T, N, Ns...>,
- std::integer_sequence<T, Rs...>> {
- using Type =
- typename ExclusiveScanImpl<T,
- Sum + N,
- std::integer_sequence<T, Ns...>,
- std::integer_sequence<T, Rs..., Sum>>::Type;
- };
- // End of 'recursion'. The resulting type is SeqOut.
- template <typename T, T Sum, typename SeqOut>
- struct ExclusiveScanImpl<T, Sum, std::integer_sequence<T>, SeqOut> {
- using Type = SeqOut;
- };
- // Calculates the exclusive scan of the specified integer sequence. The last
- // element (the total) is not included in the resulting sequence so they have
- // same length. This means the exclusive scan of integer_sequence<int, 1, 2, 3>
- // will be integer_sequence<int, 0, 1, 3>.
- template <typename Seq>
- class ExclusiveScanT {
- using T = typename Seq::value_type;
- public:
- using Type =
- typename ExclusiveScanImpl<T, T(0), Seq, std::integer_sequence<T>>::Type;
- };
- // Helper to use exclusive scan without typename.
- template <typename Seq>
- using ExclusiveScan = typename ExclusiveScanT<Seq>::Type;
- // Removes all elements from a integer sequence corresponding to specified
- // ValueToRemove.
- //
- // This type should not be used directly but instead RemoveValue.
- template <typename T, T ValueToRemove, typename... Sequence>
- struct RemoveValueImpl;
- // Final filtered sequence
- template <typename T, T ValueToRemove, T... Values>
- struct RemoveValueImpl<T,
- ValueToRemove,
- std::integer_sequence<T, Values...>,
- std::integer_sequence<T>> {
- using type = std::integer_sequence<T, Values...>;
- };
- // Found a matching value
- template <typename T, T ValueToRemove, T... Head, T... Tail>
- struct RemoveValueImpl<T,
- ValueToRemove,
- std::integer_sequence<T, Head...>,
- std::integer_sequence<T, ValueToRemove, Tail...>>
- : RemoveValueImpl<T,
- ValueToRemove,
- std::integer_sequence<T, Head...>,
- std::integer_sequence<T, Tail...>> {};
- // Move one element from the tail to the head
- template <typename T, T ValueToRemove, T... Head, T MiddleValue, T... Tail>
- struct RemoveValueImpl<T,
- ValueToRemove,
- std::integer_sequence<T, Head...>,
- std::integer_sequence<T, MiddleValue, Tail...>>
- : RemoveValueImpl<T,
- ValueToRemove,
- std::integer_sequence<T, Head..., MiddleValue>,
- std::integer_sequence<T, Tail...>> {};
- // Start recursion by splitting the integer sequence into two separate ones
- template <typename T, T ValueToRemove, T... Tail>
- struct RemoveValueImpl<T, ValueToRemove, std::integer_sequence<T, Tail...>>
- : RemoveValueImpl<T,
- ValueToRemove,
- std::integer_sequence<T>,
- std::integer_sequence<T, Tail...>> {};
- // RemoveValue takes an integer Sequence of arbitrary type and removes all
- // elements matching ValueToRemove.
- //
- // In contrast to RemoveValueImpl, this implementation deduces the value type
- // eliminating the need to specify it explicitly.
- //
- // As an example, RemoveValue<std::integer_sequence<int, 1, 2, 3>, 4>::type will
- // not transform the type of the original sequence. However,
- // RemoveValue<std::integer_sequence<int, 0, 0, 2>, 2>::type will generate a new
- // sequence of type std::integer_sequence<int, 0, 0> by removing the value 2.
- template <typename Sequence, typename Sequence::value_type ValueToRemove>
- struct RemoveValue
- : RemoveValueImpl<typename Sequence::value_type, ValueToRemove, Sequence> {
- };
- // Convenience template alias for RemoveValue.
- template <typename Sequence, typename Sequence::value_type ValueToRemove>
- using RemoveValue_t = typename RemoveValue<Sequence, ValueToRemove>::type;
- // Returns true if all elements of Values are equal to HeadValue.
- //
- // Returns true if Values is empty.
- template <typename T, T HeadValue, T... Values>
- inline constexpr bool AreAllEqual_v = ((HeadValue == Values) && ...);
- // Predicate determining whether an integer sequence is either empty or all
- // values are equal.
- template <typename Sequence>
- struct IsEmptyOrAreAllEqual;
- // Empty case.
- template <typename T>
- struct IsEmptyOrAreAllEqual<std::integer_sequence<T>> : std::true_type {};
- // General case for sequences containing at least one value.
- template <typename T, T HeadValue, T... Values>
- struct IsEmptyOrAreAllEqual<std::integer_sequence<T, HeadValue, Values...>>
- : std::integral_constant<bool, AreAllEqual_v<T, HeadValue, Values...>> {};
- // Convenience variable template for IsEmptyOrAreAllEqual.
- template <class Sequence>
- inline constexpr bool IsEmptyOrAreAllEqual_v =
- IsEmptyOrAreAllEqual<Sequence>::value;
- } // namespace ceres::internal
- #endif // CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
|