MathFu
An open source project by FPL.
 All Classes Namespaces Files Functions Variables Typedefs Friends Groups Pages
vector.h
Go to the documentation of this file.
1 /*
2 * Copyright 2014 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #ifndef MATHFU_VECTOR_H_
17 #define MATHFU_VECTOR_H_
18 
19 #include "mathfu/utilities.h"
20 
21 #include <math.h>
22 
23 /// @file mathfu/vector.h Vector
24 /// @brief Vector class and functions.
25 /// @addtogroup mathfu_vector
26 
27 // Disable spurious warnings generated by MATHFU_VECTOR_OPERATION().
28 #if defined(_MSC_VER)
29 #pragma warning(push)
30 #pragma warning(disable : 4127) // conditional expression is constant
31 #if _MSC_VER >= 1900 // MSVC 2015
32 #pragma warning(disable : 4456) // allow shadowing in unrolled loops
33 #endif // _MSC_VER >= 1900
34 #elif defined(__clang__)
35 #pragma clang diagnostic push
36 #pragma clang diagnostic ignored "-Warray-bounds"
37 #endif
38 
39 /// @cond MATHFU_INTERNAL
40 #define MATHFU_VECTOR_OPERATION(OP) MATHFU_UNROLLED_LOOP(i, d, OP)
41 /// @endcond
42 
43 /// @cond MATHFU_INTERNAL
44 #define MATHFU_VECTOR_OPERATOR(OP) \
45  { \
46  Vector<T, d> result; \
47  MATHFU_VECTOR_OPERATION(result[i] = OP); \
48  return result; \
49  }
50 /// @endcond
51 
52 /// @cond MATHFU_INTERNAL
53 #define MATHFU_VECTOR_SELF_OPERATOR(OP) \
54  { \
55  MATHFU_VECTOR_OPERATION(OP); \
56  return *this; \
57  }
58 /// @endcond
59 
60 namespace mathfu {
61 
62 template <class T, int d>
63 class Vector;
64 
65 /// @cond MATHFU_INTERNAL
66 template <class T, int d>
67 static inline T DotProductHelper(const Vector<T, d>& v1,
68  const Vector<T, d>& v2);
69 template <class T>
70 static inline T DotProductHelper(const Vector<T, 2>& v1,
71  const Vector<T, 2>& v2);
72 template <class T>
73 static inline T DotProductHelper(const Vector<T, 3>& v1,
74  const Vector<T, 3>& v2);
75 template <class T>
76 static inline T DotProductHelper(const Vector<T, 4>& v1,
77  const Vector<T, 4>& v2);
78 
79 template <typename T, int d, typename CompatibleT>
80 static inline Vector<T, d> FromTypeHelper(const CompatibleT& compatible);
81 
82 template <typename T, int d, typename CompatibleT>
83 static inline CompatibleT ToTypeHelper(const Vector<T, d>& v);
84 /// @endcond
85 
86 /// @addtogroup mathfu_vector
87 /// @{
88 
89 /// @class VectorPacked "mathfu/vector.h"
90 /// @brief Packed N-dimensional vector.
91 ///
92 /// Some Vector classes are padded so that it's possible to use the data
93 /// structures with SIMD instructions. This structure can be used in
94 /// conjunction with unpacked Vector classes to pack data
95 /// into flat arrays suitable for sending to a GPU (e.g vertex buffers).
96 ///
97 /// <p>
98 /// For example, to pack (store) an unpacked to packed vector:<br>
99 /// <blockquote><code><pre>
100 /// VectorPacked<float, 3> packed;
101 /// Vector<float, 3> vector(3, 2, 1);
102 /// vector.Pack(&packed);
103 /// </pre></code></blockquote>
104 /// or<br>
105 /// <blockquote><code><pre>
106 /// Vector<float, 3> vector(3, 2, 1);
107 /// VectorPacked<float, 3> packed = vector;
108 /// </pre></code></blockquote>
109 /// </p>
110 ///
111 /// <p>
112 /// To initialize a vector from a packed vector:<br>
113 /// <blockquote><code><pre>
114 /// VectorPacked<float, 3> packed = { 3, 2, 1 };
115 /// Vector<float, 3> vector(packed);
116 /// </pre></code></blockquote>
117 ///
118 /// @tparam T type of VectorPacked elements.
119 /// @tparam d dimensions (number of elements) in the VectorPacked structure.
120 template <class T, int d>
121 struct VectorPacked {
122  /// Create an uninitialized VectorPacked.
124 
125  /// Create a VectorPacked from a Vector.
126  ///
127  /// Both VectorPacked and Vector must have the same number of dimensions.
128  /// @param vector Vector to create the VectorPacked from.
129  explicit VectorPacked(const Vector<T, d>& vector) { vector.Pack(this); }
130 
131  /// Copy a Vector to a VectorPacked.
132  ///
133  /// Both VectorPacked and Vector must have the same number of dimensions.
134  /// @param vector Vector to copy to the VectorPacked.
135  /// @returns A reference to this VectorPacked.
137  vector.Pack(this);
138  return *this;
139  }
140 
141  /// Elements of the packed vector one per dimension.
142  T data[d];
143 };
144 /// @}
145 
146 /// @addtogroup mathfu_vector
147 /// @{
148 /// @class Vector "mathfu/vector.h"
149 /// @brief Vector of d elements with type T
150 ///
151 /// Vector stores <b>d</b> elements of type <b>T</b> and provides a set
152 /// functions to perform operations on the set of elements.
153 ///
154 /// @tparam T type of Vector elements.
155 /// @tparam d dimensions (number of elements) in the Vector structure.
156 template <class T, int d>
157 class Vector {
158  public:
159  /// @brief Element type to enable reference by other classes.
160  typedef T Scalar;
161 
162  /// @brief Create an uninitialized Vector.
163  inline Vector() {}
164 
165  /// @brief Create a vector from another vector copying each element.
166  ///
167  /// @param v Vector that the data will be copied from.
168  inline Vector(const Vector<T, d>& v) {
169  MATHFU_VECTOR_OPERATION(data_[i] = v.data_[i]);
170  }
171 
172  /// @brief Create a vector from another vector of a different type.
173  ///
174  /// This copies each element of a Vector which makes it possible to between
175  /// vectors of different types, for example
176  /// <code>float/double/int</code> vectors.
177  /// @param v Vector that the data will be copied from.
178  /// @tparam U type of Vector elements to copy.
179  template <typename U>
180  explicit inline Vector(const Vector<U, d>& v) {
181  MATHFU_VECTOR_OPERATION(data_[i] = static_cast<T>(v[i]));
182  }
183 
184  /// @brief Create a vector from a single float.
185  ///
186  /// Each elements is set to be equal to the value given.
187  /// @param s Scalar value that the vector will be initialized to.
188  explicit inline Vector(const T& s) { MATHFU_VECTOR_OPERATION(data_[i] = s); }
189 
190  /// @brief Create a vector form the first d elements of an array.
191  ///
192  /// @param a Array of values that the vector will be iniitlized to.
193  explicit inline Vector(const T* a) {
194  MATHFU_VECTOR_OPERATION(data_[i] = a[i]);
195  }
196 
197  /// @brief Create a vector from two values.
198  ///
199  /// @note This method only works when the vector is of size two.
200  ///
201  /// @param s1 Scalar value for the first element of the vector.
202  /// @param s2 Scalar value for the second element of the vector.
203  inline Vector(const T& s1, const T& s2) {
204  MATHFU_STATIC_ASSERT(d == 2);
205  data_[0] = s1;
206  data_[1] = s2;
207  }
208 
209  /// @brief Create a vector from three values.
210  ///
211  /// @note This method only works when the vector is of size three.
212  ///
213  /// @param s1 Scalar value for the first element of the vector.
214  /// @param s2 Scalar value for the second element of the vector.
215  /// @param s3 Scalar value for the third element of the vector.
216  inline Vector(const T& s1, const T& s2, const T& s3) {
217  MATHFU_STATIC_ASSERT(d == 3);
218  data_[0] = s1;
219  data_[1] = s2;
220  data_[2] = s3;
221  }
222 
223  /// @brief Create a vector from a 2 component vector and a third value.
224  ///
225  /// @note This method only works when the vector is of size three.
226  ///
227  /// @param v12 Vector containing the first 2 values.
228  /// @param s3 Scalar value for the third element of the vector.
229  inline Vector(const Vector<T, 2>& v12, const T& s3) {
230  MATHFU_STATIC_ASSERT(d == 3);
231  data_[0] = v12[0];
232  data_[1] = v12[1];
233  data_[2] = s3;
234  }
235 
236  /// @brief Create a vector from four values.
237  ///
238  /// @note This method only works when the vector is of size four.
239  ///
240  /// @param s1 Scalar value for the first element of the vector.
241  /// @param s2 Scalar value for the second element of the vector.
242  /// @param s3 Scalar value for the third element of the vector.
243  /// @param s4 Scalar value for the forth element of the vector.
244  inline Vector(const T& s1, const T& s2, const T& s3, const T& s4) {
245  MATHFU_STATIC_ASSERT(d == 4);
246  data_[0] = s1;
247  data_[1] = s2;
248  data_[2] = s3;
249  data_[3] = s4;
250  }
251 
252  /// @brief Create a 4-dimensional vector from a Vector<T, 3>.
253  ///
254  /// The last element is initialized to the specified value.
255  /// @note This method only works with 4 element vectors.
256  ///
257  /// @param vector3 Vector used to initialize the first 3 elements.
258  /// @param value Value used to set the last element of the vector.
259  inline Vector(const Vector<T, 3>& vector3, const T& value) {
260  MATHFU_STATIC_ASSERT(d == 4);
261  data_[0] = vector3[0];
262  data_[1] = vector3[1];
263  data_[2] = vector3[2];
264  data_[3] = value;
265  }
266 
267  /// @brief Create a vector from two 2 component vectors.
268  ///
269  /// @note This method only works when the vector is of size four.
270  ///
271  /// @param v12 Vector containing the first 2 values.
272  /// @param v34 Vector containing the last 2 values.
273  inline Vector(const Vector<T, 2>& v12, const Vector<T, 2>& v34) {
274  MATHFU_STATIC_ASSERT(d == 4);
275  data_[0] = v12[0];
276  data_[1] = v12[1];
277  data_[2] = v34[0];
278  data_[3] = v34[1];
279  }
280 
281  /// @brief Create a vector from packed vector (VectorPacked).
282  ///
283  /// @param vector Packed vector used to initialize an unpacked.
284  explicit inline Vector(const VectorPacked<T, d>& vector) {
285  MATHFU_VECTOR_OPERATION(data_[i] = vector.data[i]);
286  }
287 
288  /// @brief Access an element of the vector.
289  ///
290  /// @param i Index of the element to access.
291  /// @return A reference to the accessed data that can be modified by the
292  /// caller.
293  inline T& operator()(const int i) { return data_[i]; }
294 
295  /// @brief Access an element of the vector.
296  ///
297  /// @param i Index of the element to access.
298  /// @return A reference to the accessed data.
299  inline const T& operator()(const int i) const { return data_[i]; }
300 
301  /// @brief Access an element of the vector.
302  ///
303  /// @param i Index of the element to access.
304  /// @return A reference to the accessed data that can be modified by the
305  /// caller.
306  inline T& operator[](const int i) { return data_[i]; }
307 
308  /// @brief Access an element of the vector.
309  ///
310  /// @param i Index of the element to access.
311  /// @return A const reference to the accessed.
312  inline const T& operator[](const int i) const { return data_[i]; }
313 
314  /// @brief GLSL style 3 element accessor.
315  ///
316  /// This only works with vectors that contain more than 3 elements.
317  /// @returns A 3-dimensional Vector containing the first 3 elements of
318  // this Vector.
319  inline Vector<T, 3> xyz() {
320  MATHFU_STATIC_ASSERT(d > 3);
321  return Vector<T, 3>(data_[0], data_[1], data_[2]);
322  }
323 
324  /// @brief GLSL style 3 element accessor.
325  ///
326  /// This only works with vectors that contain more than 3 elements.
327  /// @returns A 3-dimensional Vector containing the first 3 elements of
328  // this Vector.
329  inline const Vector<T, 3> xyz() const {
330  MATHFU_STATIC_ASSERT(d > 3);
331  return Vector<T, 3>(data_[0], data_[1], data_[2]);
332  }
333 
334  /// @brief GLSL style 2 element accessor.
335  ///
336  /// This only works with vectors that contain more than 2 elements.
337  /// @returns A 2-dimensional Vector with the first 2 elements of this Vector.
338  inline Vector<T, 2> xy() {
339  MATHFU_STATIC_ASSERT(d > 2);
340  return Vector<T, 2>(data_[0], data_[1]);
341  }
342 
343  /// @brief GLSL style 2 element accessor.
344  ///
345  /// This only works with vectors that contain more than 2 elements.
346  /// @returns A 2-dimensional Vector with the first 2 elements of this Vector.
347  inline const Vector<T, 2> xy() const {
348  MATHFU_STATIC_ASSERT(d > 2);
349  return Vector<T, 2>(data_[0], data_[1]);
350  }
351 
352  /// @brief GLSL style 2 element accessor.
353  ///
354  /// This only works with vectors that contain 4 elements.
355  /// @returns A 2-dimensional Vector with the last 2 elements of this Vector.
356  inline Vector<T, 2> zw() {
357  MATHFU_STATIC_ASSERT(d == 4);
358  return Vector<T, 2>(data_[2], data_[3]);
359  }
360 
361  /// @brief GLSL style 2 element accessor.
362  ///
363  /// This only works with vectors that contain 4 elements.
364  /// @returns A 2-dimensional Vector with the last 2 elements of this Vector.
365  inline const Vector<T, 2> zw() const {
366  MATHFU_STATIC_ASSERT(d == 4);
367  return Vector<T, 2>(data_[2], data_[3]);
368  }
369 
370  /// @brief Pack a Vector to a packed "d" element vector structure.
371  ///
372  /// @param vector Packed "d" element vector to write to.
373  inline void Pack(VectorPacked<T, d>* const vector) const {
374  MATHFU_VECTOR_OPERATION(vector->data[i] = data_[i]);
375  }
376 
377  /// @brief Calculate the squared length of this vector.
378  ///
379  /// @return The length of this vector squared.
380  inline T LengthSquared() const { return LengthSquaredHelper(*this); }
381 
382  /// @brief Calculate the length of this vector.
383  ///
384  /// @return The length of this vector.
385  inline T Length() const { return LengthHelper(*this); }
386 
387  /// @brief Normalize this vector in-place.
388  ///
389  /// @return The length of this vector.
390  inline T Normalize() { return NormalizeHelper(*this); }
391 
392  /// @brief Calculate the normalized version of this vector.
393  ///
394  /// @return The normalized vector.
395  inline Vector<T, d> Normalized() const { return NormalizedHelper(*this); }
396 
397  /// @brief Load from any type that is some formulation of a length d array of
398  /// type T.
399  ///
400  /// Essentially this is just a type cast and a load, but it happens safely
401  /// so that we avoid aliasing bugs.
402  ///
403  /// @return `compatible` cast to `Vector<T,d>` and dereferenced.
404  template <typename CompatibleT>
405  static inline Vector<T, d> FromType(const CompatibleT& compatible) {
406  return FromTypeHelper<T, d, CompatibleT>(compatible);
407  }
408 
409  /// @brief Load into any type that is some formulation of a length d array of
410  /// type T.
411  ///
412  /// Essentially this is just a type cast and a load, but it happens safely
413  /// so that we avoid aliasing bugs.
414  ///
415  /// @return `v` cast to `CompatibleT` and dereferenced.
416  template <typename CompatibleT>
417  static inline CompatibleT ToType(const Vector<T, d>& v) {
418  return ToTypeHelper<T, d, CompatibleT>(v);
419  }
420 
421  /// @brief Calculate the dot product of two vectors.
422  ///
423  /// @param v1 First vector.
424  /// @param v2 Second vector.
425  /// @return The dot product of v1 and v2.
426  static inline T DotProduct(const Vector<T, d>& v1, const Vector<T, d>& v2) {
427  return DotProductHelper(v1, v2);
428  }
429 
430  /// @brief Calculate the hadamard or componentwise product of two vectors.
431  ///
432  /// @param v1 First vector.
433  /// @param v2 Second vector.
434  /// @return The hadamard product of v1 and v2.
435  static inline Vector<T, d> HadamardProduct(const Vector<T, d>& v1,
436  const Vector<T, d>& v2) {
437  return HadamardProductHelper(v1, v2);
438  }
439 
440  /// @brief Calculate the cross product of two vectors.
441  ///
442  /// Note that this function is only defined for 3-dimensional Vectors.
443  /// @param v1 First vector.
444  /// @param v2 Second vector.
445  /// @return The cross product of v1 and v2.
446  static inline Vector<T, 3> CrossProduct(const Vector<T, 3>& v1,
447  const Vector<T, 3>& v2) {
448  return CrossProductHelper(v1, v2);
449  }
450 
451  /// @brief Linearly interpolate two vectors.
452  ///
453  /// @param v1 First vector.
454  /// @param v2 Second vector.
455  /// @param percent Percentage from v1 to v2 in range 0.0...1.0.
456  /// @return The hadamard product of v1 and v2.
457  static inline Vector<T, d> Lerp(const Vector<T, d>& v1,
458  const Vector<T, d>& v2, const T percent) {
459  return LerpHelper(v1, v2, percent);
460  }
461 
462  /// @brief Generates a random vector.
463  ///
464  /// The range of each component is bounded by min and max.
465  /// @param min Minimum value of the vector.
466  /// @param max Maximum value of the vector.
467  static inline Vector<T, d> RandomInRange(const Vector<T, d>& min,
468  const Vector<T, d>& max) {
469  return RandomInRangeHelper(min, max);
470  }
471 
472  /// @brief Compare each component and returns max values.
473  ///
474  /// @param v1 First vector.
475  /// @param v2 Second vector.
476  /// @return Max value of v1 and v2.
477  static inline Vector<T, d> Max(const Vector<T, d>& v1,
478  const Vector<T, d>& v2) {
479  return MaxHelper(v1, v2);
480  }
481 
482  /// @brief Compare each component and returns min values.
483  ///
484  /// @param v1 First vector.
485  /// @param v2 Second vector.
486  /// @return Min value of v1 and v2.
487  static inline Vector<T, d> Min(const Vector<T, d>& v1,
488  const Vector<T, d>& v2) {
489  return MinHelper(v1, v2);
490  }
491 
493 
494  /// Elements of the vector.
495  T data_[d];
496 };
497 /// @}
498 
499 /// @addtogroup mathfu_vector
500 /// @{
501 
502 /// @brief Compare 2 Vectors of the same size for equality.
503 ///
504 /// @note: The likelyhood of two float values being the same is very small.
505 /// Instead consider comparing the difference between two float vectors using
506 /// LengthSquared() with an epsilon value.
507 /// For example, v1.LengthSquared(v2) < epsilon.
508 ///
509 /// @return true if the 2 vectors contains the same value, false otherwise.
510 template <class T, int d>
511 inline bool operator==(const Vector<T, d>& lhs, const Vector<T, d>& rhs) {
512  for (int i = 0; i < d; ++i) {
513  if (lhs[i] != rhs[i]) return false;
514  }
515  return true;
516 }
517 
518 /// @brief Compare 2 Vectors of the same size for inequality.
519 ///
520 /// @return true if the elements of two vectors differ, false otherwise.
521 template <class T, int d>
522 inline bool operator!=(const Vector<T, d>& lhs, const Vector<T, d>& rhs) {
523  return !(lhs == rhs);
524 }
525 
526 /// @brief Negate all elements of the Vector.
527 ///
528 /// @return A new Vector containing the result.
529 template <class T, int d>
531  MATHFU_VECTOR_OPERATOR(-v.data_[i]);
532 }
533 
534 /// @brief Multiply a Vector by a scalar.
535 ///
536 /// Multiplies each component of the specified Vector with a scalar.
537 ///
538 /// @param s scalar to multiply.
539 /// @param v Vector to multiply.
540 /// @return Vector containing the result.
541 /// @related Vector
542 template <class T, int d>
543 inline Vector<T, d> operator*(const T& s, const Vector<T, d>& v) {
544  MATHFU_VECTOR_OPERATOR(v.data_[i] * s);
545 }
546 
547 /// @brief Divide a Vector by a scalar.
548 ///
549 /// Divides each component of the specified Vector by a scalar.
550 ///
551 /// @param v Vector to be divided.
552 /// @param s scalar to divide the vector by.
553 /// @return Vector containing the result.
554 /// @related Vector
555 template <class T, int d>
556 inline Vector<T, d> operator/(const Vector<T, d>& v, const T& s) {
557  MATHFU_VECTOR_OPERATOR(v.data_[i] / s);
558 }
559 
560 /// @brief Add a scalar to each element of a Vector.
561 ///
562 /// @param s scalar to add to each element of a Vector.
563 /// @param v Vector to add the scalar to.
564 /// @return Vector containing the result.
565 /// @related Vector
566 template <class T, int d>
567 inline Vector<T, d> operator+(const T& s, const Vector<T, d>& v) {
568  MATHFU_VECTOR_OPERATOR(v.data_[i] + s);
569 }
570 
571 /// @brief Subtract a scalar from each element of a Vector.
572 ///
573 /// @param s scalar to subtract from each element of a Vector.
574 /// @param v Vector to subtract the scalar from.
575 /// @return Vector containing the result.
576 /// @related Vector
577 template <class T, int d>
578 inline Vector<T, d> operator-(const T& s, const Vector<T, d>& v) {
579  MATHFU_VECTOR_OPERATOR(v.data_[i] - s);
580 }
581 
582 /// @brief Multiply a vector by another Vector.
583 ///
584 /// In line with GLSL, this performs component-wise multiplication.
585 /// @param lhs First vector to use as a starting point.
586 /// @param rhs Second vector to multiply by.
587 /// @return A new Vector containing the result.
588 template <class T, int d>
590  const Vector<T, d>& rhs) {
591  return HadamardProductHelper(lhs, rhs);
592 }
593 
594 /// @brief Divide a vector by another Vector.
595 ///
596 /// In line with GLSL, this performs component-wise division.
597 /// @param lhs First vector to use as a starting point.
598 /// @param rhs Second vector to divide by.
599 /// @return A new Vector containing the result.
600 template <class T, int d>
602  const Vector<T, d>& rhs) {
603  MATHFU_VECTOR_OPERATOR(lhs.data_[i] / rhs[i]);
604 }
605 
606 /// @brief Add a vector with another Vector.
607 ///
608 /// @param lhs First vector to use as a starting point.
609 /// @param rhs Second vector to add by.
610 /// @return A new vector containing the result.
611 template <class T, int d>
613  const Vector<T, d>& rhs) {
614  MATHFU_VECTOR_OPERATOR(lhs.data_[i] + rhs[i]);
615 }
616 
617 /// @brief subtract a vector with another Vector.
618 ///
619 /// @param lhs First vector to use as a starting point.
620 /// @param rhs Second vector to subtract by.
621 /// @return A new vector containing the result.
622 template <class T, int d>
624  const Vector<T, d>& rhs) {
625  MATHFU_VECTOR_OPERATOR(lhs.data_[i] - rhs[i]);
626 }
627 
628 /// @brief Multiply a vector with a scalar.
629 ///
630 /// @param v Vector for the operation.
631 /// @param s A scalar to multiply the vector with.
632 /// @return A new vector containing the result.
633 template <class T, int d>
634 inline Vector<T, d> operator*(const Vector<T, d>& v, const T& s) {
635  MATHFU_VECTOR_OPERATOR(v.data_[i] * s);
636 }
637 
638 /// @brief Add a scalar to all elements of a vector.
639 ///
640 /// @param v Vector for the operation.
641 /// @param s A scalar to add to the vector.
642 /// @return A new vector containing the result.
643 template <class T, int d>
644 inline Vector<T, d> operator+(const Vector<T, d>& v, const T& s) {
645  MATHFU_VECTOR_OPERATOR(v.data_[i] + s);
646 }
647 
648 /// @brief Subtract a scalar from all elements of a vector.
649 ///
650 /// @param v Vector for the operation.
651 /// @param s A scalar to subtract from a vector.
652 /// @return A new vector that stores the result.
653 template <class T, int d>
654 inline Vector<T, d> operator-(const Vector<T, d>& v, const T& s) {
655  MATHFU_VECTOR_OPERATOR(v.data_[i] - s);
656 }
657 
658 /// @brief Multiply (in-place) a vector with another Vector.
659 ///
660 /// In line with GLSL, this performs component-wise multiplication.
661 /// @param lhs First vector to use as a starting point.
662 /// @param rhs Second vector to multiply by.
663 /// @return A reference to the input <b>v</b> vector.
664 template <class T, int d>
666  MATHFU_VECTOR_OPERATION(lhs.data_[i] *= rhs[i]);
667  return lhs;
668 }
669 
670 /// @brief Divide (in-place) a vector by another Vector.
671 ///
672 /// In line with GLSL, this performs component-wise division.
673 /// @param lhs First vector to use as a starting point.
674 /// @param rhs Second vector to divide by.
675 /// @return A reference to the input <b>v</b> vector.
676 template <class T, int d>
678  MATHFU_VECTOR_OPERATION(lhs.data_[i] /= rhs[i]);
679  return lhs;
680 }
681 
682 /// @brief Add (in-place) a vector with another Vector.
683 ///
684 /// @param lhs First vector to use as a starting point.
685 /// @param rhs Second vector to add.
686 /// @return A reference to the input <b>v</b> vector.
687 template <class T, int d>
689  MATHFU_VECTOR_OPERATION(lhs.data_[i] += rhs[i]);
690  return lhs;
691 }
692 
693 /// @brief Subtract (in-place) another Vector from a vector.
694 ///
695 /// @param lhs First vector to use as a starting point.
696 /// @param rhs Second vector to subtract by.
697 /// @return A reference to the input <b>v</b> vector.
698 template <class T, int d>
700  MATHFU_VECTOR_OPERATION(lhs.data_[i] -= rhs[i]);
701  return lhs;
702 }
703 
704 /// @brief Multiply (in-place) each element of a vector with a scalar.
705 ///
706 /// @param v Vector for the operation.
707 /// @param s A scalar to multiply the vector with.
708 /// @return A reference to the input <b>v</b> vector.
709 template <class T, int d>
710 inline Vector<T, d>& operator*=(Vector<T, d>& v, const T& s) {
711  MATHFU_VECTOR_OPERATION(v.data_[i] *= s);
712  return v;
713 }
714 
715 /// @brief Divide (in-place) each element of a vector by a scalar.
716 ///
717 /// @param v Vector for the operation.
718 /// @param s A scalar to divide the vector by.
719 /// @return A reference to the input <b>v</b> vector.
720 template <class T, int d>
721 inline Vector<T, d>& operator/=(Vector<T, d>& v, const T& s) {
722  MATHFU_VECTOR_OPERATION(v.data_[i] /= s);
723  return v;
724 }
725 
726 /// @brief Add (in-place) a scalar to each element of a vector.
727 ///
728 /// @param v Vector for the operation.
729 /// @param s A scalar to add the vector to.
730 /// @return A reference to the input <b>v</b> vector.
731 template <class T, int d>
732 inline Vector<T, d>& operator+=(Vector<T, d>& v, const T& s) {
733  MATHFU_VECTOR_OPERATION(v.data_[i] += s);
734  return v;
735 }
736 
737 /// @brief Subtract (in-place) a scalar from each element of a vector.
738 ///
739 /// @param v Vector for the operation.
740 /// @param s A scalar to subtract from the vector.
741 /// @return A reference to the input <b>v</b> vector.
742 template <class T, int d>
743 inline Vector<T, d>& operator-=(Vector<T, d>& v, const T& s) {
744  MATHFU_VECTOR_OPERATION(v.data_[i] -= s);
745  return v;
746 }
747 
748 /// @brief Calculate the hadamard or componentwise product of two vectors.
749 ///
750 /// @param v1 First vector.
751 /// @param v2 Second vector.
752 /// @return The hadamard product of v1 and v2.
753 template <class T, int d>
755  const Vector<T, d>& v2) {
756  MATHFU_VECTOR_OPERATOR(v1[i] * v2[i]);
757 }
758 
759 /// @brief Calculate the cross product of two vectors.
760 ///
761 /// Note that this function is only defined for 3-dimensional Vectors.
762 /// @param v1 First vector.
763 /// @param v2 Second vector.
764 /// @return The cross product of v1 and v2.
765 template <class T>
767  const Vector<T, 3>& v2) {
768  return Vector<T, 3>(v1[1] * v2[2] - v1[2] * v2[1],
769  v1[2] * v2[0] - v1[0] * v2[2],
770  v1[0] * v2[1] - v1[1] * v2[0]);
771 }
772 
773 /// @brief Calculate the squared length of a vector.
774 ///
775 /// @param v Vector to get the squared length of.
776 /// @return The length of the vector squared.
777 template <class T, int d>
778 inline T LengthSquaredHelper(const Vector<T, d>& v) {
779  return DotProductHelper(v, v);
780 }
781 
782 /// @brief Calculate the length of a vector.
783 ///
784 /// @param v Vector to get the squared length of.
785 /// @return The length of the vector.
786 template <class T, int d>
787 inline T LengthHelper(const Vector<T, d>& v) {
788  return sqrt(LengthSquaredHelper(v));
789 }
790 
791 /// @brief Normalize a vector in-place.
792 ///
793 /// @param v Vector to get the squared length of.
794 /// @return The length of the vector.
795 template <class T, int d>
797  const T length = LengthHelper(v);
798  v *= (T(1) / length);
799  return length;
800 }
801 
802 /// @brief Calculate the normalized version of a vector.
803 ///
804 /// @param v Vector to get the squared length of.
805 /// @return The normalized vector.
806 template <class T, int d>
808  return v * (T(1) / LengthHelper(v));
809 }
810 
811 /// @brief Linearly interpolate two vectors.
812 ///
813 /// @param v1 First vector.
814 /// @param v2 Second vector.
815 /// @param percent Percentage from v1 to v2 in range 0.0...1.0.
816 /// @return The hadamard product of v1 and v2.
817 template <class T, int d>
818 inline Vector<T, d> LerpHelper(const Vector<T, d>& v1, const Vector<T, d>& v2,
819  const T percent) {
820  const T one_minus_percent = static_cast<T>(1.0) - percent;
821  MATHFU_VECTOR_OPERATOR(one_minus_percent * v1[i] + percent * v2[i]);
822 }
823 
824 /// @brief Generates a random vector.
825 ///
826 /// The range of each component is bounded by min and max.
827 /// @param min Minimum value of the vector.
828 /// @param max Maximum value of the vector.
829 template <class T, int d>
831  const Vector<T, d>& max) {
832  Vector<T, d> result;
833  MATHFU_VECTOR_OPERATION(result[i] = mathfu::RandomInRange<T>(min[i], max[i]));
834  return result;
835 }
836 
837 /// @brief Compare each component and returns max values.
838 ///
839 /// @param v1 First vector.
840 /// @param v2 Second vector.
841 /// @return Max value of v1 and v2.
842 template <class T, int d>
843 inline Vector<T, d> MaxHelper(const Vector<T, d>& v1, const Vector<T, d>& v2) {
844  Vector<T, d> result;
845  MATHFU_VECTOR_OPERATION(result[i] = std::max(v1[i], v2[i]));
846  return result;
847 }
848 
849 /// @brief Compare each component and returns min values.
850 ///
851 /// @param v1 First vector.
852 /// @param v2 Second vector.
853 /// @return Min value of v1 and v2.
854 template <class T, int d>
855 inline Vector<T, d> MinHelper(const Vector<T, d>& v1, const Vector<T, d>& v2) {
856  Vector<T, d> result;
857  MATHFU_VECTOR_OPERATION(result[i] = std::min(v1[i], v2[i]));
858  return result;
859 }
860 
861 /// @brief Check if val is within [range_start..range_end), denoting a
862 /// rectangular area.
863 ///
864 /// @param val 2D vector to be tested.
865 /// @param range_start Starting point of the range (inclusive).
866 /// @param range_end Ending point of the range (non-inclusive).
867 /// @return Bool indicating success.
868 ///
869 /// @tparam T Type of vector components to test.
870 template <class T>
872  const mathfu::Vector<T, 2>& range_start,
873  const mathfu::Vector<T, 2>& range_end) {
874  return InRange(val[0], range_start[0], range_end[0]) &&
875  InRange(val[1], range_start[1], range_end[1]);
876 }
877 
878 /// @cond MATHFU_INTERNAL
879 /// @brief Calculate the dot product of two vectors.
880 ///
881 /// @param v1 First vector.
882 /// @param v2 Second vector.
883 /// @return The dot product of v1 and v2.
884 /// @related Vector
885 template <class T, int d>
886 static inline T DotProductHelper(const Vector<T, d>& v1,
887  const Vector<T, d>& v2) {
888  T result = 0;
889  MATHFU_VECTOR_OPERATION(result += v1[i] * v2[i]);
890  return result;
891 }
892 /// @endcond
893 
894 /// @cond MATHFU_INTERNAL
895 template <class T>
896 static inline T DotProductHelper(const Vector<T, 2>& v1,
897  const Vector<T, 2>& v2) {
898  return v1[0] * v2[0] + v1[1] * v2[1];
899 }
900 /// @endcond
901 
902 /// @cond MATHFU_INTERNAL
903 template <class T>
904 static inline T DotProductHelper(const Vector<T, 3>& v1,
905  const Vector<T, 3>& v2) {
906  return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
907 }
908 /// @endcond
909 
910 /// @cond MATHFU_INTERNAL
911 template <class T>
912 static inline T DotProductHelper(const Vector<T, 4>& v1,
913  const Vector<T, 4>& v2) {
914  return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2] + v1[3] * v2[3];
915 }
916 /// @endcond
917 
918 /// @cond MATHFU_INTERNAL
919 template <typename T, int d, typename CompatibleT>
920 static inline Vector<T, d> FromTypeHelper(const CompatibleT& compatible) {
921 // C++11 is required for constructed unions.
922 #if __cplusplus >= 201103L
923  // Use a union instead of reinterpret_cast to avoid aliasing bugs.
924  union ConversionUnion {
925  ConversionUnion() {} // C++11.
926  CompatibleT compatible;
927  VectorPacked<T, d> packed;
928  } u;
929  static_assert(sizeof(u.compatible) == d * sizeof(T),
930  "Conversion size mismatch.");
931 
932  // The read of `compatible` and write to `u.compatible` gets optimized away,
933  // and this becomes essentially a safe reinterpret_cast.
934  u.compatible = compatible;
935 
936  // Call the packed vector constructor with the `compatible` data.
937  return Vector<T, d>(u.packed);
938 #else
939  // Use the less-desirable memcpy technique if C++11 is not available.
940  // Most compilers understand memcpy deep enough to avoid replace the function
941  // call with a series of load/stores, which should then get optimized away,
942  // however in the worst case the optimize away may not happen.
943  // Note: Memcpy avoids aliasing bugs because it operates via unsigned char*,
944  // which is allowed to alias any type.
945  // See:
946  // http://stackoverflow.com/questions/15745030/type-punning-with-void-without-breaking-the-strict-aliasing-rule-in-c99
947  Vector<T, d> v;
948  assert(sizeof(compatible) == d * sizeof(T));
949  memcpy(&v, &compatible, sizeof(compatible));
950  return v;
951 #endif // __cplusplus >= 201103L
952 }
953 /// @endcond
954 
955 /// @cond MATHFU_INTERNAL
956 template <typename T, int d, typename CompatibleT>
957 static inline CompatibleT ToTypeHelper(const Vector<T, d>& v) {
958 // See FromTypeHelper() for comments.
959 #if __cplusplus >= 201103L
960  union ConversionUnion {
961  ConversionUnion() {}
962  CompatibleT compatible;
963  VectorPacked<T, d> packed;
964  } u;
965  static_assert(sizeof(u.compatible) == d * sizeof(T), "Conversion size mismatch.");
966  v.Pack(&u.packed);
967  return u.compatible;
968 #else
969  CompatibleT compatible;
970  assert(sizeof(compatible) == d * sizeof(T));
971  memcpy(&compatible, &v, sizeof(compatible));
972  return compatible;
973 #endif // __cplusplus >= 201103L
974 }
975 /// @endcond
976 
977 /// @}
978 
979 /// @addtogroup mathfu_utilities
980 /// @{
981 
982 /// @brief Specialized version of RoundUpToPowerOf2 for vector.
983 template <typename T, int d>
985  Vector<T, d> ret;
986  MATHFU_VECTOR_OPERATION(ret(i) = RoundUpToPowerOf2(v(i)));
987  return ret;
988 }
989 /// @}
990 
991 } // namespace mathfu
992 
993 // Include the specializations to avoid template errors.
994 // For example, if you include vector.h, use Vector<float, 3>, and then
995 // include vector_3.h, you the compiler will generate an error since you're
996 // specializing something that has already been instantiated.
1000 
1001 #if defined(_MSC_VER)
1002 #pragma warning(pop)
1003 #elif defined(__clang__)
1004 #pragma clang diagnostic pop
1005 #endif
1006 
1007 #endif // MATHFU_VECTOR_H_
Vector< T, d > & operator*=(Vector< T, d > &lhs, const Vector< T, d > &rhs)
Multiply (in-place) a vector with another Vector.
Definition: vector.h:665
Definition: vector_3.h:24
T LengthHelper(const Vector< T, d > &v)
Calculate the length of a vector.
Definition: vector.h:787
Vector(const Vector< T, 2 > &v12, const T &s3)
Create a vector from a 2 component vector and a third value.
Definition: vector.h:229
T LengthSquared() const
Calculate the squared length of this vector.
Definition: vector.h:380
T RoundUpToPowerOf2(T x)
Round a value up to the nearest power of 2.
Definition: utilities.h:425
const Vector< T, 3 > xyz() const
GLSL style 3 element accessor.
Definition: vector.h:329
VectorPacked & operator=(const Vector< T, d > &vector)
Definition: vector.h:136
Vector of d elements with type T.
Definition: vector.h:63
Definition: vector_2.h:24
static Vector< T, d > Min(const Vector< T, d > &v1, const Vector< T, d > &v2)
Compare each component and returns min values.
Definition: vector.h:487
T & operator[](const int i)
Access an element of the vector.
Definition: vector.h:306
Utility macros and functions.
T Length() const
Calculate the length of this vector.
Definition: vector.h:385
#define MATHFU_DEFINE_CLASS_SIMD_AWARE_NEW_DELETE
Macro which defines the new and delete for MathFu classes.
Definition: utilities.h:600
VectorPacked()
Create an uninitialized VectorPacked.
Definition: vector.h:123
Vector< T, d > NormalizedHelper(const Vector< T, d > &v)
Calculate the normalized version of a vector.
Definition: vector.h:807
Vector(const T &s1, const T &s2)
Create a vector from two values.
Definition: vector.h:203
static Vector< T, d > Max(const Vector< T, d > &v1, const Vector< T, d > &v2)
Compare each component and returns max values.
Definition: vector.h:477
Vector< T, d > & operator+=(Vector< T, d > &lhs, const Vector< T, d > &rhs)
Add (in-place) a vector with another Vector.
Definition: vector.h:688
MATHFU_DEFINE_CLASS_SIMD_AWARE_NEW_DELETE T data_[d]
Elements of the vector.
Definition: vector.h:495
Vector(const Vector< T, 3 > &vector3, const T &value)
Create a 4-dimensional vector from a Vector<T, 3>.
Definition: vector.h:259
Vector< T, d > MinHelper(const Vector< T, d > &v1, const Vector< T, d > &v2)
Compare each component and returns min values.
Definition: vector.h:855
#define MATHFU_STATIC_ASSERT(x)
Compile time assert for pre-C++11 compilers.
Definition: utilities.h:244
T Normalize()
Normalize this vector in-place.
Definition: vector.h:390
Vector< T, d > operator+(const Vector< T, d > &lhs, const Vector< T, d > &rhs)
Add a vector with another Vector.
Definition: vector.h:612
Vector< T, d > operator/(const Vector< T, d > &v, const T &s)
Divide a Vector by a scalar.
Definition: vector.h:556
Vector< T, d > & operator-=(Vector< T, d > &lhs, const Vector< T, d > &rhs)
Subtract (in-place) another Vector from a vector.
Definition: vector.h:699
Vector(const Vector< T, d > &v)
Create a vector from another vector copying each element.
Definition: vector.h:168
Vector< T, d > operator*(const Vector< T, d > &lhs, const Vector< T, d > &rhs)
Multiply a vector by another Vector.
Definition: vector.h:589
static Vector< T, d > HadamardProduct(const Vector< T, d > &v1, const Vector< T, d > &v2)
Calculate the hadamard or componentwise product of two vectors.
Definition: vector.h:435
static CompatibleT ToType(const Vector< T, d > &v)
Load into any type that is some formulation of a length d array of type T.
Definition: vector.h:417
bool InRange2D(const mathfu::Vector< T, 2 > &val, const mathfu::Vector< T, 2 > &range_start, const mathfu::Vector< T, 2 > &range_end)
Check if val is within [range_start..range_end), denoting a rectangular area.
Definition: vector.h:871
Vector< T, 3 > CrossProductHelper(const Vector< T, 3 > &v1, const Vector< T, 3 > &v2)
Calculate the cross product of two vectors.
Definition: vector.h:766
Vector< T, 2 > zw()
GLSL style 2 element accessor.
Definition: vector.h:356
Vector(const T &s)
Create a vector from a single float.
Definition: vector.h:188
T LengthSquaredHelper(const Vector< T, d > &v)
Calculate the squared length of a vector.
Definition: vector.h:778
Definition: vector_4.h:25
Vector< T, d > HadamardProductHelper(const Vector< T, d > &v1, const Vector< T, d > &v2)
Calculate the hadamard or componentwise product of two vectors.
Definition: vector.h:754
const Vector< T, 2 > xy() const
GLSL style 2 element accessor.
Definition: vector.h:347
Vector(const T &s1, const T &s2, const T &s3, const T &s4)
Create a vector from four values.
Definition: vector.h:244
Vector< T, d > operator*(const T &s, const Vector< T, d > &v)
Multiply a Vector by a scalar.
Definition: vector.h:543
Vector< T, 2 > xy()
GLSL style 2 element accessor.
Definition: vector.h:338
Vector(const T &s1, const T &s2, const T &s3)
Create a vector from three values.
Definition: vector.h:216
T data[d]
Elements of the packed vector one per dimension.
Definition: vector.h:142
Vector< T, d > Normalized() const
Calculate the normalized version of this vector.
Definition: vector.h:395
static T DotProduct(const Vector< T, d > &v1, const Vector< T, d > &v2)
Calculate the dot product of two vectors.
Definition: vector.h:426
const T & operator()(const int i) const
Access an element of the vector.
Definition: vector.h:299
bool InRange(T val, T range_start, T range_end)
Check if val is within [range_start..range_end).
Definition: utilities.h:343
Vector(const Vector< T, 2 > &v12, const Vector< T, 2 > &v34)
Create a vector from two 2 component vectors.
Definition: vector.h:273
Vector< T, d > operator+(const T &s, const Vector< T, d > &v)
Add a scalar to each element of a Vector.
Definition: vector.h:567
Vector< T, d > operator-(const Vector< T, d > &v)
Negate all elements of the Vector.
Definition: vector.h:530
Vector(const T *a)
Create a vector form the first d elements of an array.
Definition: vector.h:193
3-dimensional specialization of mathfu::Vector for SIMD optimized builds.
Vector< T, d > RandomInRangeHelper(const Vector< T, d > &min, const Vector< T, d > &max)
Generates a random vector.
Definition: vector.h:830
Vector< T, d > operator/(const Vector< T, d > &lhs, const Vector< T, d > &rhs)
Divide a vector by another Vector.
Definition: vector.h:601
Packed N-dimensional vector.
Definition: vector.h:121
void Pack(VectorPacked< T, d > *const vector) const
Pack a Vector to a packed "d" element vector structure.
Definition: vector.h:373
4-dimensional specialization of mathfu::Vector for SIMD optimized builds.
static Vector< T, d > RandomInRange(const Vector< T, d > &min, const Vector< T, d > &max)
Generates a random vector.
Definition: vector.h:467
VectorPacked(const Vector< T, d > &vector)
Definition: vector.h:129
T & operator()(const int i)
Access an element of the vector.
Definition: vector.h:293
const Vector< T, 2 > zw() const
GLSL style 2 element accessor.
Definition: vector.h:365
static Vector< T, d > Lerp(const Vector< T, d > &v1, const Vector< T, d > &v2, const T percent)
Linearly interpolate two vectors.
Definition: vector.h:457
T NormalizeHelper(Vector< T, d > &v)
Normalize a vector in-place.
Definition: vector.h:796
bool operator==(const Rect< T > &r1, const Rect< T > &r2)
Check if two rects are identical.
Definition: rect.h:67
static Vector< T, 3 > CrossProduct(const Vector< T, 3 > &v1, const Vector< T, 3 > &v2)
Calculate the cross product of two vectors.
Definition: vector.h:446
2-dimensional specialization of mathfu::Vector for SIMD optimized builds.
const T & operator[](const int i) const
Access an element of the vector.
Definition: vector.h:312
Vector()
Create an uninitialized Vector.
Definition: vector.h:163
Vector(const Vector< U, d > &v)
Create a vector from another vector of a different type.
Definition: vector.h:180
Vector(const VectorPacked< T, d > &vector)
Create a vector from packed vector (VectorPacked).
Definition: vector.h:284
Vector< T, d > operator-(const T &s, const Vector< T, d > &v)
Subtract a scalar from each element of a Vector.
Definition: vector.h:578
Vector< T, d > MaxHelper(const Vector< T, d > &v1, const Vector< T, d > &v2)
Compare each component and returns max values.
Definition: vector.h:843
Vector< T, d > & operator/=(Vector< T, d > &lhs, const Vector< T, d > &rhs)
Divide (in-place) a vector by another Vector.
Definition: vector.h:677
Vector< T, 3 > xyz()
GLSL style 3 element accessor.
Definition: vector.h:319
bool operator!=(const Rect< T > &r1, const Rect< T > &r2)
Check if two rects are not identical.
Definition: rect.h:76
static Vector< T, d > FromType(const CompatibleT &compatible)
Load from any type that is some formulation of a length d array of type T.
Definition: vector.h:405
Vector< T, d > LerpHelper(const Vector< T, d > &v1, const Vector< T, d > &v2, const T percent)
Linearly interpolate two vectors.
Definition: vector.h:818
T Scalar
Element type to enable reference by other classes.
Definition: vector.h:160