vmmlib  1.10.0
Templatized C++ vector and matrix math library
vector.hpp
1 /*
2  * Copyright (c) 2006-2016, Visualization and Multimedia Lab,
3  * University of Zurich <http://vmml.ifi.uzh.ch>,
4  * Eyescale Software GmbH,
5  * Blue Brain Project, EPFL
6  *
7  * This file is part of VMMLib <https://github.com/VMML/vmmlib/>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * Redistributions of source code must retain the above copyright notice, this
13  * list of conditions and the following disclaimer. Redistributions in binary
14  * form must reproduce the above copyright notice, this list of conditions and
15  * the following disclaimer in the documentation and/or other materials provided
16  * with the distribution. Neither the name of the Visualization and Multimedia
17  * Lab, University of Zurich nor the names of its contributors may be used to
18  * endorse or promote products derived from this software without specific prior
19  * written permission.
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #ifndef __VMML__VECTOR__HPP__
34 #define __VMML__VECTOR__HPP__
35 
36 #include <vmmlib/math.hpp>
37 #include <vmmlib/enable_if.hpp>
38 
39 #include <algorithm>
40 #include <cstring>
41 #include <iomanip>
42 #include <iostream>
43 #include <limits>
44 #include <stdexcept>
45 #include <stdint.h>
46 #include <string>
47 #include <vector>
48 
49 namespace vmml
50 {
51 template< size_t M, typename T > class vector
52 {
53 public:
54  typedef T value_type;
55  typedef T* iterator;
56  typedef const T* const_iterator;
57  typedef std::reverse_iterator< iterator > reverse_iterator;
58  typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
59 
60  static const size_t DIMENSION = M;
61 
62  // constructors
63  vector() : array() {} // http://stackoverflow.com/questions/5602030
64  explicit vector( const T& a ); // sets all components to a;
65  vector( const T& x, const T& y );
66  vector( const T& x, const T& y, const T& z );
67  vector( const T& x, const T& y, const T& z, const T& w );
68 
69 #ifndef SWIG
70  // initializes the first M-1 values from vector_, the last from last_
71  vector( const vector< M-1, T >& vector_, T last_ );
72 #endif
73 
74  vector( const T* values );
75 
76 #ifdef __OSG_MATH
77  template< typename OSGVEC3 >
78  explicit vector( const OSGVEC3& from,
79  typename enable_if< M == 3, OSGVEC3 >::type* = 0 );
80 #endif
81 
82  // vec< M > with homogeneous coordinates <-> vec< M-1 > conversion ctor
83  // to-homogenous-coordinates ctor
84  template< size_t N >
85  vector( const vector< N, T >& source_,
86  typename enable_if< N == M - 1 >::type* = 0 );
87 
88  // from-homogenous-coordinates vector
89  template< size_t N >
90  vector( const vector< N, T >& source_,
91  typename enable_if< N == M + 1 >::type* = 0 );
92 
93  template< typename U > vector( const vector< M, U >& source_ );
94 
95  // iterators
96  inline iterator begin();
97  inline iterator end();
98  inline const_iterator begin() const;
99  inline const_iterator end() const;
100  inline reverse_iterator rbegin();
101  inline reverse_iterator rend();
102  inline const_reverse_iterator rbegin() const;
103  inline const_reverse_iterator rend() const;
104 
105 # ifndef VMMLIB_NO_CONVERSION_OPERATORS
106  // conversion operators
107  inline operator T*();
108  inline operator const T*() const;
109 # else
110  inline T& operator[]( size_t index );
111  inline const T& operator[]( size_t index ) const;
112 # endif
113 
114  // accessors
115  inline T& operator()( size_t index );
116  inline const T& operator()( size_t index ) const;
117 
118  inline T& at( size_t index );
119  inline const T& at( size_t index ) const;
120 
121  // element accessors for M <= 4;
122  inline T& x();
123  inline T& y();
124  inline T& z();
125  inline T& w();
126  inline const T& x() const;
127  inline const T& y() const;
128  inline const T& z() const;
129  inline const T& w() const;
130 
131  // pixel color element accessors for M<= 4
132  inline T& r();
133  inline T& g();
134  inline T& b();
135  inline T& a();
136  inline const T& r() const;
137  inline const T& g() const;
138  inline const T& b() const;
139  inline const T& a() const;
140 
141  bool operator==( const vector& other ) const;
142  bool operator!=( const vector& other ) const;
143  bool equals( const vector& other,
144  T tolerance = std::numeric_limits< T >::epsilon( )) const;
145  bool operator<( const vector& other ) const;
146 
147  // remember kids: c_arrays are dangerous and evil!
148  vector& operator=( const T* c_array );
149  T operator=( T filler );
150 
151  vector& operator=( const vector& other );
152 
153  // returns void to avoid 'silent' loss of precision when chaining
154  template< typename U > void operator=( const vector< M, U >& other );
155 
156  // to-homogenous-coordinates assignment operator
157  // non-chainable because of sfinae
158  template< size_t N >
159  typename enable_if< N == M - 1 >::type*
160  operator=( const vector< N, T >& source_ );
161 
162  // from-homogenous-coordinates assignment operator
163  // non-chainable because of sfinae
164  template< size_t N >
165  typename enable_if< N == M + 1 >::type*
166  operator=( const vector< N, T >& source_ );
167 
168  vector operator*( const vector& other ) const;
169  vector operator/( const vector& other ) const;
170  vector operator+( const vector& other ) const;
171  vector operator-( const vector& other ) const;
172 
173  void operator*=( const vector& other );
174  void operator/=( const vector& other );
175  void operator+=( const vector& other );
176  void operator-=( const vector& other );
177 
178  vector operator*( const T other ) const;
179  vector operator/( const T other ) const;
180  vector operator+( const T other ) const;
181  vector operator-( const T other ) const;
182 
183  void operator*=( const T other );
184  void operator/=( const T other );
185  void operator+=( const T other );
186  void operator-=( const T other );
187 
188  vector operator-() const;
189 
190  const vector& negate();
191 
192  void set( T a ); // sets all components to a;
193 #ifndef SWIG
194  void set( const vector< M-1, T >& v, T a );
195 #endif
196  template< size_t N >
197  void set( const vector< N, T >& v );
198 
199  // sets the first few components to a certain value
200  void set( T x, T y );
201  void set( T x, T y, T z );
202  void set( T x, T y, T z, T w );
203 
204  template< typename input_iterator_t >
205  void iter_set( input_iterator_t begin_, input_iterator_t end_ );
206 
207  // compute the cross product of two vectors
208  // note: there's also a free function:
209  // vector<> cross( const vector<>, const vector<> )
210  template< typename TT >
211  vector< M, T >& cross( const vector< M, TT >& b,
212  typename enable_if< M == 3, TT >::type* = 0 );
213 
214  // compute the dot product of two vectors
215  // note: there's also a free function:
216  // T dot( const vector<>, const vector<> );
217  inline T dot( const vector& other ) const;
218 
219  // normalize the vector
220  // note: there's also a free function:
221  // vector<> normalize( const vector<> );
222  inline T normalize();
223 
224  //sets all vector components to random values
225  //remember to set srand( seed );
226  //if seed is set to -1, srand( seed ) was set outside set_random
227  //otherwise srand( seed ) will be called with the given seed
228  void set_random( int seed = -1 );
229 
230  inline T length() const;
231  inline T squared_length() const;
232 
233  inline T distance( const vector& other ) const;
234  inline T squared_distance( const vector& other ) const;
235 
237  T product() const;
238 
239  template< typename TT >
240  vector< 3, T >& rotate( T theta, vector< M, TT > axis,
241  typename enable_if< M == 3, TT >::type* = 0 );
242 
244  template< size_t N, size_t O = 0 >
245  vector< N, T > get_sub_vector( typename enable_if< M >= N+O >::type* = 0 )
246  const;
247 
249  template< size_t N, size_t O = 0 >
250  void set_sub_vector( const vector< N, T >& sub,
251  typename enable_if< M >= N+O >::type* = 0 );
252 
253  // sphere functions - sphere layout: center xyz, radius w
254  template< typename TT >
255  inline vector< 3, T > project_point_onto_sphere(
256  const vector< 3, TT >& point,
257  typename enable_if< M == 4, TT >::type* = 0 ) const;
258 
259  // returns a negative distance if the point lies in the sphere
260  template< typename TT >
261  inline T distance_to_sphere( const vector< 3, TT >& point,
262  typename enable_if< M == 4, TT >::type* = 0 ) const;
263 
264  // plane functions - plane layout; normal xyz, distance w
265  template< typename TT >
266  inline T distance_to_plane( const vector< 3, TT >& point,
267  typename enable_if< M == 4, TT >::type* = 0 ) const;
268 
269  template< typename TT >
270  inline vector< 3, T > project_point_onto_plane(
271  const vector< 3, TT >& point,
272  typename enable_if< M == 4, TT >::type* = 0 ) const;
273 
274  // returns the index of the minimal resp. maximal value in the vector
275  size_t find_min_index() const;
276  size_t find_max_index() const;
277 
278  // returns the index of the minimal resp. maximal value in the vector
279  size_t find_abs_min_index() const;
280  size_t find_abs_max_index() const;
281 
282  // returns minimal resp. maximal value in the vector
283  T& find_min();
284  T& find_max();
285  const T& find_min() const;
286  const T& find_max() const;
287 
288  void clamp( const T& min = 0.0, const T& max = 1.0 );
289 
290  inline static size_t size(); // returns M
291 
292  bool is_unit_vector() const;
293 
294  // perturbs each component by randomly + or - the perturbation parameter
295  void perturb( T perturbation = 0.0001 );
296 
297  void sqrt_elementwise();
298  double norm() const; //l2 norm
299 
300  // computes the reciprocal value for each component, x = 1/x;
301  // WARNING: might result in nans if division by 0!
302  void reciprocal();
303  // computes the reciprocal value for each component, x = 1/x;
304  // checks every component for 0, sets to max value if zero.
305  void reciprocal_safe();
306 
307  template< typename TT >
308  void cast_from( const vector< M, TT >& other );
309 
310  size_t nnz() const;
311 
312  // test each component of the vector for isnan and isinf
313  // inline bool is_valid() const; -> moved to class validator
314 
315  friend std::ostream& operator<< ( std::ostream& os, const vector& vector_ )
316  {
317  const std::ios::fmtflags flags = os.flags();
318  const int prec = os.precision();
319 
320  os.setf( std::ios::right, std::ios::adjustfield );
321  os.precision( 5 );
322  os << "[ ";
323  for( size_t index = 0; index < M; ++index )
324  os << std::setw(10) << vector_.at( index ) << " ";
325  os << "]";
326  os.precision( prec );
327  os.setf( flags );
328  return os;
329  }
330 
331  T array[ M ];
332 
333 #ifndef SWIG
334  // Vector3 defaults
335  static const vector FORWARD;
336  static const vector BACKWARD;
337  static const vector UP;
338  static const vector DOWN;
339  static const vector LEFT;
340  static const vector RIGHT;
341 
342  static const vector ONE;
343  static const vector ZERO;
344 
345  // Unit vectors
346  static const vector UNIT_X;
347  static const vector UNIT_Y;
348  static const vector UNIT_Z;
349 #endif
350 
351 }; // class vector
352 
353 //
354 // typedefs and statics
355 //
356 #ifndef SWIG
357 template< size_t M, typename T >
358 const vector< M, T > vector< M, T >::FORWARD( 0, 0, -1 );
359 template< size_t M, typename T >
361 template< size_t M, typename T >
362 const vector< M, T > vector< M, T >::UP( 0, 1, 0 );
363 template< size_t M, typename T >
364 const vector< M, T > vector< M, T >::DOWN( 0, -1, 0 );
365 template< size_t M, typename T >
366 const vector< M, T > vector< M, T >::LEFT( -1, 0, 0 );
367 template< size_t M, typename T >
368 const vector< M, T > vector< M, T >::RIGHT( 1, 0, 0 );
369 template< size_t M, typename T >
370 
371 const vector< M, T > vector< M, T >::ONE( static_cast< T >( 1 ));
372 template< size_t M, typename T >
373 const vector< M, T > vector< M, T >::ZERO( static_cast< T >( 0 ));
374 template< size_t M, typename T >
375 
376 const vector< M, T > vector< M, T >::UNIT_X( 1, 0, 0 );
377 template< size_t M, typename T >
378 const vector< M, T > vector< M, T >::UNIT_Y( 0, 1, 0 );
379 template< size_t M, typename T >
380 const vector< M, T > vector< M, T >::UNIT_Z( 0, 0, 1 );
381 #endif
382 
383 //
384 // some free functions for convenience
385 //
386 
387 template< size_t M, typename T >
388 bool equals( const vector< M, T >& a, const vector< M, T >& b )
389 {
390  return a.equals( b );
391 }
392 
393 // allows float * vector, not only vector * float
394 template< size_t M, typename T >
395 static vector< M, T > operator* ( T factor, const vector< M, T >& vector_ )
396 {
397  return vector_ * factor;
398 }
399 
400 template< size_t M, typename T >
401 inline T dot( const vector< M, T >& first, const vector< M, T >& second )
402 {
403  return first.dot( second );
404 }
405 
406 template< size_t M, typename T >
407 inline vector< M, T > cross( vector< M, T > a, const vector< M, T >& b )
408 {
409  return a.cross( b );
410 }
411 
412 template< size_t M, typename T >
413 vector< M, T > compute_normal( const vector< M, T >& a, const vector< M, T >& b,
414  const vector< M, T >& c )
415 {
416  // right hand system, CCW triangle
417  const vector< M, T > u = b - a;
418  const vector< M, T > v = c - a;
419  vector< M, T > w = cross( u, v );
420  w.normalize();
421  return w;
422 }
423 
424 template< typename T >
425 vector< 3, T > rotate( vector< 3, T > vec, const T theta,
426  const vector< 3, T >& axis )
427 {
428  return vec.rotate( theta, axis );
429 }
430 
431 
432 template< size_t M, typename T >
433 inline vector< M, T > normalize( vector< M, T > vector_ )
434 {
435  vector_.normalize();
436  return vector_;
437 }
438 
439 template< typename T >
440 inline vector< 4, T > compute_plane( const vector< 3, T >& a,
441  const vector< 3, T >& b,
442  const vector< 3, T >& c )
443 {
444  const vector< 3, T > cb = b - c;
445  const vector< 3, T > ba = a - b;
446 
447  vector< 4, T > plane = vector< 4, T >( cross( cb, ba ));
448  plane.normalize();
449  plane.w() = -plane.x() * a.x() - plane.y() * a.y() - plane.z() * a.z();
450  return plane;
451 }
452 
453 template< size_t M, typename T >
454 vector< M, T >::vector( const T& _a )
455 {
456  for( iterator it = begin(), it_end = end(); it != it_end; ++it )
457  {
458  *it = _a;
459  }
460 }
461 
462 template< size_t M, typename T >
463 vector< M, T >::vector( const T& _x, const T& _y )
464 {
465  array[ 0 ] = _x;
466  array[ 1 ] = _y;
467 }
468 
469 template< size_t M, typename T >
470 vector< M, T >::vector( const T& _x, const T& _y, const T& _z )
471 {
472  array[ 0 ] = _x;
473  array[ 1 ] = _y;
474  array[ 2 ] = _z;
475 }
476 
477 template< size_t M, typename T >
478 vector< M, T >::vector( const T& _x, const T& _y, const T& _z, const T& _w )
479 {
480  array[ 0 ] = _x;
481  array[ 1 ] = _y;
482  array[ 2 ] = _z;
483  array[ 3 ] = _w;
484 }
485 
486 template< size_t M, typename T >
487 vector< M, T >::vector( const T* values )
488 {
489  memcpy( array, values, M * sizeof( T ));
490 }
491 
492 #ifdef __OSG_MATH
493 template< size_t M, typename T >
494 template< typename OSGVEC3 >
495 vector< M, T >::vector( const OSGVEC3& from,
496  typename enable_if< M == 3, OSGVEC3 >::type* )
497 {
498  array[ 0 ] = from.x();
499  array[ 1 ] = from.y();
500  array[ 2 ] = from.z();
501 }
502 #endif
503 
504 #ifndef SWIG
505 template< size_t M, typename T >
506 // initializes the first M-1 values from vector_, the last from last_
507 vector< M, T >::vector( const vector< M-1, T >& vector_, T last_ )
508 {
509  typename vector< M-1, T >::const_iterator
510  it = vector_.begin(), it_end = vector_.end();
511 
512  iterator my_it = begin();
513 
514  for( ; it != it_end; ++it, ++my_it )
515  {
516  (*my_it) = *it;
517  }
518  (*my_it) = last_;
519 }
520 #endif
521 
522 // to-homogenous-coordinates ctor
523 template< size_t M, typename T >
524 template< size_t N >
525 vector< M, T >::vector( const vector< N, T >& source_,
526  typename enable_if< N == M - 1 >::type* )
527 {
528  (*this) = source_;
529 }
530 
531 // from-homogenous-coordinates ctor
532 template< size_t M, typename T >
533 template< size_t N >
534 vector< M, T >::vector( const vector< N, T >& source_,
535  typename enable_if< N == M + 1 >::type* )
536 {
537  (*this) = source_;
538 }
539 
540 template< size_t M, typename T >
541 template< typename U >
542 vector< M, T >::vector( const vector< M, U >& source_ )
543 {
544  (*this) = source_;
545 }
546 
547 template< size_t M, typename T > void vector< M, T >::set( T _a )
548 {
549  for( iterator it = begin(), it_end = end(); it != it_end; ++it )
550  *it = _a;
551 }
552 
553 #ifndef SWIG
554 template< size_t M, typename T >
555 void vector< M, T >::set( const vector< M-1, T >& v, T _a )
556 {
557  memcpy( array, v.array, sizeof( T ) * (M-1) );
558  at( M-1 ) = _a;
559 }
560 #endif
561 
562 template< size_t M, typename T > template< size_t N >
563 void vector< M, T >::set( const vector< N, T >& v )
564 {
565  size_t minimum = M;
566  if (N < M) minimum = N;
567  memcpy( array, v.array, sizeof( T ) * minimum );
568 }
569 
570 template< size_t M, typename T >
571 void vector< M, T >::set( T _x, T _y )
572 {
573  array[ 0 ] = _x;
574  array[ 1 ] = _y;
575 }
576 
577 template< size_t M, typename T >
578 void vector< M, T >::set( T _x, T _y, T _z )
579 {
580  array[ 0 ] = _x;
581  array[ 1 ] = _y;
582  array[ 2 ] = _z;
583 }
584 
585 template< size_t M, typename T >
586 void vector< M, T >::set( T _x, T _y, T _z, T _w )
587 {
588  array[ 0 ] = _x;
589  array[ 1 ] = _y;
590  array[ 2 ] = _z;
591  array[ 3 ] = _w;
592 }
593 
594 template< size_t M, typename T >
595 inline T&
596 vector< M, T >::operator()( size_t index )
597 {
598  return at( index );
599 }
600 
601 template< size_t M, typename T >
602 inline const T&
603 vector< M, T >::operator()( size_t index ) const
604 {
605  return at( index );
606 }
607 
608 template< size_t M, typename T >
609 inline T&
610 vector< M, T >::at( size_t index )
611 {
612  if( index >= M )
613  throw std::runtime_error( "at() - index out of bounds" );
614  return array[ index ];
615 }
616 
617 template< size_t M, typename T >
618 inline const T&
619 vector< M, T >::at( size_t index ) const
620 {
621  if ( index >= M )
622  throw std::runtime_error( "at() - index out of bounds" );
623  return array[ index ];
624 }
625 
626 #ifndef VMMLIB_NO_CONVERSION_OPERATORS
627 
628 template< size_t M, typename T >
629 vector< M, T >::operator T*()
630 {
631  return array;
632 }
633 
634 template< size_t M, typename T >
635 vector< M, T >::operator const T*() const
636 {
637  return array;
638 }
639 #else
640 
641 template< size_t M, typename T >
642 T&
643 vector< M, T >::operator[]( size_t index )
644 {
645  return at( index );
646 }
647 
648 template< size_t M, typename T >
649 const T&
650 vector< M, T >::operator[]( size_t index ) const
651 {
652  return at( index );
653 }
654 
655 #endif
656 
657 #if 0
658 template< size_t M, typename T >
659 inline T&
660 vector< M, T >::operator[]( size_t index )
661 {
662  return at( index );
663 }
664 
665 template< size_t M, typename T >
666 inline const T&
667 vector< M, T >::operator[]( size_t index ) const
668 {
669  return at( index );
670 }
671 #endif
672 
673 template< size_t M, typename T >
674 vector< M, T >
675 vector< M, T >::operator*( const vector< M, T >& other ) const
676 {
677  vector< M, T > result;
678  for( size_t index = 0; index < M; ++index )
679  result.at( index ) = at( index ) * other.at( index );
680  return result;
681 }
682 
683 template< size_t M, typename T >
684 vector< M, T >
685 vector< M, T >::operator/( const vector< M, T >& other ) const
686 {
687  vector< M, T > result;
688  for( size_t index = 0; index < M; ++index )
689  result.at( index ) = at( index ) / other.at( index );
690  return result;
691 }
692 
693 template< size_t M, typename T >
694 vector< M, T >
695 vector< M, T >::operator+( const vector< M, T >& other ) const
696 {
697  vector< M, T > result;
698  for( size_t index = 0; index < M; ++index )
699  result.at( index ) = at( index ) + other.at( index );
700  return result;
701 }
702 
703 template< size_t M, typename T >
704 vector< M, T >
705 vector< M, T >::operator-( const vector< M, T >& other ) const
706 {
707  vector< M, T > result;
708  for( size_t index = 0; index < M; ++index )
709  result.at( index ) = at( index ) - other.at( index );
710  return result;
711 }
712 
713 template< size_t M, typename T >
714 void
715 vector< M, T >::operator*=( const vector< M, T >& other )
716 {
717  for( size_t index = 0; index < M; ++index )
718  at( index ) *= other.at( index );
719 }
720 
721 template< size_t M, typename T >
722 void
723 vector< M, T >::operator/=( const vector< M, T >& other )
724 {
725  for( size_t index = 0; index < M; ++index )
726  at( index ) /= other.at( index );
727 }
728 
729 template< size_t M, typename T >
730 void
731 vector< M, T >::operator+=( const vector< M, T >& other )
732 {
733  for( size_t index = 0; index < M; ++index )
734  at( index ) += other.at( index );
735 }
736 
737 template< size_t M, typename T >
738 void
739 vector< M, T >::operator-=( const vector< M, T >& other )
740 {
741  for( size_t index = 0; index < M; ++index )
742  at( index ) -= other.at( index );
743 }
744 
745 template< size_t M, typename T >
746 vector< M, T >
747 vector< M, T >::operator*( const T other ) const
748 {
749  vector< M, T > result;
750  for( size_t index = 0; index < M; ++index )
751  result.at( index ) = at( index ) * other;
752  return result;
753 }
754 
755 template< size_t M, typename T >
756 vector< M, T >
757 vector< M, T >::operator/( const T other ) const
758 {
759  vector< M, T > result;
760  for( size_t index = 0; index < M; ++index )
761  result.at( index ) = at( index ) / other;
762  return result;
763 }
764 
765 template< size_t M, typename T >
766 vector< M, T >
767 vector< M, T >::operator+( const T other ) const
768 {
769  vector< M, T > result;
770  for( size_t index = 0; index < M; ++index )
771  result.at( index ) = at( index ) + other;
772  return result;
773 }
774 
775 template< size_t M, typename T >
776 vector< M, T >
777 vector< M, T >::operator-( const T other ) const
778 {
779  vector< M, T > result;
780  for( size_t index = 0; index < M; ++index )
781  result.at( index ) = at( index ) - other;
782  return result;
783 }
784 
785 template< size_t M, typename T >
786 void
787 vector< M, T >::operator*=( const T other )
788 {
789  for( size_t index = 0; index < M; ++index )
790  at( index ) *= other;
791 }
792 
793 template< size_t M, typename T >
794 void
795 vector< M, T >::operator/=( const T other )
796 {
797  for( size_t index = 0; index < M; ++index )
798  at( index ) /= other;
799 }
800 
801 template< size_t M, typename T >
802 void
803 vector< M, T >::operator+=( const T other )
804 {
805  for( size_t index = 0; index < M; ++index )
806  at( index ) += other;
807 }
808 
809 template< size_t M, typename T >
810 void
811 vector< M, T >::operator-=( const T other )
812 {
813  for( size_t index = 0; index < M; ++index )
814  at( index ) -= other;
815 }
816 
817 template< size_t M, typename T >
818 vector< M, T >
819 vector< M, T >::operator-() const
820 {
821  vector< M, T > v( *this );
822  return v.negate();
823 }
824 
825 template< size_t M, typename T >
826 const vector< M, T >&
827 vector< M, T >::negate()
828 {
829  for( size_t index = 0; index < M; ++index )
830  array[ index ] = -array[ index ];
831  return *this;
832 }
833 
834 template< size_t M, typename T >
835 inline T&
836 vector< M, T >::x()
837 {
838  return array[ 0 ];
839 }
840 
841 template< size_t M, typename T >
842 inline T&
843 vector< M, T >::y()
844 {
845  return array[ 1 ];
846 }
847 
848 template< size_t M, typename T >
849 inline T&
850 vector< M, T >::z()
851 {
852  return array[ 2 ];
853 }
854 
855 template< size_t M, typename T >
856 inline T&
857 vector< M, T >::w()
858 {
859  return array[ 3 ];
860 }
861 
862 template< size_t M, typename T >
863 inline const T&
864 vector< M, T >::x() const
865 {
866  return array[ 0 ];
867 }
868 
869 template< size_t M, typename T >
870 inline const T&
871 vector< M, T >::y() const
872 {
873  return array[ 1 ];
874 }
875 
876 template< size_t M, typename T >
877 inline const T&
878 vector< M, T >::z() const
879 {
880  return array[ 2 ];
881 }
882 
883 template< size_t M, typename T >
884 inline const T&
885 vector< M, T >::w() const
886 {
887  return array[ 3 ];
888 }
889 
890 template< size_t M, typename T >
891 inline T&
892 vector< M, T >::r()
893 {
894  return array[ 0 ];
895 }
896 
897 template< size_t M, typename T >
898 inline T&
899 vector< M, T >::g()
900 {
901  return array[ 1 ];
902 }
903 
904 template< size_t M, typename T >
905 inline T&
906 vector< M, T >::b()
907 {
908  return array[ 2 ];
909 }
910 
911 template< size_t M, typename T >
912 inline T&
913 vector< M, T >::a()
914 {
915  return array[ 3 ];
916 }
917 
918 template< size_t M, typename T >
919 inline const T&
920 vector< M, T >::r() const
921 {
922  return array[ 0 ];
923 }
924 
925 template< size_t M, typename T >
926 inline const T&
927 vector< M, T >::g() const
928 {
929  return array[ 1 ];
930 }
931 
932 template< size_t M, typename T >
933 inline const T&
934 vector< M, T >::b() const
935 {
936  return array[ 2 ];
937 }
938 
939 template< size_t M, typename T >
940 inline const T&
941 vector< M, T >::a() const
942 {
943  return array[ 3 ];
944 }
945 
946 template< size_t M, typename T > template< typename TT >
947 vector< M, T >& vector< M, T >::cross( const vector< M, TT >& rhs,
948  typename enable_if< M == 3, TT >::type* )
949 {
950  const T x_ = y() * rhs.z() - z() * rhs.y();
951  const T y_ = z() * rhs.x() - x() * rhs.z();
952  const T z_ = x() * rhs.y() - y() * rhs.x();
953  x() = x_;
954  y() = y_;
955  z() = z_;
956  return *this;
957 }
958 
959 template< size_t M, typename T >
960 inline T vector< M, T >::dot( const vector< M, T >& other ) const
961 {
962  T tmp = 0.0;
963  for( size_t index = 0; index < M; ++index )
964  tmp += at( index ) * other.at( index );
965 
966  return tmp;
967 }
968 
969 template< size_t M, typename T > inline T vector< M, T >::normalize()
970 {
971  const T len = length();
972  if ( len <= std::numeric_limits< T >::epsilon( ))
973  return 0;
974 
975  const T tmp = 1.0 / len;
976  (*this) *= tmp;
977  return len;
978 }
979 
980 template< size_t M, typename T >
981 inline T vector< M, T >::length() const
982 {
983  return std::sqrt( squared_length() );
984 }
985 
986 template< size_t M, typename T >
987 inline T vector< M, T >::squared_length() const
988 {
989  T _squared_length = 0.0;
990  for( const_iterator it = begin(), it_end = end(); it != it_end; ++it )
991  _squared_length += (*it) * (*it);
992 
993  return _squared_length;
994 }
995 
996 template< size_t M, typename T >
997 inline T
998 vector< M, T >::distance( const vector< M, T >& other ) const
999 {
1000  return std::sqrt( squared_distance( other ) );
1001 }
1002 
1003 template< size_t M, typename T >
1004 inline T vector< M, T >::squared_distance( const vector< M, T >& other ) const
1005 {
1006  vector< M, T > tmp( *this );
1007  tmp -= other;
1008  return tmp.squared_length();
1009 }
1010 
1011 template< size_t M, typename T > inline T vector< M, T >::product() const
1012 {
1013  T result = at( 0 );
1014  for( size_t i = 1; i < M; ++i )
1015  result *= at( i );
1016  return result;
1017 }
1018 
1019 template< size_t M, typename T > template< typename TT >
1021  typename enable_if< M==3, TT >::type* )
1022 {
1023  const T costheta = std::cos( theta );
1024  const T sintheta = std::sin( theta );
1025 
1026  axis.normalize();
1027  return *this = vector< 3, T >(
1028  (costheta + ( 1 - costheta ) * axis.x() * axis.x() ) * x() +
1029  (( 1 - costheta ) * axis.x() * axis.y() - axis.z() * sintheta ) * y() +
1030  (( 1 - costheta ) * axis.x() * axis.z() + axis.y() * sintheta ) * z(),
1031 
1032  (( 1 - costheta ) * axis.x() * axis.y() + axis.z() * sintheta ) * x() +
1033  ( costheta + ( 1 - costheta ) * axis.y() * axis.y() ) * y() +
1034  (( 1 - costheta ) * axis.y() * axis.z() - axis.x() * sintheta ) * z(),
1035 
1036  (( 1 - costheta ) * axis.x() * axis.z() - axis.y() * sintheta ) * x() +
1037  (( 1 - costheta ) * axis.y() * axis.z() + axis.x() * sintheta ) * y() +
1038  ( costheta + ( 1 - costheta ) * axis.z() * axis.z() ) * z( ));
1039 }
1040 
1041 // sphere layout: center xyz, radius w
1042 template< size_t M, typename T > template< typename TT > inline vector< 3, T >
1043 vector< M, T >::project_point_onto_sphere( const vector< 3, TT >& point,
1044  typename enable_if< M == 4, TT >::type* ) const
1045 {
1046  const vector< 3, T >& center_ = get_sub_vector< 3 >();
1047 
1048  vector< 3, T > projected_point( point );
1049  projected_point -= center_;
1050  projected_point.normalize();
1051  projected_point *= w();
1052  return center_ + projected_point;
1053 }
1054 
1055 // sphere layout: center xyz, radius w
1056 template< size_t M, typename T > template< typename TT > inline T
1057 vector< M, T >::distance_to_sphere( const vector< 3, TT >& point,
1058  typename enable_if< M == 4, TT >::type* )
1059  const
1060 {
1061  const vector< 3, T >& center_ = get_sub_vector< 3 >();
1062  return ( point - center_ ).length() - w();
1063 }
1064 
1065 template< size_t M, typename T > template< size_t N, size_t O >
1067  typename enable_if< M >= N+O >::type* ) const
1068 {
1069  return vector< N, T >( array + O );
1070 }
1071 
1072 template< size_t M, typename T > template< size_t N, size_t O >
1074  typename enable_if< M >= N+O >::type* )
1075 {
1076  ::memcpy( array + O, sub.array, N * sizeof( T ));
1077 }
1078 
1079 // plane: normal xyz, distance w
1080 template< size_t M, typename T > template< typename TT >
1081 inline T vector< M, T >::distance_to_plane( const vector< 3, TT >& point,
1082  typename enable_if< M == 4, TT >::type* ) const
1083 {
1084  const vector< 3, T >& normal = get_sub_vector< 3 >();
1085  return normal.dot( point ) + w();
1086 }
1087 
1088 // plane: normal xyz, distance w
1089 template< size_t M, typename T > template< typename TT > vector< 3, T >
1090 vector< M, T >::project_point_onto_plane( const vector< 3, TT >& point,
1091  typename enable_if< M == 4, TT >::type* ) const
1092 {
1093  const vector< 3, T >& normal = get_sub_vector< 3 >();
1094  return point - ( normal * distance_to_plane( point ) );
1095 }
1096 
1097 template< size_t M, typename T >
1098 bool vector< M, T >::operator==( const vector< M, T >& other ) const
1099 {
1100  return memcmp( array, other.array, sizeof( array )) == 0;
1101 }
1102 
1103 template< size_t M, typename T >
1104 bool vector< M, T >::operator!=( const vector< M, T >& other ) const
1105 {
1106  return ! this->operator==( other );
1107 }
1108 
1109 template< size_t M, typename T >
1110 bool vector< M, T >::equals( const vector< M, T >& other, T tolerance ) const
1111 {
1112  for( size_t index = 0; index < M; ++index )
1113  if( fabs( at( index ) - other( index ) ) >= tolerance )
1114  return false;
1115  return true;
1116 
1117 }
1118 
1119 template< size_t M, typename T >
1120 bool
1121 vector< M, T >::operator<( const vector< M, T >& other ) const
1122 {
1123  for(size_t index = 0; index < M; ++index )
1124  {
1125  if (at( index ) < other.at( index )) return true;
1126  if (other.at( index ) < at( index )) return false;
1127  }
1128  return false;
1129 }
1130 
1131 // to-homogenous-coordinates assignment operator
1132 // non-chainable because of sfinae
1133 template< size_t M, typename T > template< size_t N >
1134 typename enable_if< N == M - 1 >::type*
1135 vector< M, T >::operator=( const vector< N, T >& source_ )
1136 {
1137  std::copy( source_.begin(), source_.end(), begin() );
1138  at( M - 1 ) = static_cast< T >( 1.0 );
1139  return 0;
1140 }
1141 
1142 // from-homogenous-coordinates assignment operator
1143 // non-chainable because of sfinae
1144 template< size_t M, typename T > template< size_t N >
1145 typename enable_if< N == M + 1 >::type*
1146 vector< M, T >::operator=( const vector< N, T >& source_ )
1147 {
1148  const T w_reci = static_cast< T >( 1.0 ) / source_( M );
1149  iterator it = begin(), it_end = end();
1150  for( size_t index = 0; it != it_end; ++it, ++index )
1151  *it = source_( index ) * w_reci;
1152  return 0;
1153 }
1154 
1155 template< size_t M, typename T >
1156 vector< M, T >& vector< M, T >::operator=( const T* c_array )
1157 {
1158  iter_set( c_array, c_array + M );
1159  return *this;
1160 }
1161 
1162 template< size_t M, typename T >
1163 T vector< M, T >::operator=( T filler_value )
1164 {
1165  for( size_t index = 0; index < M; ++index )
1166  at( index ) = filler_value;
1167  return filler_value;
1168 }
1169 
1170 template< size_t M, typename T >
1171 vector< M, T >& vector< M, T >::operator=( const vector< M, T >& other )
1172 {
1173  if( this != &other )
1174  memcpy( array, other.array, M * sizeof( T ) );
1175  return *this;
1176 }
1177 
1178 // returns void to avoid 'silent' loss of precision when chaining
1179 template< size_t M, typename T > template< typename U >
1180 void vector< M, T >::operator=( const vector< M, U >& source_ )
1181 {
1182  typedef typename vector< M, U >::const_iterator u_c_iter;
1183  u_c_iter it = source_.begin(), it_end = source_.end();
1184  for( iterator my_it = begin(); it != it_end; ++it, ++my_it )
1185  *my_it = static_cast< T >( *it );
1186 }
1187 
1188 template< size_t M, typename T >
1189 template< typename input_iterator_t >
1190 void
1191 vector< M, T >::iter_set( input_iterator_t begin_, input_iterator_t end_ )
1192 {
1193  input_iterator_t in_it = begin_;
1194  iterator it = begin(), it_end = end();
1195  for( ; it != it_end && in_it != end_; ++it, ++in_it )
1196  (*it) = static_cast< T >( *in_it );
1197 }
1198 
1199 template< size_t M, typename T >
1200 void vector< M, T >::clamp( const T& min, const T& max )
1201 {
1202  for( size_t i = 0; i < M; ++i )
1203  {
1204  if( array[i] < min )
1205  array[i] = min;
1206  if( array[i] > max )
1207  array[i] = max;
1208  }
1209 }
1210 
1211 template< size_t M, typename T >
1212 inline size_t
1213 vector< M, T >::size()
1214 {
1215  return M;
1216 }
1217 
1218 template< size_t M, typename T >
1219 size_t
1220 vector< M, T >::find_min_index() const
1221 {
1222  return std::min_element( begin(), end() ) - begin();
1223 }
1224 
1225 template< size_t M, typename T >
1226 size_t
1227 vector< M, T >::find_max_index() const
1228 {
1229  return std::max_element( begin(), end() ) - begin();
1230 }
1231 
1232 template< size_t M, typename T >
1233 size_t
1234 vector< M, T >::find_abs_min_index() const
1235 {
1236  return std::min_element( begin(), end(), vmml::math::abs_less< T >() ) - begin();
1237 }
1238 
1239 template< size_t M, typename T >
1240 size_t
1241 vector< M, T >::find_abs_max_index() const
1242 {
1243  return std::max_element( begin(), end(), vmml::math::abs_greater< T >() ) - begin();
1244 }
1245 
1246 template< size_t M, typename T >
1247 T&
1248 vector< M, T >::find_min()
1249 {
1250  return *std::min_element( begin(), end() );
1251 }
1252 
1253 template< size_t M, typename T >
1254 const T&
1255 vector< M, T >::find_min() const
1256 {
1257  return *std::min_element( begin(), end() );
1258 }
1259 
1260 template< size_t M, typename T >
1261 T&
1262 vector< M, T >::find_max()
1263 {
1264  return *std::max_element( begin(), end() );
1265 }
1266 
1267 template< size_t M, typename T >
1268 const T&
1269 vector< M, T >::find_max() const
1270 {
1271  return *std::max_element( begin(), end() );
1272 }
1273 
1274 template< size_t M, typename T >
1275 inline typename vector< M, T >::iterator
1276 vector< M, T >::begin()
1277 {
1278  return array;
1279 }
1280 
1281 template< size_t M, typename T >
1282 inline typename vector< M, T >::iterator
1283 vector< M, T >::end()
1284 {
1285  return array + M; ;
1286 }
1287 
1288 template< size_t M, typename T >
1289 inline typename vector< M, T >::const_iterator
1290 vector< M, T >::begin() const
1291 {
1292  return array;
1293 }
1294 
1295 template< size_t M, typename T >
1296 inline typename vector< M, T >::const_iterator
1297 vector< M, T >::end() const
1298 {
1299  return array + M; ;
1300 }
1301 
1302 template< size_t M, typename T >
1303 inline typename vector< M, T >::reverse_iterator
1304 vector< M, T >::rbegin()
1305 {
1306  return array + M - 1;
1307 }
1308 
1309 template< size_t M, typename T >
1310 inline typename vector< M, T >::reverse_iterator
1311 vector< M, T >::rend()
1312 {
1313  return array - 1;
1314 }
1315 
1316 template< size_t M, typename T >
1317 inline typename vector< M, T >::const_reverse_iterator
1318 vector< M, T >::rbegin() const
1319 {
1320  return array + M - 1;
1321 }
1322 
1323 template< size_t M, typename T >
1324 inline typename vector< M, T >::const_reverse_iterator
1325 vector< M, T >::rend() const
1326 {
1327  return array - 1;
1328 }
1329 
1330 template< size_t M, typename T >
1331 bool
1332 vector< M, T >::is_unit_vector() const
1333 {
1334  const_iterator it = begin(), it_end = end();
1335  bool one = false;
1336  for( ; it != it_end; ++it )
1337  {
1338  if ( *it == 1.0 )
1339  {
1340  if ( one )
1341  return false;
1342  one = true;
1343  }
1344  else if ( *it != 0.0 )
1345  {
1346  return false;
1347  }
1348  }
1349  return one;
1350 }
1351 
1352 template< size_t M, typename T >
1353 void
1354 vector< M, T >::perturb( T perturbation )
1355 {
1356  for( iterator it = begin(), it_end = end(); it != it_end; ++it )
1357  {
1358  (*it) += ( rand() & 1u ) ? perturbation : -perturbation;
1359  }
1360 
1361 }
1362 
1363 template< size_t M, typename T >
1364 void
1365 vector< M, T >::sqrt_elementwise()
1366 {
1367  for( iterator it = begin(), it_end = end(); it != it_end; ++it )
1368  {
1369  (*it) = std::sqrt(*it);
1370  }
1371 }
1372 
1373 template< size_t M, typename T > void vector< M, T >::reciprocal()
1374 {
1375  for( iterator it = begin(), it_end = end(); it != it_end; ++it )
1376  (*it) = static_cast< T >( 1 ) / (*it);
1377 }
1378 
1379 template< size_t M, typename T > void vector< M, T >::reciprocal_safe()
1380 {
1381  for( iterator it = begin(), it_end = end(); it != it_end; ++it )
1382  {
1383  T& v = *it;
1384 
1385  if( v == 0 )
1386  v = std::numeric_limits< T >::max();
1387  else
1388  v = static_cast< T >( 1 ) / v;
1389  }
1390 }
1391 
1392 template< size_t M, typename T >
1393 template< typename TT >
1394 void
1395 vector< M, T >::cast_from( const vector< M, TT >& other )
1396 {
1397  typedef vmml::vector< M, TT > vector_tt_type ;
1398  typedef typename vector_tt_type::const_iterator tt_const_iterator;
1399 
1400  iterator it = begin(), it_end = end();
1401  tt_const_iterator other_it = other.begin();
1402  for( ; it != it_end; ++it, ++other_it )
1403  {
1404  *it = static_cast< T >( *other_it );
1405  }
1406 }
1407 
1408 template< size_t M, typename T >
1409 size_t
1410 vector< M, T >::nnz() const
1411 {
1412  size_t counter = 0;
1413 
1414  const_iterator it = begin(),
1415  it_end = end();
1416  for( ; it != it_end; ++it)
1417  {
1418  if ( *it != 0 ) {
1419  ++counter;
1420  }
1421  }
1422 
1423  return counter;
1424 }
1425 
1426 template< size_t M, typename T >
1427 double
1428 vector< M, T >::norm( ) const
1429 {
1430  double norm_v = 0.0;
1431 
1432  const_iterator it = begin(), it_end = end();
1433  for( ; it != it_end; ++it )
1434  {
1435  norm_v += *it * *it;
1436  }
1437 
1438  return std::sqrt(norm_v);
1439 }
1440 
1441 template< size_t M, typename T >
1442 void
1443 vector< M, T >::set_random( int seed )
1444 {
1445  if ( seed >= 0 )
1446  srand( seed );
1447 
1448  for( size_t i = 0; i < M; ++i )
1449  {
1450  const double fillValue = double( rand( )) / double( RAND_MAX );
1451  at( i ) = -1.0 + 2.0 * fillValue;
1452  }
1453 }
1454 
1455 } // namespace vmml
1456 
1457 #endif
heavily inspired by boost::enable_if http://www.boost.org, file: boost/utility/enable_if.hpp, Copyright 2003 Jaakko Järvi, Jeremiah Willcock, Andrew Lumsdaine
Definition: aabb.hpp:40
T array[M]
storage
Definition: vector.hpp:331
T product() const
Definition: vector.hpp:1011
void set_sub_vector(const vector< N, T > &sub, typename enable_if< M >=N+O >::type *=0)
Set the sub vector of the given length at the given offset.
Definition: vector.hpp:1073
vector< N, T > get_sub_vector(typename enable_if< M >=N+O >::type *=0) const
Definition: vector.hpp:1066