vector4-inl.h
1 // Copyright 2003 Google, Inc.
2 // All Rights Reserved.
3 //
4 //
5 // A simple class to handle vectors in 4D
6 // The aim of this class is to be able to manipulate vectors in 4D
7 // as naturally as possible and make calculations readable.
8 // For that reason, the operators +, -, * are overloaded.
9 // (Reading a = a + b*2 - c is much easier to read than
10 // a = Sub(Add(a, Mul(b,2)),c) )
11 // The code generated using this vector class is easily optimized by
12 // the compiler and does not generate overhead compared to manually
13 // writing the operations component by component
14 // (e.g a.x = b.x + c.x; a.y = b.y + c.y...)
15 //
16 // Operator overload is not usually allowed, but in this case an
17 // exemption has been granted by the C++ style committee.
18 //
19 // Please be careful about overflows when using those vectors with integer types
20 // The calculations are carried with the same type as the vector's components
21 // type. eg : if you are using uint8 as the base type, all values will be modulo
22 // 256.
23 // This feature is necessary to use the class in a more general framework with
24 // VType != plain old data type.
25 
26 #ifndef UTIL_MATH_VECTOR4_INL_H__
27 #define UTIL_MATH_VECTOR4_INL_H__
28 
29 #include "util/math/vector4.h"
30 
31 #include <algorithm>
32 using std::min;
33 using std::max;
34 using std::swap;
35 using std::reverse;
36 
37 #include <math.h>
38 #include "base/integral_types.h"
39 
40 #include "base/type_traits.h"
41 #include "util/math/mathutil.h"
42 #include "util/math/vector2.h"
43 #include "util/math/vector3.h"
44 
45 template <typename VType>
47  Clear();
48 }
49 
50 template <typename VType>
51 Vector4<VType>::Vector4(const VType x, const VType y, const VType z,
52  const VType w) {
53  c_[0] = x;
54  c_[1] = y;
55  c_[2] = z;
56  c_[3] = w;
57 }
58 
59 template <typename VType>
60 Vector4<VType>::Vector4(const Self &vb) {
61  c_[0] = vb.c_[0];
62  c_[1] = vb.c_[1];
63  c_[2] = vb.c_[2];
64  c_[3] = vb.c_[3];
65 }
66 
67 template <typename VType>
68 Vector4<VType>::Vector4(const Vector2<VType> &vb, const VType z,
69  const VType w) {
70  c_[0] = vb.x();
71  c_[1] = vb.y();
72  c_[2] = z;
73  c_[3] = w;
74 }
75 
76 template <typename VType>
78  c_[0] = vb1.x();
79  c_[1] = vb1.y();
80  c_[2] = vb2.x();
81  c_[3] = vb2.y();
82 }
83 
84 template <typename VType>
85 Vector4<VType>::Vector4(const Vector3<VType> &vb, const VType w) {
86  c_[0] = vb.x();
87  c_[1] = vb.y();
88  c_[2] = vb.z();
89  c_[3] = w;
90 }
91 
92 template <typename VType> template <typename VType2>
94  return Self(static_cast<VType>(vb[0]),
95  static_cast<VType>(vb[1]),
96  static_cast<VType>(vb[2]),
97  static_cast<VType>(vb[3]));
98 }
99 
100 template <typename VType>
101 bool Vector4<VType>::operator==(const Self& vb) const {
102  return (c_[0] == vb.c_[0])
103  && (c_[1] == vb.c_[1])
104  && (c_[2] == vb.c_[2])
105  && (c_[3] == vb.c_[3]);
106 }
107 
108 template <typename VType>
109 bool Vector4<VType>::operator!=(const Self& vb) const {
110  return (c_[0] != vb.c_[0])
111  || (c_[1] != vb.c_[1])
112  || (c_[2] != vb.c_[2])
113  || (c_[3] != vb.c_[3]);
114 }
115 
116 template <typename VType>
117 bool Vector4<VType>::aequal(const Self &vb, FloatType margin) const {
118  return (fabs(c_[0] - vb.c_[0]) < margin)
119  && (fabs(c_[1] - vb.c_[1]) < margin)
120  && (fabs(c_[2] - vb.c_[2]) < margin)
121  && (fabs(c_[3] - vb.c_[3]) < margin);
122 }
123 
124 template <typename VType>
125 bool Vector4<VType>::operator<(const Self &vb) const {
126  if ( c_[0] < vb.c_[0] ) return true;
127  if ( vb.c_[0] < c_[0] ) return false;
128  if ( c_[1] < vb.c_[1] ) return true;
129  if ( vb.c_[1] < c_[1] ) return false;
130  if ( c_[2] < vb.c_[2] ) return true;
131  if ( vb.c_[2] < c_[2] ) return false;
132  if ( c_[3] < vb.c_[3] ) return true;
133  return false;
134 }
135 
136 template <typename VType>
137 bool Vector4<VType>::operator>(const Self &vb) const {
138  return vb.operator<(*this);
139 }
140 
141 template <typename VType>
142 bool Vector4<VType>::operator<=(const Self &vb) const {
143  return !operator>(vb);
144 }
145 
146 template <typename VType>
147 bool Vector4<VType>::operator>=(const Self &vb) const {
148  return !operator<(vb);
149 }
150 
151 template <typename VType>
152 void Vector4<VType>::Set(const VType x, const VType y, const VType z,
153  const VType w) {
154  c_[0] = x;
155  c_[1] = y;
156  c_[2] = z;
157  c_[3] = w;
158 }
159 
160 template <typename VType>
161 Vector4<VType>& Vector4<VType>::operator=(const Self& vb) {
162  c_[0] = vb.c_[0];
163  c_[1] = vb.c_[1];
164  c_[2] = vb.c_[2];
165  c_[3] = vb.c_[3];
166  return (*this);
167 }
168 
169 template <typename VType>
171  c_[0] += vb.c_[0];
172  c_[1] += vb.c_[1];
173  c_[2] += vb.c_[2];
174  c_[3] += vb.c_[3];
175  return (*this);
176 }
177 
178 template <typename VType>
180  c_[0] -= vb.c_[0];
181  c_[1] -= vb.c_[1];
182  c_[2] -= vb.c_[2];
183  c_[3] -= vb.c_[3];
184  return (*this);
185 }
186 
187 template <typename VType>
189  c_[0] *= k;
190  c_[1] *= k;
191  c_[2] *= k;
192  c_[3] *= k;
193  return (*this);
194 }
195 
196 template <typename VType>
198  c_[0] /= k;
199  c_[1] /= k;
200  c_[2] /= k;
201  c_[3] /= k;
202  return (*this);
203 }
204 
205 template <typename VType>
206 Vector4<VType> Vector4<VType>::MulComponents(const Self &vb) const {
207  return Self(c_[0] * vb.c_[0], c_[1] * vb.c_[1],
208  c_[2] * vb.c_[2], c_[3] * vb.c_[3]);
209 }
210 
211 template <typename VType>
212 Vector4<VType> Vector4<VType>::DivComponents(const Self &vb) const {
213  return Self(c_[0] / vb.c_[0], c_[1] / vb.c_[1],
214  c_[2] / vb.c_[2], c_[3] / vb.c_[3]);
215 }
216 
217 template <typename VType>
218 Vector4<VType> Vector4<VType>::operator+(const Self &vb) const {
219  return Self(*this) += vb;
220 }
221 
222 template <typename VType>
223 Vector4<VType> Vector4<VType>::operator-(const Self &vb) const {
224  return Self(*this) -= vb;
225 }
226 
227 template <typename VType>
228 VType Vector4<VType>::DotProd(const Self &vb) const {
229  return c_[0]*vb.c_[0] + c_[1]*vb.c_[1] + c_[2]*vb.c_[2] + c_[3]*vb.c_[3];
230 }
231 
232 template <typename VType>
233 Vector4<VType> Vector4<VType>::operator*(const VType k) const {
234  return Self(*this) *= k;
235 }
236 
237 template <typename VType>
238 Vector4<VType> Vector4<VType>::operator/(const VType k) const {
239  return Self(*this) /= k;
240 }
241 
242 template <typename VType>
243 VType& Vector4<VType>::operator[](const int b) {
244  DCHECK(b >=0);
245  DCHECK(b <=3);
246  return c_[b];
247 }
248 
249 template <typename VType>
250 VType Vector4<VType>::operator[](const int b) const {
251  DCHECK(b >=0);
252  DCHECK(b <=3);
253  return c_[b];
254 }
255 
256 template <typename VType>
257 void Vector4<VType>::x(const VType &v) {
258  c_[0] = v;
259 }
260 
261 template <typename VType>
262 VType Vector4<VType>::x() const {
263  return c_[0];
264 }
265 
266 template <typename VType>
267 void Vector4<VType>::y(const VType &v) {
268  c_[1] = v;
269 }
270 
271 template <typename VType>
272 VType Vector4<VType>::y() const {
273  return c_[1];
274 }
275 
276 template <typename VType>
277 void Vector4<VType>::z(const VType &v) {
278  c_[2] = v;
279 }
280 
281 template <typename VType>
282 VType Vector4<VType>::z() const {
283  return c_[2];
284 }
285 
286 template <typename VType>
287 void Vector4<VType>::w(const VType &v) {
288  c_[3] = v;
289 }
290 
291 template <typename VType>
292 VType Vector4<VType>::w() const {
293  return c_[3];
294 }
295 
296 template <typename VType>
297 VType* Vector4<VType>::Data() {
298  return reinterpret_cast<VType*>(c_);
299 }
300 
301 template <typename VType>
302 const VType* Vector4<VType>::Data() const {
303  return reinterpret_cast<const VType*>(c_);
304 }
305 
306 template <typename VType>
307 VType Vector4<VType>::Norm2(void) const {
308  return c_[0]*c_[0] + c_[1]*c_[1] + c_[2]*c_[2] + c_[3]*c_[3];
309 }
310 
311 template <typename VType>
312 typename Vector4<VType>::FloatType Vector4<VType>::Norm(void) const {
313  return sqrt(Norm2());
314 }
315 
316 template <typename VType>
318  COMPILE_ASSERT(!base::is_integral<VType>::value, must_be_floating_point);
319  VType n = Norm();
320  if (n != 0) {
321  n = 1.0 / n;
322  }
323  return Self(*this) *= n;
324 }
325 
326 template <typename VType>
328  return Self(sqrt(c_[0]), sqrt(c_[1]), sqrt(c_[2]), sqrt(c_[3]));
329 }
330 
331 template <typename VType>
333  return Self(fabs(c_[0]), fabs(c_[1]), fabs(c_[2]), fabs(c_[3]));
334 }
335 
336 template <typename VType>
338  COMPILE_ASSERT(base::is_integral<VType>::value, use_Fabs_for_float_types);
339  COMPILE_ASSERT(static_cast<VType>(-1) == -1, type_must_be_signed);
340  COMPILE_ASSERT(sizeof(VType) <= sizeof(int), Abs_truncates_to_int);
341  return Self(abs(c_[0]), abs(c_[1]), abs(c_[2]), abs(c_[3]));
342 }
343 
344 template <typename VType>
346  return Self(floor(c_[0]),
347  floor(c_[1]),
348  floor(c_[2]),
349  floor(c_[3]));
350 }
351 
352 template <typename VType>
354  return Self(ceil(c_[0]), ceil(c_[1]), ceil(c_[2]), ceil(c_[3]));
355 }
356 
357 template <typename VType>
359  return Self(rint(c_[0]), rint(c_[1]),
360  rint(c_[2]), rint(c_[3]));
361 }
362 
363 template <typename VType>
365  return Vector4<int>(lrint(c_[0]), lrint(c_[1]),
366  lrint(c_[2]), lrint(c_[3]));
367 }
368 
369 template <typename VType>
370 void Vector4<VType>::Clear() {
371  c_[3] = c_[2] = c_[1] = c_[0] = VType();
372 }
373 
374 template <typename VType>
375 bool Vector4<VType>::IsNaN() const {
376  return isnan(c_[0]) || isnan(c_[1]) || isnan(c_[2]) || isnan(c_[3]);
377 }
378 
379 template <typename VType>
381  return Self(MathUtil::NaN(), MathUtil::NaN(),
382  MathUtil::NaN(), MathUtil::NaN());
383 }
384 
385 template <typename VType>
386 Vector4<VType> operator-(const Vector4<VType> &vb) {
387  return Vector4<VType>( -vb[0], -vb[1], -vb[2], -vb[3]);
388 }
389 
390 template <typename ScalarType, typename VType>
391 Vector4<VType> operator*(const ScalarType k, const Vector4<VType> &v) {
392  return Vector4<VType>(k*v[0], k*v[1], k*v[2], k*v[3]);
393 }
394 
395 template <typename ScalarType, typename VType>
396 Vector4<VType> operator/(const ScalarType k, const Vector4<VType> &v) {
397  return Vector4<VType>(k/v[0], k/v[1], k/v[2], k/v[3]);
398 }
399 
400 template <typename VType>
401 Vector4<VType> Max(const Vector4<VType> &v1, const Vector4<VType> &v2) {
402  return Vector4<VType>(max(v1[0], v2[0]),
403  max(v1[1], v2[1]),
404  max(v1[2], v2[2]),
405  max(v1[3], v2[3]));
406 }
407 
408 template <typename VType>
409 Vector4<VType> Min(const Vector4<VType> &v1, const Vector4<VType> &v2) {
410  return Vector4<VType>(min(v1[0], v2[0]),
411  min(v1[1], v2[1]),
412  min(v1[2], v2[2]),
413  min(v1[3], v2[3]));
414 }
415 
416 template <typename VType>
417 std::ostream &operator <<(std::ostream &out, const Vector4<VType> &va) {
418  out << "["
419  << va[0] << ", "
420  << va[1] << ", "
421  << va[2] << ", "
422  << va[3] << "]";
423  return out;
424 }
425 
426 // TODO(user): Vector4<T> does not actually satisfy the definition of a POD
427 // type even when T is a POD. Pretending that Vector4<T> is a POD probably
428 // won't cause any immediate problems, but eventually this should be fixed.
429 PROPAGATE_POD_FROM_TEMPLATE_ARGUMENT(Vector4);
430 
431 #endif // UTIL_MATH_VECTOR4_INL_H__