MathFu
An open source project by FPL.
 All Classes Namespaces Files Functions Variables Typedefs Friends Groups Pages
vector_3_simd.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_3_SIMD_H_
17 #define MATHFU_VECTOR_3_SIMD_H_
18 
19 #include "mathfu/internal/vector_3.h"
20 #include "mathfu/utilities.h"
21 
22 #include <math.h>
23 
24 #ifdef MATHFU_COMPILE_WITH_SIMD
25 #include "vectorial/simd4f.h"
26 #endif
27 
28 /// @file mathfu/internal/vector_3_simd.h MathFu Vector<T, 3> Specialization
29 /// @brief 3-dimensional specialization of mathfu::Vector for SIMD optimized
30 /// builds.
31 /// @see mathfu::Vector
32 
33 /// @cond MATHFU_INTERNAL
34 /// Add macros to account for both the case where the vector is stored as a
35 /// simd intrinsic using 4 elements or as 3 values of type T.
36 /// MATHFU_VECTOR3_STORE3/MATHFU_VECTOR3_LOAD3 are additional operations used
37 /// to load/store the non simd values from and to simd datatypes. If intrinsics
38 /// are used these amount to essentially noops. MATHFU_VECTOR3_INIT3 either
39 /// creates a simd datatype if the intrinsic is used or sets the T values if
40 /// not.
41 #ifdef MATHFU_COMPILE_WITH_PADDING
42 #define MATHFU_VECTOR3_STORE3(simd_to_store, data) \
43  { (data).simd = simd_to_store; }
44 #define MATHFU_VECTOR3_LOAD3(data) (data).simd
45 #define MATHFU_VECTOR3_INIT3(data, v1, v2, v3) \
46  { (data).simd = simd4f_create(v1, v2, v3, 0); }
47 #else
48 #define MATHFU_VECTOR3_STORE3(simd_to_store, data) \
49  { simd4f_ustore3(simd_to_store, (data).data_); }
50 #define MATHFU_VECTOR3_LOAD3(data) simd4f_uload3((data).data_)
51 #define MATHFU_VECTOR3_INIT3(data, v1, v2, v3) \
52  { \
53  (data).data_[0] = v1; \
54  (data).data_[1] = v2; \
55  (data).data_[2] = v3; \
56  }
57 #endif // MATHFU_COMPILE_WITH_PADDING
58 /// @endcond
59 
60 namespace mathfu {
61 
62 #ifdef MATHFU_COMPILE_WITH_SIMD
63 /// @cond MATHFU_INTERNAL
64 // This class should remain plain old data.
65 template <>
66 class Vector<float, 3> {
67  public:
68  typedef float Scalar;
69 
70  inline Vector() {}
71 
72  inline Vector(const Vector<float, 3>& v) {
73 #ifdef MATHFU_COMPILE_WITH_PADDING
74  simd = v.simd;
75 #else
76  MATHFU_VECTOR3_INIT3(*this, v[0], v[1], v[2]);
77 #endif // MATHFU_COMPILE_WITH_PADDING
78  }
79 
80  explicit inline Vector(const Vector<int, 3>& v) {
81  MATHFU_VECTOR3_INIT3(*this, static_cast<float>(v[0]),
82  static_cast<float>(v[1]), static_cast<float>(v[2]));
83  }
84 
85  inline Vector(const simd4f& v) { MATHFU_VECTOR3_STORE3(v, *this); }
86 
87  explicit inline Vector(const float& s) {
88  MATHFU_VECTOR3_INIT3(*this, s, s, s);
89  }
90 
91  inline Vector(const float& v1, const float& v2, const float& v3) {
92  MATHFU_VECTOR3_INIT3(*this, v1, v2, v3);
93  }
94 
95  inline Vector(const Vector<float, 2>& v12, const float& v3) {
96  MATHFU_VECTOR3_INIT3(*this, v12[0], v12[1], v3);
97  }
98 
99  explicit inline Vector(const float* v) {
100 #ifdef MATHFU_COMPILE_WITH_PADDING
101  simd = simd4f_uload3(v);
102 #else
103  MATHFU_VECTOR3_INIT3(*this, v[0], v[1], v[2]);
104 #endif // MATHFU_COMPILE_WITH_PADDING
105  }
106 
107  explicit inline Vector(const VectorPacked<float, 3>& vector) {
108 #ifdef MATHFU_COMPILE_WITH_PADDING
109  simd = simd4f_uload3(vector.data);
110 #else
111  MATHFU_VECTOR3_INIT3(*this, vector.data[0], vector.data[1], vector.data[2]);
112 #endif // MATHFU_COMPILE_WITH_PADDING
113  }
114 
115  inline float& operator()(const int i) { return data_[i]; }
116 
117  inline const float& operator()(const int i) const { return data_[i]; }
118 
119  inline float& operator[](const int i) { return data_[i]; }
120 
121  inline const float& operator[](const int i) const { return data_[i]; }
122 
123  /// GLSL style multi-component accessors.
124  inline Vector<float, 2> xy() { return Vector<float, 2>(x, y); }
125  inline const Vector<float, 2> xy() const { return Vector<float, 2>(x, y); }
126 
127  inline void Pack(VectorPacked<float, 3>* const vector) const {
128 #ifdef MATHFU_COMPILE_WITH_PADDING
129  simd4f_ustore3(simd, vector->data);
130 #else
131  vector->data[0] = data_[0];
132  vector->data[1] = data_[1];
133  vector->data[2] = data_[2];
134 #endif // MATHFU_COMPILE_WITH_PADDING
135  }
136 
137  inline Vector<float, 3> operator-() const {
138  return Vector<float, 3>(
139  simd4f_sub(simd4f_zero(), MATHFU_VECTOR3_LOAD3(*this)));
140  }
141 
142  inline Vector<float, 3> operator*(const Vector<float, 3>& v) const {
143  return Vector<float, 3>(
144  simd4f_mul(MATHFU_VECTOR3_LOAD3(*this), MATHFU_VECTOR3_LOAD3(v)));
145  }
146 
147  inline Vector<float, 3> operator/(const Vector<float, 3>& v) const {
148  return Vector<float, 3>(
149  simd4f_div(MATHFU_VECTOR3_LOAD3(*this), MATHFU_VECTOR3_LOAD3(v)));
150  }
151 
152  inline Vector<float, 3> operator+(const Vector<float, 3>& v) const {
153  return Vector<float, 3>(
154  simd4f_add(MATHFU_VECTOR3_LOAD3(*this), MATHFU_VECTOR3_LOAD3(v)));
155  }
156 
157  inline Vector<float, 3> operator-(const Vector<float, 3>& v) const {
158  return Vector<float, 3>(
159  simd4f_sub(MATHFU_VECTOR3_LOAD3(*this), MATHFU_VECTOR3_LOAD3(v)));
160  }
161 
162  inline Vector<float, 3> operator*(const float& s) const {
163  return Vector<float, 3>(
164  simd4f_mul(MATHFU_VECTOR3_LOAD3(*this), simd4f_splat(s)));
165  }
166 
167  inline Vector<float, 3> operator/(const float& s) const {
168  return Vector<float, 3>(
169  simd4f_div(MATHFU_VECTOR3_LOAD3(*this), simd4f_splat(s)));
170  }
171 
172  inline Vector<float, 3> operator+(const float& s) const {
173  return Vector<float, 3>(
174  simd4f_add(MATHFU_VECTOR3_LOAD3(*this), simd4f_splat(s)));
175  }
176 
177  inline Vector<float, 3> operator-(const float& s) const {
178  return Vector<float, 3>(
179  simd4f_sub(MATHFU_VECTOR3_LOAD3(*this), simd4f_splat(s)));
180  }
181 
182  inline Vector<float, 3>& operator*=(const Vector<float, 3>& v) {
183  *this = simd4f_mul(MATHFU_VECTOR3_LOAD3(*this), MATHFU_VECTOR3_LOAD3(v));
184  return *this;
185  }
186 
187  inline Vector<float, 3>& operator/=(const Vector<float, 3>& v) {
188  *this = simd4f_div(MATHFU_VECTOR3_LOAD3(*this), MATHFU_VECTOR3_LOAD3(v));
189  return *this;
190  }
191 
192  inline Vector<float, 3>& operator+=(const Vector<float, 3>& v) {
193  *this = simd4f_add(MATHFU_VECTOR3_LOAD3(*this), MATHFU_VECTOR3_LOAD3(v));
194  return *this;
195  }
196 
197  inline Vector<float, 3>& operator-=(const Vector<float, 3>& v) {
198  *this = simd4f_sub(MATHFU_VECTOR3_LOAD3(*this), MATHFU_VECTOR3_LOAD3(v));
199  return *this;
200  }
201 
202  inline Vector<float, 3>& operator*=(const float& s) {
203  *this = simd4f_mul(MATHFU_VECTOR3_LOAD3(*this), simd4f_splat(s));
204  return *this;
205  }
206 
207  inline Vector<float, 3>& operator/=(const float& s) {
208  *this = simd4f_div(MATHFU_VECTOR3_LOAD3(*this), simd4f_splat(s));
209  return *this;
210  }
211 
212  inline Vector<float, 3>& operator+=(const float& s) {
213  *this = simd4f_add(MATHFU_VECTOR3_LOAD3(*this), simd4f_splat(s));
214  return *this;
215  }
216 
217  inline Vector<float, 3>& operator-=(const float& s) {
218  *this = simd4f_sub(MATHFU_VECTOR3_LOAD3(*this), simd4f_splat(s));
219  return *this;
220  }
221 
222  inline bool operator==(const Vector<float, 3>& v) const {
223  for (int i = 0; i < 3; ++i) {
224  if ((*this)[i] != v[i]) return false;
225  }
226  return true;
227  }
228 
229  inline bool operator!=(const Vector<float, 3>& v) const {
230  return !operator==(v);
231  }
232 
233  inline float LengthSquared() const {
234  return simd4f_dot3_scalar(MATHFU_VECTOR3_LOAD3(*this),
235  MATHFU_VECTOR3_LOAD3(*this));
236  }
237 
238  inline float Length() const {
239  return simd4f_get_x(simd4f_length3(MATHFU_VECTOR3_LOAD3(*this)));
240  }
241 
242  inline float Normalize() {
243  const float length = Length();
244  *this = simd4f_mul(MATHFU_VECTOR3_LOAD3(*this), simd4f_splat(1 / length));
245  return length;
246  }
247 
248  inline Vector<float, 3> Normalized() const {
249  return Vector<float, 3>(simd4f_normalize3(MATHFU_VECTOR3_LOAD3(*this)));
250  }
251 
252  template <typename CompatibleT>
253  static inline Vector<float, 3> FromType(const CompatibleT& compatible) {
254  return FromTypeHelper<float, 3, CompatibleT>(compatible);
255  }
256 
257  template <typename CompatibleT>
258  static inline CompatibleT ToType(const Vector<float, 3>& v) {
259  return ToTypeHelper<float, 3, CompatibleT>(v);
260  }
261 
262  static inline float DotProduct(const Vector<float, 3>& v1,
263  const Vector<float, 3>& v2) {
264  return simd4f_dot3_scalar(MATHFU_VECTOR3_LOAD3(v1),
265  MATHFU_VECTOR3_LOAD3(v2));
266  }
267 
268  static inline Vector<float, 3> CrossProduct(const Vector<float, 3>& v1,
269  const Vector<float, 3>& v2) {
270  return Vector<float, 3>(
271  simd4f_cross3(MATHFU_VECTOR3_LOAD3(v1), MATHFU_VECTOR3_LOAD3(v2)));
272  }
273 
274  static inline Vector<float, 3> HadamardProduct(const Vector<float, 3>& v1,
275  const Vector<float, 3>& v2) {
276  return Vector<float, 3>(
277  simd4f_mul(MATHFU_VECTOR3_LOAD3(v1), MATHFU_VECTOR3_LOAD3(v2)));
278  }
279 
280  static inline Vector<float, 3> Lerp(const Vector<float, 3>& v1,
281  const Vector<float, 3>& v2,
282  float percent) {
283  const Vector<float, 3> percentv(percent);
284  const Vector<float, 3> one(1.0f);
285  const Vector<float, 3> one_minus_percent = one - percentv;
286  return Vector<float, 3>(simd4f_add(
287  simd4f_mul(MATHFU_VECTOR3_LOAD3(one_minus_percent),
288  MATHFU_VECTOR3_LOAD3(v1)),
289  simd4f_mul(MATHFU_VECTOR3_LOAD3(percentv), MATHFU_VECTOR3_LOAD3(v2))));
290  }
291 
292  /// Generates a random vector, where the range for each component is
293  /// bounded by min and max.
294  static inline Vector<float, 3> RandomInRange(const Vector<float, 3>& min,
295  const Vector<float, 3>& max) {
296  return Vector<float, 3>(mathfu::RandomInRange<float>(min[0], max[0]),
297  mathfu::RandomInRange<float>(min[1], max[1]),
298  mathfu::RandomInRange<float>(min[2], max[2]));
299  }
300 
301  static inline Vector<float, 3> Max(const Vector<float, 3>& v1,
302  const Vector<float, 3>& v2) {
303 #ifdef MATHFU_COMPILE_WITH_PADDING
304  return Vector<float, 3>(
305  simd4f_max(MATHFU_VECTOR3_LOAD3(v1), MATHFU_VECTOR3_LOAD3(v2)));
306 #else
307  return Vector<float, 3>(std::max(v1[0], v2[0]), std::max(v1[1], v2[1]),
308  std::max(v1[2], v2[2]));
309 #endif // MATHFU_COMPILE_WITH_PADDING
310  }
311 
312  static inline Vector<float, 3> Min(const Vector<float, 3>& v1,
313  const Vector<float, 3>& v2) {
314 #ifdef MATHFU_COMPILE_WITH_PADDING
315  return Vector<float, 3>(
316  simd4f_min(MATHFU_VECTOR3_LOAD3(v1), MATHFU_VECTOR3_LOAD3(v2)));
317 #else
318  return Vector<float, 3>(std::min(v1[0], v2[0]), std::min(v1[1], v2[1]),
319  std::min(v1[2], v2[2]));
320 #endif // MATHFU_COMPILE_WITH_PADDING
321  }
322 
323  template <class T, int rows, int cols>
324  friend class Matrix;
325  template <class T, int d>
326  friend class Vector;
327 
329 
330 #include "mathfu/internal/disable_warnings_begin.h"
331  union {
332 #ifdef MATHFU_COMPILE_WITH_PADDING
333  simd4f simd;
334  float data_[4];
335 #else
336  float data_[3];
337 #endif // MATHFU_COMPILE_WITH_PADDING
338 
339  struct {
340  float x;
341  float y;
342  float z;
343  };
344  };
345 #include "mathfu/internal/disable_warnings_end.h"
346 };
347 /// @endcond
348 #endif // MATHFU_COMPILE_WITH_SIMD
349 
350 } // namespace mathfu
351 
352 #endif // MATHFU_VECTOR_3_SIMD_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
T LengthSquared() const
Calculate the squared length of this vector.
Definition: vector.h:380
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
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
T Normalize()
Normalize this vector in-place.
Definition: vector.h:390
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
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
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< 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
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
void Pack(VectorPacked< T, d > *const vector) const
Pack a Vector to a packed "d" element vector structure.
Definition: vector.h:373
static Vector< T, d > RandomInRange(const Vector< T, d > &min, const Vector< T, d > &max)
Generates a random vector.
Definition: vector.h:467
T & operator()(const int i)
Access an element of the vector.
Definition: vector.h:293
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
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
Vector()
Create an uninitialized Vector.
Definition: vector.h:163
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 > & operator/=(Vector< T, d > &lhs, const Vector< T, d > &rhs)
Divide (in-place) a vector by another Vector.
Definition: vector.h:677
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
T Scalar
Element type to enable reference by other classes.
Definition: vector.h:160