26struct IsScalar<Eigen::Matrix<double, N, 1, Eigen::ColMajor, N, 1>>
31template <std::
size_t IndexInTuple,
typename Tuple>
34 auto const& value = std::get<IndexInTuple>(tuple);
36 if constexpr (
IsScalar<std::remove_cvref_t<
decltype(value)>>::value)
42 return value[component];
52 template <
typename Function,
typename TupleOfArgs,
53 typename PerturbationStrategy, std::size_t PerturbedArgIdx,
54 std::size_t... AllArgIdcs>
55 auto operator()(Function
const& f, TupleOfArgs
const& args,
56 PerturbationStrategy
const& pert_strat,
57 std::integral_constant<std::size_t, PerturbedArgIdx>,
58 Eigen::Index
const perturbed_arg_component,
59 std::index_sequence<AllArgIdcs...>)
const
61 auto const value_plus = f(pert_strat.perturbIf(
62 std::bool_constant<PerturbedArgIdx == AllArgIdcs>{},
63 std::get<AllArgIdcs>(args), 1.0, perturbed_arg_component)...);
65 auto const value_minus = f(pert_strat.perturbIf(
66 std::bool_constant<PerturbedArgIdx == AllArgIdcs>{},
67 std::get<AllArgIdcs>(args), -1.0, perturbed_arg_component)...);
69 auto const pert = pert_strat.getPerturbation(
71 args, perturbed_arg_component));
74 decltype(value_plus) deriv = (value_plus - value_minus) / (2 * pert);
84template <
typename Value>
92 template <
typename Function,
typename TupleOfArgs,
93 typename PerturbationStrategy, std::size_t PerturbedArgIdx,
94 std::size_t... AllArgIdcs>
95 Value
operator()(Function
const& f, TupleOfArgs
const& args,
96 PerturbationStrategy
const& pert_strat,
97 std::integral_constant<std::size_t, PerturbedArgIdx>,
98 Eigen::Index
const perturbed_arg_component,
99 std::index_sequence<AllArgIdcs...>)
const
101 auto const value_plus = f(pert_strat.perturbIf(
102 std::bool_constant<PerturbedArgIdx == AllArgIdcs>{},
103 std::get<AllArgIdcs>(args), 1.0, perturbed_arg_component)...);
105 auto const pert = pert_strat.getPerturbation(
107 args, perturbed_arg_component));
128 auto const pert = std::abs(value) *
rel_eps_;
130 if (std::abs(pert) >= std::abs(
min_pert_))
138 template <
typename T>
139 static T
const&
perturbIf(std::false_type, T
const& value,
146 double perturbIf(std::true_type,
double value,
double const plus_or_minus,
155 Eigen::Matrix<double, N, 1, Eigen::ColMajor, N, 1>
const& vec,
156 double const plus_or_minus,
157 Eigen::Index comp)
const
159 Eigen::Vector<double, N> vec_pert = vec;
175 template <
typename Function,
typename... Args>
177 Function
const& , Args
const&... )
188 template <
typename Function,
typename... Args>
200template <
typename DerivativeStrategy>
209 template <
typename Function,
typename... Args>
210 auto operator()(Function
const& f, Args
const&... args)
const
212 auto const d_by_dScalar =
213 DerivativeStrategy::createDByDScalar(f, args...);
217 std::forward_as_tuple(args...),
219 std::make_index_sequence<
sizeof...(Args)>{});
223 template <
typename Function,
typename TupleOfArgs,
typename DByDScalar,
224 std::size_t... AllArgIdcs>
226 DByDScalar
const& d_by_dScalar,
227 std::index_sequence<AllArgIdcs...> all_arg_idcs)
const
231 std::tuple_element_t<AllArgIdcs, TupleOfArgs>>>{},
232 f, args, d_by_dScalar,
233 std::integral_constant<std::size_t, AllArgIdcs>{},
238 template <
typename Function,
typename TupleOfArgs,
typename DByDScalar,
239 std::size_t... AllArgIdcs, std::size_t PerturbedArgIdx>
241 std::true_type , Function
const& f,
242 TupleOfArgs
const& args, DByDScalar
const& d_by_dScalar,
243 std::integral_constant<std::size_t, PerturbedArgIdx> perturbed_arg_idx,
244 std::index_sequence<AllArgIdcs...> all_arg_idcs)
const
246 constexpr Eigen::Index component_does_not_matter = -1;
248 return d_by_dScalar(f, args,
pert_strat_, perturbed_arg_idx,
249 component_does_not_matter, all_arg_idcs);
253 template <
typename Function,
typename TupleOfArgs,
typename DByDScalar,
254 std::size_t... AllArgIdcs, std::size_t PerturbedArgIdx>
256 std::false_type , Function
const& f,
257 TupleOfArgs
const& args, DByDScalar
const& d_by_dScalar,
258 std::integral_constant<std::size_t, PerturbedArgIdx> perturbed_arg_idx,
259 std::index_sequence<AllArgIdcs...> all_arg_idcs)
const
261 using VectorialArg = std::remove_cvref_t<
262 std::tuple_element_t<PerturbedArgIdx, TupleOfArgs>>;
263 constexpr int N = VectorialArg::RowsAtCompileTime;
265 static_assert(
N != Eigen::Dynamic);
266 static_assert(VectorialArg::ColsAtCompileTime == 1,
267 "Row vectors are not supported, yet. If you implement "
268 "support for them, make sure to test your implementation "
272 f, args, d_by_dScalar,
273 std::make_integer_sequence<Eigen::Index, N>{}, perturbed_arg_idx,
277 template <
typename Function,
typename TupleOfArgs,
typename DByDScalar,
278 Eigen::Index... PerturbedArgComponents, std::size_t... AllArgIdcs,
279 std::size_t PerturbedArgIdx>
281 Function
const& f, TupleOfArgs
const& args,
282 DByDScalar
const& d_by_dScalar,
283 std::integer_sequence<Eigen::Index, PerturbedArgComponents...>,
284 std::integral_constant<std::size_t, PerturbedArgIdx> perturbed_arg_idx,
285 std::index_sequence<AllArgIdcs...> all_arg_idcs)
const
288 d_by_dScalar(f, args,
pert_strat_, perturbed_arg_idx,
289 PerturbedArgComponents, all_arg_idcs)...
double getScalarOrVectorComponent(Tuple const &tuple, Eigen::Index component)
BaseLib::StrongType< double, struct RelativeEpsilonTag > RelativeEpsilon
BaseLib::StrongType< double, struct MinimumPerturbationTag > MinimumPerturbation
static detail::ComputeDerivativeWrtOneScalar_CD createDByDScalar(Function const &, Args const &...)
static auto createDByDScalar(Function const &f, Args const &... args)
auto differentiateWrtScalarOrVectorialArgument(std::false_type, Function const &f, TupleOfArgs const &args, DByDScalar const &d_by_dScalar, std::integral_constant< std::size_t, PerturbedArgIdx > perturbed_arg_idx, std::index_sequence< AllArgIdcs... > all_arg_idcs) const
detail::DefaultPerturbationStrategy pert_strat_
auto operator()(Function const &f, Args const &... args) const
NumericalDerivative(RelativeEpsilon const &rel_eps, MinimumPerturbation const &min_pert)
auto differentiateWrtScalarOrVectorialArgument(std::true_type, Function const &f, TupleOfArgs const &args, DByDScalar const &d_by_dScalar, std::integral_constant< std::size_t, PerturbedArgIdx > perturbed_arg_idx, std::index_sequence< AllArgIdcs... > all_arg_idcs) const
auto differentiateWrtAllVectorComponents(Function const &f, TupleOfArgs const &args, DByDScalar const &d_by_dScalar, std::integer_sequence< Eigen::Index, PerturbedArgComponents... >, std::integral_constant< std::size_t, PerturbedArgIdx > perturbed_arg_idx, std::index_sequence< AllArgIdcs... > all_arg_idcs) const
auto differentiate(Function const &f, TupleOfArgs const &args, DByDScalar const &d_by_dScalar, std::index_sequence< AllArgIdcs... > all_arg_idcs) const
auto operator()(Function const &f, TupleOfArgs const &args, PerturbationStrategy const &pert_strat, std::integral_constant< std::size_t, PerturbedArgIdx >, Eigen::Index const perturbed_arg_component, std::index_sequence< AllArgIdcs... >) const
ComputeDerivativeWrtOneScalar_FD(Value &&unperturbed_value)
Value operator()(Function const &f, TupleOfArgs const &args, PerturbationStrategy const &pert_strat, std::integral_constant< std::size_t, PerturbedArgIdx >, Eigen::Index const perturbed_arg_component, std::index_sequence< AllArgIdcs... >) const
static T const & perturbIf(std::false_type, T const &value, double const, Eigen::Index)
double perturbIf(std::true_type, double value, double const plus_or_minus, Eigen::Index) const
DefaultPerturbationStrategy(RelativeEpsilon const &rel_eps, MinimumPerturbation const &min_pert)
double getPerturbation(double const value) const
Eigen::Vector< double, N > perturbIf(std::true_type, Eigen::Matrix< double, N, 1, Eigen::ColMajor, N, 1 > const &vec, double const plus_or_minus, Eigen::Index comp) const