| // 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: sergiu.deitsch@gmail.com (Sergiu Deitsch) | 
 | // | 
 |  | 
 | #ifndef CERES_PUBLIC_INTERNAL_JET_TRAITS_H_ | 
 | #define CERES_PUBLIC_INTERNAL_JET_TRAITS_H_ | 
 |  | 
 | #include <tuple> | 
 | #include <type_traits> | 
 | #include <utility> | 
 |  | 
 | #include "ceres/internal/integer_sequence_algorithm.h" | 
 | #include "ceres/jet_fwd.h" | 
 |  | 
 | namespace ceres { | 
 | namespace internal { | 
 |  | 
 | // 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> | 
 | inline 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. | 
 | template <typename T1, typename... Types> | 
 | inline constexpr bool AreAllSame_v = (std::is_same<T1, 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> | 
 | inline 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> | 
 | inline 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> | 
 | inline constexpr bool PromotableJetOperands_v = | 
 |     PromotableJetOperands<Types...>::value; | 
 |  | 
 | }  // namespace ceres | 
 |  | 
 | #endif  // CERES_PUBLIC_INTERNAL_JET_TRAITS_H_ |