Theoretica
Scientific Computing
Loading...
Searching...
No Matches
vec.h
Go to the documentation of this file.
1
5
6#ifndef THEORETICA_VECTOR_H
7#define THEORETICA_VECTOR_H
8
9#ifndef THEORETICA_NO_PRINT
10#include <sstream>
11#include <ostream>
12#endif
13
14#include "../core/error.h"
15#include "../core/real_analysis.h"
16#include "./algebra.h"
17#include <vector>
18
19
20namespace theoretica {
21
22
28 template<typename Vector, typename ReturnType = vector_element_t<Vector>&>
30
31 private:
32
34 Vector& vector;
35
37 size_t i;
38
39 public:
40
41 using iterator_category = std::forward_iterator_tag;
42 using value_type = vector_element_t<Vector>;
43 using pointer = value_type*;
44 using reference = value_type&;
45
48 vec_iterator(Vector& vector, size_t index) : vector(vector), i(index) {}
49
53 return vector[i];
54 }
55
58 ++i;
59 return *this;
60 }
61
63 // vec_iterator& operator--() {
64 // --i;
65 // return *this;
66 // }
67
68
70 size_t index() {
71 return i;
72 }
73
74
76 bool operator==(const vec_iterator& other) const {
77 return i == other.i;
78 }
79
80 bool operator!=(const vec_iterator& other) const {
81 return !(*this == other);
82 }
83 };
84
85
91 template<typename Type = real, unsigned int N = 0>
92 class vec {
93
94 private:
95 Type elements[N];
96
97 public:
98
99 // Vector size template argument
100 static constexpr size_t size_argument = N;
101
104 vec() {
105 algebra::vec_zeroes(*this);
106 }
107
108
112
113 for (unsigned int i = 0; i < N; ++i)
114 elements[i] = val;
115 }
116
117
121 vec(unsigned int size, Type val) {
122
123 if (N != size) {
124 TH_MATH_ERROR("vec::vec(size, val)", size, MathError::InvalidArgument);
125 algebra::vec_error(*this);
126 return;
127 }
128
129 for (unsigned int i = 0; i < N; ++i)
130 elements[i] = val;
131 }
132
133
135 template <
136 typename Vector,
137 enable_vector<Vector> = true
138 >
139 vec(const Vector& other) {
140 algebra::vec_copy(*this, other);
141 }
142
143
146 template<typename... Args>
148
149 static_assert(
150 2 + sizeof...(args) == N,
151 "Number of arguments must match vector size"
152 );
153
154 *this = {x1, x2, args...};
155 }
156
157
159 template<typename Vector>
161
162 if (N == other.size())
163 return algebra::vec_copy(*this, other);
164 else
165 return algebra::vec_error(*this);
166 }
167
168
170 vec(std::initializer_list<Type> l) {
171
172 if(l.size() != N) {
173 TH_MATH_ERROR("vec::vec(initializer_list<Type>)", l.size(), MathError::InvalidArgument);
174 algebra::vec_error(*this);
175 return;
176 }
177
178 std::copy(l.begin(), l.end(), &elements[0]);
179 }
180
181 ~vec() = default;
182
183
185 inline vec<Type, N> operator+() const {
186 return *this;
187 }
188
189
192
195 return result;
196 }
197
198
200 inline vec<Type, N> operator-() const {
201 return *this * (Type) -1;
202 }
203
204
207
210 return result;
211 }
212
213
217
218 for (unsigned int i = 0; i < N; ++i)
219 result.elements[i] = scalar * elements[i];
220
221 return result;
222 }
223
224
228
229 for (unsigned int i = 0; i < N; ++i)
230 result.elements[i] = elements[i] / scalar;
231
232 return result;
233 }
234
235
237 template<typename Vector, enable_vector<Vector> = true>
238 inline Type dot(const Vector& other) const {
239 return algebra::dot(*this, other);
240 }
241
242
244 template<typename Vector, enable_vector<Vector> = true>
245 inline Type operator*(const Vector& other) const {
246 return dot(other);
247 }
248
249
251 inline vec<Type, N> cross(const vec<Type, N>& other) const {
252 static_assert(N == 3, "The vector must be three dimensional");
253 return algebra::cross(*this, other);
254 }
255
256
258 template<typename Vector>
259 inline vec<Type, N> cross(const Vector& other) const {
260 return algebra::cross(*this, other);
261 }
262
263
265 template<typename Vector>
267
268 for (unsigned int i = 0; i < N; ++i)
269 elements[i] += other.elements[i];
270
271 return *this;
272 }
273
274
276 template<typename Vector>
278
279 for (unsigned int i = 0; i < N; ++i)
280 elements[i] -= other.elements[i];
281
282 return *this;
283 }
284
285
288
289 for (unsigned int i = 0; i < N; ++i)
290 elements[i] *= scalar;
291
292 return *this;
293 }
294
295
298
299 if(abs(scalar) < MACH_EPSILON) {
300 TH_MATH_ERROR("vec::operator/=", scalar, MathError::DivByZero);
301 algebra::vec_error(*this);
302 return *this;
303 }
304
305 for (unsigned int i = 0; i < N; ++i)
306 elements[i] /= scalar;
307
308 return *this;
309 }
310
311
313 inline Type norm() const {
314 return algebra::norm(*this);
315 }
316
317
319 inline Type sqr_norm() const {
320 return algebra::sqr_norm(*this);
321 }
322
323
325 inline Type& operator[](unsigned int i) {
326 return elements[i];
327 }
328
329
331 inline const Type& operator[](unsigned int i) const {
332 return elements[i];
333 }
334
335
340 inline Type& at(unsigned int i) {
341
342 if (i >= N) {
343 throw std::out_of_range(
344 "The element index in vec::at() is out of bounds"
345 );
346 }
347
348 return elements[i];
349 }
350
351
356 inline Type at(unsigned int i) const {
357
358 if (i >= N) {
359 throw std::out_of_range(
360 "The element index in vec::at() is out of bounds"
361 );
362 }
363
364 return elements[i];
365 }
366
367
370
373
374
377 inline auto begin() {
378 return iterator(*this, 0);
379 }
380
381
384 inline auto end() {
385 return iterator(*this, size());
386 }
387
388
390 inline auto begin() const {
391 return const_iterator(*this, 0);
392 }
393
394
397 inline auto end() const {
398 return const_iterator(*this, size());
399 }
400
401
403 inline Type* data() {
404 return elements;
405 }
406
407
409 inline const Type* data() const {
410 return elements;
411 }
412
413
415 inline void normalize() {
417 }
418
419
421 inline vec<Type, N> normalized() const {
422 return algebra::normalize(*this);
423 }
424
425
427 template<typename Vector>
428 inline bool operator==(const Vector& other) const {
429
430 if(size() != other.size())
431 return false;
432
433 for (unsigned int i = 0; i < N; ++i)
434 if(elements[i] != other[i])
435 return false;
436
437 return true;
438 }
439
440
442 template<typename Vector>
443 inline bool operator!=(const Vector& other) const {
444 return !(*this == other);
445 }
446
447
449 inline TH_CONSTEXPR unsigned int size() const {
450 return N;
451 }
452
453
459 inline void resize(size_t n) const {
460
461 if(N != n) {
462 TH_MATH_ERROR("vec::resize", N, MathError::InvalidArgument);
463 }
464 }
465
466
474 inline void resize(size_t n, const Type& value) const {
475
476 if(N != n) {
477 TH_MATH_ERROR("vec::resize", N, MathError::InvalidArgument);
478 }
479 }
480
481
485 unsigned int i, unsigned int n = N) {
486
487 if(i >= n) {
488 TH_MATH_ERROR("vec::euclidean_base", i, MathError::InvalidArgument);
489 return make_error<vec<Type, N>>(n);
490 }
491
493 e_i.resize(n);
494 e_i[i] = 1;
495
496 return e_i;
497 }
498
499
502 inline friend vec<Type, N> operator*(Type a, const vec<Type, N>& v) {
503 return v * a;
504 }
505
506
507#ifndef THEORETICA_NO_PRINT
508
510 inline std::string to_string(
511 const std::string& separator = ", ",
512 bool parenthesis = true) const {
513
514 std::stringstream res;
515
516 if(parenthesis)
517 res << "(";
518
519 for (unsigned int i = 0; i < N; ++i) {
520 res << elements[i];
521 if(i != N - 1)
522 res << separator;
523 }
524
525 if(parenthesis)
526 res << ")";
527
528 return res.str();
529 }
530
531
533 inline operator std::string() {
534 return to_string();
535 }
536
537
539 inline friend std::ostream& operator<<(
540 std::ostream& out, const vec<Type, N>& obj) {
541 return out << obj.to_string();
542 }
543
544#endif
545
546 };
547
548
554 template<typename Type>
555 class vec<Type, 0> {
556
557 // Container type for storage (alias for std::vector)
558 template<typename T>
559 using Container = std::vector<T>;
560
561 private:
562 Container<Type> elements;
563
564 public:
565
566 // Vector size template argument
567 static constexpr size_t size_argument = 0;
568
570 vec() = default;
571
574 vec(unsigned int n) {
575 resize(n);
576 algebra::vec_zeroes(*this);
577 }
578
581 vec(unsigned int n, Type a) {
582 elements = std::vector<Type>(n, a);
583 }
584
586 template <
587 typename Vector,
589 >
590 vec(const Vector& other) {
591 algebra::vec_copy(*this, other);
592 }
593
596 template<typename... Args>
597 vec(Type x1, Type x2, Args... args) {
598
599 elements = {x1, x2, args...};
600 }
601
602
604 vec(std::initializer_list<Type> l) : elements(l) {}
605
606
608 inline vec<Type> operator+() const {
609 return *this;
610 }
611
612
614 template<typename Vector>
615 inline vec<Type> operator+(const Vector& other) const {
616
618 result.resize(size());
620 return result;
621 }
622
623
625 inline vec<Type> operator-() const {
626 return *this * (Type) -1;
627 }
628
629
631 template<typename Vector>
632 inline vec<Type> operator-(const Vector& other) const {
633
635 result.resize(size());
637 return result;
638 }
639
640
642 inline vec<Type> operator*(Type scalar) const {
643
645 result.resize(size());
646
647 for (unsigned int i = 0; i < size(); ++i)
648 result.elements[i] = scalar * elements[i];
649
650 return result;
651 }
652
653
655 inline vec<Type> operator/(Type scalar) const {
656
658 result.resize(size());
659
660 for (unsigned int i = 0; i < size(); ++i)
661 result.elements[i] = elements[i] / scalar;
662
663 return result;
664 }
665
666
668 template<typename Vector, enable_vector<Vector> = true>
669 inline Type dot(const Vector& other) const {
670 return algebra::dot(*this, other);
671 }
672
673
675 template<typename Vector, enable_vector<Vector> = true>
676 inline Type operator*(const Vector& other) const {
677 return dot(other);
678 }
679
680
682 template<typename Vector>
683 inline vec<Type> cross(const Vector& other) const {
684 return algebra::cross(*this, other);
685 }
686
687
689 template<typename Vector>
690 inline vec<Type>& operator+=(const Vector& other) {
691
692 // If the vector is uninitialized,
693 // initialize it to be a zero vector
694 // with the target size
695 if(size() == 0)
696 resize(other.size());
697
698 if(size() != other.size()) {
699 TH_MATH_ERROR("vec::operator+=", size(), MathError::InvalidArgument);
700 return (*this = vec<Type>(max(size(), 1), nan()));
701 }
702
703 for (unsigned int i = 0; i < size(); ++i)
704 elements[i] += other.elements[i];
705
706 return *this;
707 }
708
709
711 template<typename Vector>
712 inline vec<Type>& operator-=(const Vector& other) {
713
714 if(size() != other.size()) {
715 TH_MATH_ERROR("vec::operator-=", size(), MathError::InvalidArgument);
716 return (*this = vec<Type>(max(size(), 1), nan()));
717 }
718
719 for (unsigned int i = 0; i < size(); ++i)
720 elements[i] -= other.elements[i];
721
722 return *this;
723 }
724
725
728
729 for (unsigned int i = 0; i < size(); ++i)
730 elements[i] *= scalar;
731
732 return *this;
733 }
734
735
738
739 if(abs(scalar) < MACH_EPSILON) {
740 TH_MATH_ERROR("vec::operator/=", scalar, MathError::DivByZero);
741 *this = vec<Type>(max(size(), 1), nan());
742 return *this;
743 }
744
745 for (unsigned int i = 0; i < size(); ++i)
746 elements[i] /= scalar;
747
748 return *this;
749 }
750
751
753 inline Type norm() const {
754 return algebra::norm(*this);
755 }
756
757
759 inline Type sqr_norm() const {
760 return algebra::sqr_norm(*this);
761 }
762
763
765 inline Type& operator[](unsigned int i) {
766 return elements[i];
767 }
768
769
771 inline const Type& operator[](unsigned int i) const {
772 return elements[i];
773 }
774
775
780 inline Type& at(unsigned int i) {
781 return elements.at(i);
782 }
783
784
789 inline Type at(unsigned int i) const {
790 return elements.at(i);
791 }
792
793
794 using iterator = typename Container<Type>::iterator;
795
796
799 inline auto begin() {
800 return elements.begin();
801 }
802
803
806 inline auto begin() const {
807 return elements.cbegin();
808 }
809
810
813 inline auto end() {
814 return elements.end();
815 }
816
817
820 inline auto end() const {
821 return elements.cend();
822 }
823
824
826 inline Type* data() {
827 return elements.data();
828 }
829
830
832 inline const Type* data() const {
833 return elements.data();
834 }
835
836
838 inline void normalize() {
840 }
841
842
844 inline vec<Type> normalized() const {
845 return algebra::normalize(*this);
846 }
847
848
850 template<typename Vector>
851 inline bool operator==(const Vector& other) const {
852
853 if(size() != other.size())
854 return false;
855
856 for (unsigned int i = 0; i < size(); ++i)
857 if(elements[i] != other[i])
858 return false;
859
860 return true;
861 }
862
863
865 template<typename Vector>
866 inline bool operator!=(const Vector& other) const {
867 return !(*this == other);
868 }
869
870
872 inline TH_CONSTEXPR unsigned int size() const {
873 return elements.size();
874 }
875
876
878 inline void resize(size_t n) {
879 elements.resize(n);
880 }
881
882
884 inline void resize(size_t n, const Type& value) {
885 elements.resize(n, value);
886 }
887
888
891 inline void append(const Type& x) {
892 elements.push_back(x);
893 }
894
895
898 inline void append(Type&& x) {
899 elements.push_back(x);
900 }
901
902
905 inline static vec<Type> euclidean_base(
906 unsigned int i, unsigned int n) {
907
908 if(i >= n) {
909 TH_MATH_ERROR("vec::euclidean_base", i, MathError::InvalidArgument);
910 return vec<Type>(n, nan());
911 }
912
913 vec<Type> e_i = vec<Type>(n, Type(0.0));
914 e_i.resize(n);
915 e_i[i] = 1;
916
917 return e_i;
918 }
919
920
923 inline friend vec<Type> operator*(Type a, const vec<Type>& v) {
924 return v * a;
925 }
926
927
928#ifndef THEORETICA_NO_PRINT
929
931 inline std::string to_string(
932 const std::string& separator = ", ",
933 bool parenthesis = true) const {
934
935 std::stringstream res;
936
937 if(parenthesis)
938 res << "(";
939
940 for (unsigned int i = 0; i < size(); ++i) {
941 res << elements[i];
942 if(i != size() - 1)
943 res << separator;
944 }
945
946 if(parenthesis)
947 res << ")";
948
949 return res.str();
950 }
951
952
954 inline operator std::string() {
955 return to_string();
956 }
957
958
960 inline friend std::ostream& operator<<(std::ostream& out, const vec<Type>& obj) {
961 return out << obj.to_string();
962 }
963
964#endif
965
966 };
967
968}
969
970
971#endif
Linear algebra routines.
A sequential iterator for traversing vector-like containers.
Definition vec.h:29
ReturnType operator*()
Dereference the iterator to get the current element.
Definition vec.h:52
vec_iterator(Vector &vector, size_t index)
Construct the iterator from a pointer to the elements and a starting index.
Definition vec.h:48
size_t index()
Move to the previous element in the vector.
Definition vec.h:70
vec_iterator & operator++()
Move to the next element in the vector.
Definition vec.h:57
bool operator==(const vec_iterator &other) const
Comparison operators.
Definition vec.h:76
A statically allocated N-dimensional vector with elements of the given type.
Definition vec.h:92
const Type & operator[](unsigned int i) const
Get the i-th component by value.
Definition vec.h:331
vec< Type, N > cross(const vec< Type, N > &other) const
Cross product between vectors.
Definition vec.h:251
Type & operator[](unsigned int i)
Access i-th component by reference.
Definition vec.h:325
bool operator!=(const Vector &other) const
Check whether all elements of both vectors are unequal.
Definition vec.h:443
Type dot(const Vector &other) const
Dot product between vectors (v * w = v.x * w.x + ...)
Definition vec.h:238
auto begin() const
Get a const iterator to the first element of the vector.
Definition vec.h:390
vec_iterator< vec< Type, N >, Type & > iterator
Sequential iterator for statically allocated vectors.
Definition vec.h:369
void resize(size_t n) const
Compatibility function to allow for allocation or resizing of dynamic vectors.
Definition vec.h:459
vec()
Construct a vector with all elements equal to zero.
Definition vec.h:104
const Type * data() const
Get a raw pointer to the elements of the vector.
Definition vec.h:409
auto end()
Get an iterator to one plus the last element of the vector.
Definition vec.h:384
static vec< Type, N > euclidean_base(unsigned int i, unsigned int n=N)
Returns an N-dimensional euclidean base unit vector with the i-th element set to 1.
Definition vec.h:484
vec_iterator< const vec< Type, N >, const Type & > const_iterator
Const sequential iterator for statically allocated vectors.
Definition vec.h:372
vec(unsigned int size, Type val)
Construct a vector with all elements equal to the given value, checking that the given size matches t...
Definition vec.h:121
void resize(size_t n, const Type &value) const
Compatibility function to allow for allocation or resizing of dynamic vectors.
Definition vec.h:474
vec< Type, N > & operator*=(Type scalar)
Multiply the vector itself by a scalar.
Definition vec.h:287
Type sqr_norm() const
Compute the square norm of the vector (v * v)
Definition vec.h:319
std::string to_string(const std::string &separator=", ", bool parenthesis=true) const
Convert the vector to string representation.
Definition vec.h:510
vec< Type, N > & operator+=(const Vector &other)
Sum a vector the the vector itself.
Definition vec.h:266
vec< Type, N > operator-(const vec< Type, N > &other) const
Vector subtraction.
Definition vec.h:206
vec(Type x1, Type x2, Args... args)
Construct a vector from its elements, provided they are more than two (to avoid conflict with other c...
Definition vec.h:147
TH_CONSTEXPR unsigned int size() const
Returns the size of the vector (N)
Definition vec.h:449
vec(const Vector &other)
Copy constructor.
Definition vec.h:139
vec< Type, N > & operator-=(const Vector &other)
Subtract a vector the the vector itself.
Definition vec.h:277
vec< Type, N > cross(const Vector &other) const
Cross product between vectors.
Definition vec.h:259
vec< Type, N > & operator=(const Vector &other)
Copy from other.
Definition vec.h:160
Type norm() const
Compute the norm of the vector (sqrt(v * v))
Definition vec.h:313
friend vec< Type, N > operator*(Type a, const vec< Type, N > &v)
Friend operator to enable equations of the form (Type) * (vec)
Definition vec.h:502
void normalize()
Vector normalization (v / |v|)
Definition vec.h:415
vec(std::initializer_list< Type > l)
Initialize from a list, e.g. {1, 2, 3}.
Definition vec.h:170
Type & at(unsigned int i)
Access i-th element by reference, with bound checking.
Definition vec.h:340
vec< Type, N > normalized() const
Return the normalized vector (v / |v|)
Definition vec.h:421
auto begin()
Get an iterator to the first element of the vector.
Definition vec.h:377
vec< Type, N > operator+(const vec< Type, N > &other) const
Vector sum (v + w = (v.x + w.x, ...))
Definition vec.h:191
friend std::ostream & operator<<(std::ostream &out, const vec< Type, N > &obj)
Stream the vector in string representation to an output stream (std::ostream)
Definition vec.h:539
bool operator==(const Vector &other) const
Check whether all elements of both vectors are equal.
Definition vec.h:428
auto end() const
Get a const iterator to one plus the last element of the vector.
Definition vec.h:397
vec< Type, N > operator/(Type scalar) const
Scalar division (v / a = (v.x / a, ...))
Definition vec.h:226
Type at(unsigned int i) const
Get the i-th element by value, with bound checking.
Definition vec.h:356
vec(Type val)
Construct a vector with all elements equal to the given value.
Definition vec.h:111
vec< Type, N > & operator/=(Type scalar)
Divide the vector itself by a scalar.
Definition vec.h:297
vec< Type, N > operator+() const
Identity.
Definition vec.h:185
Type operator*(const Vector &other) const
Dot product between vectors (v * w = v.x * w.x + ...)
Definition vec.h:245
vec< Type, N > operator*(Type scalar) const
Scalar multiplication (av = (v.x * a, ...))
Definition vec.h:215
Type * data()
Get a raw pointer to the elements of the vector.
Definition vec.h:403
vec< Type, N > operator-() const
Opposite vector.
Definition vec.h:200
#define TH_CONSTEXPR
Enable constexpr in function declarations if C++14 is supported.
Definition constants.h:170
#define TH_MATH_ERROR(F_NAME, VALUE, EXCEPTION)
TH_MATH_ERROR is a macro which throws exceptions or modifies errno (depending on which compilation op...
Definition error.h:225
Vector1 cross(const Vector1 &v1, const Vector2 &v2)
Compute the cross product between two tridimensional vectors.
Definition algebra.h:476
Vector & make_normalized(Vector &v)
Normalize a given vector overwriting it.
Definition algebra.h:430
Vector1 & vec_copy(Vector1 &dest, const Vector2 &src)
Copy a vector by overwriting another.
Definition algebra.h:241
auto dot(const Vector1 &v, const Vector2 &w)
Computes the dot product between two vectors, using the Hermitian form if needed.
Definition algebra.h:454
auto sqr_norm(const Vector &v)
Returns the square of the Euclidean/Hermitian norm of the given vector.
Definition algebra.h:378
Vector2 & vec_sum(Vector1 &v1, const Vector2 &v2)
Sum two vectors and store the result in the first vector.
Definition algebra.h:1202
Vector2 & vec_diff(Vector1 &v1, const Vector2 &v2)
Subtract two vectors and store the result in the first vector.
Definition algebra.h:1247
Vector & vec_zeroes(Vector &v)
Overwrite a vector with all zeroes.
Definition algebra.h:197
Vector & vec_error(Vector &v)
Overwrite the given vector with the error vector with NaN values.
Definition algebra.h:58
auto norm(const Vector &v)
Returns the Euclidean/Hermitian norm of the given vector.
Definition algebra.h:395
Vector normalize(const Vector &v)
Returns the normalized vector.
Definition algebra.h:405
Main namespace of the library which contains all functions and objects.
Definition algebra.h:27
dual2 abs(dual2 x)
Compute the absolute value of a second order dual number.
Definition dual2_functions.h:242
Vector make_error()
Create a vector representing an error state, with all NaN values.
Definition algebra.h:103
auto max(const Vector &X)
Finds the maximum value inside a dataset.
Definition dataset.h:330
TH_CONSTEXPR real nan()
Return a quiet NaN number in floating point representation.
Definition error.h:78
@ InvalidArgument
Invalid argument.
@ DivByZero
Division by zero.
constexpr real MACH_EPSILON
Machine epsilon for the real type.
Definition constants.h:216