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
23namespace ModelFitting {
25template <typename DataType, typename ModelType, typename WeightType, typename Comparator>
26DataVsModelResiduals<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) << ")";
40template <typename DataType, typename ModelType, typename WeightType, typename Comparator>
41DataVsModelResiduals<DataType,ModelType,WeightType,Comparator>::~DataVsModelResiduals() = default;
43template <typename DataType, typename ModelType, typename WeightType, typename Comparator>
44std::size_t DataVsModelResiduals<DataType,ModelType,WeightType,Comparator>::numberOfResiduals() const {
48template <typename DataType, typename ModelType, typename WeightType, typename Comparator>
49void 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";
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.
111template <typename DataType, typename ModelType, typename WeightType, typename Comparator>
112std::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