| // Ceres Solver - A fast non-linear least squares minimizer | |
| // Copyright 2022 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: sergiu.deitsch@gmail.com (Sergiu Deitsch) | |
| // | |
| namespace ceres { | |
| namespace internal { | |
| // Predicate that determines whether T is a Jet. | |
| template <typename T, typename E = void> | |
| struct IsJet : std::false_type {}; | |
| template <typename T, int N> | |
| struct IsJet<Jet<T, N>> : std::true_type {}; | |
| // Convenience variable template for IsJet. | |
| template <typename T> | |
| constexpr bool IsJet_v = IsJet<T>::value; | |
| // Predicate that determines whether any of the Types is a Jet. | |
| template <typename... Types> | |
| struct AreAnyJet : std::false_type {}; | |
| template <typename T, typename... Types> | |
| struct AreAnyJet<T, Types...> : AreAnyJet<Types...> {}; | |
| template <typename T, int N, typename... Types> | |
| struct AreAnyJet<Jet<T, N>, Types...> : std::true_type {}; | |
| // Convenience variable template for AreAnyJet. | |
| template <typename... Types> | |
| constexpr bool AreAnyJet_v = AreAnyJet<Types...>::value; | |
| // Extracts the underlying floating-point from a type T. | |
| template <typename T, typename E = void> | |
| struct UnderlyingScalar { | |
| using type = T; | |
| }; | |
| template <typename T, int N> | |
| struct UnderlyingScalar<Jet<T, N>> : UnderlyingScalar<T> {}; | |
| // Convenience template alias for UnderlyingScalar type trait. | |
| template <typename T> | |
| using UnderlyingScalar_t = typename UnderlyingScalar<T>::type; | |
| // Predicate determining whether all Types in the pack are the same. | |
| // | |
| // Specifically, the predicate applies std::is_same recursively to pairs of | |
| // Types in the pack. | |
| // | |
| // The predicate is defined only for template packs containing at least two | |
| // types. | |
| template <typename T1, typename T2, typename... Types> | |
| // clang-format off | |
| struct AreAllSame : std::integral_constant | |
| < | |
| bool, | |
| AreAllSame<T1, T2>::value && | |
| AreAllSame<T2, Types...>::value | |
| > | |
| // clang-format on | |
| {}; | |
| // AreAllSame pairwise test. | |
| template <typename T1, typename T2> | |
| struct AreAllSame<T1, T2> : std::is_same<T1, T2> {}; | |
| // Convenience variable template for AreAllSame. | |
| template <typename... Types> | |
| constexpr bool AreAllSame_v = AreAllSame<Types...>::value; | |
| // Determines the rank of a type. This allows to ensure that types passed as | |
| // arguments are compatible to each other. The rank of Jet is determined by the | |
| // dimensions of the dual part. The rank of a scalar is always 0. | |
| // Non-specialized types default to a rank of -1. | |
| template <typename T, typename E = void> | |
| struct Rank : std::integral_constant<int, -1> {}; | |
| // The rank of a scalar is 0. | |
| template <typename T> | |
| struct Rank<T, std::enable_if_t<std::is_scalar<T>::value>> | |
| : std::integral_constant<int, 0> {}; | |
| // The rank of a Jet is given by its dimensionality. | |
| template <typename T, int N> | |
| struct Rank<Jet<T, N>> : std::integral_constant<int, N> {}; | |
| // Convenience variable template for Rank. | |
| template <typename T> | |
| constexpr int Rank_v = Rank<T>::value; | |
| // Constructs an integer sequence of ranks for each of the Types in the pack. | |
| template <typename... Types> | |
| using Ranks_t = std::integer_sequence<int, Rank_v<Types>...>; | |
| // Returns the scalar part of a type. This overload acts as an identity. | |
| template <typename T> | |
| constexpr decltype(auto) AsScalar(T&& value) noexcept { | |
| return std::forward<T>(value); | |
| } | |
| // Recursively unwraps the scalar part of a Jet until a non-Jet scalar type is | |
| // encountered. | |
| template <typename T, int N> | |
| constexpr decltype(auto) AsScalar(const Jet<T, N>& value) noexcept( | |
| noexcept(AsScalar(value.a))) { | |
| return AsScalar(value.a); | |
| } | |
| } // namespace internal | |
| // Type trait ensuring at least one of the types is a Jet, | |
| // the underlying scalar types are the same and Jet dimensions match. | |
| // | |
| // The type trait can be further specialized if necessary. | |
| // | |
| // This trait is a candidate for a concept definition once C++20 features can | |
| // be used. | |
| template <typename... Types> | |
| // clang-format off | |
| struct CompatibleJetOperands : std::integral_constant | |
| < | |
| bool, | |
| // At least one of the types is a Jet | |
| internal::AreAnyJet_v<Types...> && | |
| // The underlying floating-point types are exactly the same | |
| internal::AreAllSame_v<internal::UnderlyingScalar_t<Types>...> && | |
| // Non-zero ranks of types are equal | |
| internal::IsEmptyOrAreAllEqual_v<internal::RemoveValue_t<internal::Ranks_t<Types...>, 0>> | |
| > | |
| // clang-format on | |
| {}; | |
| // Single Jet operand is always compatible. | |
| template <typename T, int N> | |
| struct CompatibleJetOperands<Jet<T, N>> : std::true_type {}; | |
| // Single non-Jet operand is always incompatible. | |
| template <typename T> | |
| struct CompatibleJetOperands<T> : std::false_type {}; | |
| // Empty operands are always incompatible. | |
| template <> | |
| struct CompatibleJetOperands<> : std::false_type {}; | |
| // Convenience variable template ensuring at least one of the types is a Jet, | |
| // the underlying scalar types are the same and Jet dimensions match. | |
| // | |
| // This trait is a candidate for a concept definition once C++20 features can | |
| // be used. | |
| template <typename... Types> | |
| constexpr bool CompatibleJetOperands_v = CompatibleJetOperands<Types...>::value; | |
| // Type trait ensuring at least one of the types is a Jet, | |
| // the underlying scalar types are compatible among each other and Jet | |
| // dimensions match. | |
| // | |
| // The type trait can be further specialized if necessary. | |
| // | |
| // This trait is a candidate for a concept definition once C++20 features can | |
| // be used. | |
| template <typename... Types> | |
| // clang-format off | |
| struct PromotableJetOperands : std::integral_constant | |
| < | |
| bool, | |
| // Types can be compatible among each other | |
| internal::AreAnyJet_v<Types...> && | |
| // Non-zero ranks of types are equal | |
| internal::IsEmptyOrAreAllEqual_v<internal::RemoveValue_t<internal::Ranks_t<Types...>, 0>> | |
| > | |
| // clang-format on | |
| {}; | |
| // Convenience variable template ensuring at least one of the types is a Jet, | |
| // the underlying scalar types are compatible among each other and Jet | |
| // dimensions match. | |
| // | |
| // This trait is a candidate for a concept definition once C++20 features can | |
| // be used. | |
| template <typename... Types> | |
| constexpr bool PromotableJetOperands_v = PromotableJetOperands<Types...>::value; | |
| } // namespace ceres | |