SourceXtractorPlusPlus 1.0.3
SourceXtractor++, the next generation SExtractor
Loading...
Searching...
No Matches
DependentParameter.h
Go to the documentation of this file.
1
22
23#ifndef MODELFITTING_DEPENDENTPARAMETER_H
24#define MODELFITTING_DEPENDENTPARAMETER_H
25
26#include <array>
27#include <vector>
28#include <memory>
30
31namespace ModelFitting {
32
46
47template<typename... Parameters>
49
50public:
51
52 static constexpr int PARAM_NO = sizeof...(Parameters);
53
55
60 DependentParameter(ValueCalculator calculator, Parameters... parameters)
61 : BasicParameter {calculator(parameters->getValue()...)},
62 m_calculator {new ValueCalculator{std::move(calculator)}},
63 m_params {new std::array<std::shared_ptr<BasicParameter>, PARAM_NO>{{parameters...}}} {
64 inputParameterLoop(parameters...);
65 //m_get_value_hook = std::bind(&DependentParameter::getValueHook, this);
66 }
67
68 virtual ~DependentParameter() = default;
69
70 double getValue() const override {
71 if (!this->isObserved()) {
72 const_cast<DependentParameter*>(this)->update((*m_params)[0]->getValue());
73 }
74 return m_value;
75 }
76
77private:
78
81
82 // Array of the input parameter
84
85 /* The two following methods represent the mechanism to loop over
86 * the arbitrary number of variadic elements, the first one is called
87 * as long as there is more than one elements in the list and the
88 * second one is called when there is only one left.
89 */
90 template<typename First, typename ... Rest>
91 void inputParameterLoop(First& first, Rest&... rest) {
92 addParameterObserver(PARAM_NO - sizeof...(rest) - 1, first);
93 inputParameterLoop(rest...);
94 }
95
96 template<typename Last>
97 void inputParameterLoop(Last& last) {
99 }
100
101 /* The two update methods below are called by the observer function
102 * passed to the param.addObserver() method. They are used to transform
103 * the array of input parameter values to a series of doubles
104 * (val1, val2, ...) which is require to call the setValue (of the
105 * BasicParameter class)
106 */
107 template <typename... ParamValues>
108 void update(ParamValues... values) {
109 update(values..., (*m_params)[sizeof...(values)]->getValue());
110 }
111
112 void update(decltype(std::declval<Parameters>()->getValue())... values) {
113 /* Beware that it is the updated value (m_calculator(values...)) that
114 * is passed to the setValue
115 */
117 }
118
119 template<typename Param>
120 void addParameterObserver(int, Param& param) {
121 param->addObserver([this](double){
122 // Do not bother updating live if there are no observers
123 if (this->isObserved()) {
124 this->update((*m_params)[0]->getValue());
125 }
126 });
127 }
128};
129
130template<typename ... Parameters>
132 typename DependentParameter<Parameters...>::ValueCalculator value_calculator, Parameters... parameters) {
133 return std::make_shared<DependentParameter<Parameters...>>(value_calculator, parameters...);
134}
135
136}
137
138#endif /* MODELFITTING_DEPENDENTPARAMETER_H */
BasicParameter(const BasicParameter &)=delete
virtual void setValue(const double new_value)
Implementation of a parameter depending on an arbitrary number of other parameters.
void update(decltype(std::declval< Parameters >() ->getValue())... values)
void update(ParamValues... values)
void addParameterObserver(int, Param &param)
virtual ~DependentParameter()=default
std::function< double(decltype(std::declval< Parameters >() ->getValue())...)> ValueCalculator
std::shared_ptr< std::array< std::shared_ptr< BasicParameter >, PARAM_NO > > m_params
void inputParameterLoop(First &first, Rest &... rest)
DependentParameter(ValueCalculator calculator, Parameters... parameters)
std::shared_ptr< ValueCalculator > m_calculator
function to calculate the dependent parameter value
T declval(T... args)
T make_shared(T... args)
T move(T... args)
std::shared_ptr< DependentParameter< Parameters... > > createDependentParameter(typename DependentParameter< Parameters... >::ValueCalculator value_calculator, Parameters... parameters)
STL namespace.