1 /** Copyright © 2019 Université de Genève, LMU Munich - Faculty of Physics, IAP-CNRS/Sorbonne Université
3 * This library is free software; you can redistribute it and/or modify it under
4 * the terms of the GNU Lesser General Public License as published by the Free
5 * Software Foundation; either version 3.0 of the License, or (at your option)
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 * @file DataVsModelResiduals.icpp
19 * @date August 20, 2015
20 * @author Nikolaos Apostolakos
23 namespace ModelFitting {
25 template <typename DataType, typename ModelType, typename WeightType, typename Comparator>
26 DataVsModelResiduals<DataType,ModelType,WeightType,Comparator>::DataVsModelResiduals(
27 DataType data, ModelType model, WeightType weight, Comparator comparator)
28 : m_data{std::move(data)}, m_model{std::move(model)}, m_weight{std::move(weight)},
29 m_comparator(std::move(comparator)), m_residual_no{DataTraits::size(m_data)} {
30 if (DataTraits::size(m_data) != ModelTraits::size(m_model)) {
31 throw Elements::Exception() << "Data size (" << DataTraits::size(m_data)
32 << ") is different than model size (" << ModelTraits::size(m_model) << ")";
34 if (DataTraits::size(m_data) != WeightTraits::size(m_weight)) {
35 throw Elements::Exception() << "Data size (" << DataTraits::size(m_data)
36 << ") is different than weight size (" << WeightTraits::size(m_weight) << ")";
40 template <typename DataType, typename ModelType, typename WeightType, typename Comparator>
41 DataVsModelResiduals<DataType,ModelType,WeightType,Comparator>::~DataVsModelResiduals() = default;
43 template <typename DataType, typename ModelType, typename WeightType, typename Comparator>
44 std::size_t DataVsModelResiduals<DataType,ModelType,WeightType,Comparator>::numberOfResiduals() const {
48 template <typename DataType, typename ModelType, typename WeightType, typename Comparator>
49 void DataVsModelResiduals<DataType,ModelType,WeightType,Comparator>::populateResidualBlock(IterType output_iter) {
50 auto data_iter = DataTraits::begin(m_data);
51 auto model_iter = ModelTraits::begin(m_model);
52 auto weight_iter = WeightTraits::begin(m_weight);
54 // static double diff = 0;
55 for (; data_iter!=DataTraits::end(m_data); ++data_iter, ++model_iter, ++weight_iter, ++output_iter) {
56 *output_iter = m_comparator(*data_iter, *model_iter, *weight_iter);
57 // test += *output_iter;
59 // std::cout << test << " -- " << test-diff << "\n";
63 // NOTE TO DEVELOPERS:
65 // The following factory function looks (and is) complicated, but it greatly
66 // simplifies the code using the library. For example, using the factory method,
67 // the code for creating a DataVsModelResiduals looks like:
69 // std::vector<double> data = ...;
70 // std::vector<double> model = ...;
71 // std::vector<double> weights = ...;
72 // auto res_prov = createDataVsModelResiduals(data, model, weights, ChiSquareComparator{});
74 // The equivalent command when using directly the constructor would be:
76 // std::vector<double> data = ...;
77 // std::vector<double> model = ...;
78 // std::vector<double> weights = ...;
79 // unique_ptr<DataVsModelResiduals<std::vector<double>, std::vector<double>,
80 // std::vector<double>, ChiSquareComparator>> res_prov {
81 // new DataVsModelResiduals<std::vector<double>, std::vector<double>,
82 // std::vector<double>, ChiSquareComparator> {
83 // y_data, model, weight, ChiSquareComparator{}
87 // The above shows the importance of the existence of this factory. Here are
88 // some tips, to help you understand how the function works:
90 // - The function perfect-forwards its parameters to the constructor, so it can
91 // be the exact equivalent with calling the constructor, regardless the
92 // r-valueness or l-valueness of the parameters. If you don't know what the
93 // perfect forwarding is, search the internet for a good explanation before
94 // you continue trying to understand this code.
96 // - The template parameters of the factory method are NOT the same with the ones
97 // of the DataVsModelResiduals object being created. This is a result of the
98 // use of the perfect forwarding. More precisely, the template types of the
99 // factory method are lvalue or rvalue REFERENCES (which is how perfect
100 // forwarding works), when the template types of the DataVsModelResiduals are
101 // the actual types (and no references to them).
103 // - The "typename std::remove_reference<...>::type" (which is used a lot bellow)
104 // simply removes any reference from the type, creating the proper template
105 // parameter for the DataVsModelResiduals class. The keyword "typename" has to
106 // be used because, during the first passage, the compiler will fail to recognize
107 // that the "std::remove_reference<...>::type" is an existing type (because
108 // it contains a template parameter itself).
110 // I hope the above will help you to understand how the factory method works.
111 template <typename DataType, typename ModelType, typename WeightType, typename Comparator>
112 std::unique_ptr<DataVsModelResiduals<typename std::remove_reference<DataType>::type,
113 typename std::remove_reference<ModelType>::type,
114 typename std::remove_reference<WeightType>::type,
115 typename std::remove_reference<Comparator>::type>
116 > createDataVsModelResiduals(DataType&& data, ModelType&& model,
117 WeightType&& weight, Comparator&& comparator) {
118 return std::unique_ptr<DataVsModelResiduals<typename std::remove_reference<DataType>::type,
119 typename std::remove_reference<ModelType>::type,
120 typename std::remove_reference<WeightType>::type,
121 typename std::remove_reference<Comparator>::type>
123 new DataVsModelResiduals<typename std::remove_reference<DataType>::type,
124 typename std::remove_reference<ModelType>::type,
125 typename std::remove_reference<WeightType>::type,
126 typename std::remove_reference<Comparator>::type> {
127 std::forward<DataType>(data), std::forward<ModelType>(model),
128 std::forward<WeightType>(weight), std::forward<Comparator>(comparator)
133 } // end of namespace ModelFitting