Chi-Tech
dynamic_vector.h
Go to the documentation of this file.
1#ifndef CHI_MATH_DYNAMIC_VECTOR_H
2#define CHI_MATH_DYNAMIC_VECTOR_H
3
4#include <vector>
5#include <stdexcept>
6#include <sstream>
7
8namespace chi_mesh
9{
10struct Vector3;
11}
12
13namespace chi_math
14{
15template <class NumberFormat>
16class DynamicVector;
17}
18
19// ###################################################################
20/** General dynamic vector utility.*/
21template <class NumberFormat>
23{
24public:
25 std::vector<NumberFormat> elements_;
26
27 /**Default constructor. Does nothing.*/
29 {
30 static_assert(std::is_floating_point<NumberFormat>::value,
31 "Only floating point number formats are "
32 "supported for DVectorNX.");
33 }
34
35 /**Constructor with number of entries. Value defaults.*/
36 explicit DynamicVector(size_t N) : elements_(N)
37 {
38 static_assert(std::is_floating_point<NumberFormat>::value,
39 "Only floating point number formats are "
40 "supported for DVectorNX.");
41 }
42
43 /**Constructor with number of entries and default value.*/
44 DynamicVector(size_t N, NumberFormat value) : elements_(N, value)
45 {
46 static_assert(std::is_floating_point<NumberFormat>::value,
47 "Only floating point number formats are "
48 "supported for DVectorNX.");
49 }
50
51 /**Copy constructor.*/
53
54 /**Assignment operator.*/
56 {
57 elements_ = other.elements_;
58 return *this;
59 }
60
61 /**Move constructor.*/
62 DynamicVector(DynamicVector&& other) noexcept
63 {
64 elements_ = std::move(other.elements_);
65 }
66
67 /**Move assignment operator.*/
69 {
70 elements_ = std::move(other.elements_);
71 return *this;
72 }
73
74 /**Constructor with vector.*/
75 explicit DynamicVector(const std::vector<double>& in) { elements_ = in; }
76
77 /**Copy constructor with vector.*/
78 DynamicVector& operator=(const std::vector<double>& in)
79 {
80 elements_ = in;
81 return *this;
82 }
83
84 /**Constructor with vector.*/
85 DynamicVector(std::initializer_list<NumberFormat> in) { elements_ = in; }
86
87 /**Copy constructor with vector.*/
88 DynamicVector& operator=(std::initializer_list<NumberFormat> in)
89 {
90 elements_ = in;
91 return *this;
92 }
93
94 //============================================= Element access
95 NumberFormat& operator[](size_t i) { return elements_[i]; }
96 const NumberFormat& operator[](size_t i) const { return elements_[i]; }
97
98 NumberFormat& at(size_t i) { return elements_.at(i); }
99
100 NumberFormat& back() { return elements_.back(); }
101
102 NumberFormat& front() { return elements_.front(); }
103
104 NumberFormat* data() { return elements_.data(); }
105
106 void clear() { elements_.clear(); }
107
108 void resize(size_t dim) { elements_.resize(dim); }
109 void resize(size_t dim, const NumberFormat& val)
110 {
111 elements_.resize(dim, val);
112 for (auto& entry : elements_)
113 entry = val;
114 }
115
116 void reserve(size_t dim) { elements_.reserve(dim); }
117
118 void push_back(const NumberFormat& val) { elements_.push_back(val); }
119 void pop_back() { elements_.pop_back(); }
120
121 bool empty() const noexcept { return elements_.empty(); }
122
123 //============================================= Iterator access
124 typename std::vector<NumberFormat>::iterator begin()
125 {
126 return elements_.begin();
127 }
128
129 typename std::vector<NumberFormat>::iterator end() { return elements_.end(); }
130
131 size_t size() const { return elements_.size(); }
132
133 void bounds_check(const size_t a, const size_t b) const
134 {
135 if (a != b) { throw std::length_error("Mismatched sizes of DVectorNX"); }
136 }
137
138 //============================================= Addition
139 /**Component-wise addition of two vectors.
140 * \f$ \vec{w} = \vec{x} + \vec{y} \f$*/
142 {
143 bounds_check(size(), rhs.size());
145 for (int i = 0; i < size(); ++i)
146 newVector.elements_[i] = elements_[i] + rhs.elements_[i];
147
148 return newVector;
149 }
150
151 /**In-place component-wise addition of two vectors.
152 * \f$ \vec{x} = \vec{x} + \vec{y} \f$*/
154 {
155 bounds_check(size(), rhs.size());
156 for (int i = 0; i < size(); ++i)
157 elements_[i] += rhs.elements_[i];
158
159 return *this;
160 }
161
162 //=========================================== Subtraction
163 /**Component-wise subtraction.
164 * \f$ \vec{w} = \vec{x} - \vec{y} \f$*/
166 {
167 bounds_check(size(), rhs.size());
169 for (int i = 0; i < size(); ++i)
170 newVector.elements_[i] = elements_[i] - rhs.elements_[i];
171
172 return newVector;
173 }
174
175 /**In-place component-wise subtraction.
176 * \f$ \vec{x} = \vec{x} - \vec{y} \f$*/
178 {
179 bounds_check(size(), rhs.size());
180 for (int i = 0; i < size(); ++i)
181 elements_[i] -= rhs.elements_[i];
182
183 return *this;
184 }
185
186 //=========================================== Multiplication
187 /**Vector component-wise multiplication by scalar.
188 * \f$ \vec{w} = \vec{x} \alpha \f$*/
189 DynamicVector operator*(const NumberFormat value) const
190 {
192 for (int i = 0; i < size(); ++i)
193 newVector.elements_[i] = elements_[i] * value;
194
195 return newVector;
196 }
197
198 /**Vector in-place component-wise multiplication by scalar.
199 * \f$ \vec{x} = \vec{x} \alpha \f$*/
200 DynamicVector& operator*=(const NumberFormat value)
201 {
202 for (int i = 0; i < size(); ++i)
203 elements_[i] *= value;
204
205 return *this;
206 }
207
208 /**Vector component-wise multiplication.
209 * \f$ w_i = x_i y_i \f$*/
211 {
212 bounds_check(size(), rhs.size());
214 for (int i = 0; i < size(); ++i)
215 newVector.elements_[i] = elements_[i] * rhs.elements_[i];
216
217 return newVector;
218 }
219
220 /**Vector in-place component-wise multiplication.
221 * \f$ x_i = x_i y_i \f$*/
223 {
224 bounds_check(size(), rhs.size());
225 for (int i = 0; i < size(); ++i)
226 elements_[i] *= rhs.elements_[i];
227
228 return *this;
229 }
230
231 //=========================================== Division
232 /**Vector component-wise division by scalar.
233 * \f$ w_i = \frac{x_i}{\alpha} \f$*/
234 DynamicVector operator/(const NumberFormat value) const
235 {
237 for (int i = 0; i < size(); ++i)
238 newVector.elements_[i] = elements_[i] / value;
239
240 return newVector;
241 }
242
243 /**Vector in-place component-wise division by scalar.
244 * \f$ x_i = \frac{x_i}{\alpha} \f$*/
245 DynamicVector& operator/=(const NumberFormat value)
246 {
247 for (int i = 0; i < size(); ++i)
248 elements_[i] /= value;
249
250 return *this;
251 }
252
253 /**Vector component-wise division.
254 * \f$ w_i = \frac{x_i}{y_i} \f$*/
256 {
257 bounds_check(size(), rhs.size());
259 for (int i = 0; i < size(); ++i)
260 newVector.elements_[i] = elements_[i] / rhs.elements_[i];
261
262 return newVector;
263 }
264
265 /**Vector in-place component-wise division.
266 * \f$ x_i = \frac{x_i}{y_i} \f$*/
268 {
269 bounds_check(size(), rhs.size());
270 for (int i = 0; i < size(); ++i)
271 elements_[i] /= rhs.elements_[i];
272
273 return *this;
274 }
275
276 //============================================= Operations
277 /**Vector dot-product.
278 * \f$ \vec{w} = \vec{x} \bullet \vec{y} \f$ */
279 NumberFormat Dot(const DynamicVector& rhs) const
280 {
281 bounds_check(size(), rhs.size());
282 NumberFormat value = 0.0;
283 for (int i = 0; i < size(); ++i)
284 value += elements_[i] * rhs.elements_[i];
285
286 return value;
287 }
288
289 /**Computes the L2-norm of the vector. Otherwise known as the length of
290 * a 3D vector.*/
291 NumberFormat Norm() const
292 {
293 NumberFormat value = 0.0;
294 for (int i = 0; i < size(); ++i)
295 value += elements_[i] * elements_[i];
296
297 value = sqrt(value);
298 return value;
299 }
300
301 /**Computes the square of the L2-norm of the vector. This eliminates the
302 * usage of the square root and is therefore less expensive that a proper
303 * L2-norm. Useful if only comparing distances.*/
304 NumberFormat NormSquare() const
305 {
306 NumberFormat value = 0.0;
307 for (int i = 0; i < size(); ++i)
308 value += elements_[i] * elements_[i];
309
310 return value;
311 }
312
313 /**Normalizes the vector in-place.*/
315 {
316 NumberFormat norm = this->Norm();
317 for (int i = 0; i < size(); ++i)
318 elements_[i] = elements_[i] / norm;
319 }
320
321 /**Returns a normalized version of the vector.*/
323 {
324 NumberFormat norm = this->Norm();
326 for (int i = 0; i < size(); ++i)
327 newVector.elements_[i] = elements_[i] / norm;
328
329 return newVector;
330 }
331
332 /**Sets all the elements of the vector to the specified value.*/
333 void Set(NumberFormat value)
334 {
335 for (int i = 0; i < size(); ++i)
336 elements_[i] = value;
337 }
338
339 /**Prints the vector to a string and then returns the string.*/
340 std::string PrintStr() const
341 {
342 std::stringstream out;
343 out << "[";
344 for (int i = 0; i < (size() - 1); ++i)
345 out << elements_[i] << " ";
346 out << elements_[size() - 1] << "]";
347
348 return out.str();
349 }
350};
351
352/**Multiplication by a scalar from the left.*/
353template <class NumberFormat>
355operator*(const double value, const chi_math::DynamicVector<NumberFormat>& that)
356{
358 for (int i = 0; i < that.size(); ++i)
359 newVector.elements_[i] = that.elements_[i] * value;
360 return newVector;
361}
362
363#endif // CHI_MATH_DYNAMIC_VECTOR_H
DynamicVector operator+(const DynamicVector &rhs) const
NumberFormat & at(size_t i)
DynamicVector Normalized() const
DynamicVector & operator=(const std::vector< double > &in)
DynamicVector & operator-=(const DynamicVector &rhs)
void resize(size_t dim)
DynamicVector & operator=(std::initializer_list< NumberFormat > in)
DynamicVector & operator=(const DynamicVector &other)
DynamicVector(DynamicVector &&other) noexcept
DynamicVector & operator=(DynamicVector &&other) noexcept
NumberFormat * data()
DynamicVector(size_t N, NumberFormat value)
void bounds_check(const size_t a, const size_t b) const
DynamicVector operator-(const DynamicVector &rhs) const
DynamicVector & operator+=(const DynamicVector &rhs)
std::vector< NumberFormat > elements_
void reserve(size_t dim)
void resize(size_t dim, const NumberFormat &val)
void Set(NumberFormat value)
std::vector< NumberFormat >::iterator begin()
DynamicVector operator*(const NumberFormat value) const
DynamicVector operator/(const NumberFormat value) const
DynamicVector operator/(const DynamicVector &rhs) const
DynamicVector & operator/=(const DynamicVector &rhs)
NumberFormat & operator[](size_t i)
NumberFormat & back()
DynamicVector & operator*=(const NumberFormat value)
DynamicVector & operator/=(const NumberFormat value)
NumberFormat NormSquare() const
NumberFormat & front()
std::vector< NumberFormat >::iterator end()
DynamicVector & operator*=(const DynamicVector &rhs)
DynamicVector(std::initializer_list< NumberFormat > in)
bool empty() const noexcept
NumberFormat Norm() const
DynamicVector(const std::vector< double > &in)
const NumberFormat & operator[](size_t i) const
DynamicVector(const DynamicVector &other)
DynamicVector operator*(const DynamicVector &rhs) const
NumberFormat Dot(const DynamicVector &rhs) const
std::string PrintStr() const
void push_back(const NumberFormat &val)
chi_math::DynamicVector< NumberFormat > operator*(const double value, const chi_math::DynamicVector< NumberFormat > &that)
VectorN< 3 > Vector3