Mantid
Loading...
Searching...
No Matches
EigenVector.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//----------------------------------------------------------------------
11
12#include <algorithm>
13#include <boost/math/special_functions/fpclassify.hpp>
14#include <cmath>
15#include <iomanip>
16#include <numeric>
17#include <sstream>
18#include <stdexcept>
19#include <utility>
20
21namespace Mantid::CurveFitting {
22
25
28EigenVector::EigenVector(const size_t n) : m_data(n), m_view(EigenVector_View(m_data.data(), n)) {}
29
32EigenVector::EigenVector(std::vector<double> v)
33 : m_data(std::move(v)), m_view(EigenVector_View(m_data.data(), m_data.size())) {}
34
37EigenVector::EigenVector(std::initializer_list<double> ilist) : EigenVector(ilist.size()) {
38 for (auto cell = ilist.begin(); cell != ilist.end(); ++cell) {
39 auto i = static_cast<size_t>(std::distance(ilist.begin(), cell));
40 set(i, *cell);
41 }
42}
43
47 : m_data(v.m_data), m_view(EigenVector_View(m_data.data(), m_data.size())) {}
48
51EigenVector::EigenVector(const Eigen::VectorXd *v)
52 : m_data(v->size()), m_view(EigenVector_View(m_data.data(), m_data.size())) {
53 for (size_t i = 0; i < (size_t)v->size(); ++i) {
54 m_data[i] = (*v)(i);
55 }
56}
57
59 : m_data(std::move(v.m_data)), m_view(EigenVector_View(m_data.data(), size())) {}
60
64 m_data = v.m_data;
65 m_view = EigenVector_View(m_data.data(), m_data.size());
66 return *this;
67}
68
70EigenVector &EigenVector::operator=(const std::vector<double> &v) {
71 if (v.empty()) {
72 m_data.resize(1);
73 } else {
74 m_data = v;
75 }
76 m_view = EigenVector_View(m_data.data(), m_data.size());
77 return *this;
78}
79
81EigenVector &EigenVector::operator=(const Eigen::VectorXd v) {
82 if (v.size() == 0) {
83 m_data.resize(1);
84 } else {
85 m_data.resize(v.size());
86 for (size_t i = 0; i < (size_t)v.size(); ++i) {
87 m_data[i] = v(i);
88 }
89 }
90 m_view = EigenVector_View(m_data.data(), m_data.size());
91 return *this;
92}
93
96void EigenVector::resize(const size_t n) {
97 if (n == 0) {
98 // vector minimum size is 1, retained from gsl for consistency.
99 m_data.resize(1);
100 m_view = EigenVector_View(m_data.data(), m_data.size());
101 } else if (n != size()) {
102 m_data.resize(n);
103 m_view = EigenVector_View(m_data.data(), m_data.size());
104 }
105}
106
108size_t EigenVector::size() const { return m_data.size(); }
109
113void EigenVector::set(const size_t i, const double value) {
114 if (i < m_data.size())
115 m_data[i] = value;
116 else {
117 std::stringstream errmsg;
118 errmsg << "EigenVector index = " << i << " is out of range = " << m_data.size() << " in EigenVector.set()";
119 throw std::out_of_range(errmsg.str());
120 }
121}
124double EigenVector::get(const size_t i) const {
125 if (i < m_data.size())
126 return m_data[i];
127
128 std::stringstream errmsg;
129 errmsg << "EigenVector index = " << i << " is out of range = " << m_data.size() << " in EigenVector.get()";
130 throw std::out_of_range(errmsg.str());
131}
132
133// Set all elements to zero
134void EigenVector::zero() { m_data.assign(m_data.size(), 0.0); }
135
139 if (size() != v.size()) {
140 throw std::runtime_error("EigenVectors have different sizes.");
141 }
142 mutator() = inspector() + v.inspector();
143 return *this;
144}
145
149 if (size() != v.size()) {
150 throw std::runtime_error("EigenVectors have different sizes.");
151 }
152 mutator() = inspector() - v.inspector();
153 return *this;
154}
155
158 if (size() != v.size()) {
159 throw std::runtime_error("EigenVectors have different sizes.");
160 }
161 mutator() = inspector() * v.inspector();
162 return *this;
163}
164
168 std::transform(m_data.begin(), m_data.end(), m_data.begin(), [d](double x) { return x * d; });
169 return *this;
170}
171
175 std::transform(m_data.begin(), m_data.end(), m_data.begin(), [d](double x) { return x + d; });
176 return *this;
177}
178
179// Normalise this vector
181 double N = norm();
182 if (N == 0.0 || !boost::math::isfinite(N)) {
183 throw std::runtime_error("Cannot normalize null vector.");
184 }
185 *this *= 1.0 / N;
186}
187
189double EigenVector::norm() const { return sqrt(norm2()); }
190
192double EigenVector::norm2() const {
193 return std::accumulate(m_data.cbegin(), m_data.cend(), 0.,
194 [](double sum, double element) { return sum + element * element; });
195}
196
199double EigenVector::dot(const EigenVector &v) const {
200 if (size() != v.size()) {
201 throw std::runtime_error("Vectors have different sizes in dot product.");
202 }
203 double res = 0.0;
204 res = (inspector()).dot(v.inspector());
205 return res;
206}
207
210 if (m_data.empty()) {
211 throw std::runtime_error("Cannot find min element of empty vector.");
212 }
213 auto it = std::min_element(m_data.begin(), m_data.end());
214 if (it == m_data.end()) {
215 // can it ever happen?
216 throw std::runtime_error("Cannot find min element of vector.");
217 }
218 return static_cast<size_t>(std::distance(m_data.begin(), it));
219}
220
223 if (m_data.empty()) {
224 throw std::runtime_error("Cannot find ax element of empty vector.");
225 }
226 auto it = std::max_element(m_data.begin(), m_data.end());
227 if (it == m_data.end()) {
228 // can it ever happen?
229 throw std::runtime_error("Cannot find max element of vector.");
230 }
231 return static_cast<size_t>(std::distance(m_data.begin(), it));
232}
233
235std::pair<size_t, size_t> EigenVector::indicesOfMinMaxElements() const {
236 if (m_data.empty()) {
237 throw std::runtime_error("Cannot find min or max element of empty vector.");
238 }
239 auto pit = std::minmax_element(m_data.begin(), m_data.end());
240 if (pit.first == m_data.end() || pit.second == m_data.end()) {
241 // can it ever happen?
242 throw std::runtime_error("Cannot find min or max element of vector.");
243 }
244 return std::make_pair(static_cast<size_t>(std::distance(m_data.begin(), pit.first)),
245 static_cast<size_t>(std::distance(m_data.begin(), pit.second)));
246}
247
251std::vector<size_t> EigenVector::sortIndices(bool ascending) const {
252 std::vector<size_t> indices(size());
253 for (size_t i = 0; i < size(); ++i) {
254 indices[i] = i;
255 }
256 if (ascending) {
257 std::sort(indices.begin(), indices.end(), [this](size_t i, size_t j) { return this->m_data[i] < m_data[j]; });
258 } else {
259 std::sort(indices.begin(), indices.end(), [this](size_t i, size_t j) { return this->m_data[i] > m_data[j]; });
260 }
261 return indices;
262}
263
266void EigenVector::sort(const std::vector<size_t> &indices) {
267 std::vector<double> data(size());
268 for (size_t i = 0; i < size(); ++i) {
269 data[i] = m_data[indices[i]];
270 }
271 std::swap(m_data, data);
272 m_view = EigenVector_View(m_data.data(), m_data.size());
273}
274
276std::vector<double> EigenVector::toStdVector() const { return m_data; }
277
279std::vector<double> &EigenVector::StdVectorRef() { return m_data; }
280
282std::ostream &operator<<(std::ostream &ostr, const EigenVector &v) {
283 std::ios::fmtflags fflags(ostr.flags());
284 ostr << std::scientific << std::setprecision(6);
285 for (size_t j = 0; j < v.size(); ++j) {
286 ostr << std::setw(13) << v[j] << ' ';
287 }
288 ostr.flags(fflags);
289 return ostr;
290}
291} // namespace Mantid::CurveFitting
double value
The value of the point.
Definition: FitMW.cpp:51
const std::vector< Type > & m_data
Definition: TableColumn.h:417
A wrapper around Eigen::Vector.
Definition: EigenVector.h:27
std::vector< double > m_data
Default element storage.
Definition: EigenVector.h:108
void set(const size_t i, const double value)
Set an element.
size_t indexOfMinElement() const
Get index of the minimum element.
double dot(const EigenVector &v) const
Calculate the dot product.
size_t indexOfMaxElement() const
Get index of the maximum element.
EigenVector & operator+=(const EigenVector &v)
Add a vector.
EigenVector & operator*=(const EigenVector &v)
Multiply by a vector (per element)
EigenVector & operator-=(const EigenVector &v)
Subtract a vector.
double get(const size_t i) const
Get an element.
vec_map_type & mutator()
Get the map of the eigen vector.
Definition: EigenVector.h:51
void resize(const size_t n)
Resize the vector.
Definition: EigenVector.cpp:96
double norm2() const
Get vector norm squared.
std::pair< size_t, size_t > indicesOfMinMaxElements() const
Get indices of both the minimum and maximum elements.
double norm() const
Get vector norm (length)
void sort(const std::vector< size_t > &indices)
Sort this vector in order defined by an index array.
EigenVector_View m_view
The map to the Eigen vector.
Definition: EigenVector.h:110
EigenVector & operator=(const EigenVector &v)
Copy assignment operator.
Definition: EigenVector.cpp:63
std::vector< double > toStdVector() const
Copy the values to an std vector of doubles.
std::vector< size_t > sortIndices(bool ascending=true) const
Create an index array that would sort this vector.
void normalize()
Normalise this vector.
const vec_map_type inspector() const
Get the const map of the eigen vector.
Definition: EigenVector.h:53
std::vector< double > & StdVectorRef()
Return a reference to m_data.
size_t size() const
Size of the vector.
MANTID_API_DLL std::ostream & operator<<(std::ostream &, const AlgorithmHistory &)
Prints a text representation.
STL namespace.