scsl  1.0.0
Shimmering Clarity Standard Library
Vector.h
Go to the documentation of this file.
1 
23 #ifndef SCMATH_GEOM_VECTORS_H
24 #define SCMATH_GEOM_VECTORS_H
25 
26 
27 #include <array>
28 #include <cassert>
29 #include <cmath>
30 #include <initializer_list>
31 #include <ostream>
32 #include <iostream>
33 
34 #include <scmp/Math.h>
35 
36 
37 // This implementation is essentially a C++ translation of a Python library
38 // I wrote for Coursera's "Linear Algebra for Machine Learning" course. Many
39 // of the test vectors come from quiz questions in the class.
40 
41 
42 namespace scmp {
43 namespace geom {
44 
45 
56 template<typename T, size_t N>
57 class Vector {
58 public:
61  {
62  T unitLength = (T) 1.0 / std::sqrt(N);
63  for (size_t i = 0; i < N; i++) {
64  this->arr[i] = unitLength;
65  }
66 
67  scmp::DefaultEpsilon(this->epsilon);
68  }
69 
70 
77  Vector(std::initializer_list<T> ilst)
78  {
79  assert(ilst.size() == N);
80 
81  scmp::DefaultEpsilon(this->epsilon);
82  std::copy(ilst.begin(), ilst.end(), this->arr.begin());
83  }
84 
85 
92  T At(size_t index) const
93  {
94  if (index > this->arr.size()) {
95  throw std::out_of_range("index " +
96  std::to_string(index) + " > " +
97  std::to_string(this->arr.size()));
98  }
99  return this->arr.at(index);
100  }
101 
102 
111  void Set(size_t index, T value)
112  {
113  if (index > this->arr.size()) {
114  throw std::out_of_range("index " +
115  std::to_string(index) + " > " +
116  std::to_string(this->arr.size()));
117  }
118 
119  this->arr[index] = value;
120  }
121 
122 
123 
124 
125 
129  T Magnitude() const
130  {
131  T result = 0;
132 
133  for (size_t i = 0; i < N; i++) {
134  result += (this->arr[i] * this->arr[i]);
135  }
136  return std::sqrt(result);
137  }
138 
139 
147  void
148  SetEpsilon(T eps)
149  {
150  this->epsilon = eps;
151  }
152 
153 
157  bool
158  IsZero() const
159  {
160  for (size_t i = 0; i < N; i++) {
161  if (!scmp::WithinTolerance(this->arr[i], (T) 0.0, this->epsilon)) {
162  return false;
163  }
164  }
165  return true;
166  }
167 
168 
172  Vector
173  UnitVector() const
174  {
175  return *this / this->Magnitude();
176  }
177 
178 
182  bool
183  IsUnitVector() const
184  {
185  return scmp::WithinTolerance(this->Magnitude(), (T) 1.0, this->epsilon);
186  }
187 
188 
193  T
194  Angle(const Vector<T, N> &other) const
195  {
196  Vector<T, N> unitA = this->UnitVector();
197  Vector<T, N> unitB = other.UnitVector();
198 
199  // Can't compute angles with a zero vector.
200  assert(!this->IsZero());
201  assert(!other.IsZero());
202  return static_cast<T>(std::acos(unitA * unitB));
203  }
204 
205 
210  bool
211  IsParallel(const Vector<T, N> &other) const
212  {
213  if (this->IsZero() || other.IsZero()) {
214  return true;
215  }
216 
217  T angle = this->Angle(other);
218  if (scmp::WithinTolerance(angle, (T) 0.0, this->epsilon)) {
219  return true;
220  }
221 
222  return false;
223  }
224 
225 
231  bool
232  IsOrthogonal(const Vector<T, N> &other) const
233  {
234  if (this->IsZero() || other.IsZero()) {
235  return true;
236  }
237 
238  return scmp::WithinTolerance(*this * other, (T) 0.0, this->epsilon);
239  }
240 
241 
247  Vector
248  ProjectParallel(const Vector<T, N> &basis) const
249  {
250  Vector<T, N> unit_basis = basis.UnitVector();
251 
252  return unit_basis * (*this * unit_basis);
253  }
254 
255 
263  Vector
265  {
266  Vector<T, N> spar = this->ProjectParallel(basis);
267  return *this - spar;
268  }
269 
270 
279  Vector
280  Cross(const Vector<T, N> &other) const
281  {
282  assert(N == 3);
283  if (N != 3) {
284  throw std::out_of_range("Cross-product can only called on Vector<T, 3>.");
285  }
286 
287  return Vector<T, N>{
288  (this->arr[1] * other.arr[2]) - (other.arr[1] * this->arr[2]),
289  -((this->arr[0] * other.arr[2]) - (other.arr[0] * this->arr[2])),
290  (this->arr[0] * other.arr[1]) - (other.arr[0] * this->arr[1])
291  };
292  }
293 
294 
300  Vector
301  operator+(const Vector<T, N> &other) const
302  {
303  Vector<T, N> vec;
304 
305  for (size_t i = 0; i < N; i++) {
306  vec.arr[i] = this->arr[i] + other.arr[i];
307  }
308 
309  return vec;
310  }
311 
312 
318  Vector
319  operator-(const Vector<T, N> &other) const
320  {
321  Vector<T, N> vec;
322 
323  for (size_t i = 0; i < N; i++) {
324  vec.arr[i] = this->arr[i] - other.arr[i];
325  }
326 
327  return vec;
328  }
329 
330 
335  Vector
336  operator*(const T k) const
337  {
338  Vector<T, N> vec;
339 
340  for (size_t i = 0; i < N; i++) {
341  vec.arr[i] = this->arr[i] * k;
342  }
343 
344  return vec;
345  }
346 
347 
352  Vector
353  operator/(const T k) const
354  {
355  Vector<T, N> vec;
356 
357  for (size_t i = 0; i < N; i++) {
358  vec.arr[i] = this->arr[i] / k;
359  }
360 
361  return vec;
362  }
363 
364 
369  T
370  operator*(const Vector<T, N> &other) const
371  {
372  T result = 0;
373 
374  for (size_t i = 0; i < N; i++) {
375  result += (this->arr[i] * other.arr[i]);
376  }
377 
378  return result;
379  }
380 
381 
387  bool
388  operator==(const Vector<T, N> &other) const
389  {
390  for (size_t i = 0; i < N; i++) {
391  if (!scmp::WithinTolerance(this->arr[i], other.arr[i], this->epsilon)) {
392  return false;
393  }
394  }
395  return true;
396  }
397 
398 
404  bool
405  operator!=(const Vector<T, N> &other) const
406  {
407  return !(*this == other);
408  }
409 
410 
423  const T &
424  operator[](size_t i) const
425  {
426  return this->arr[i];
427  }
428 
429 
435  friend std::ostream &
436  operator<<(std::ostream &outs, const Vector<T, N> &vec)
437  {
438  outs << "<";
439  for (size_t i = 0; i < N; i++) {
440  outs << vec.arr[i];
441  if (i < (N - 1)) {
442  outs << ", ";
443  }
444  }
445  outs << ">";
446  return outs;
447  }
448 
449 private:
450  static const size_t dim = N;
451  T epsilon;
452  std::array<T, N> arr;
453 };
454 
458 
463 
467 
471 
475 
479 
483 
487 
488 
489 } // namespace geom
490 } // namespace scmp
491 
492 
493 #endif // SCMATH_GEOM_VECTORS_H
Common math functions.
Vectors represent a direction and Magnitude.
Definition: Vector.h:57
Vector ProjectOrthogonal(const Vector< T, N > &basis)
Project this vector perpendicularly onto some basis vector.
Definition: Vector.h:264
Vector operator/(const T k) const
Scalar division.
Definition: Vector.h:353
T Magnitude() const
Compute the length of the vector.
Definition: Vector.h:129
Vector Cross(const Vector< T, N > &other) const
Compute the cross product of two vectors.
Definition: Vector.h:280
bool IsUnitVector() const
Determine if this is a unit vector.
Definition: Vector.h:183
friend std::ostream & operator<<(std::ostream &outs, const Vector< T, N > &vec)
Write a vector a stream in the form "<i, j, ...>".
Definition: Vector.h:436
void Set(size_t index, T value)
Set a new value for the vector.
Definition: Vector.h:111
bool IsZero() const
Determine whether this is a zero vector.
Definition: Vector.h:158
bool operator==(const Vector< T, N > &other) const
Vector equivalence.
Definition: Vector.h:388
void SetEpsilon(T eps)
Set equivalence tolerance.
Definition: Vector.h:148
Vector operator*(const T k) const
Scalar multiplication.
Definition: Vector.h:336
T At(size_t index) const
Return the element At index i.
Definition: Vector.h:92
Vector UnitVector() const
Obtain the unit vector for this vector.
Definition: Vector.h:173
bool IsParallel(const Vector< T, N > &other) const
Determine whether two vectors are parallel.
Definition: Vector.h:211
Vector operator-(const Vector< T, N > &other) const
Vector subtraction.
Definition: Vector.h:319
T operator*(const Vector< T, N > &other) const
Compute the Dot product between two vectors.
Definition: Vector.h:370
T Angle(const Vector< T, N > &other) const
Compute the Angle between two vectors.
Definition: Vector.h:194
const T & operator[](size_t i) const
Array indexing into vector.
Definition: Vector.h:424
Vector()
Construct a unit vector of a given type and size.
Definition: Vector.h:60
bool operator!=(const Vector< T, N > &other) const
Vector non-equivalence.
Definition: Vector.h:405
Vector operator+(const Vector< T, N > &other) const
Vector addition.
Definition: Vector.h:301
Vector ProjectParallel(const Vector< T, N > &basis) const
Project this vector onto some basis vector.
Definition: Vector.h:248
Vector(std::initializer_list< T > ilst)
Construct a Vector with initial values.
Definition: Vector.h:77
bool IsOrthogonal(const Vector< T, N > &other) const
Determine if two vectors are orthogonal or perpendicular to each other.
Definition: Vector.h:232
Vector< float, 3 > Vector3F
Type alias for a three-dimensional float vector.
Definition: Vector.h:470
Vector< double, 2 > Vector2D
Type alias for a two-dimensional double vector.
Definition: Vector.h:478
Vector< double, 3 > Vector3D
Type alias for a three-dimensional double vector.
Definition: Vector.h:482
Vector< double, 4 > Vector4D
Type alias for a four-dimensional double vector.
Definition: Vector.h:486
Vector< float, 4 > Vector4F
Type alias for a four-dimensional float vector.
Definition: Vector.h:474
Vector< float, 2 > Vector2F
Type alias for a two-dimensional float vector.
Definition: Vector.h:466
Shimmering Clarity Math & Physics toolkit.
Definition: estimation.h:31
void DefaultEpsilon(double &epsilon)
Get the default epsilon value.