Voxel
 All Classes Namespaces Files Functions Typedefs Enumerations Enumerator Macros Pages
vector.h
Go to the documentation of this file.
1 #pragma once
2 
3 #ifndef VECTOR_H
4 #define VECTOR_H
5 
6 
7 /**
8  \file
9  \brief Contains Vector class.
10 
11  In addition to the Vector class itself, this file also defines a large
12  number of operators and functions acting on vectors.
13 */
14 
15 
16 
17 
18 #include "helpers.h"
19 
20 #include <iostream>
21 #include <algorithm>
22 #include <cmath>
23 #include <type_traits>
24 
25 #include <assert.h>
26 
27 
28 
29 
30 /*==============================================================================
31  RESULT_TYPE macro
32 ==============================================================================*/
33 
34 /// \brief Finds the type of \p ee, and removes reference, const and volatile.
35 #define RESULT_TYPE( ee ) typename std::decay< decltype( ee ) >::type
36 
37 
38 
39 
40 /*==============================================================================
41  Vector class
42 ==============================================================================*/
43 
44 
45 /// \brief Generates code for the assignment operator \p op (=,+=,*=,etc) taking a Vector argument.
46 #define VECTOR_VECTOR_ASSIGNMENT_OPERATOR( op ) \
47  template< typename t_OtherType > \
48  inline Vector const& operator op ( Vector< t_OtherType, t_Size > const& other ) { \
49  for ( size_t ii = 0; ii < t_Size; ++ii ) \
50  data[ ii ] op other.data[ ii ]; \
51  return *this; \
52  }
53 
54 /// \brief Generates code for the assignment operator \p op (=,+=,*=,etc) taking a scalar argument.
55 #define VECTOR_SCALAR_ASSIGNMENT_OPERATOR( op ) \
56  template< typename t_OtherType > \
57  inline Vector const& operator op ( t_OtherType const& other ) { \
58  for ( size_t ii = 0; ii < t_Size; ++ii ) \
59  data[ ii ] op other; \
60  return *this; \
61  }
62 
63 
64 /**
65  \brief Vector class.
66 
67  \param t_Type Type of elements.
68  \param t_Size Number of elements.
69 
70  This class is an awful lot like \c std::array, with the main difference
71  being that, for Vectors, a large number of operators and functions are also
72  defined. Like \c std::array, it supports aggregate initialization, meaning
73  that you can initialize a Vector as:
74 
75  Vector< float, 3 > vector = { { 1, 0, -1 } };
76 
77  Every C++ operator is overloaded, including the bitwise operators, *except*
78  for the pre/post increment/decrement operators \c ++ and \c \-\-.
79  Comparisons are lexicographic, like \c std::array, which enables instances
80  of this class to be used in standard containers (although one could make a
81  case for vector comparisons returning vector results, with the comparison
82  being performed element-by-element). Also, many standard math functions
83  have Vector overloads, including everything relevant in the cmath header,
84  \c std::min and \c std::max, and the \c Square and \c Cube functions found
85  in helpers.h. Adding new function overloads is pretty simple: see
86  VECTOR_FUNCTION() and the related macros.
87 
88  The operators and functions which work on this class try to follow the same
89  automatic casting rules as the underlying operations. For example, if you
90  add a <tt>Vector< float, 3 ></tt> to a <tt>Vector< int, 3 ></tt>, the
91  result will be a <tt>Vector< float, 3 ></tt>, with the result type being
92  determined from that of *scalar* addition of a float and an int (using \c
93  decltype).
94 */
95 template< typename t_Type, size_t t_Size >
96 struct Vector {
97 
98  typedef t_Type value_type;
99 
100 
101  inline t_Type& operator[]( size_t const index );
102  inline t_Type const& operator[]( size_t const index ) const;
103 
104 
105  inline Vector const& operator=( Vector const& other );
106 
107 
108  // **TODO: pre/post increment/decrement?
109 
111 
122 
133 
134 
135  inline t_Type Sum() const; ///< Returns the sum of all elements.
136  inline t_Type Product() const; ///< Returns the product of all elements.
137  inline t_Type Maximum() const; ///< Returns the maximum element.
138  inline t_Type Minimum() const; ///< Returns the minimum element.
139 
140  /// Returns the sum of the squares of the elements.
141  inline t_Type NormSquared() const;
142 
143  /// Returns the 2-norm of the vector (the square root of the sum of the squares of the elements).
144  inline RESULT_TYPE( std::sqrt( *static_cast< t_Type const* >( NULL ) ) ) Norm() const; // as of gcc 4.6.3, we can't put decltype( NormSquared() ) in a trailing return type (auto ... -> result) because it doesn't know about "this"
145 
146 
147  t_Type data[ t_Size ];
148 };
149 
150 
151 #undef VECTOR_VECTOR_ASSIGNMENT_OPERATOR
152 #undef VECTOR_SCALAR_ASSIGNMENT_OPERATOR
153 
154 
155 
156 
157 /*==============================================================================
158  Vector methods
159 ==============================================================================*/
160 
161 
162 template< typename t_Type, size_t t_Size >
163 t_Type& Vector< t_Type, t_Size >::operator[]( size_t const index ) {
164 
165  assert( index < t_Size );
166  return data[ index ];
167 }
168 
169 
170 template< typename t_Type, size_t t_Size >
171 t_Type const& Vector< t_Type, t_Size >::operator[]( size_t const index ) const {
172 
173  assert( index < t_Size );
174  return data[ index ];
175 }
176 
177 
178 template< typename t_Type, size_t t_Size >
180 
181  for ( size_t ii = 0; ii < t_Size; ++ii )
182  data[ ii ] = other.data[ ii ];
183  return *this;
184 }
185 
186 
187 template< typename t_Type, size_t t_Size >
189 
190  t_Type result = 0;
191  for ( size_t ii = 0; ii < t_Size; ++ii )
192  result += data[ ii ];
193  return result;
194 }
195 
196 
197 template< typename t_Type, size_t t_Size >
199 
200  t_Type result = 1;
201  for ( size_t ii = 0; ii < t_Size; ++ii )
202  result *= data[ ii ];
203  return result;
204 }
205 
206 
207 template< typename t_Type, size_t t_Size >
209 
210  static_assert( t_Size > 0, "cannot find Maximum of an empty vector!" );
211  t_Type result = data[ 0 ];
212  for ( size_t ii = 1; ii < t_Size; ++ii )
213  if ( data[ ii ] > result )
214  result = data[ ii ];
215  return result;
216 }
217 
218 
219 template< typename t_Type, size_t t_Size >
221 
222  static_assert( t_Size > 0, "cannot find Minimum of an empty vector!" );
223  t_Type result = data[ 0 ];
224  for ( size_t ii = 1; ii < t_Size; ++ii )
225  if ( data[ ii ] < result )
226  result = data[ ii ];
227  return result;
228 }
229 
230 
231 template< typename t_Type, size_t t_Size >
233 
234  t_Type result = 0;
235  for ( size_t ii = 0; ii < t_Size; ++ii )
236  result += Square( data[ ii ] );
237  return result;
238 }
239 
240 
241 template< typename t_Type, size_t t_Size >
242 RESULT_TYPE( std::sqrt( *static_cast< t_Type const* >( NULL ) ) ) Vector< t_Type, t_Size >::Norm() const {
243 
244  return std::sqrt( NormSquared() );
245 }
246 
247 
248 
249 
250 /*==============================================================================
251  Vector functions
252 ==============================================================================*/
253 
254 
255 /// Compares its arguments lexicographically, returning -1 if \p left is smaller than \p right, 1 if it is larger, and 0 if they are equal.
256 template< typename t_LeftType, typename t_RightType, size_t t_Size >
257 inline int Compare( Vector< t_LeftType, t_Size > const& left, Vector< t_RightType, t_Size > const& right ) { // like std::array, comparisons are lexicographic
258 
259  int result = 0;
260  for ( size_t ii = 0; ii < t_Size; ++ii ) {
261 
262  if ( left.data[ ii ] < right.data[ ii ] ) {
263 
264  result = -1;
265  break;
266  }
267  else if ( left.data[ ii ] > right[ ii ] ) {
268 
269  result = 1;
270  break;
271  }
272  }
273  return result;
274 }
275 
276 
277 /// Returns the dot product of its arguments.
278 template< typename t_LeftType, typename t_RightType, size_t t_Size >
279 inline auto Dot( Vector< t_LeftType, t_Size > const& left, Vector< t_RightType, t_Size > const& right ) -> RESULT_TYPE( left.data[ 0 ] * right.data[ 0 ] ) {
280 
281  RESULT_TYPE( left.data[ 0 ] * right.data[ 0 ] ) result = 0;
282  for ( size_t ii = 0; ii < t_Size; ++ii )
283  result += left.data[ ii ] * right.data[ ii ];
284  return result;
285 }
286 
287 
288 /// Returns the cross product of its (3D) arguments.
289 template< typename t_LeftType, typename t_RightType >
290 inline auto Cross( Vector< t_LeftType, 3 > const& left, Vector< t_RightType, 3 > const& right ) -> Vector< RESULT_TYPE( left.data[ 0 ] * right.data[ 0 ] ), 3 > {
291 
292  Vector< RESULT_TYPE( left.data[ 0 ] * right.data[ 0 ] ), 3 > result = { {
293  left.data[ 1 ] * right.data[ 2 ] - left.data[ 2 ] * right.data[ 1 ],
294  left.data[ 2 ] * right.data[ 0 ] - left.data[ 0 ] * right.data[ 2 ],
295  left.data[ 0 ] * right.data[ 1 ] - left.data[ 1 ] * right.data[ 0 ]
296  } };
297  return result;
298 }
299 
300 
301 /// Outputs the vector contents (as text) to the given stream.
302 template< typename t_Type, size_t t_Size >
303 inline std::ostream& operator<<( std::ostream& out, Vector< t_Type, t_Size > const& vector ) {
304 
305  out << '[';
306  if ( t_Size > 0 ) {
307 
308  out << vector.data[ 0 ];
309  for ( size_t ii = 1; ii < t_Size; ++ii )
310  out << ',' << vector.data[ ii ];
311  }
312  out << ']';
313 
314  return out;
315 }
316 
317 
318 
319 
320 /*==============================================================================
321  Vector macro'ed operators
322 ==============================================================================*/
323 
324 
325 /// \brief Generates code for the unary operator \p op (-,~).
326 #define VECTOR_OPERATOR( op ) \
327  template< typename t_Type, size_t t_Size > \
328  inline Vector< t_Type, t_Size > operator op ( Vector< t_Type, t_Size > const& vector ) { \
329  Vector< t_Type, t_Size > result; \
330  for ( size_t ii = 0; ii < t_Size; ++ii ) \
331  result.data[ ii ] = ( op vector.data[ ii ] ); \
332  return result; \
333  }
334 
335 /// \brief Generates code for the binary operator \p op (+,*,<<,etc) taking two Vector arguments.
336 #define VECTOR_VECTOR_OPERATOR( op ) \
337  template< typename t_LeftType, typename t_RightType, size_t t_Size > \
338  inline auto operator op ( Vector< t_LeftType, t_Size > const& left, Vector< t_RightType, t_Size > const& right ) -> Vector< RESULT_TYPE( left.data[ 0 ] op right.data[ 0 ] ), t_Size > { \
339  Vector< RESULT_TYPE( left.data[ 0 ] op right.data[ 0 ] ), t_Size > result; \
340  for ( size_t ii = 0; ii < t_Size; ++ii ) \
341  result.data[ ii ] = ( left.data[ ii ] op right.data[ ii ] ); \
342  return result; \
343  }
344 
345 /// \brief Generates code for the binary operator \p op (+,*,<<,etc) taking a Vector argument on the left, and scalar on the right.
346 #define VECTOR_SCALAR_OPERATOR( op ) \
347  template< typename t_LeftType, typename t_RightType, size_t t_Size > \
348  inline auto operator op ( Vector< t_LeftType, t_Size > const& left, t_RightType const& right ) -> Vector< RESULT_TYPE( left.data[ 0 ] op right ), t_Size > { \
349  Vector< RESULT_TYPE( left.data[ 0 ] op right ), t_Size > result; \
350  for ( size_t ii = 0; ii < t_Size; ++ii ) \
351  result.data[ ii ] = ( left.data[ ii ] op right ); \
352  return result; \
353  }
354 
355 /// \brief Generates code for the binary operator \p op (+,*,<<,etc) taking a scalar argument on the left, and Vector on the right.
356 #define SCALAR_VECTOR_OPERATOR( op ) \
357  template< typename t_LeftType, typename t_RightType, size_t t_Size > \
358  inline auto operator op ( t_LeftType const& left, Vector< t_RightType, t_Size > const& right ) -> Vector< RESULT_TYPE( left op right.data[ 0 ] ), t_Size > { \
359  Vector< RESULT_TYPE( left op right.data[ 0 ] ), t_Size > result; \
360  for ( size_t ii = 0; ii < t_Size; ++ii ) \
361  result.data[ ii ] = ( left op right.data[ ii ] ); \
362  return result; \
363  }
364 
365 /// \brief Generates code for the binary comparison operator \p op (==,<,etc) taking two Vector arguments. The resulting code simply calls the Compare() function, which orders lexicographically.
366 #define VECTOR_COMPARISON_OPERATOR( op ) \
367  template< typename t_LeftType, typename t_RightType, size_t t_Size > \
368  inline bool operator op ( Vector< t_LeftType, t_Size > const& left, Vector< t_RightType, t_Size > const& right ) { \
369  return( Compare( left, right ) op 0 ); \
370  }
371 
372 
373 VECTOR_OPERATOR( - )
374 VECTOR_OPERATOR( ~ )
375 
386 
397 
408 
415 
416 
417 #undef VECTOR_VECTOR_OPERATOR
418 #undef VECTOR_SCALAR_OPERATOR
419 #undef SCALAR_VECTOR_OPERATOR
420 #undef VECTOR_COMPARISON_OPERATOR
421 
422 
423 
424 
425 /*==============================================================================
426  Vector macro'ed functions
427 ==============================================================================*/
428 
429 
430 /// \brief Generates code for the unary function \p fun taking a Vector argument. The resulting code simply calls the scalar version of \p fun for each element.
431 #define VECTOR_FUNCTION( fun ) \
432  template< typename t_Type, size_t t_Size > \
433  inline auto fun( Vector< t_Type, t_Size > const& vector ) -> Vector< RESULT_TYPE( fun( vector.data[ 0 ] ) ), t_Size > { \
434  Vector< RESULT_TYPE( fun( vector.data[ 0 ] ) ), t_Size > result; \
435  for ( size_t ii = 0; ii < t_Size; ++ii ) \
436  result.data[ ii ] = fun( vector.data[ ii ] ); \
437  return result; \
438  }
439 
440 /// \brief Generates code for the binary function \p fun taking two Vector arguments. The resulting code simply calls the scalar version of \p fun for each element.
441 #define VECTOR_VECTOR_FUNCTION( fun ) \
442  template< typename t_LeftType, typename t_RightType, size_t t_Size > \
443  inline auto fun( Vector< t_LeftType, t_Size > const& left, Vector< t_RightType, t_Size > const& right ) -> Vector< RESULT_TYPE( fun( left.data[ 0 ], right.data[ 0 ] ) ), t_Size > { \
444  Vector< RESULT_TYPE( fun( left.data[ 0 ], right.data[ 0 ] ) ), t_Size > result; \
445  for ( size_t ii = 0; ii < t_Size; ++ii ) \
446  result.data[ ii ] = fun( left.data[ ii ], right.data[ ii ] ); \
447  return result; \
448  }
449 
450 /// \brief Generates code for the binary function \p fun taking a Vector argument on the left, and scalar on the right. The resulting code simply calls the scalar version of \p fun for each element.
451 #define VECTOR_SCALAR_FUNCTION( fun ) \
452  template< typename t_LeftType, typename t_RightType, size_t t_Size > \
453  inline auto fun( Vector< t_LeftType, t_Size > const& left, t_RightType const& right ) -> Vector< RESULT_TYPE( fun( left.data[ 0 ], right ) ), t_Size > { \
454  Vector< RESULT_TYPE( fun( left.data[ 0 ], right ) ), t_Size > result; \
455  for ( size_t ii = 0; ii < t_Size; ++ii ) \
456  result.data[ ii ] = fun( left.data[ ii ], right ); \
457  return result; \
458  }
459 
460 /// \brief Generates code for the binary function \p fun taking a scalar argument on the left, and Vector on the right. The resulting code simply calls the scalar version of \p fun for each element.
461 #define SCALAR_VECTOR_FUNCTION( fun ) \
462  template< typename t_LeftType, typename t_RightType, size_t t_Size > \
463  inline auto fun( t_LeftType const& left, Vector< t_RightType, t_Size > const& right ) -> Vector< RESULT_TYPE( fun( left, right.data[ 0 ] ) ), t_Size > { \
464  Vector< RESULT_TYPE( fun( left, right.data[ 0 ] ) ), t_Size > result; \
465  for ( size_t ii = 0; ii < t_Size; ++ii ) \
466  result.data[ ii ] = fun( left, right.data[ ii ] ); \
467  return result; \
468  }
469 
470 
473 
474 namespace std {
475 
476 VECTOR_FUNCTION( abs )
477 VECTOR_FUNCTION( acos )
478 VECTOR_FUNCTION( asin )
479 VECTOR_FUNCTION( atan )
480 VECTOR_FUNCTION( ceil )
481 VECTOR_FUNCTION( cos )
482 VECTOR_FUNCTION( cosh )
483 VECTOR_FUNCTION( exp )
484 VECTOR_FUNCTION( fabs )
485 VECTOR_FUNCTION( floor )
486 VECTOR_FUNCTION( log )
487 VECTOR_FUNCTION( log10 )
488 VECTOR_FUNCTION( sin )
489 VECTOR_FUNCTION( sinh )
490 VECTOR_FUNCTION( sqrt )
491 VECTOR_FUNCTION( tan )
492 VECTOR_FUNCTION( tanh )
493 
494 VECTOR_VECTOR_FUNCTION( atan2 )
496 VECTOR_VECTOR_FUNCTION( ldexp )
500 
501 VECTOR_SCALAR_FUNCTION( atan2 )
503 VECTOR_SCALAR_FUNCTION( ldexp )
507 
508 SCALAR_VECTOR_FUNCTION( atan2 )
510 SCALAR_VECTOR_FUNCTION( ldexp )
514 
515 } // namespace std
516 
517 
518 #undef VECTOR_FUNCTION
519 #undef VECTOR_VECTOR_FUNCTION
520 #undef VECTOR_SCALAR_FUNCTION
521 #undef SCALAR_VECTOR_FUNCTION
522 
523 
524 
525 
526 /*==============================================================================
527  RESULT_TYPE macro
528 ==============================================================================*/
529 
530 #undef RESULT_TYPE
531 
532 
533 
534 
535 #endif // VECTOR_H