123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- #ifndef CERES_PUBLIC_INTERNAL_AUTODIFF_H_
- #define CERES_PUBLIC_INTERNAL_AUTODIFF_H_
- #include <array>
- #include <cstddef>
- #include <utility>
- #include "ceres/internal/array_selector.h"
- #include "ceres/internal/eigen.h"
- #include "ceres/internal/fixed_array.h"
- #include "ceres/internal/parameter_dims.h"
- #include "ceres/internal/variadic_evaluate.h"
- #include "ceres/jet.h"
- #include "ceres/types.h"
- #include "glog/logging.h"
- #ifndef CERES_AUTODIFF_MAX_PARAMETERS_ON_STACK
- #define CERES_AUTODIFF_MAX_PARAMETERS_ON_STACK 50
- #endif
- #ifndef CERES_AUTODIFF_MAX_RESIDUALS_ON_STACK
- #define CERES_AUTODIFF_MAX_RESIDUALS_ON_STACK 20
- #endif
- namespace ceres::internal {
- template <int j, int N, int Offset, typename T, typename JetT>
- struct Make1stOrderPerturbation {
- public:
- inline static void Apply(const T* src, JetT* dst) {
- if (j == 0) {
- DCHECK(src);
- DCHECK(dst);
- }
- dst[j] = JetT(src[j], j + Offset);
- Make1stOrderPerturbation<j + 1, N, Offset, T, JetT>::Apply(src, dst);
- }
- };
- template <int N, int Offset, typename T, typename JetT>
- struct Make1stOrderPerturbation<N, N, Offset, T, JetT> {
- public:
- static void Apply(const T* , JetT* ) {}
- };
- template <typename Seq, int ParameterIdx = 0, int Offset = 0>
- struct Make1stOrderPerturbations;
- template <int N, int... Ns, int ParameterIdx, int Offset>
- struct Make1stOrderPerturbations<std::integer_sequence<int, N, Ns...>,
- ParameterIdx,
- Offset> {
- template <typename T, typename JetT>
- inline static void Apply(T const* const* parameters, JetT* x) {
- Make1stOrderPerturbation<0, N, Offset, T, JetT>::Apply(
- parameters[ParameterIdx], x + Offset);
- Make1stOrderPerturbations<std::integer_sequence<int, Ns...>,
- ParameterIdx + 1,
- Offset + N>::Apply(parameters, x);
- }
- };
- template <int ParameterIdx, int Total>
- struct Make1stOrderPerturbations<std::integer_sequence<int>,
- ParameterIdx,
- Total> {
- template <typename T, typename JetT>
- static void Apply(T const* const* , JetT* ) {}
- };
- template <typename JetT, typename T>
- inline void Take0thOrderPart(int M, const JetT* src, T dst) {
- DCHECK(src);
- for (int i = 0; i < M; ++i) {
- dst[i] = src[i].a;
- }
- }
- template <int N0, int N, typename JetT, typename T>
- inline void Take1stOrderPart(const int M, const JetT* src, T* dst) {
- DCHECK(src);
- DCHECK(dst);
- for (int i = 0; i < M; ++i) {
- Eigen::Map<Eigen::Matrix<T, N, 1>>(dst + N * i, N) =
- src[i].v.template segment<N>(N0);
- }
- }
- template <typename Seq, int ParameterIdx = 0, int Offset = 0>
- struct Take1stOrderParts;
- template <int N, int... Ns, int ParameterIdx, int Offset>
- struct Take1stOrderParts<std::integer_sequence<int, N, Ns...>,
- ParameterIdx,
- Offset> {
- template <typename JetT, typename T>
- inline static void Apply(int num_outputs, JetT* output, T** jacobians) {
- if (jacobians[ParameterIdx]) {
- Take1stOrderPart<Offset, N>(num_outputs, output, jacobians[ParameterIdx]);
- }
- Take1stOrderParts<std::integer_sequence<int, Ns...>,
- ParameterIdx + 1,
- Offset + N>::Apply(num_outputs, output, jacobians);
- }
- };
- template <int ParameterIdx, int Offset>
- struct Take1stOrderParts<std::integer_sequence<int>, ParameterIdx, Offset> {
- template <typename T, typename JetT>
- static void Apply(int ,
- JetT* ,
- T** ) {}
- };
- template <int kNumResiduals,
- typename ParameterDims,
- typename Functor,
- typename T>
- inline bool AutoDifferentiate(const Functor& functor,
- T const* const* parameters,
- int dynamic_num_outputs,
- T* function_value,
- T** jacobians) {
- using JetT = Jet<T, ParameterDims::kNumParameters>;
- using Parameters = typename ParameterDims::Parameters;
- if (kNumResiduals != DYNAMIC) {
- DCHECK_EQ(kNumResiduals, dynamic_num_outputs);
- }
- ArraySelector<JetT,
- ParameterDims::kNumParameters,
- CERES_AUTODIFF_MAX_PARAMETERS_ON_STACK>
- parameters_as_jets(ParameterDims::kNumParameters);
-
- std::array<JetT*, ParameterDims::kNumParameterBlocks> unpacked_parameters =
- ParameterDims::GetUnpackedParameters(parameters_as_jets.data());
-
-
-
-
- const int num_outputs =
- kNumResiduals == DYNAMIC ? dynamic_num_outputs : kNumResiduals;
- DCHECK_GT(num_outputs, 0);
- ArraySelector<JetT, kNumResiduals, CERES_AUTODIFF_MAX_RESIDUALS_ON_STACK>
- residuals_as_jets(num_outputs);
-
-
- for (int i = 0; i < num_outputs; ++i) {
- residuals_as_jets[i].a = kImpossibleValue;
- residuals_as_jets[i].v.setConstant(kImpossibleValue);
- }
- Make1stOrderPerturbations<Parameters>::Apply(parameters,
- parameters_as_jets.data());
- if (!VariadicEvaluate<ParameterDims>(
- functor, unpacked_parameters.data(), residuals_as_jets.data())) {
- return false;
- }
- Take0thOrderPart(num_outputs, residuals_as_jets.data(), function_value);
- Take1stOrderParts<Parameters>::Apply(
- num_outputs, residuals_as_jets.data(), jacobians);
- return true;
- }
- }
- #endif
|