| // 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_ |