Mantid
Loading...
Searching...
No Matches
ChebyshevPolyFit.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7//-----------------------------------------------------------------------------
8// Includes
9//-----------------------------------------------------------------------------
12#include <cassert>
13#include <gsl/gsl_multifit.h>
14
15namespace Mantid::Kernel {
16
17//-----------------------------------------------------------------------------
18// ChebyshevPolyFitImpl - Keeps the gsl stuff out of the headers
19//-----------------------------------------------------------------------------
21class ChebyshevPolyFitImpl {
22public:
23 explicit ChebyshevPolyFitImpl(const size_t order) : m_order(order) {}
24
25 std::vector<double> fit(const std::vector<double> &x, const std::vector<double> &y, const std::vector<double> &w);
26
27private:
28 const size_t m_order;
29};
30
31//-----------------------------------------------------------------------------
32// ChebyshevPolyFitImpl Public Members
33//-----------------------------------------------------------------------------
34// See doc for main class for parameter descriptions
35std::vector<double> ChebyshevPolyFitImpl::fit(const std::vector<double> &x, const std::vector<double> &y,
36 const std::vector<double> &w) {
37 assert(x.size() == y.size());
38 assert(y.size() == w.size());
39
40 const size_t npts(y.size()), degp1(m_order + 1);
41 const double xmin(x.front()), xmax(x.back());
42
43 // Compute the weighted pseudo Vandermonde matrix
44 // and y*w
45 gsl_matrix *MX = gsl_matrix_alloc(npts, degp1);
46 auto *yw = gsl_vector_alloc(npts);
47 ChebyshevPolynomial chebyp;
48 for (size_t i = 0; i < npts; ++i) {
49 const auto xi = x[i];
50 const auto wi = w[i];
51 const auto xbar = ((xi - xmin) - (xmax - xi)) / (xmax - xmin);
52 gsl_vector_set(yw, i, wi * y[i]);
53 for (size_t j = 0; j < degp1; ++j) {
54 gsl_matrix_set(MX, i, j, wi * chebyp(j, xbar));
55 }
56 }
57
58 // Least-squares fit to determine c
59 auto *c = gsl_vector_alloc(degp1);
60 auto *cov = gsl_matrix_alloc(degp1, degp1);
61 auto *work = gsl_multifit_linear_alloc(npts, degp1);
62 double chisq(0.0);
63 gsl_multifit_linear(MX, yw, c, cov, &chisq, work);
64 gsl_vector_free(yw);
65 gsl_matrix_free(cov);
66 gsl_matrix_free(MX);
67 gsl_multifit_linear_free(work);
68
69 std::vector<double> coeffs(c->data, c->data + degp1);
70 gsl_vector_free(c);
71 return coeffs;
72}
73
75
76//-----------------------------------------------------------------------------
77// ChebyshevPolyFit Public members
78//-----------------------------------------------------------------------------
84ChebyshevPolyFit::ChebyshevPolyFit(const size_t n) : m_impl(new ChebyshevPolyFitImpl(n)) {}
85
88
101std::vector<double> ChebyshevPolyFit::operator()(const std::vector<double> &xs, const std::vector<double> &ys,
102 const std::vector<double> &wgts) {
103 return m_impl->fit(xs, ys, wgts);
104}
105
106} // namespace Mantid::Kernel
std::vector< double > operator()(const std::vector< double > &xs, const std::vector< double > &ys, const std::vector< double > &wgts)
Find coefficients of polynomial that minimizes the sum of the squares of the residuals: e_r = w_r(y_r...
ChebyshevPolyFit(const size_t n)
Constructor.
std::unique_ptr< ChebyshevPolyFitImpl > m_impl