vmmlib  1.12.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/enable_if.hpp>
37 
38 #include <algorithm>
39 #include <cmath>
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  template< typename TT >
72  vector( const vector< M-1, TT >& vector_, T last_,
73  typename enable_if< M == 4, TT >::type* = nullptr );
74 #endif
75 
76  explicit vector( const T* values );
77 
78 #ifdef __OSG_MATH
79  template< typename OSGVEC3 >
80  explicit vector( const OSGVEC3& from,
81  typename enable_if< M == 3, OSGVEC3 >::type* = nullptr );
82 #endif
83 
84  // vec< M > with homogeneous coordinates <-> vec< M-1 > conversion ctor
85  // to-homogenous-coordinates ctor
86  template< typename TT >
87  vector( const vector< 3, TT >& source_,
88  typename enable_if< M == 4, TT >::type* = nullptr );
89 
90  // from-homogenous-coordinates vector
91  template< typename TT >
92  vector( const vector< 4, TT >& source_,
93  typename enable_if< M == 3, TT >::type* = nullptr );
94 
95  template< typename U > vector( const vector< M, U >& source_ );
96 
97  // iterators
98  inline iterator begin();
99  inline iterator end();
100  inline const_iterator begin() const;
101  inline const_iterator end() const;
102  inline reverse_iterator rbegin();
103  inline reverse_iterator rend();
104  inline const_reverse_iterator rbegin() const;
105  inline const_reverse_iterator rend() const;
106 
107  // conversion operators
108  inline operator T*();
109  inline operator const T*() const;
110  // accessors
111  inline T& operator()( size_t index );
112  inline const T& operator()( size_t index ) const;
113 
114  inline T& at( size_t index );
115  inline const T& at( size_t index ) const;
116 
117  // element accessors for M <= 4;
118  inline T& x();
119  inline T& y();
120  inline T& z();
121  inline T& w();
122  inline const T& x() const;
123  inline const T& y() const;
124  inline const T& z() const;
125  inline const T& w() const;
126 
127  // pixel color element accessors for M<= 4
128  inline T& r();
129  inline T& g();
130  inline T& b();
131  inline T& a();
132  inline const T& r() const;
133  inline const T& g() const;
134  inline const T& b() const;
135  inline const T& a() const;
136 
137  bool operator==( const vector& other ) const;
138  bool operator!=( const vector& other ) const;
139  bool equals( const vector& other,
140  T tolerance = std::numeric_limits< T >::epsilon( )) const;
141  bool operator<( const vector& other ) const;
142 
143  // remember kids: c_arrays are dangerous and evil!
144  T operator=( T filler );
145 
146  vector& operator=( const vector& other );
147 
148  // returns void to avoid 'silent' loss of precision when chaining
149  template< typename U > void operator=( const vector< M, U >& other );
150 
151  vector operator*( const vector& other ) const;
152  vector operator/( const vector& other ) const;
153  vector operator+( const vector& other ) const;
154  vector operator-( const vector& other ) const;
155 
156  void operator*=( const vector& other );
157  void operator/=( const vector& other );
158  void operator+=( const vector& other );
159  void operator-=( const vector& other );
160 
161  vector operator*( const T other ) const;
162  vector operator/( const T other ) const;
163  vector operator+( const T other ) const;
164  vector operator-( const T other ) const;
165 
166  void operator*=( const T other );
167  void operator/=( const T other );
168  void operator+=( const T other );
169  void operator-=( const T other );
170 
171  vector operator-() const;
172 
173  const vector& negate();
174 
175  void set( T a ); // sets all components to a;
176  template< size_t N >
177  void set( const vector< N, T >& v );
178 
179  // sets the first few components to a certain value
180  void set( T x, T y );
181  void set( T x, T y, T z );
182  void set( T x, T y, T z, T w );
183 
184  template< typename input_iterator_t >
185  void iter_set( input_iterator_t begin_, input_iterator_t end_ );
186 
187  // compute the cross product of two vectors
188  // note: there's also a free function:
189  // vector<> cross( const vector<>, const vector<> )
190  template< typename TT >
191  vector< M, T >& cross( const vector< M, TT >& b,
192  typename enable_if< M == 3, TT >::type* = nullptr );
193 
194  // compute the dot product of two vectors
195  // note: there's also a free function:
196  // T dot( const vector<>, const vector<> );
197  inline T dot( const vector& other ) const;
198 
199  // normalize the vector
200  // note: there's also a free function:
201  // vector<> normalize( const vector<> );
202  inline T normalize();
203 
204  //sets all vector components to random values
205  //remember to set srand( seed );
206  //if seed is set to -1, srand( seed ) was set outside set_random
207  //otherwise srand( seed ) will be called with the given seed
208  void set_random( int seed = -1 );
209 
210  inline T length() const;
211  inline T squared_length() const;
212 
213  inline T distance( const vector& other ) const;
214  inline T squared_distance( const vector& other ) const;
215 
217  T product() const;
218 
219  template< typename TT >
220  vector< 3, T >& rotate( T theta, vector< M, TT > axis,
221  typename enable_if< M == 3, TT >::type* = nullptr );
222 
224  template< size_t N, size_t O > vector< N, T >
225  get_sub_vector( typename enable_if< M >= N+O >::type* = nullptr ) const;
226 
228  template< size_t N, size_t O >
229  void set_sub_vector( const vector< N, T >& sub,
230  typename enable_if< M >= N+O >::type* = nullptr );
231 
232  // sphere functions - sphere layout: center xyz, radius w
233  template< typename TT >
234  inline vector< 3, T > project_point_onto_sphere(
235  const vector< 3, TT >& point,
236  typename enable_if< M == 4, TT >::type* = nullptr ) const;
237 
238  // returns a negative distance if the point lies in the sphere
239  template< typename TT >
240  inline T distance_to_sphere( const vector< 3, TT >& point,
241  typename enable_if< M == 4, TT >::type* = nullptr ) const;
242 
243  // plane functions - plane layout; normal xyz, distance w
244  template< typename TT >
245  inline T distance_to_plane( const vector< 3, TT >& point,
246  typename enable_if< M == 4, TT >::type* = nullptr ) const;
247 
248  template< typename TT >
249  inline vector< 3, T > project_point_onto_plane(
250  const vector< 3, TT >& point,
251  typename enable_if< M == 4, TT >::type* = nullptr ) const;
252 
253  // returns the index of the minimal resp. maximal value in the vector
254  size_t find_min_index() const;
255  size_t find_max_index() const;
256 
257  // returns minimal resp. maximal value in the vector
258  T& find_min();
259  T& find_max();
260  const T& find_min() const;
261  const T& find_max() const;
262 
263  void clamp( const T& min = 0.0, const T& max = 1.0 );
264 
265  inline static size_t size(); // returns M
266 
267  bool is_unit_vector() const;
268 
269  // perturbs each component by randomly + or - the perturbation parameter
270  void perturb( T perturbation = 0.0001 );
271 
272  void sqrt_elementwise();
273  double norm() const; //l2 norm
274 
275  // computes the reciprocal value for each component, x = 1/x;
276  // WARNING: might result in nans if division by 0!
277  void reciprocal();
278  // computes the reciprocal value for each component, x = 1/x;
279  // checks every component for 0, sets to max value if zero.
280  void reciprocal_safe();
281 
282  template< typename TT >
283  void cast_from( const vector< M, TT >& other );
284 
285  size_t nnz() const;
286 
287  friend std::ostream& operator<< ( std::ostream& os, const vector& vector_ )
288  {
289  os << "[ ";
290  for( size_t index = 0; index < M; ++index )
291  os << vector_.at( index ) << " ";
292  return os << "]";
293  }
294 
297  static vector< M, T > zero();
298  static vector< M, T > forward();
299  static vector< M, T > backward();
300  static vector< M, T > up();
301  static vector< M, T > down();
302  static vector< M, T > left();
303  static vector< M, T > right();
304  static vector< M, T > unitX();
305  static vector< M, T > unitY();
306  static vector< M, T > unitZ();
308 
309  T array[ M ];
310 };
311 
312 //
313 // some free functions for convenience
314 //
315 
316 template< size_t M, typename T >
317 bool equals( const vector< M, T >& a, const vector< M, T >& b )
318 {
319  return a.equals( b );
320 }
321 
322 // allows float * vector, not only vector * float
323 template< size_t M, typename T >
324 static vector< M, T > operator* ( T factor, const vector< M, T >& vector_ )
325 {
326  return vector_ * factor;
327 }
328 
329 template< size_t M, typename T >
330 inline T dot( const vector< M, T >& first, const vector< M, T >& second )
331 {
332  return first.dot( second );
333 }
334 
335 template< size_t M, typename T >
336 inline vector< M, T > cross( vector< M, T > a, const vector< M, T >& b )
337 {
338  return a.cross( b );
339 }
340 
341 template< size_t M, typename T >
342 vector< M, T > compute_normal( const vector< M, T >& a, const vector< M, T >& b,
343  const vector< M, T >& c )
344 {
345  // right hand system, CCW triangle
346  const vector< M, T > u = b - a;
347  const vector< M, T > v = c - a;
348  vector< M, T > w = cross( u, v );
349  w.normalize();
350  return w;
351 }
352 
353 template< typename T >
354 vector< 3, T > rotate( vector< 3, T > vec, const T theta,
355  const vector< 3, T >& axis )
356 {
357  return vec.rotate( theta, axis );
358 }
359 
360 
361 template< size_t M, typename T >
362 inline vector< M, T > normalize( vector< M, T > vector_ )
363 {
364  vector_.normalize();
365  return vector_;
366 }
367 
368 template< typename T >
369 inline vector< 4, T > compute_plane( const vector< 3, T >& a,
370  const vector< 3, T >& b,
371  const vector< 3, T >& c )
372 {
373  const vector< 3, T > cb = b - c;
374  const vector< 3, T > ba = a - b;
375 
376  vector< 4, T > plane = vector< 4, T >( cross( cb, ba ));
377  plane.normalize();
378  plane.w() = -plane.x() * a.x() - plane.y() * a.y() - plane.z() * a.z();
379  return plane;
380 }
381 
382 template< size_t M, typename T >
383 vector< M, T >::vector( const T& _a )
384 {
385  for( iterator it = begin(), it_end = end(); it != it_end; ++it )
386  {
387  *it = _a;
388  }
389 }
390 
391 template< size_t M, typename T >
392 vector< M, T >::vector( const T& _x, const T& _y )
393 {
394  array[ 0 ] = _x;
395  array[ 1 ] = _y;
396 }
397 
398 template< size_t M, typename T >
399 vector< M, T >::vector( const T& _x, const T& _y, const T& _z )
400 {
401  array[ 0 ] = _x;
402  array[ 1 ] = _y;
403  array[ 2 ] = _z;
404 }
405 
406 template< size_t M, typename T >
407 vector< M, T >::vector( const T& _x, const T& _y, const T& _z, const T& _w )
408 {
409  array[ 0 ] = _x;
410  array[ 1 ] = _y;
411  array[ 2 ] = _z;
412  array[ 3 ] = _w;
413 }
414 
415 template< size_t M, typename T >
416 vector< M, T >::vector( const T* values )
417 {
418  memcpy( array, values, M * sizeof( T ));
419 }
420 
421 #ifdef __OSG_MATH
422 template< size_t M, typename T >
423 template< typename OSGVEC3 >
424 vector< M, T >::vector( const OSGVEC3& from,
425  typename enable_if< M == 3, OSGVEC3 >::type* )
426 {
427  array[ 0 ] = from.x();
428  array[ 1 ] = from.y();
429  array[ 2 ] = from.z();
430 }
431 #endif
432 
433 #ifndef SWIG
434 template< size_t M, typename T > template< typename TT >
435 // initializes the first M-1 values from vector_, the last from last_
436 vector< M, T >::vector( const vector< M-1, TT >& vector_, T last_,
437  typename enable_if< M == 4, TT >::type* )
438 {
439  array[0] = vector_.array[0];
440  array[1] = vector_.array[1];
441  array[2] = vector_.array[2];
442  array[3] = last_;
443 }
444 #endif
445 
446 // to-homogenous-coordinates ctor
447 template< size_t M, typename T > template< typename TT >
449  typename enable_if< M == 4, TT >::type* )
450 {
451  std::copy( source_.begin(), source_.end(), begin() );
452  at( M - 1 ) = static_cast< T >( 1.0 );
453 }
454 
455 // from-homogenous-coordinates ctor
456 template< size_t M, typename T > template< typename TT >
458  typename enable_if< M == 3, TT >::type* )
459 {
460  const T w_reci = static_cast< T >( 1.0 ) / source_( M );
461  iterator it = begin(), it_end = end();
462  for( size_t index = 0; it != it_end; ++it, ++index )
463  *it = source_( index ) * w_reci;
464 }
465 
466 template< size_t M, typename T >
467 template< typename U >
468 vector< M, T >::vector( const vector< M, U >& source_ )
469 {
470  (*this) = source_;
471 }
472 
473 namespace
474 {
475 template< size_t M, typename T >
476 vector< M, T > _createVector( const T x, const T y, const T z,
477  typename enable_if< M == 3 >::type* = nullptr )
478 {
479  return vector< M, T >( x, y, z );
480 }
481 
482 template< size_t M, typename T >
483 vector< M, T > _createVector( const T x, const T y, const T z,
484  typename enable_if< M == 4 >::type* = nullptr )
485 {
486  return vector< M, T >( x, y, z, 1 );
487 }
488 }
489 
490 template< size_t M, typename T > vector< M, T > vector< M, T >::zero()
491 {
492  return _createVector< M, T >( 0, 0, 0 );
493 }
494 
495 template< size_t M, typename T > vector< M, T > vector< M, T >::forward()
496 {
497  return _createVector< M, T >( 0, 0, -1 );
498 }
499 
500 template< size_t M, typename T > vector< M, T > vector< M, T >::backward()
501 {
502  return _createVector< M, T >( 0, 0, 1 );
503 }
504 
505 template< size_t M, typename T > vector< M, T > vector< M, T >::up()
506 {
507  return _createVector< M, T >( 0, 1, 0 );
508 }
509 
510 template< size_t M, typename T > vector< M, T > vector< M, T >::down()
511 {
512  return _createVector< M, T >( 0, -1, 0 );
513 }
514 
515 template< size_t M, typename T > vector< M, T > vector< M, T >::left()
516 {
517  return _createVector< M, T >( -1, 0, 0 );
518 }
519 
520 template< size_t M, typename T > vector< M, T > vector< M, T >::right()
521 {
522  return _createVector< M, T >( 1, 0, 0 );
523 }
524 
525 template< size_t M, typename T > vector< M, T > vector< M, T >::unitX()
526 {
527  return _createVector< M, T >( 1, 0, 0 );
528 }
529 
530 template< size_t M, typename T > vector< M, T > vector< M, T >::unitY()
531 {
532  return _createVector< M, T >( 0, 1, 0 );
533 }
534 
535 template< size_t M, typename T > vector< M, T > vector< M, T >::unitZ()
536 {
537  return _createVector< M, T >( 0, 0, 1 );
538 }
539 
540 template< size_t M, typename T > void vector< M, T >::set( T _a )
541 {
542  for( iterator it = begin(), it_end = end(); it != it_end; ++it )
543  *it = _a;
544 }
545 
546 template< size_t M, typename T > template< size_t N >
547 void vector< M, T >::set( const vector< N, T >& v )
548 {
549  size_t minimum = M;
550  if (N < M) minimum = N;
551  memcpy( array, v.array, sizeof( T ) * minimum );
552 }
553 
554 template< size_t M, typename T >
555 void vector< M, T >::set( T _x, T _y )
556 {
557  array[ 0 ] = _x;
558  array[ 1 ] = _y;
559 }
560 
561 template< size_t M, typename T >
562 void vector< M, T >::set( T _x, T _y, T _z )
563 {
564  array[ 0 ] = _x;
565  array[ 1 ] = _y;
566  array[ 2 ] = _z;
567 }
568 
569 template< size_t M, typename T >
570 void vector< M, T >::set( T _x, T _y, T _z, T _w )
571 {
572  array[ 0 ] = _x;
573  array[ 1 ] = _y;
574  array[ 2 ] = _z;
575  array[ 3 ] = _w;
576 }
577 
578 template< size_t M, typename T >
579 inline T&
580 vector< M, T >::operator()( size_t index )
581 {
582  return at( index );
583 }
584 
585 template< size_t M, typename T >
586 inline const T&
587 vector< M, T >::operator()( size_t index ) const
588 {
589  return at( index );
590 }
591 
592 template< size_t M, typename T >
593 inline T&
594 vector< M, T >::at( size_t index )
595 {
596  if( index >= M )
597  throw std::runtime_error( "at() - index out of bounds" );
598  return array[ index ];
599 }
600 
601 template< size_t M, typename T >
602 inline const T&
603 vector< M, T >::at( size_t index ) const
604 {
605  if ( index >= M )
606  throw std::runtime_error( "at() - index out of bounds" );
607  return array[ index ];
608 }
609 
610 template< size_t M, typename T >
612 {
613  return array;
614 }
615 
616 template< size_t M, typename T >
617 vector< M, T >::operator const T*() const
618 {
619  return array;
620 }
621 
622 template< size_t M, typename T >
624 vector< M, T >::operator*( const vector< M, T >& other ) const
625 {
626  vector< M, T > result;
627  for( size_t index = 0; index < M; ++index )
628  result.at( index ) = at( index ) * other.at( index );
629  return result;
630 }
631 
632 template< size_t M, typename T >
634 vector< M, T >::operator/( const vector< M, T >& other ) const
635 {
636  vector< M, T > result;
637  for( size_t index = 0; index < M; ++index )
638  result.at( index ) = at( index ) / other.at( index );
639  return result;
640 }
641 
642 template< size_t M, typename T >
644 vector< M, T >::operator+( const vector< M, T >& other ) const
645 {
646  vector< M, T > result;
647  for( size_t index = 0; index < M; ++index )
648  result.at( index ) = at( index ) + other.at( index );
649  return result;
650 }
651 
652 template< size_t M, typename T >
654 vector< M, T >::operator-( const vector< M, T >& other ) const
655 {
656  vector< M, T > result;
657  for( size_t index = 0; index < M; ++index )
658  result.at( index ) = at( index ) - other.at( index );
659  return result;
660 }
661 
662 template< size_t M, typename T >
663 void
665 {
666  for( size_t index = 0; index < M; ++index )
667  at( index ) *= other.at( index );
668 }
669 
670 template< size_t M, typename T >
671 void
673 {
674  for( size_t index = 0; index < M; ++index )
675  at( index ) /= other.at( index );
676 }
677 
678 template< size_t M, typename T >
679 void
681 {
682  for( size_t index = 0; index < M; ++index )
683  at( index ) += other.at( index );
684 }
685 
686 template< size_t M, typename T >
687 void
689 {
690  for( size_t index = 0; index < M; ++index )
691  at( index ) -= other.at( index );
692 }
693 
694 template< size_t M, typename T >
696 vector< M, T >::operator*( const T other ) const
697 {
698  vector< M, T > result;
699  for( size_t index = 0; index < M; ++index )
700  result.at( index ) = at( index ) * other;
701  return result;
702 }
703 
704 template< size_t M, typename T >
706 vector< M, T >::operator/( const T other ) const
707 {
708  vector< M, T > result;
709  for( size_t index = 0; index < M; ++index )
710  result.at( index ) = at( index ) / other;
711  return result;
712 }
713 
714 template< size_t M, typename T >
716 vector< M, T >::operator+( const T other ) const
717 {
718  vector< M, T > result;
719  for( size_t index = 0; index < M; ++index )
720  result.at( index ) = at( index ) + other;
721  return result;
722 }
723 
724 template< size_t M, typename T >
726 vector< M, T >::operator-( const T other ) const
727 {
728  vector< M, T > result;
729  for( size_t index = 0; index < M; ++index )
730  result.at( index ) = at( index ) - other;
731  return result;
732 }
733 
734 template< size_t M, typename T >
735 void
736 vector< M, T >::operator*=( const T other )
737 {
738  for( size_t index = 0; index < M; ++index )
739  at( index ) *= other;
740 }
741 
742 template< size_t M, typename T >
743 void
744 vector< M, T >::operator/=( const T other )
745 {
746  for( size_t index = 0; index < M; ++index )
747  at( index ) /= other;
748 }
749 
750 template< size_t M, typename T >
751 void
752 vector< M, T >::operator+=( const T other )
753 {
754  for( size_t index = 0; index < M; ++index )
755  at( index ) += other;
756 }
757 
758 template< size_t M, typename T >
759 void
760 vector< M, T >::operator-=( const T other )
761 {
762  for( size_t index = 0; index < M; ++index )
763  at( index ) -= other;
764 }
765 
766 template< size_t M, typename T >
769 {
770  vector< M, T > v( *this );
771  return v.negate();
772 }
773 
774 template< size_t M, typename T >
775 const vector< M, T >&
777 {
778  for( size_t index = 0; index < M; ++index )
779  array[ index ] = -array[ index ];
780  return *this;
781 }
782 
783 template< size_t M, typename T >
784 inline T&
786 {
787  return array[ 0 ];
788 }
789 
790 template< size_t M, typename T >
791 inline T&
793 {
794  return array[ 1 ];
795 }
796 
797 template< size_t M, typename T >
798 inline T&
800 {
801  return array[ 2 ];
802 }
803 
804 template< size_t M, typename T >
805 inline T&
807 {
808  return array[ 3 ];
809 }
810 
811 template< size_t M, typename T >
812 inline const T&
813 vector< M, T >::x() const
814 {
815  return array[ 0 ];
816 }
817 
818 template< size_t M, typename T >
819 inline const T&
820 vector< M, T >::y() const
821 {
822  return array[ 1 ];
823 }
824 
825 template< size_t M, typename T >
826 inline const T&
827 vector< M, T >::z() const
828 {
829  return array[ 2 ];
830 }
831 
832 template< size_t M, typename T >
833 inline const T&
834 vector< M, T >::w() const
835 {
836  return array[ 3 ];
837 }
838 
839 template< size_t M, typename T >
840 inline T&
842 {
843  return array[ 0 ];
844 }
845 
846 template< size_t M, typename T >
847 inline T&
849 {
850  return array[ 1 ];
851 }
852 
853 template< size_t M, typename T >
854 inline T&
856 {
857  return array[ 2 ];
858 }
859 
860 template< size_t M, typename T >
861 inline T&
863 {
864  return array[ 3 ];
865 }
866 
867 template< size_t M, typename T >
868 inline const T&
869 vector< M, T >::r() const
870 {
871  return array[ 0 ];
872 }
873 
874 template< size_t M, typename T >
875 inline const T&
876 vector< M, T >::g() const
877 {
878  return array[ 1 ];
879 }
880 
881 template< size_t M, typename T >
882 inline const T&
883 vector< M, T >::b() const
884 {
885  return array[ 2 ];
886 }
887 
888 template< size_t M, typename T >
889 inline const T&
890 vector< M, T >::a() const
891 {
892  return array[ 3 ];
893 }
894 
895 template< size_t M, typename T > template< typename TT >
897  typename enable_if< M == 3, TT >::type* )
898 {
899  const T x_ = y() * rhs.z() - z() * rhs.y();
900  const T y_ = z() * rhs.x() - x() * rhs.z();
901  const T z_ = x() * rhs.y() - y() * rhs.x();
902  x() = x_;
903  y() = y_;
904  z() = z_;
905  return *this;
906 }
907 
908 template< size_t M, typename T >
909 inline T vector< M, T >::dot( const vector< M, T >& other ) const
910 {
911  T tmp = 0.0;
912  for( size_t index = 0; index < M; ++index )
913  tmp += at( index ) * other.at( index );
914 
915  return tmp;
916 }
917 
918 template< size_t M, typename T > inline T vector< M, T >::normalize()
919 {
920  const T len = length();
921  if ( len <= std::numeric_limits< T >::epsilon( ))
922  return 0;
923 
924  const T tmp = 1.0 / len;
925  (*this) *= tmp;
926  return len;
927 }
928 
929 template< size_t M, typename T >
930 inline T vector< M, T >::length() const
931 {
932  return std::sqrt( squared_length() );
933 }
934 
935 template< size_t M, typename T >
936 inline T vector< M, T >::squared_length() const
937 {
938  T _squared_length = 0.0;
939  for( const_iterator it = begin(), it_end = end(); it != it_end; ++it )
940  _squared_length += (*it) * (*it);
941 
942  return _squared_length;
943 }
944 
945 template< size_t M, typename T >
946 inline T
947 vector< M, T >::distance( const vector< M, T >& other ) const
948 {
949  return std::sqrt( squared_distance( other ) );
950 }
951 
952 template< size_t M, typename T >
953 inline T vector< M, T >::squared_distance( const vector< M, T >& other ) const
954 {
955  vector< M, T > tmp( *this );
956  tmp -= other;
957  return tmp.squared_length();
958 }
959 
960 template< size_t M, typename T > inline T vector< M, T >::product() const
961 {
962  T result = at( 0 );
963  for( size_t i = 1; i < M; ++i )
964  result *= at( i );
965  return result;
966 }
967 
968 template< size_t M, typename T > template< typename TT >
970  typename enable_if< M==3, TT >::type* )
971 {
972  const T costheta = std::cos( theta );
973  const T sintheta = std::sin( theta );
974 
975  axis.normalize();
976  return *this = vector< 3, T >(
977  (costheta + ( 1 - costheta ) * axis.x() * axis.x() ) * x() +
978  (( 1 - costheta ) * axis.x() * axis.y() - axis.z() * sintheta ) * y() +
979  (( 1 - costheta ) * axis.x() * axis.z() + axis.y() * sintheta ) * z(),
980 
981  (( 1 - costheta ) * axis.x() * axis.y() + axis.z() * sintheta ) * x() +
982  ( costheta + ( 1 - costheta ) * axis.y() * axis.y() ) * y() +
983  (( 1 - costheta ) * axis.y() * axis.z() - axis.x() * sintheta ) * z(),
984 
985  (( 1 - costheta ) * axis.x() * axis.z() - axis.y() * sintheta ) * x() +
986  (( 1 - costheta ) * axis.y() * axis.z() + axis.x() * sintheta ) * y() +
987  ( costheta + ( 1 - costheta ) * axis.z() * axis.z() ) * z( ));
988 }
989 
990 // sphere layout: center xyz, radius w
991 template< size_t M, typename T > template< typename TT > inline vector< 3, T >
993  typename enable_if< M == 4, TT >::type* ) const
994 {
995  const vector< 3, T >& center_ = get_sub_vector< 3 >();
996 
997  vector< 3, T > projected_point( point );
998  projected_point -= center_;
999  projected_point.normalize();
1000  projected_point *= w();
1001  return center_ + projected_point;
1002 }
1003 
1004 // sphere layout: center xyz, radius w
1005 template< size_t M, typename T > template< typename TT > inline T
1007  typename enable_if< M == 4, TT >::type* )
1008  const
1009 {
1010  const vector< 3, T >& center_ = get_sub_vector< 3 >();
1011  return ( point - center_ ).length() - w();
1012 }
1013 
1014 template< size_t M, typename T > template< size_t N, size_t O >
1016  typename enable_if< M >= N+O >::type* ) const
1017 {
1018  return vector< N, T >( array + O );
1019 }
1020 
1021 template< size_t M, typename T > template< size_t N, size_t O >
1023  typename enable_if< M >= N+O >::type* )
1024 {
1025  ::memcpy( array + O, sub.array, N * sizeof( T ));
1026 }
1027 
1028 // plane: normal xyz, distance w
1029 template< size_t M, typename T > template< typename TT >
1030 inline T vector< M, T >::distance_to_plane( const vector< 3, TT >& point,
1031  typename enable_if< M == 4, TT >::type* ) const
1032 {
1033  const vector< 3, T >& normal = get_sub_vector< 3 >();
1034  return normal.dot( point ) + w();
1035 }
1036 
1037 // plane: normal xyz, distance w
1038 template< size_t M, typename T > template< typename TT > vector< 3, T >
1040  typename enable_if< M == 4, TT >::type* ) const
1041 {
1042  const vector< 3, T >& normal = get_sub_vector< 3 >();
1043  return point - ( normal * distance_to_plane( point ) );
1044 }
1045 
1046 template< size_t M, typename T >
1047 bool vector< M, T >::operator==( const vector< M, T >& other ) const
1048 {
1049  return memcmp( array, other.array, sizeof( array )) == 0;
1050 }
1051 
1052 template< size_t M, typename T >
1053 bool vector< M, T >::operator!=( const vector< M, T >& other ) const
1054 {
1055  return ! this->operator==( other );
1056 }
1057 
1058 template< size_t M, typename T >
1059 bool vector< M, T >::equals( const vector< M, T >& other, T tolerance ) const
1060 {
1061  for( size_t index = 0; index < M; ++index )
1062  if( fabs( at( index ) - other( index ) ) >= tolerance )
1063  return false;
1064  return true;
1065 
1066 }
1067 
1068 template< size_t M, typename T >
1069 bool
1070 vector< M, T >::operator<( const vector< M, T >& other ) const
1071 {
1072  for(size_t index = 0; index < M; ++index )
1073  {
1074  if (at( index ) < other.at( index )) return true;
1075  if (other.at( index ) < at( index )) return false;
1076  }
1077  return false;
1078 }
1079 
1080 template< size_t M, typename T >
1081 T vector< M, T >::operator=( T filler_value )
1082 {
1083  for( size_t index = 0; index < M; ++index )
1084  at( index ) = filler_value;
1085  return filler_value;
1086 }
1087 
1088 template< size_t M, typename T >
1090 {
1091  if( this != &other )
1092  memcpy( array, other.array, M * sizeof( T ) );
1093  return *this;
1094 }
1095 
1096 // returns void to avoid 'silent' loss of precision when chaining
1097 template< size_t M, typename T > template< typename U >
1098 void vector< M, T >::operator=( const vector< M, U >& source_ )
1099 {
1100  typedef typename vector< M, U >::const_iterator u_c_iter;
1101  u_c_iter it = source_.begin(), it_end = source_.end();
1102  for( iterator my_it = begin(); it != it_end; ++it, ++my_it )
1103  *my_it = static_cast< T >( *it );
1104 }
1105 
1106 template< size_t M, typename T >
1107 template< typename input_iterator_t >
1108 void
1109 vector< M, T >::iter_set( input_iterator_t begin_, input_iterator_t end_ )
1110 {
1111  input_iterator_t in_it = begin_;
1112  iterator it = begin(), it_end = end();
1113  for( ; it != it_end && in_it != end_; ++it, ++in_it )
1114  (*it) = static_cast< T >( *in_it );
1115 }
1116 
1117 template< size_t M, typename T >
1118 void vector< M, T >::clamp( const T& min, const T& max )
1119 {
1120  for( size_t i = 0; i < M; ++i )
1121  {
1122  if( array[i] < min )
1123  array[i] = min;
1124  if( array[i] > max )
1125  array[i] = max;
1126  }
1127 }
1128 
1129 template< size_t M, typename T >
1130 inline size_t
1132 {
1133  return M;
1134 }
1135 
1136 template< size_t M, typename T >
1137 size_t
1139 {
1140  return std::min_element( begin(), end() ) - begin();
1141 }
1142 
1143 template< size_t M, typename T >
1144 size_t
1146 {
1147  return std::max_element( begin(), end() ) - begin();
1148 }
1149 
1150 template< size_t M, typename T >
1151 T&
1153 {
1154  return *std::min_element( begin(), end() );
1155 }
1156 
1157 template< size_t M, typename T >
1158 const T&
1160 {
1161  return *std::min_element( begin(), end() );
1162 }
1163 
1164 template< size_t M, typename T >
1165 T&
1167 {
1168  return *std::max_element( begin(), end() );
1169 }
1170 
1171 template< size_t M, typename T >
1172 const T&
1174 {
1175  return *std::max_element( begin(), end() );
1176 }
1177 
1178 template< size_t M, typename T >
1179 inline typename vector< M, T >::iterator
1181 {
1182  return array;
1183 }
1184 
1185 template< size_t M, typename T >
1186 inline typename vector< M, T >::iterator
1188 {
1189  return array + M; ;
1190 }
1191 
1192 template< size_t M, typename T >
1193 inline typename vector< M, T >::const_iterator
1194 vector< M, T >::begin() const
1195 {
1196  return array;
1197 }
1198 
1199 template< size_t M, typename T >
1200 inline typename vector< M, T >::const_iterator
1201 vector< M, T >::end() const
1202 {
1203  return array + M; ;
1204 }
1205 
1206 template< size_t M, typename T >
1207 inline typename vector< M, T >::reverse_iterator
1209 {
1210  return array + M - 1;
1211 }
1212 
1213 template< size_t M, typename T >
1214 inline typename vector< M, T >::reverse_iterator
1216 {
1217  return array - 1;
1218 }
1219 
1220 template< size_t M, typename T >
1221 inline typename vector< M, T >::const_reverse_iterator
1222 vector< M, T >::rbegin() const
1223 {
1224  return array + M - 1;
1225 }
1226 
1227 template< size_t M, typename T >
1228 inline typename vector< M, T >::const_reverse_iterator
1229 vector< M, T >::rend() const
1230 {
1231  return array - 1;
1232 }
1233 
1234 template< size_t M, typename T >
1235 bool
1237 {
1238  const_iterator it = begin(), it_end = end();
1239  bool one = false;
1240  for( ; it != it_end; ++it )
1241  {
1242  if ( *it == 1.0 )
1243  {
1244  if ( one )
1245  return false;
1246  one = true;
1247  }
1248  else if ( *it != 0.0 )
1249  {
1250  return false;
1251  }
1252  }
1253  return one;
1254 }
1255 
1256 template< size_t M, typename T >
1257 void
1258 vector< M, T >::perturb( T perturbation )
1259 {
1260  for( iterator it = begin(), it_end = end(); it != it_end; ++it )
1261  {
1262  (*it) += ( rand() & 1u ) ? perturbation : -perturbation;
1263  }
1264 
1265 }
1266 
1267 template< size_t M, typename T >
1268 void
1270 {
1271  for( iterator it = begin(), it_end = end(); it != it_end; ++it )
1272  {
1273  (*it) = std::sqrt(*it);
1274  }
1275 }
1276 
1277 template< size_t M, typename T > void vector< M, T >::reciprocal()
1278 {
1279  for( iterator it = begin(), it_end = end(); it != it_end; ++it )
1280  (*it) = static_cast< T >( 1 ) / (*it);
1281 }
1282 
1283 template< size_t M, typename T > void vector< M, T >::reciprocal_safe()
1284 {
1285  for( iterator it = begin(), it_end = end(); it != it_end; ++it )
1286  {
1287  T& v = *it;
1288 
1289  if( v == 0 )
1290  v = std::numeric_limits< T >::max();
1291  else
1292  v = static_cast< T >( 1 ) / v;
1293  }
1294 }
1295 
1296 template< size_t M, typename T >
1297 template< typename TT >
1298 void
1300 {
1301  typedef vmml::vector< M, TT > vector_tt_type ;
1302  typedef typename vector_tt_type::const_iterator tt_const_iterator;
1303 
1304  iterator it = begin(), it_end = end();
1305  tt_const_iterator other_it = other.begin();
1306  for( ; it != it_end; ++it, ++other_it )
1307  {
1308  *it = static_cast< T >( *other_it );
1309  }
1310 }
1311 
1312 template< size_t M, typename T >
1313 size_t
1314 vector< M, T >::nnz() const
1315 {
1316  size_t counter = 0;
1317 
1318  const_iterator it = begin(),
1319  it_end = end();
1320  for( ; it != it_end; ++it)
1321  {
1322  if ( *it != 0 ) {
1323  ++counter;
1324  }
1325  }
1326 
1327  return counter;
1328 }
1329 
1330 template< size_t M, typename T >
1331 double
1332 vector< M, T >::norm( ) const
1333 {
1334  double norm_v = 0.0;
1335 
1336  const_iterator it = begin(), it_end = end();
1337  for( ; it != it_end; ++it )
1338  {
1339  norm_v += *it * *it;
1340  }
1341 
1342  return std::sqrt(norm_v);
1343 }
1344 
1345 template< size_t M, typename T >
1346 void
1347 vector< M, T >::set_random( int seed )
1348 {
1349  if ( seed >= 0 )
1350  srand( seed );
1351 
1352  for( size_t i = 0; i < M; ++i )
1353  {
1354  const double fillValue = double( rand( )) / double( RAND_MAX );
1355  at( i ) = -1.0 + 2.0 * fillValue;
1356  }
1357 }
1358 
1359 } // namespace vmml
1360 
1361 #endif
vector< N, T > get_sub_vector(typename enable_if< M >=N+O >::type *=nullptr) const
Definition: vector.hpp:1015
void set_sub_vector(const vector< N, T > &sub, typename enable_if< M >=N+O >::type *=nullptr)
Set the sub vector of the given length at the given offset.
Definition: vector.hpp:1022
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:309
T product() const
Definition: vector.hpp:960