2018-10-07 19:56:26 +02:00
|
|
|
// Ceres Solver - A fast non-linear least squares minimizer
|
2022-02-01 21:11:14 +01:00
|
|
|
// Copyright 2022 Google Inc. All rights reserved.
|
2018-10-07 19:56:26 +02:00
|
|
|
// 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)
|
2022-02-01 21:11:14 +01:00
|
|
|
// sergiu.deitsch@gmail.com (Sergiu Deitsch)
|
2018-10-07 19:56:26 +02:00
|
|
|
//
|
|
|
|
|
// 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_
|
|
|
|
|
|
2020-05-30 11:30:01 +01:00
|
|
|
#include <utility>
|
2018-10-07 19:56:26 +02:00
|
|
|
|
2022-02-01 21:11:14 +01:00
|
|
|
#include "ceres/jet_fwd.h"
|
|
|
|
|
|
2018-10-07 19:56:26 +02:00
|
|
|
namespace ceres {
|
|
|
|
|
namespace internal {
|
|
|
|
|
|
|
|
|
|
// Implementation of calculating the sum of an integer sequence.
|
|
|
|
|
// Recursively instantiate SumImpl and calculate the sum of the N first
|
|
|
|
|
// numbers. This reduces the number of instantiations and speeds up
|
|
|
|
|
// compilation.
|
|
|
|
|
//
|
|
|
|
|
// Examples:
|
|
|
|
|
// 1) integer_sequence<int, 5>:
|
|
|
|
|
// Value = 5
|
|
|
|
|
//
|
|
|
|
|
// 2) integer_sequence<int, 4, 2>:
|
|
|
|
|
// Value = 4 + 2 + SumImpl<integer_sequence<int>>::Value
|
|
|
|
|
// Value = 4 + 2 + 0
|
|
|
|
|
//
|
|
|
|
|
// 3) integer_sequence<int, 2, 1, 4>:
|
|
|
|
|
// Value = 2 + 1 + SumImpl<integer_sequence<int, 4>>::Value
|
|
|
|
|
// Value = 2 + 1 + 4
|
|
|
|
|
template <typename Seq>
|
|
|
|
|
struct SumImpl;
|
|
|
|
|
|
|
|
|
|
// Strip of and sum the first number.
|
|
|
|
|
template <typename T, T N, T... Ns>
|
2020-05-30 11:30:01 +01:00
|
|
|
struct SumImpl<std::integer_sequence<T, N, Ns...>> {
|
2020-09-06 21:04:24 +02:00
|
|
|
static constexpr T Value =
|
|
|
|
|
N + SumImpl<std::integer_sequence<T, Ns...>>::Value;
|
2018-10-07 19:56:26 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Strip of and sum the first two numbers.
|
|
|
|
|
template <typename T, T N1, T N2, T... Ns>
|
2020-05-30 11:30:01 +01:00
|
|
|
struct SumImpl<std::integer_sequence<T, N1, N2, Ns...>> {
|
2018-10-07 19:56:26 +02:00
|
|
|
static constexpr T Value =
|
2020-05-30 11:30:01 +01:00
|
|
|
N1 + N2 + SumImpl<std::integer_sequence<T, Ns...>>::Value;
|
2018-10-07 19:56:26 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Strip of and sum the first four numbers.
|
|
|
|
|
template <typename T, T N1, T N2, T N3, T N4, T... Ns>
|
2020-05-30 11:30:01 +01:00
|
|
|
struct SumImpl<std::integer_sequence<T, N1, N2, N3, N4, Ns...>> {
|
2018-10-07 19:56:26 +02:00
|
|
|
static constexpr T Value =
|
2020-05-30 11:30:01 +01:00
|
|
|
N1 + N2 + N3 + N4 + SumImpl<std::integer_sequence<T, Ns...>>::Value;
|
2018-10-07 19:56:26 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Only one number is left. 'Value' is just that number ('recursion' ends).
|
|
|
|
|
template <typename T, T N>
|
2020-05-30 11:30:01 +01:00
|
|
|
struct SumImpl<std::integer_sequence<T, N>> {
|
2018-10-07 19:56:26 +02:00
|
|
|
static constexpr T Value = N;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// No number is left. 'Value' is the identity element (for sum this is zero).
|
|
|
|
|
template <typename T>
|
2020-05-30 11:30:01 +01:00
|
|
|
struct SumImpl<std::integer_sequence<T>> {
|
2018-10-07 19:56:26 +02:00
|
|
|
static constexpr T Value = T(0);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Calculate the sum of an integer sequence. The resulting sum will be stored in
|
|
|
|
|
// 'Value'.
|
|
|
|
|
template <typename Seq>
|
|
|
|
|
class Sum {
|
|
|
|
|
using T = typename Seq::value_type;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
static constexpr T Value = SumImpl<Seq>::Value;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 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>
|
2020-09-06 21:04:24 +02:00
|
|
|
struct ExclusiveScanImpl<T,
|
|
|
|
|
Sum,
|
|
|
|
|
std::integer_sequence<T, N, Ns...>,
|
2020-05-30 11:30:01 +01:00
|
|
|
std::integer_sequence<T, Rs...>> {
|
2018-10-07 19:56:26 +02:00
|
|
|
using Type =
|
2020-09-06 21:04:24 +02:00
|
|
|
typename ExclusiveScanImpl<T,
|
|
|
|
|
Sum + N,
|
|
|
|
|
std::integer_sequence<T, Ns...>,
|
2020-05-30 11:30:01 +01:00
|
|
|
std::integer_sequence<T, Rs..., Sum>>::Type;
|
2018-10-07 19:56:26 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// End of 'recursion'. The resulting type is SeqOut.
|
|
|
|
|
template <typename T, T Sum, typename SeqOut>
|
2020-05-30 11:30:01 +01:00
|
|
|
struct ExclusiveScanImpl<T, Sum, std::integer_sequence<T>, SeqOut> {
|
2018-10-07 19:56:26 +02:00
|
|
|
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 =
|
2020-05-30 11:30:01 +01:00
|
|
|
typename ExclusiveScanImpl<T, T(0), Seq, std::integer_sequence<T>>::Type;
|
2018-10-07 19:56:26 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Helper to use exclusive scan without typename.
|
|
|
|
|
template <typename Seq>
|
|
|
|
|
using ExclusiveScan = typename ExclusiveScanT<Seq>::Type;
|
|
|
|
|
|
2022-02-01 21:11:14 +01:00
|
|
|
// 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;
|
|
|
|
|
|
|
|
|
|
// Determines whether the values of an integer sequence are all the same.
|
|
|
|
|
//
|
|
|
|
|
// The integer sequence must contain at least one value. The predicate is
|
|
|
|
|
// undefined for empty sequences. The evaluation result of the predicate for a
|
|
|
|
|
// sequence containing only one value is defined to be true.
|
|
|
|
|
template <typename... Sequence>
|
|
|
|
|
struct AreAllEqual;
|
|
|
|
|
|
|
|
|
|
// The predicate result for a sequence containing one element is defined to be
|
|
|
|
|
// true.
|
|
|
|
|
template <typename T, T Value>
|
|
|
|
|
struct AreAllEqual<std::integer_sequence<T, Value>> : std::true_type {};
|
|
|
|
|
|
|
|
|
|
// Recursion end.
|
|
|
|
|
template <typename T, T Value1, T Value2>
|
|
|
|
|
struct AreAllEqual<std::integer_sequence<T, Value1, Value2>>
|
|
|
|
|
: std::integral_constant<bool, Value1 == Value2> {};
|
|
|
|
|
|
|
|
|
|
// Recursion for sequences containing at least two elements.
|
|
|
|
|
template <typename T, T Value1, T Value2, T... Values>
|
|
|
|
|
// clang-format off
|
|
|
|
|
struct AreAllEqual<std::integer_sequence<T, Value1, Value2, Values...> >
|
|
|
|
|
: std::integral_constant
|
|
|
|
|
<
|
|
|
|
|
bool,
|
|
|
|
|
AreAllEqual<std::integer_sequence<T, Value1, Value2> >::value &&
|
|
|
|
|
AreAllEqual<std::integer_sequence<T, Value2, Values...> >::value
|
|
|
|
|
>
|
|
|
|
|
// clang-format on
|
|
|
|
|
{};
|
|
|
|
|
|
|
|
|
|
// Convenience variable template for AreAllEqual.
|
|
|
|
|
template <class Sequence>
|
|
|
|
|
constexpr bool AreAllEqual_v = AreAllEqual<Sequence>::value;
|
|
|
|
|
|
|
|
|
|
// 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...>>
|
|
|
|
|
: AreAllEqual<std::integer_sequence<T, HeadValue, Values...>> {};
|
|
|
|
|
|
|
|
|
|
// Convenience variable template for IsEmptyOrAreAllEqual.
|
|
|
|
|
template <class Sequence>
|
|
|
|
|
constexpr bool IsEmptyOrAreAllEqual_v = IsEmptyOrAreAllEqual<Sequence>::value;
|
|
|
|
|
|
2018-10-07 19:56:26 +02:00
|
|
|
} // namespace internal
|
|
|
|
|
} // namespace ceres
|
|
|
|
|
|
|
|
|
|
#endif // CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
|