All Classes Files Functions Variables Typedefs Pages
VectorCore.hpp
Go to the documentation of this file.
1 #pragma once
2 
11 #include <cmath>
12 #include <cstddef>
13 #include <stdexcept>
14 #include <type_traits>
15 
16 namespace lumina {
17 namespace internal {
18 
19 // =============================================================================
20 // Internal Helper: The following is for internal use only!
21 // =============================================================================
29 template <typename T, std::size_t N>
30 struct VectorImpl {
31  static_assert(N > 1, "Are you fucking kidding me?");
32 
33  union {
34  T data[N];
35  struct {
36  T x;
37  T y;
38  T z;
39  T w;
40  };
41  };
42 
43  template <typename... Ts>
44  VectorImpl(Ts... vals)
45  : data{static_cast<T>(vals)...} {
46  static_assert(sizeof...(Ts) == N, "Number of constructor arguments do not "
47  "match the template parameter N!");
48  }
49 
50  VectorImpl()
51  : data{static_cast<T>(0)} {
52  }
53 };
54 
55 // specialization for 2d
56 template <typename T>
57 struct VectorImpl<T, 2> {
58  union {
59  T data[2];
60  struct {
61  T x;
62  T y;
63  };
64  };
65 
66  VectorImpl(T x, T y) : x(x), y(y) {}
67  VectorImpl() : VectorImpl(0, 0) {}
68 };
69 
70 // specialization for 3d
71 template <typename T>
72 struct VectorImpl<T, 3> {
73  union {
74  T data[3];
75  struct {
76  T x;
77  T y;
78  T z;
79  };
80  };
81 
82  VectorImpl(T x, T y, T z) : x(x), y(y), z(z) {}
83  VectorImpl() : VectorImpl(0, 0, 0) {}
84 };
85 
86 // specialization for 4d
87 template <typename T>
88 struct VectorImpl<T, 4> {
89  union {
90  T data[4];
91  struct {
92  T x;
93  T y;
94  T z;
95  T w;
96  };
97  };
98 
99  VectorImpl(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {}
100  VectorImpl() : VectorImpl(0, 0, 0, 0) {}
101 };
102 
103 
113 constexpr std::size_t vecMin(std::size_t a, std::size_t b) {
114  return (a > b) ? b : a;
115 }
116 
118 constexpr double vecPI = 3.14159265359;
119 
120 } // namespace internal
121 
122 // forward declare VectorIterator
123 template <typename T, std::size_t N>
125 
126 
127 
128 // =============================================================================
129 // Definition of Vector
130 // =============================================================================
137 template <typename T, std::size_t N>
138 struct Vector : public internal::VectorImpl<T, N> {
139 
140  /***** Constructors, typedefs, data access, conversion **********************/
143  Vector() = default;
144  template <typename U>
145  Vector(Vector<U, N> other) {
146  for(int i = 0; i < N; ++i) {
147  this->data[i] = static_cast<T>(other.data[i]);
148  }
149  }
150 
154  using type = T;
156  static constexpr std::size_t size = N;
157 
159  T& operator[] (std::size_t index) {
160  if(index >= N) {
161  throw std::out_of_range("Invalid subscript");
162  }
163  return this->data[index];
164  }
165 
166  T operator[] (std::size_t index) const {
167  if(index >= N) {
168  throw std::out_of_range("Invalid subscript");
169  }
170  return this->data[index];
171  }
172 
173 
174  /***** simple arithmetic operators, altering the object *********************/
175  template <typename OT>
176  Vector<T, N>& operator+=(const Vector<OT, N>& v) {
177  for(int i = 0; i < N; ++i) {
178  this->data[i] += v.data[i];
179  }
180  return *this;
181  }
182 
183  template <typename OT>
184  Vector<T, N>& operator-=(const Vector<OT, N>& v) {
185  for(int i = 0; i < N; ++i) {
186  this->data[i] -= v.data[i];
187  }
188  return *this;
189  }
190 
191  template <typename S>
192  Vector<T, N>& operator*=(S scalar) {
193  for(int i = 0; i < N; ++i) {
194  this->data[i] *= scalar;
195  }
196  return *this;
197  }
198 
199  template <typename S>
200  Vector<T, N>& operator/=(S scalar) {
201  for(int i = 0; i < N; ++i) {
202  this->data[i] /= scalar;
203  }
204  return *this;
205  }
206 
207 
208  /***** Unary operators ******************************************************/
209  Vector<T, N> operator+() const {
210  return *this;
211  }
212 
213  Vector<T, N> operator-() const {
214  Vector<T, N> out(*this);
215  for(int i = 0; i < N; ++i) {
216  out.data[i] = -out.data[i];
217  }
218  return out;
219  }
220 
221 
222  /***** comparison operators *************************************************/
223  bool operator==(const Vector<T, N>& other) const {
224  for(int i = 0; i < N; ++i) {
225  if(this->data[i] != other.data[i])
226  return false;
227  }
228  return true;
229  }
230 
231  bool operator!=(const Vector<T, N>& other) const {
232  return !(*this == other);
233  }
234 
235  // TODO: does this make sense?
236  bool operator<(const Vector<T, N>& other) const {
237  for(int i = 0; i < N; ++i) {
238  if(this->data[i] < other.data[i])
239  return true;
240  if(this->data[i] > other.data[i])
241  return false;
242  }
243  return false;
244  }
245 
246  bool operator>(const Vector<T, N>& other) const {
247  return (other < *this);
248  }
249 
250  bool operator<=(const Vector<T, N>& other) const {
251  return (*this < other || *this == other);
252  }
253 
254  bool operator>=(const Vector<T, N>& other) const {
255  return (other < *this || *this == other);
256  }
257 
258 
259  /***** Arithmetic functions with sclar output *******************************/
260  T lengthSquared() const {
261  T out = 0;
262  for(int i = 0; i < N; ++i) {
263  out += this->data[i] * this->data[i];
264  }
265  return out;
266  }
267 
268  template <typename Tout = decltype(sqrt(T(0)))>
269  Tout length() const {
270  return static_cast<Tout>(sqrt(lengthSquared()));
271  }
272 
273  auto phi() const -> decltype(atan2(T(0), T(0))) {
274  static_assert(N >= 2, "You cannot calculate phi of a vector which "
275  "dimension is lower than 2!");
276  auto phi = atan2(this->data[1], this->data[0]);
277  return (phi < 0) ? (phi + 2*internal::vecPI) : phi;
278  }
279 
280  auto theta() const -> decltype(acos(T(0))) {
281  static_assert(N >= 3, "You cannot calculate theta of a vector which "
282  "dimension is lower than 3!");
283  return acos(this->data[2] / length());
284  }
285 
286  T linearSize() const {
287  T out = this->data[0];
288  for(int i = 1; i < N; ++i) {
289  out *= this->data[i];
290  }
291  return out;
292  }
293 
294 
295  /***** Arithmetic functions with vector output ******************************/
296  Vector<T, N>& normalize() {
297  auto lensq = lengthSquared();
298  if(lensq != 0)
299  (*this) /= sqrt(lensq);
300  return *this;
301  }
302 
303  Vector<T, N> normalized() const {
304  return Vector<T, N>(*this).normalize();
305  }
306 
307  template <typename To>
308  Vector<T, N>& scale(const Vector<To, N>& o) {
309  for(int i = 0; i < N; ++i) {
310  this->data[i] *= o.data[i];
311  }
312  return *this;
313  }
314 
315  template <typename To>
316  Vector<T, N> scaled(const Vector<To, N>& o) {
317  return Vector<T, N>(*this).scale(o);
318  }
319 
320  template <typename Ta>
321  Vector<T, N>& rotate(Ta phi, Ta theta) {
322  *this = rotated(phi, theta);
323  return *this;
324  }
325 
326  template <typename Ta>
327  Vector<T, N> rotated(Ta phi, Ta theta) const {
328  return Vector<T, N>(
329  cos(theta) * cos(phi) * this->x
330  - cos(theta) * sin(phi) * this->y
331  + sin(theta) * this->z,
332  sin(phi) * this->x
333  + cos(phi) * this->y,
334  -sin(theta) * cos(phi) * this->x
335  + sin(theta) * sin(phi) * this->y
336  + cos(theta) * this->z
337  );
338  }
339 
340  template <typename To>
341  Vector<T, N>& reflect(const Vector<To, N>& normal) {
342  *this -= normal * 2 * dot(*this, normal);
343  return *this;
344  }
345 
346  template <typename To>
347  auto reflected(const Vector<To, N>& normal)
348  const -> Vector<decltype(T(0) - To(0)), N> {
349  return Vector<decltype(T(0) - To(0)), N>(*this).reflect(normal);
350  }
351 };
352 
353 
354 
355 // =============================================================================
356 // Definition of non member functions for Vector
357 // =============================================================================
358 /***** Simple arithmetic operators ********************************************/
359 template <typename T1, typename T2, std::size_t N>
360 auto operator+(const Vector<T1, N>& v1, const Vector<T2, N>& v2)
361  -> Vector<decltype(T1(0) + T2(0)), N> {
362  Vector<decltype(T1(0) + T2(0)), N> out(v1);
363  return (out += v2);
364 }
365 
366 template <typename T1, typename T2, std::size_t N>
367 auto operator-(const Vector<T1, N>& v1, const Vector<T2, N>& v2)
368  -> Vector<decltype(T1(0) - T2(0)), N> {
369  Vector<decltype(T1(0) - T2(0)), N> out(v1);
370  return (out -= v2);
371 }
372 
373 template <typename T1, typename T2, std::size_t N>
374 auto operator*(const Vector<T1, N>& v, T2 scalar)
375  -> Vector<decltype(T1(0) * T2(0)), N> {
376  Vector<decltype(T1(0) * T2(0)), N> out(v);
377  return out *= scalar;
378 }
379 
380 template <typename T1, typename T2, std::size_t N>
381 auto operator*(T2 scalar, const Vector<T1, N>& v)
382  -> Vector<decltype(T1(0) * T2(0)), N> {
383  Vector<decltype(T1(0) * T2(0)), N> out(v);
384  return out *= scalar;
385 }
386 
387 template <typename T1, typename T2, std::size_t N>
388 auto operator/(const Vector<T1, N>& v, T2 scalar)
389  -> Vector<decltype(T1(0) / T2(0)), N> {
390  Vector<decltype(T1(0) / T2(0)), N> out(v);
391  return out *= scalar;
392 }
393 
394 template <typename T1, typename T2, std::size_t N>
395 auto operator/(T2 scalar, const Vector<T1, N>& v)
396  -> Vector<decltype(T1(0) / T2(0)), N> {
397  Vector<decltype(T1(0) / T2(0)), N> out(v);
398  return out *= scalar;
399 }
400 
401 
402 /***** commutative vector calculations ****************************************/
403 template <typename T1, typename T2, std::size_t N>
404 auto dot(const Vector<T1, N>& lh, const Vector<T2, N>& rh)
405  -> decltype(T1(0) + T2(0)) {
406  decltype(T1(0) + T2(0)) out = 0;
407  for(int i = 0; i < N; ++i) {
408  out += lh.data[i] * rh.data[i];
409  }
410  return out;
411 }
412 
413 template <typename T1, typename T2>
414 auto cross(const Vector<T1, 3>& lh, const Vector<T2, 3>& rh)
415  -> Vector<decltype(T1(0) * T2(0)), 3> {
416  return Vector<decltype(T1(0) + T2(0)), 3>(lh.y * rh.z - lh.z * rh.y,
417  lh.z * rh.x - lh.x * rh.z,
418  lh.x * rh.y - lh.y * rh.x);
419 }
420 
421 
422 template <typename T1, typename T2, std::size_t N>
423 auto distance(const Vector<T1, N>& a, const Vector<T2, N>& b)
424  -> decltype((a - b).length()) {
425  return (a - b).length();
426 }
427 
428 template <typename T1, typename T2, std::size_t N>
429 auto angle(const Vector<T1, N>& a, const Vector<T2, N>& b)
430  -> decltype(acos(a.length() * b.length())) {
431  return acos(dot(a, b) / (a.length() * b.length()));
432 }
433 
434 
435 /***** vector_cast definition *************************************************/
436 template <typename Tdst, typename Tsrc, std::size_t N>
437 Vector<Tdst, N> vector_cast(const Vector<Tsrc, N>& in) {
438  Vector<Tdst, N> out;
439  for(int i = 0; i < N; ++i) {
440  out.data[i] = static_cast<Tdst>(in.data[i]);
441  }
442  return out;
443 }
444 
445 template <std::size_t Ndst, std::size_t Nsrc, typename T>
446 Vector<T, Ndst> vector_cast(const Vector<T, Nsrc>& in) {
447  Vector<T, Ndst> out;
448  for(int i = 0; i < internal::vecMin(Ndst, Nsrc); ++i) {
449  out.data[i] = in.data[i];
450  }
451  return out;
452 }
453 
454 template <typename Tdst, std::size_t Ndst, typename Tsrc, std::size_t Nsrc>
455 Vector<Tdst, Ndst> vector_cast(const Vector<Tsrc, Nsrc>& in) {
456  Vector<Tdst, Ndst> out;
457  for(int i = 0; i < internal::vecMin(Ndst, Nsrc); ++i) {
458  out.data[i] = static_cast<Tdst>(in.data[i]);
459  }
460  return out;
461 }
462 
463 
464 
465 // =============================================================================
466 // Typedefs for common types
467 // =============================================================================
468 template <typename T>
469 using Vec2 = Vector<T, 2>;
470 using Vec2f = Vector<float, 2>;
471 using Vec2i = Vector<int, 2>;
472 
473 template <typename T>
474 using Vec3 = Vector<T, 3>;
475 using Vec3f = Vector<float, 3>;
476 using Vec3i = Vector<int, 3>;
477 
478 template <typename T>
479 using Vec4 = Vector<T, 4>;
480 using Vec4f = Vector<float, 4>;
481 using Vec4i = Vector<int, 4>;
482 
483 
484 
485 // =============================================================================
486 // VectorIterator definition and functions
487 // =============================================================================
488 template <typename T, std::size_t N>
489 class VectorIterator : public Vector<T, N> {
490 private:
491  // Vector<T, N> m_current;
492  Vector<T, N> m_target;
493 
494  template <typename Tf, std::size_t Nf>
495  friend typename Vector<Tf, Nf>::iterator begin(Vector<Tf, Nf> v);
496  template <typename Tf, std::size_t Nf>
497  friend typename Vector<Tf, Nf>::iterator end(Vector<Tf, Nf> v);
498 
499  using iterator = void;
500 
501  VectorIterator(Vector<T, N> v) : m_target(v) {}
502 
503  void skipToEnd() {
504  this->data[0] = m_target.data[0];
505  }
506 
507 public:
508  // T operator*() const {
509  // T out = 0;
510  // for(int i = 0; i < N; ++i) {
511  // T add = this->data[i];
512  // for(int j = i + 1; j < N; ++j) {
513  // add *= m_target.data[j];
514  // }
515  // out += add;
516  // }
517  // return out;
518  // }
519 
520  Vector<T, N> operator*() const {
521  return static_cast<Vector<T, N>>(*this);
522  }
523 
524  VectorIterator& operator++() {
525  for(int i = N - 1; i > 0; --i) {
526  if(++this->data[i] < m_target.data[i])
527  return *this;
528 
529  this->data[i] = 0;
530  }
531  ++this->data[0];
532  return *this;
533  }
534 
535  VectorIterator<T, N> operator++(int) {
536  VectorIterator<T, N> pre(*this);
537  ++(*this);
538  return pre;
539  }
540 };
541 
542 template <typename T, std::size_t N>
543 typename Vector<T, N>::iterator begin(Vector<T, N> v) {
544  static_assert(!std::is_floating_point<T>::value,
545  "You cannot obtain a iterator of an floating pointer vector type!");
546  return typename Vector<T, N>::iterator(v);
547 }
548 
549 template <typename T, std::size_t N>
550 typename Vector<T, N>::iterator end(Vector<T, N> v) {
551  static_assert(!std::is_floating_point<T>::value,
552  "You cannot obtain a iterator of an floating pointer vector type!");
553  typename Vector<T, N>::iterator out(v);
554  out.skipToEnd();
555  return out;
556 }
557 
558 
559 
560 };
Represents a vector with arbitrary dimension and type of elements.
Definition: VectorCore.hpp:138
Specialized helper base struct for Vector.
Definition: VectorCore.hpp:30
VectorIterator< T, N > iterator
iterator type
Definition: VectorCore.hpp:152
Definition: VectorCore.hpp:124
int type
type of the vector's elements
Definition: VectorCore.hpp:154