blob: 2a38c05b7dab672b9807ee9a7502fb9c795f9ac5 [file] [log] [blame]
// 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)
//
#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 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
#endif // CERES_PUBLIC_INTERNAL_JET_TRAITS_H_