LCOV - code coverage report
Current view: top level - vmmlib - vector.hpp (source / functions) Hit Total Coverage
Test: vmmlib Lines: 255 270 94.4 %
Date: 2015-11-02 15:45:14 Functions: 145 147 98.6 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2006-2015, 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/vmmlib_config.hpp>
      37             : #include <vmmlib/math.hpp>
      38             : #include <vmmlib/enable_if.hpp>
      39             : #include <vmmlib/exception.hpp>
      40             : 
      41             : #include <iostream>
      42             : #include <iomanip>
      43             : #include <vector>
      44             : #include <string>
      45             : #include <cstring>
      46             : #include <limits>
      47             : #include <algorithm>
      48             : 
      49             : namespace vmml
      50             : {
      51             : 
      52             : template< size_t M, typename T = float >
      53             : class vector
      54             : {
      55             : public:
      56             :     typedef T                                       value_type;
      57             :     typedef T*                                      iterator;
      58             :     typedef const T*                                const_iterator;
      59             :     typedef std::reverse_iterator< iterator >       reverse_iterator;
      60             :     typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
      61             : 
      62             :     static const size_t DIMENSION = M;
      63             : 
      64             :     // constructors
      65          79 :     vector() : array() {} // http://stackoverflow.com/questions/5602030
      66             :     explicit vector( const T& a ); // sets all components to a;
      67             :     vector( const T& x, const T& y );
      68             :     vector( const T& x, const T& y, const T& z );
      69             :     vector( const T& x, const T& y, const T& z, const T& w );
      70             : 
      71             : #ifndef SWIG
      72             :     // initializes the first M-1 values from vector_, the last from last_
      73             :     vector( const vector< M-1, T >& vector_, T last_ );
      74             : #endif
      75             : 
      76             :     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* = 0 );
      82             : #endif
      83             : 
      84             :     // vec< M > with homogeneous coordinates <-> vec< M-1 > conversion ctor
      85             :     // to-homogenous-coordinates ctor
      86             :     template< size_t N >
      87             :     vector( const vector< N, T >& source_,
      88             :             typename enable_if< N == M - 1 >::type* = 0 );
      89             : 
      90             :     // from-homogenous-coordinates vector
      91             :     template< size_t N >
      92             :     vector( const vector< N, T >& source_,
      93             :             typename enable_if< N == M + 1 >::type* = 0  );
      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             : #  ifndef VMMLIB_NO_CONVERSION_OPERATORS
     108             :     // conversion operators
     109             :     inline operator T*();
     110             :     inline operator const T*() const;
     111             : #  else
     112             :     inline T& operator[]( size_t index );
     113             :     inline const T& operator[]( size_t index ) const;
     114             : #  endif
     115             : 
     116             :     // accessors
     117             :     inline T& operator()( size_t index );
     118             :     inline const T& operator()( size_t index ) const;
     119             : 
     120             :     inline T& at( size_t index );
     121             :     inline const T& at( size_t index ) const;
     122             : 
     123             :     // element accessors for M <= 4;
     124             :     inline T& x();
     125             :     inline T& y();
     126             :     inline T& z();
     127             :     inline T& w();
     128             :     inline const T& x() const;
     129             :     inline const T& y() const;
     130             :     inline const T& z() const;
     131             :     inline const T& w() const;
     132             : 
     133             :     // pixel color element accessors for M<= 4
     134             :     inline T& r();
     135             :     inline T& g();
     136             :     inline T& b();
     137             :     inline T& a();
     138             :     inline const T& r() const;
     139             :     inline const T& g() const;
     140             :     inline const T& b() const;
     141             :     inline const T& a() const;
     142             : 
     143             :     bool operator==( const vector& other ) const;
     144             :     bool operator!=( const vector& other ) const;
     145             :     bool equals( const vector& other,
     146             :                  T tolerance = std::numeric_limits< T >::epsilon() ) const;
     147             :     bool operator<( const vector& other ) const;
     148             : 
     149             :     // remember kids: c_arrays are dangerous and evil!
     150             :     vector& operator=( const T* c_array );
     151             :     T operator=( T filler );
     152             : 
     153             :     vector& operator=( const vector& other );
     154             : 
     155             :     // returns void to avoid 'silent' loss of precision when chaining
     156             :     template< typename U > void operator=( const vector< M, U >& other );
     157             : 
     158             :     // to-homogenous-coordinates assignment operator
     159             :     // non-chainable because of sfinae
     160             :     template< size_t N >
     161             :     typename enable_if< N == M - 1 >::type*
     162             :         operator=( const vector< N, T >& source_ );
     163             : 
     164             :     // from-homogenous-coordinates assignment operator
     165             :     // non-chainable because of sfinae
     166             :     template< size_t N >
     167             :     typename enable_if< N == M + 1 >::type*
     168             :         operator=( const vector< N, T >& source_ );
     169             : 
     170             :     vector operator*( const vector& other ) const;
     171             :     vector operator/( const vector& other ) const;
     172             :     vector operator+( const vector& other ) const;
     173             :     vector operator-( const vector& other ) const;
     174             : 
     175             :     void operator*=( const vector& other );
     176             :     void operator/=( const vector& other );
     177             :     void operator+=( const vector& other );
     178             :     void operator-=( const vector& other );
     179             : 
     180             :     vector operator*( const T other ) const;
     181             :     vector operator/( const T other ) const;
     182             :     vector operator+( const T other ) const;
     183             :     vector operator-( const T other ) const;
     184             : 
     185             :     void operator*=( const T other );
     186             :     void operator/=( const T other );
     187             :     void operator+=( const T other );
     188             :     void operator-=( const T other );
     189             : 
     190             :     vector operator-() const;
     191             : 
     192             :     const vector& negate();
     193             : 
     194             :     void set( T a ); // sets all components to a;
     195             : #ifndef SWIG
     196             :     void set( const vector< M-1, T >& v, T a );
     197             : #endif
     198             :     template< size_t N >
     199             :     void set( const vector< N, T >& v );
     200             : 
     201             :     // sets the first few components to a certain value
     202             :     void set( T x, T y );
     203             :     void set( T x, T y, T z );
     204             :     void set( T x, T y, T z, T w );
     205             : 
     206             :     template< typename input_iterator_t >
     207             :     void iter_set( input_iterator_t begin_, input_iterator_t end_ );
     208             : 
     209             :     // compute the cross product of two vectors
     210             :     // note: there's also a free function:
     211             :     // vector<> cross( const vector<>, const vector<> )
     212             : 
     213             :     // result = vec1.cross( vec2 ) => retval result = vec1 x vec2
     214             :     template< typename TT >
     215             :     vector cross( const vector< M, TT >& rhs,
     216             :                   typename enable_if< M == 3, TT >::type* = 0 ) const;
     217             : 
     218             :     // result.cross( vec1, vec2 ) => (this) = vec1 x vec2
     219             :     template< typename TT >
     220             :     void cross( const vector< M, TT >& a, const vector< M, TT >& b,
     221             :                 typename enable_if< M == 3, TT >::type* = 0 );
     222             : 
     223             : 
     224             :     // compute the dot product of two vectors
     225             :     // note: there's also a free function:
     226             :     // T dot( const vector<>, const vector<> );
     227             :     inline T dot( const vector& other ) const;
     228             : 
     229             : 
     230             :     // normalize the vector
     231             :     // note: there's also a free function:
     232             :     // vector<> normalize( const vector<> );
     233             :     inline T normalize();
     234             : 
     235             :     //sets all vector components to random values
     236             :     //remember to set srand( seed );
     237             :     //if seed is set to -1, srand( seed ) was set outside set_random
     238             :     //otherwise srand( seed ) will be called with the given seed
     239             :     void set_random( int seed = -1 );
     240             : 
     241             :     inline T length() const;
     242             :     inline T squared_length() const;
     243             : 
     244             :     inline T distance( const vector& other ) const;
     245             :     inline T squared_distance( const vector& other ) const;
     246             : 
     247             :     /** @return the product of all elements of this vector */
     248             :     T product() const;
     249             : 
     250             :     template< typename TT >
     251             :     vector< 3, T > rotate( const T theta, vector< M, TT > axis,
     252             :                            typename enable_if< M == 3, TT >::type* = 0 ) const;
     253             : 
     254             :     // right hand system, CCW triangle
     255             :     // (*this) = normal of v0,v1,v2
     256             :     void compute_normal( const vector& v0, const vector& v1, const vector& v2 );
     257             :     // retval = normal of (this), v1, v2
     258             :     vector compute_normal( const vector& v1, const vector& v2 ) const;
     259             : 
     260             :     /** @return the sub vector at the given position and length. */
     261             :     template< size_t N >
     262             :     vector< N, T >& get_sub_vector( size_t offset = 0,
     263             :         typename enable_if< M >= N >::type* = 0 );
     264             : 
     265             :     /** @return the sub vector at the given position and length. */
     266             :     template< size_t N >
     267             :     const vector< N, T >& get_sub_vector( size_t offset = 0,
     268             :         typename enable_if< M >= N >::type* = 0 ) const;
     269             : 
     270             :     // sphere functions - sphere layout: center xyz, radius w
     271             :     template< typename TT >
     272             :     inline vector< 3, T > project_point_onto_sphere(
     273             :         const vector< 3, TT >& point,
     274             :         typename enable_if< M == 4, TT >::type* = 0 ) const;
     275             : 
     276             :     // returns a negative distance if the point lies in the sphere
     277             :     template< typename TT >
     278             :     inline T distance_to_sphere( const vector< 3, TT >& point,
     279             :         typename enable_if< M == 4, TT >::type* = 0 ) const;
     280             : 
     281             :     // plane functions - plane layout; normal xyz, distance w
     282             :     template< typename TT >
     283             :     inline T distance_to_plane( const vector< 3, TT >& point,
     284             :         typename enable_if< M == 4, TT >::type* = 0 ) const;
     285             : 
     286             :     template< typename TT >
     287             :     inline vector< 3, T > project_point_onto_plane(
     288             :         const vector< 3, TT >& point,
     289             :         typename enable_if< M == 4, TT >::type* = 0 ) const;
     290             : 
     291             :     // returns the index of the minimal resp. maximal value in the vector
     292             :     size_t      find_min_index() const;
     293             :     size_t      find_max_index() const;
     294             : 
     295             :     // returns the index of the minimal resp. maximal value in the vector
     296             :     size_t      find_abs_min_index() const;
     297             :     size_t      find_abs_max_index() const;
     298             : 
     299             :     // returns minimal resp. maximal value in the vector
     300             :     T&          find_min();
     301             :     T&          find_max();
     302             :     const T&    find_min() const;
     303             :     const T&    find_max() const;
     304             : 
     305             :     void clamp( const T& min = 0.0, const T& max = 1.0 );
     306             : 
     307             :     template< typename TT >
     308             :     void scale_to( vector< M, TT >& scaled_vector,
     309             :         T min_value = -1.0, T max_value = 1.0 ) const;
     310             : 
     311             :     inline static size_t size(); // returns M
     312             : 
     313             :     bool is_unit_vector() const;
     314             : 
     315             :     // perturbs each component by randomly + or - the perturbation parameter
     316             :     void perturb( T perturbation = 0.0001 );
     317             : 
     318             :     void sqrt_elementwise();
     319             :     double norm() const; //l2 norm
     320             : 
     321             :     // computes the reciprocal value for each component, x = 1/x;
     322             :     // WARNING: might result in nans if division by 0!
     323             :     void reciprocal();
     324             :     // computes the reciprocal value for each component, x = 1/x;
     325             :     // checks every component for 0, sets to max value if zero.
     326             :     void reciprocal_safe();
     327             : 
     328             :     template< typename TT >
     329             :     void cast_from( const vector< M, TT >& other );
     330             : 
     331             :     size_t nnz() const;
     332             : 
     333             :     // test each component of the vector for isnan and isinf
     334             :     //  inline bool is_valid() const; -> moved to class validator
     335             : 
     336           0 :     friend std::ostream& operator<< ( std::ostream& os, const vector& vector_ )
     337             :     {
     338           0 :         const std::ios::fmtflags flags = os.flags();
     339           0 :         const int                prec  = os.precision();
     340             : 
     341           0 :         os.setf( std::ios::right, std::ios::adjustfield );
     342           0 :         os.precision( 5 );
     343           0 :         os << "[ ";
     344           0 :         for( size_t index = 0; index < M; ++index )
     345           0 :             os << std::setw(10) << vector_.at( index ) << " ";
     346           0 :         os << "]";
     347           0 :         os.precision( prec );
     348           0 :         os.setf( flags );
     349           0 :         return os;
     350             :     }
     351             : 
     352             :     T array[ M ];    //!< storage
     353             : 
     354             : #ifndef SWIG
     355             :     // Vector3 defaults
     356             :     static const vector FORWARD;
     357             :     static const vector BACKWARD;
     358             :     static const vector UP;
     359             :     static const vector DOWN;
     360             :     static const vector LEFT;
     361             :     static const vector RIGHT;
     362             : 
     363             :     static const vector ONE;
     364             :     static const vector ZERO;
     365             : 
     366             :     // Unit vectors
     367             :     static const vector UNIT_X;
     368             :     static const vector UNIT_Y;
     369             :     static const vector UNIT_Z;
     370             : #endif
     371             : 
     372             : }; // class vector
     373             : 
     374             : //
     375             : // typedefs and statics
     376             : //
     377             : #ifndef SWIG
     378             : template< size_t M, typename T >
     379             : const vector< M, T > vector< M, T >::FORWARD( 0, 0, -1 );
     380             : template< size_t M, typename T >
     381             : const vector< M, T > vector< M, T >::BACKWARD( 0, 0, 1 );
     382             : template< size_t M, typename T >
     383             : const vector< M, T > vector< M, T >::UP( 0, 1, 0 );
     384             : template< size_t M, typename T >
     385             : const vector< M, T > vector< M, T >::DOWN( 0, -1, 0 );
     386             : template< size_t M, typename T >
     387             : const vector< M, T > vector< M, T >::LEFT( -1, 0, 0 );
     388             : template< size_t M, typename T >
     389             : const vector< M, T > vector< M, T >::RIGHT( 1, 0, 0 );
     390             : template< size_t M, typename T >
     391             : 
     392             : const vector< M, T > vector< M, T >::ONE( static_cast< T >( 1 ));
     393             : template< size_t M, typename T >
     394             : const vector< M, T > vector< M, T >::ZERO( static_cast< T >( 0 ));
     395             : template< size_t M, typename T >
     396             : 
     397             : const vector< M, T > vector< M, T >::UNIT_X( 1, 0, 0 );
     398             : template< size_t M, typename T >
     399             : const vector< M, T > vector< M, T >::UNIT_Y( 0, 1, 0 );
     400             : template< size_t M, typename T >
     401             : const vector< M, T > vector< M, T >::UNIT_Z( 0, 0, 1 );
     402             : #endif
     403             : 
     404             : #ifndef VMMLIB_NO_TYPEDEFS
     405             : #  ifdef _MSC_VER
     406             :      typedef UINT8 uint8_t;
     407             : #  endif
     408             : typedef vmml::vector< 2, int > Vector2i;
     409             : typedef vmml::vector< 3, int > Vector3i;
     410             : typedef vmml::vector< 4, int > Vector4i;
     411             : typedef vmml::vector< 2, unsigned > Vector2ui;
     412             : typedef vmml::vector< 3, unsigned > Vector3ui;
     413             : typedef vmml::vector< 4, unsigned > Vector4ui;
     414             : typedef vmml::vector< 3, double > Vector3d;
     415             : typedef vmml::vector< 4, double > Vector4d;
     416             : typedef vmml::vector< 2, float > Vector2f;
     417             : typedef vmml::vector< 3, float > Vector3f;
     418             : typedef vmml::vector< 4, float > Vector4f;
     419             : typedef vmml::vector< 3, uint8_t > Vector3ub;
     420             : typedef vmml::vector< 4, uint8_t > Vector4ub;
     421             : #endif
     422             : 
     423             : //
     424             : //  some free functions for convenience
     425             : //
     426             : 
     427             : template< size_t M, typename T >
     428             : bool equals( const vector< M, T >& a, const vector< M, T >& b )
     429             : {
     430             :     return a.equals( b );
     431             : }
     432             : 
     433             : 
     434             : // allows float * vector, not only vector * float
     435             : template< size_t M, typename T >
     436           1 : static vector< M, T > operator* ( T factor, const vector< M, T >& vector_ )
     437             : {
     438           1 :     return vector_ * factor;
     439             : }
     440             : 
     441             : 
     442             : template< size_t M, typename T >
     443             : inline T dot( const vector< M, T >& first, const vector< M, T >& second )
     444             : {
     445             :     return first.dot( second );
     446             : }
     447             : 
     448             : 
     449             : template< size_t M, typename T >
     450             : inline vector< M, T > cross( const vector< 3, T >& a, const vector< 3, T >& b )
     451             : {
     452             :     return a.cross( b );
     453             : }
     454             : 
     455             : 
     456             : template< size_t M, typename T >
     457             : inline vector< M, T > normalize( const vector< M, T >& vector_ )
     458             : {
     459             :     vector< M, T > v( vector_ );
     460             :     v.normalize();
     461             :     return v;
     462             : }
     463             : 
     464             : template< typename T >
     465           6 : inline vector< 4, T > compute_plane( const vector< 3, T >& a,
     466             :                                      const vector< 3, T >& b,
     467             :                                      const vector< 3, T >& c )
     468             : {
     469           6 :     const vector< 3, T > cb = b - c;
     470           6 :     const vector< 3, T > ba = a - b;
     471             : 
     472           6 :     vector< 4, T > plane = cb.cross( ba );
     473           6 :     plane.normalize();
     474           6 :     plane.w() = -plane.x() * a.x() - plane.y() * a.y() - plane.z() * a.z();
     475           6 :     return plane;
     476             : }
     477             : 
     478             : template< size_t M, typename T >
     479           3 : vector< M, T >::vector( const T& _a )
     480             : {
     481          13 :     for( iterator it = begin(), it_end = end(); it != it_end; ++it )
     482             :     {
     483          10 :         *it = _a;
     484             :     }
     485           3 : }
     486             : 
     487             : template< size_t M, typename T >
     488           9 : vector< M, T >::vector( const T& _x, const T& _y )
     489             : {
     490           9 :     array[ 0 ] = _x;
     491           9 :     array[ 1 ] = _y;
     492           9 : }
     493             : 
     494             : 
     495             : template< size_t M, typename T >
     496          33 : vector< M, T >::vector( const T& _x, const T& _y, const T& _z )
     497             : {
     498          33 :     array[ 0 ] = _x;
     499          33 :     array[ 1 ] = _y;
     500          33 :     array[ 2 ] = _z;
     501          33 : }
     502             : 
     503             : 
     504             : 
     505             : template< size_t M, typename T >
     506          19 : vector< M, T >::vector( const T& _x, const T& _y, const T& _z, const T& _w )
     507             : {
     508          19 :     array[ 0 ] = _x;
     509          19 :     array[ 1 ] = _y;
     510          19 :     array[ 2 ] = _z;
     511          19 :     array[ 3 ] = _w;
     512          19 : }
     513             : 
     514             : 
     515             : template< size_t M, typename T >
     516             : vector< M, T >::vector( const T* values )
     517             : {
     518             :     memcpy( array, values, M * sizeof( T ));
     519             : }
     520             : 
     521             : #ifdef __OSG_MATH
     522             : template< size_t M, typename T >
     523             : template< typename OSGVEC3 >
     524             : vector< M, T >::vector( const OSGVEC3& from,
     525             :                         typename enable_if< M == 3, OSGVEC3 >::type* )
     526             : {
     527             :     array[ 0 ] = from.x();
     528             :     array[ 1 ] = from.y();
     529             :     array[ 2 ] = from.z();
     530             : }
     531             : #endif
     532             : 
     533             : #ifndef SWIG
     534             : template< size_t M, typename T >
     535             : // initializes the first M-1 values from vector_, the last from last_
     536           1 : vector< M, T >::vector( const vector< M-1, T >& vector_, T last_ )
     537             : {
     538             :     typename vector< M-1, T >::const_iterator
     539           1 :         it = vector_.begin(), it_end = vector_.end();
     540             : 
     541           1 :     iterator my_it = begin();
     542             : 
     543           4 :     for( ; it != it_end; ++it, ++my_it )
     544             :     {
     545           3 :         (*my_it) = *it;
     546             :     }
     547           1 :     (*my_it) = last_;
     548           1 : }
     549             : #endif
     550             : 
     551             : 
     552             : 
     553             : // to-homogenous-coordinates ctor
     554             : template< size_t M, typename T >
     555             : template< size_t N >
     556          41 : vector< M, T >::vector( const vector< N, T >& source_,
     557             :                         typename enable_if< N == M - 1 >::type* )
     558             : {
     559          41 :     (*this) = source_;
     560          41 : }
     561             : 
     562             : 
     563             : 
     564             : 
     565             : // from-homogenous-coordinates ctor
     566             : template< size_t M, typename T >
     567             : template< size_t N >
     568           1 : vector< M, T >::vector( const vector< N, T >& source_,
     569             :                         typename enable_if< N == M + 1 >::type* )
     570             : {
     571           1 :     (*this) = source_;
     572           1 : }
     573             : 
     574             : 
     575             : template< size_t M, typename T >
     576             : template< typename U >
     577           1 : vector< M, T >::vector( const vector< M, U >& source_ )
     578             : {
     579           1 :     (*this) = source_;
     580           1 : }
     581             : 
     582             : 
     583             : 
     584           1 : template< size_t M, typename T > void vector< M, T >::set( T _a )
     585             : {
     586           5 :     for( iterator it = begin(), it_end = end(); it != it_end; ++it )
     587           4 :         *it = _a;
     588           1 : }
     589             : 
     590             : 
     591             : #ifndef SWIG
     592             : template< size_t M, typename T >
     593             : void vector< M, T >::set( const vector< M-1, T >& v, T _a )
     594             : {
     595             :     memcpy( array, v.array, sizeof( T ) * (M-1) );
     596             :     at( M-1 ) = _a;
     597             : }
     598             : #endif
     599             : 
     600             : template< size_t M, typename T > template< size_t N >
     601             : void vector< M, T >::set( const vector< N, T >& v )
     602             : {
     603             :     size_t minimum = M;
     604             :     if (N < M) minimum = N;
     605             :     memcpy( array, v.array, sizeof( T ) * minimum );
     606             : }
     607             : 
     608             : template< size_t M, typename T >
     609             : void vector< M, T >::set( T _x, T _y )
     610             : {
     611             :     array[ 0 ] = _x;
     612             :     array[ 1 ] = _y;
     613             : }
     614             : 
     615             : 
     616             : template< size_t M, typename T >
     617             : void vector< M, T >::set( T _x, T _y, T _z )
     618             : {
     619             :     array[ 0 ] = _x;
     620             :     array[ 1 ] = _y;
     621             :     array[ 2 ] = _z;
     622             : }
     623             : 
     624             : 
     625             : 
     626             : template< size_t M, typename T >
     627           1 : void vector< M, T >::set( T _x, T _y, T _z, T _w )
     628             : {
     629           1 :     array[ 0 ] = _x;
     630           1 :     array[ 1 ] = _y;
     631           1 :     array[ 2 ] = _z;
     632           1 :     array[ 3 ] = _w;
     633           1 : }
     634             : 
     635             : 
     636             : template< size_t M, typename T >
     637             : inline T&
     638             : vector< M, T >::operator()( size_t index )
     639             : {
     640             :     return at( index );
     641             : }
     642             : 
     643             : 
     644             : 
     645             : template< size_t M, typename T >
     646             : inline const T&
     647           4 : vector< M, T >::operator()( size_t index ) const
     648             : {
     649           4 :     return at( index );
     650             : }
     651             : 
     652             : 
     653             : 
     654             : template< size_t M, typename T >
     655             : inline T&
     656         346 : vector< M, T >::at( size_t index )
     657             : {
     658             :     #ifdef VMMLIB_SAFE_ACCESSORS
     659         346 :     if ( index >= M )
     660             :     {
     661           0 :         VMMLIB_ERROR( "at() - index out of bounds", VMMLIB_HERE );
     662             :     }
     663             :     #endif
     664         346 :     return array[ index ];
     665             : }
     666             : 
     667             : 
     668             : 
     669             : template< size_t M, typename T >
     670             : inline const T&
     671         524 : vector< M, T >::at( size_t index ) const
     672             : {
     673             :     #ifdef VMMLIB_SAFE_ACCESSORS
     674         524 :     if ( index >= M )
     675             :     {
     676           0 :         VMMLIB_ERROR( "at() - index out of bounds", VMMLIB_HERE );
     677             :     }
     678             :     #endif
     679         524 :     return array[ index ];
     680             : }
     681             : 
     682             : 
     683             : #ifndef VMMLIB_NO_CONVERSION_OPERATORS
     684             : 
     685             : template< size_t M, typename T >
     686             : vector< M, T >::operator T*()
     687             : {
     688             :     return array;
     689             : }
     690             : 
     691             : 
     692             : 
     693             : template< size_t M, typename T >
     694          72 : vector< M, T >::operator const T*() const
     695             : {
     696          72 :     return array;
     697             : }
     698             : #else
     699             : 
     700             : template< size_t M, typename T >
     701             : T&
     702             : vector< M, T >::operator[]( size_t index )
     703             : {
     704             :     return at( index );
     705             : }
     706             : 
     707             : template< size_t M, typename T >
     708             : const T&
     709             : vector< M, T >::operator[]( size_t index ) const
     710             : {
     711             :     return at( index );
     712             : }
     713             : 
     714             : 
     715             : #endif
     716             : 
     717             : 
     718             : #if 0
     719             : template< size_t M, typename T >
     720             : inline T&
     721             : vector< M, T >::operator[]( size_t index )
     722             : {
     723             :     return at( index );
     724             : }
     725             : 
     726             : 
     727             : 
     728             : template< size_t M, typename T >
     729             : inline const T&
     730             : vector< M, T >::operator[]( size_t index ) const
     731             : {
     732             :     return at( index );
     733             : }
     734             : #endif
     735             : 
     736             : 
     737             : template< size_t M, typename T >
     738             : vector< M, T >
     739           1 : vector< M, T >::operator*( const vector< M, T >& other ) const
     740             : {
     741           1 :     vector< M, T > result;
     742           5 :     for( size_t index = 0; index < M; ++index )
     743           4 :         result.at( index ) = at( index ) * other.at( index );
     744           1 :     return result;
     745             : }
     746             : 
     747             : 
     748             : 
     749             : template< size_t M, typename T >
     750             : vector< M, T >
     751           1 : vector< M, T >::operator/( const vector< M, T >& other ) const
     752             : {
     753           1 :     vector< M, T > result;
     754           5 :     for( size_t index = 0; index < M; ++index )
     755           4 :         result.at( index ) = at( index ) / other.at( index );
     756           1 :     return result;
     757             : }
     758             : 
     759             : 
     760             : 
     761             : template< size_t M, typename T >
     762             : vector< M, T >
     763           4 : vector< M, T >::operator+( const vector< M, T >& other ) const
     764             : {
     765           4 :     vector< M, T > result;
     766          20 :     for( size_t index = 0; index < M; ++index )
     767          16 :         result.at( index ) = at( index ) + other.at( index );
     768           4 :     return result;
     769             : }
     770             : 
     771             : 
     772             : 
     773             : template< size_t M, typename T >
     774             : vector< M, T >
     775          18 : vector< M, T >::operator-( const vector< M, T >& other ) const
     776             : {
     777          18 :     vector< M, T > result;
     778          76 :     for( size_t index = 0; index < M; ++index )
     779          58 :         result.at( index ) = at( index ) - other.at( index );
     780          18 :     return result;
     781             : }
     782             : 
     783             : 
     784             : 
     785             : 
     786             : template< size_t M, typename T >
     787             : void
     788           1 : vector< M, T >::operator*=( const vector< M, T >& other )
     789             : {
     790           5 :     for( size_t index = 0; index < M; ++index )
     791           4 :         at( index ) *= other.at( index );
     792           1 : }
     793             : 
     794             : 
     795             : 
     796             : template< size_t M, typename T >
     797             : void
     798           1 : vector< M, T >::operator/=( const vector< M, T >& other )
     799             : {
     800           5 :     for( size_t index = 0; index < M; ++index )
     801           4 :         at( index ) /= other.at( index );
     802           1 : }
     803             : 
     804             : 
     805             : 
     806             : template< size_t M, typename T >
     807             : void
     808           1 : vector< M, T >::operator+=( const vector< M, T >& other )
     809             : {
     810           5 :     for( size_t index = 0; index < M; ++index )
     811           4 :         at( index ) += other.at( index );
     812           1 : }
     813             : 
     814             : 
     815             : 
     816             : template< size_t M, typename T >
     817             : void
     818           1 : vector< M, T >::operator-=( const vector< M, T >& other )
     819             : {
     820           5 :     for( size_t index = 0; index < M; ++index )
     821           4 :         at( index ) -= other.at( index );
     822           1 : }
     823             : 
     824             : 
     825             : 
     826             : template< size_t M, typename T >
     827             : vector< M, T >
     828          14 : vector< M, T >::operator*( const T other ) const
     829             : {
     830          14 :     vector< M, T > result;
     831          58 :     for( size_t index = 0; index < M; ++index )
     832          44 :         result.at( index ) = at( index ) * other;
     833          14 :     return result;
     834             : }
     835             : 
     836             : 
     837             : 
     838             : template< size_t M, typename T >
     839             : vector< M, T >
     840           1 : vector< M, T >::operator/( const T other ) const
     841             : {
     842           1 :     vector< M, T > result;
     843           5 :     for( size_t index = 0; index < M; ++index )
     844           4 :         result.at( index ) = at( index ) / other;
     845           1 :     return result;
     846             : }
     847             : 
     848             : 
     849             : 
     850             : template< size_t M, typename T >
     851             : vector< M, T >
     852           1 : vector< M, T >::operator+( const T other ) const
     853             : {
     854           1 :     vector< M, T > result;
     855           5 :     for( size_t index = 0; index < M; ++index )
     856           4 :         result.at( index ) = at( index ) + other;
     857           1 :     return result;
     858             : }
     859             : 
     860             : 
     861             : 
     862             : template< size_t M, typename T >
     863             : vector< M, T >
     864           1 : vector< M, T >::operator-( const T other ) const
     865             : {
     866           1 :     vector< M, T > result;
     867           5 :     for( size_t index = 0; index < M; ++index )
     868           4 :         result.at( index ) = at( index ) - other;
     869           1 :     return result;
     870             : }
     871             : 
     872             : 
     873             : 
     874             : 
     875             : template< size_t M, typename T >
     876             : void
     877           9 : vector< M, T >::operator*=( const T other )
     878             : {
     879          44 :     for( size_t index = 0; index < M; ++index )
     880          35 :         at( index ) *= other;
     881           9 : }
     882             : 
     883             : 
     884             : 
     885             : template< size_t M, typename T >
     886             : void
     887           1 : vector< M, T >::operator/=( const T other )
     888             : {
     889           5 :     for( size_t index = 0; index < M; ++index )
     890           4 :         at( index ) /= other;
     891           1 : }
     892             : 
     893             : 
     894             : 
     895             : template< size_t M, typename T >
     896             : void
     897           1 : vector< M, T >::operator+=( const T other )
     898             : {
     899           5 :     for( size_t index = 0; index < M; ++index )
     900           4 :         at( index ) += other;
     901           1 : }
     902             : 
     903             : 
     904             : 
     905             : template< size_t M, typename T >
     906             : void
     907           1 : vector< M, T >::operator-=( const T other )
     908             : {
     909           5 :     for( size_t index = 0; index < M; ++index )
     910           4 :         at( index ) -= other;
     911           1 : }
     912             : 
     913             : 
     914             : 
     915             : template< size_t M, typename T >
     916             : vector< M, T >
     917           2 : vector< M, T >::operator-() const
     918             : {
     919           2 :     vector< M, T > v( *this );
     920           2 :     return v.negate();
     921             : }
     922             : 
     923             : 
     924             : 
     925             : template< size_t M, typename T >
     926             : const vector< M, T >&
     927           2 : vector< M, T >::negate()
     928             : {
     929           8 :     for( size_t index = 0; index < M; ++index )
     930           6 :         array[ index ] = -array[ index ];
     931           2 :     return *this;
     932             : }
     933             : 
     934             : 
     935             : 
     936             : template< size_t M, typename T >
     937             : inline T&
     938          27 : vector< M, T >::x()
     939             : {
     940          27 :     return array[ 0 ];
     941             : }
     942             : 
     943             : 
     944             : 
     945             : template< size_t M, typename T >
     946             : inline T&
     947          27 : vector< M, T >::y()
     948             : {
     949          27 :     return array[ 1 ];
     950             : }
     951             : 
     952             : 
     953             : 
     954             : template< size_t M, typename T >
     955             : inline T&
     956          23 : vector< M, T >::z()
     957             : {
     958          23 :     return array[ 2 ];
     959             : }
     960             : 
     961             : 
     962             : 
     963             : template< size_t M, typename T >
     964             : inline T&
     965          13 : vector< M, T >::w()
     966             : {
     967          13 :     return array[ 3 ];
     968             : }
     969             : 
     970             : 
     971             : 
     972             : template< size_t M, typename T >
     973             : inline const T&
     974         190 : vector< M, T >::x() const
     975             : {
     976         190 :     return array[ 0 ];
     977             : }
     978             : 
     979             : 
     980             : 
     981             : template< size_t M, typename T >
     982             : inline const T&
     983         184 : vector< M, T >::y() const
     984             : {
     985         184 :     return array[ 1 ];
     986             : }
     987             : 
     988             : 
     989             : 
     990             : template< size_t M, typename T >
     991             : inline const T&
     992         182 : vector< M, T >::z() const
     993             : {
     994         182 :     return array[ 2 ];
     995             : }
     996             : 
     997             : 
     998             : 
     999             : template< size_t M, typename T >
    1000             : inline const T&
    1001         100 : vector< M, T >::w() const
    1002             : {
    1003         100 :     return array[ 3 ];
    1004             : }
    1005             : 
    1006             : 
    1007             : template< size_t M, typename T >
    1008             : inline T&
    1009             : vector< M, T >::r()
    1010             : {
    1011             :     return array[ 0 ];
    1012             : }
    1013             : 
    1014             : 
    1015             : 
    1016             : template< size_t M, typename T >
    1017             : inline T&
    1018             : vector< M, T >::g()
    1019             : {
    1020             :     return array[ 1 ];
    1021             : }
    1022             : 
    1023             : 
    1024             : 
    1025             : template< size_t M, typename T >
    1026             : inline T&
    1027             : vector< M, T >::b()
    1028             : {
    1029             :     return array[ 2 ];
    1030             : }
    1031             : 
    1032             : 
    1033             : 
    1034             : template< size_t M, typename T >
    1035             : inline T&
    1036             : vector< M, T >::a()
    1037             : {
    1038             :     return array[ 3 ];
    1039             : }
    1040             : 
    1041             : 
    1042             : 
    1043             : template< size_t M, typename T >
    1044             : inline const T&
    1045             : vector< M, T >::r() const
    1046             : {
    1047             :     return array[ 0 ];
    1048             : }
    1049             : 
    1050             : 
    1051             : 
    1052             : template< size_t M, typename T >
    1053             : inline const T&
    1054             : vector< M, T >::g() const
    1055             : {
    1056             :     return array[ 1 ];
    1057             : }
    1058             : 
    1059             : 
    1060             : 
    1061             : template< size_t M, typename T >
    1062             : inline const T&
    1063             : vector< M, T >::b() const
    1064             : {
    1065             :     return array[ 2 ];
    1066             : }
    1067             : 
    1068             : 
    1069             : 
    1070             : template< size_t M, typename T >
    1071             : inline const T&
    1072             : vector< M, T >::a() const
    1073             : {
    1074             :     return array[ 3 ];
    1075             : }
    1076             : 
    1077             : // result = vec1.cross( vec2 ) => result = vec1 x vec2
    1078             : template< size_t M, typename T >
    1079             : template< typename TT >
    1080           7 : inline vector< M, T > vector< M, T >::cross( const vector< M, TT >& rhs,
    1081             :                                  typename enable_if< M == 3, TT >::type* ) const
    1082             : {
    1083           7 :     vector< M, T > result;
    1084           7 :     result.cross( *this, rhs );
    1085           7 :     return result;
    1086             : }
    1087             : 
    1088             : 
    1089             : 
    1090             : // result.cross( vec1, vec2 ) => (this) = vec1 x vec2
    1091             : template< size_t M, typename T >
    1092             : template< typename TT >
    1093           7 : void vector< M, T >::cross( const vector< M, TT >& aa,
    1094             :                             const vector< M, TT >& bb,
    1095             :                             typename enable_if< M == 3, TT >::type* )
    1096             : {
    1097           7 :     array[ 0 ] = aa.y() * bb.z() - aa.z() * bb.y();
    1098           7 :     array[ 1 ] = aa.z() * bb.x() - aa.x() * bb.z();
    1099           7 :     array[ 2 ] = aa.x() * bb.y() - aa.y() * bb.x();
    1100           7 : }
    1101             : 
    1102             : 
    1103             : 
    1104             : template< size_t M, typename T >
    1105          35 : inline T vector< M, T >::dot( const vector< M, T >& other ) const
    1106             : {
    1107          35 :     T tmp = 0.0;
    1108         174 :     for( size_t index = 0; index < M; ++index )
    1109         139 :         tmp += at( index ) * other.at( index );
    1110             : 
    1111          35 :     return tmp;
    1112             : }
    1113             : 
    1114             : 
    1115             : template< size_t M, typename T >
    1116           8 : inline T vector< M, T >::normalize()
    1117             : {
    1118           8 :     const T len = length();
    1119             : 
    1120           8 :     if ( len == 0 )
    1121           0 :         return 0;
    1122             : 
    1123           8 :     const T tmp = 1.0 / len;
    1124           8 :     (*this) *= tmp;
    1125           8 :     return len;
    1126             : }
    1127             : 
    1128             : template< size_t M, typename T >
    1129          16 : inline T vector< M, T >::length() const
    1130             : {
    1131          16 :     return std::sqrt( squared_length() );
    1132             : }
    1133             : 
    1134             : template< size_t M, typename T >
    1135          17 : inline T vector< M, T >::squared_length() const
    1136             : {
    1137          17 :     T _squared_length = 0.0;
    1138          78 :     for( const_iterator it = begin(), it_end = end(); it != it_end; ++it )
    1139          61 :         _squared_length += (*it) * (*it);
    1140             : 
    1141          17 :     return _squared_length;
    1142             : }
    1143             : 
    1144             : 
    1145             : 
    1146             : template< size_t M, typename T >
    1147             : inline T
    1148             : vector< M, T >::distance( const vector< M, T >& other ) const
    1149             : {
    1150             :     return std::sqrt( squared_distance( other ) );
    1151             : }
    1152             : 
    1153             : 
    1154             : 
    1155             : template< size_t M, typename T >
    1156             : inline T vector< M, T >::squared_distance( const vector< M, T >& other ) const
    1157             : {
    1158             :     vector< M, T > tmp( *this );
    1159             :     tmp -= other;
    1160             :     return tmp.squared_length();
    1161             : }
    1162             : 
    1163           2 : template< size_t M, typename T > inline T vector< M, T >::product() const
    1164             : {
    1165           2 :     T result = at( 0 );
    1166           6 :     for( size_t i = 1; i < M; ++i )
    1167           4 :         result *= at( i );
    1168           2 :     return result;
    1169             : }
    1170             : 
    1171             : template< size_t M, typename T >
    1172             : void vector< M, T >::compute_normal( const vector< M, T >& aa,
    1173             :                                      const vector< M, T >& bb,
    1174             :                                      const vector< M, T >& cc )
    1175             : {
    1176             :     vector< M, T > u,v;
    1177             :     // right hand system, CCW triangle
    1178             :     u = bb - aa;
    1179             :     v = cc - aa;
    1180             :     cross( u, v );
    1181             :     normalize();
    1182             : }
    1183             : 
    1184             : 
    1185             : 
    1186             : template< size_t M, typename T >
    1187             : vector< M, T >
    1188             : vector< M, T >::compute_normal( const vector< M, T >& bb,
    1189             :                                 const vector< M, T >& cc ) const
    1190             : {
    1191             :     vector< M, T > tmp;
    1192             :     tmp.compute_normal( *this, bb, cc);
    1193             :     return tmp;
    1194             : }
    1195             : 
    1196             : template< size_t M, typename T >
    1197             : template< typename TT >
    1198             : vector< 3, T > vector< M, T >::rotate( const T theta, vector< M, TT > axis,
    1199             :             typename enable_if< M == 3, TT >::type* ) const
    1200             : {
    1201             :     axis.normalize();
    1202             : 
    1203             :     const T costheta = std::cos( theta );
    1204             :     const T sintheta = std::sin( theta );
    1205             : 
    1206             :     return vector< 3, T >(
    1207             :         (costheta + ( 1.0f - costheta ) * axis.x() * axis.x() ) * x()    +
    1208             :         (( 1 - costheta ) * axis.x() * axis.y() - axis.z() * sintheta ) * y() +
    1209             :         (( 1 - costheta ) * axis.x() * axis.z() + axis.y() * sintheta ) * z(),
    1210             : 
    1211             :         (( 1 - costheta ) * axis.x() * axis.y() + axis.z() * sintheta ) * x() +
    1212             :         ( costheta + ( 1 - costheta ) * axis.y() * axis.y() ) * y() +
    1213             :         (( 1 - costheta ) * axis.y() * axis.z() - axis.x() * sintheta ) * z(),
    1214             : 
    1215             :         (( 1 - costheta ) * axis.x() * axis.z() - axis.y() * sintheta ) * x() +
    1216             :         (( 1 - costheta ) * axis.y() * axis.z() + axis.x() * sintheta ) * y() +
    1217             :         ( costheta + ( 1 - costheta ) * axis.z() * axis.z() ) * z() );
    1218             : }
    1219             : 
    1220             : 
    1221             : // sphere layout: center xyz, radius w
    1222             : template< size_t M, typename T >
    1223             : template< typename TT >
    1224             : inline vector< 3, T >
    1225             : vector< M, T >::
    1226             : project_point_onto_sphere( const vector< 3, TT >& point,
    1227             :     typename enable_if< M == 4, TT >::type* ) const
    1228             : {
    1229             :     const vector< 3, T >& _center = get_sub_vector< 3 >( 0 );
    1230             : 
    1231             :     vector< 3, T > projected_point( point );
    1232             :     projected_point -= _center;
    1233             :     projected_point.normalize();
    1234             :     projected_point *= w();
    1235             :     return _center + projected_point;
    1236             : }
    1237             : 
    1238             : 
    1239             : 
    1240             : // sphere layout: center xyz, radius w
    1241             : template< size_t M, typename T >
    1242             : template< typename TT >
    1243             : inline T
    1244             : vector< M, T >::
    1245             : distance_to_sphere( const vector< 3, TT >& point,
    1246             :     typename enable_if< M == 4, TT >::type* ) const
    1247             : {
    1248             :     const vector< 3, T >& center_ = get_sub_vector< 3 >( 0 );
    1249             :     return ( point - center_ ).length() - w();
    1250             : }
    1251             : 
    1252             : template< size_t M, typename T > template< size_t N > inline
    1253           7 : vector< N, T >& vector< M, T >::get_sub_vector( size_t offset,
    1254             :                                            typename enable_if< M >= N >::type* )
    1255             : {
    1256           7 :     assert( offset <= M - N );
    1257           7 :     return reinterpret_cast< vector< N, T >& >( *( begin() + offset ) );
    1258             : }
    1259             : 
    1260             : template< size_t M, typename T > template< size_t N > inline
    1261             : const vector< N, T >& vector< M, T >::get_sub_vector( size_t offset,
    1262             :                                      typename enable_if< M >= N >::type* ) const
    1263             : {
    1264             :     assert( offset <= M - N );
    1265             :     return reinterpret_cast< const vector< N, T >& >( *( begin() + offset ) );
    1266             : }
    1267             : 
    1268             : 
    1269             : // plane: normal xyz, distance w
    1270             : template< size_t M, typename T > template< typename TT >
    1271             : inline T vector< M, T >::distance_to_plane( const vector< 3, TT >& point,
    1272             :     typename enable_if< M == 4, TT >::type* ) const
    1273             : {
    1274             :     const vector< 3, T >& normal = get_sub_vector< 3 >( 0 );
    1275             :     return normal.dot( point ) + w();
    1276             : }
    1277             : 
    1278             : 
    1279             : 
    1280             : // plane: normal xyz, distance w
    1281             : template< size_t M, typename T >
    1282             : template< typename TT >
    1283             : vector< 3, T >
    1284             : vector< M, T >::project_point_onto_plane( const vector< 3, TT >& point,
    1285             :     typename enable_if< M == 4, TT >::type* ) const
    1286             : {
    1287             :     const vector< 3, T >& normal = get_sub_vector< 3 >( 0 );
    1288             :     return point - ( normal * distance_to_plane( point ) );
    1289             : }
    1290             : 
    1291             : 
    1292             : 
    1293             : template< size_t M, typename T >
    1294          23 : bool vector< M, T >::operator==( const vector< M, T >& other ) const
    1295             : {
    1296          23 :     return memcmp( array, other.array, sizeof( array )) == 0;
    1297             : }
    1298             : 
    1299             : 
    1300             : template< size_t M, typename T >
    1301             : bool vector< M, T >::operator!=( const vector< M, T >& other ) const
    1302             : {
    1303             :     return ! this->operator==( other );
    1304             : }
    1305             : 
    1306             : 
    1307             : template< size_t M, typename T >
    1308             : bool
    1309             : vector< M, T >::equals( const vector< M, T >& other, T tolerance ) const
    1310             : {
    1311             :     for( size_t index = 0; index < M; ++index )
    1312             :         if( fabs( at( index ) - other( index ) ) >= tolerance )
    1313             :             return false;
    1314             :     return true;
    1315             : 
    1316             : }
    1317             : 
    1318             : 
    1319             : template< size_t M, typename T >
    1320             : bool
    1321             : vector< M, T >::operator<( const vector< M, T >& other ) const
    1322             : {
    1323             :     for(size_t index = 0; index < M; ++index )
    1324             :     {
    1325             :         if (at( index ) < other.at( index )) return true;
    1326             :         if (other.at( index ) < at( index )) return false;
    1327             :     }
    1328             :     return false;
    1329             : }
    1330             : 
    1331             : 
    1332             : // to-homogenous-coordinates assignment operator
    1333             : // non-chainable because of sfinae
    1334             : template< size_t M, typename T > template< size_t N >
    1335             : typename enable_if< N == M - 1 >::type*
    1336          41 : vector< M, T >::operator=( const vector< N, T >& source_ )
    1337             : {
    1338          41 :     std::copy( source_.begin(), source_.end(), begin() );
    1339          41 :     at( M - 1 ) = static_cast< T >( 1.0 );
    1340          41 :     return 0;
    1341             : }
    1342             : 
    1343             : 
    1344             : // from-homogenous-coordinates assignment operator
    1345             : // non-chainable because of sfinae
    1346             : template< size_t M, typename T > template< size_t N >
    1347             : typename enable_if< N == M + 1 >::type*
    1348           1 : vector< M, T >::operator=( const vector< N, T >& source_ )
    1349             : {
    1350           1 :     const T w_reci = static_cast< T >( 1.0 ) / source_( M );
    1351           1 :     iterator it = begin(), it_end = end();
    1352           4 :     for( size_t index = 0; it != it_end; ++it, ++index )
    1353           3 :         *it = source_( index ) * w_reci;
    1354           1 :     return 0;
    1355             : }
    1356             : 
    1357             : 
    1358             : template< size_t M, typename T >
    1359          19 : vector< M, T >& vector< M, T >::operator=( const T* c_array )
    1360             : {
    1361          19 :     iter_set( c_array, c_array + M );
    1362          19 :     return *this;
    1363             : }
    1364             : 
    1365             : 
    1366             : 
    1367             : template< size_t M, typename T >
    1368             : T vector< M, T >::operator=( T filler_value )
    1369             : {
    1370             :     for( size_t index = 0; index < M; ++index )
    1371             :         at( index ) = filler_value;
    1372             :     return filler_value;
    1373             : }
    1374             : 
    1375             : 
    1376             : 
    1377             : 
    1378             : template< size_t M, typename T >
    1379          28 : vector< M, T >& vector< M, T >::operator=( const vector< M, T >& other )
    1380             : {
    1381          28 :     if( this != &other )
    1382          28 :         memcpy( array, other.array, M * sizeof( T ) );
    1383          28 :     return *this;
    1384             : }
    1385             : 
    1386             : 
    1387             : 
    1388             : // returns void to avoid 'silent' loss of precision when chaining
    1389             : template< size_t M, typename T > template< typename U >
    1390           2 : void vector< M, T >::operator=( const vector< M, U >& source_ )
    1391             : {
    1392             :     typedef typename vector< M, U >::const_iterator u_c_iter;
    1393           2 :     u_c_iter it = source_.begin(), it_end = source_.end();
    1394           8 :     for( iterator my_it = begin(); it != it_end; ++it, ++my_it )
    1395           6 :         *my_it = static_cast< T >( *it );
    1396           2 : }
    1397             : 
    1398             : 
    1399             : 
    1400             : template< size_t M, typename T >
    1401             : template< typename input_iterator_t >
    1402             : void
    1403          23 : vector< M, T >::iter_set( input_iterator_t begin_, input_iterator_t end_ )
    1404             : {
    1405          23 :     input_iterator_t in_it = begin_;
    1406          23 :     iterator it = begin(), it_end = end();
    1407         110 :     for( ; it != it_end && in_it != end_; ++it, ++in_it )
    1408          87 :         (*it) = static_cast< T >( *in_it );
    1409          23 : }
    1410             : 
    1411             : template< size_t M, typename T >
    1412             : void vector< M, T >::clamp( const T& min, const T& max )
    1413             : {
    1414             :     for( size_t i = 0; i < M; ++i )
    1415             :     {
    1416             :         if( array[i] < min )
    1417             :             array[i] = min;
    1418             :         if( array[i] > max )
    1419             :             array[i] = max;
    1420             :     }
    1421             : }
    1422             : 
    1423             : 
    1424             : 
    1425             : template< size_t M, typename T >
    1426             : template< typename TT >
    1427             : void
    1428             : vector< M, T >::scale_to( vector< M, TT >& result_,
    1429             :     T min_value, T max_value ) const
    1430             : {
    1431             :     T range       = max_value-min_value;
    1432             :     T half_range  = range * 0.5;
    1433             :     T scale       = ( 1.0 / range ) * static_cast< T >( std::numeric_limits< TT >::max() );
    1434             : 
    1435             :     for( size_t index = 0; index < M; ++index )
    1436             :     {
    1437             :         result_.at( index )
    1438             :             = static_cast< TT >( ( at( index ) + half_range ) * scale );
    1439             :     }
    1440             : 
    1441             : }
    1442             : 
    1443             : 
    1444             : 
    1445             : template< size_t M, typename T >
    1446             : inline size_t
    1447             : vector< M, T >::size()
    1448             : {
    1449             :     return M;
    1450             : }
    1451             : 
    1452             : 
    1453             : 
    1454             : template< size_t M, typename T >
    1455             : size_t
    1456           2 : vector< M, T >::find_min_index() const
    1457             : {
    1458           2 :     return std::min_element( begin(), end() ) - begin();
    1459             : }
    1460             : 
    1461             : 
    1462             : 
    1463             : template< size_t M, typename T >
    1464             : size_t
    1465           2 : vector< M, T >::find_max_index() const
    1466             : {
    1467           2 :     return std::max_element( begin(), end() ) - begin();
    1468             : }
    1469             : 
    1470             : 
    1471             : 
    1472             : template< size_t M, typename T >
    1473             : size_t
    1474             : vector< M, T >::find_abs_min_index() const
    1475             : {
    1476             :     return std::min_element( begin(), end(), vmml::math::abs_less< T >() ) - begin();
    1477             : }
    1478             : 
    1479             : 
    1480             : 
    1481             : template< size_t M, typename T >
    1482             : size_t
    1483             : vector< M, T >::find_abs_max_index() const
    1484             : {
    1485             :     return std::max_element( begin(), end(), vmml::math::abs_greater< T >() ) - begin();
    1486             : }
    1487             : 
    1488             : 
    1489             : 
    1490             : template< size_t M, typename T >
    1491             : T&
    1492           2 : vector< M, T >::find_min()
    1493             : {
    1494           2 :     return *std::min_element( begin(), end() );
    1495             : }
    1496             : 
    1497             : 
    1498             : 
    1499             : template< size_t M, typename T >
    1500             : const T&
    1501             : vector< M, T >::find_min() const
    1502             : {
    1503             :     return *std::min_element( begin(), end() );
    1504             : }
    1505             : 
    1506             : 
    1507             : 
    1508             : template< size_t M, typename T >
    1509             : T&
    1510           2 : vector< M, T >::find_max()
    1511             : {
    1512           2 :     return *std::max_element( begin(), end() );
    1513             : }
    1514             : 
    1515             : 
    1516             : 
    1517             : template< size_t M, typename T >
    1518             : const T&
    1519             : vector< M, T >::find_max() const
    1520             : {
    1521             :     return *std::max_element( begin(), end() );
    1522             : }
    1523             : 
    1524             : 
    1525             : template< size_t M, typename T >
    1526             : inline typename vector< M, T >::iterator
    1527          87 : vector< M, T >::begin()
    1528             : {
    1529          87 :     return array;
    1530             : }
    1531             : 
    1532             : 
    1533             : template< size_t M, typename T >
    1534             : inline typename vector< M, T >::iterator
    1535          35 : vector< M, T >::end()
    1536             : {
    1537          35 :     return array + M; ;
    1538             : }
    1539             : 
    1540             : 
    1541             : template< size_t M, typename T >
    1542             : inline typename vector< M, T >::const_iterator
    1543          70 : vector< M, T >::begin() const
    1544             : {
    1545          70 :     return array;
    1546             : }
    1547             : 
    1548             : 
    1549             : template< size_t M, typename T >
    1550             : inline typename vector< M, T >::const_iterator
    1551          66 : vector< M, T >::end() const
    1552             : {
    1553          66 :     return array + M; ;
    1554             : }
    1555             : 
    1556             : 
    1557             : 
    1558             : template< size_t M, typename T >
    1559             : inline typename vector< M, T >::reverse_iterator
    1560             : vector< M, T >::rbegin()
    1561             : {
    1562             :     return array + M - 1;
    1563             : }
    1564             : 
    1565             : 
    1566             : template< size_t M, typename T >
    1567             : inline typename vector< M, T >::reverse_iterator
    1568             : vector< M, T >::rend()
    1569             : {
    1570             :     return array - 1;
    1571             : }
    1572             : 
    1573             : 
    1574             : template< size_t M, typename T >
    1575             : inline typename vector< M, T >::const_reverse_iterator
    1576             : vector< M, T >::rbegin() const
    1577             : {
    1578             :     return array + M - 1;
    1579             : }
    1580             : 
    1581             : 
    1582             : template< size_t M, typename T >
    1583             : inline typename vector< M, T >::const_reverse_iterator
    1584             : vector< M, T >::rend() const
    1585             : {
    1586             :     return array - 1;
    1587             : }
    1588             : 
    1589             : 
    1590             : 
    1591             : template< size_t M, typename T >
    1592             : bool
    1593             : vector< M, T >::is_unit_vector() const
    1594             : {
    1595             :     const_iterator it = begin(), it_end = end();
    1596             :     bool one = false;
    1597             :     for( ; it != it_end; ++it )
    1598             :     {
    1599             :         if ( *it == 1.0 )
    1600             :         {
    1601             :             if ( one )
    1602             :                 return false;
    1603             :             one = true;
    1604             :         }
    1605             :         else if ( *it != 0.0 )
    1606             :         {
    1607             :             return false;
    1608             :         }
    1609             :     }
    1610             :     return one;
    1611             : }
    1612             : 
    1613             : 
    1614             : 
    1615             : 
    1616             : template< size_t M, typename T >
    1617             : void
    1618             : vector< M, T >::perturb( T perturbation )
    1619             : {
    1620             :     for( iterator it = begin(), it_end = end(); it != it_end; ++it )
    1621             :     {
    1622             :         (*it) += ( rand() & 1u ) ? perturbation : -perturbation;
    1623             :     }
    1624             : 
    1625             : }
    1626             : 
    1627             : template< size_t M, typename T >
    1628             : void
    1629           1 : vector< M, T >::sqrt_elementwise()
    1630             : {
    1631           5 :     for( iterator it = begin(), it_end = end(); it != it_end; ++it )
    1632             :     {
    1633           4 :         (*it) = std::sqrt(*it);
    1634             :     }
    1635           1 : }
    1636             : 
    1637             : 
    1638             : 
    1639             : template< size_t M, typename T >
    1640             : void
    1641           1 : vector< M, T >::reciprocal()
    1642             : {
    1643           5 :     for( iterator it = begin(), it_end = end(); it != it_end; ++it )
    1644             :     {
    1645           4 :         (*it) = static_cast< T >( 1.0 ) / (*it);
    1646             :     }
    1647           1 : }
    1648             : 
    1649             : 
    1650             : 
    1651             : template< size_t M, typename T >
    1652             : void
    1653             : vector< M, T >::reciprocal_safe()
    1654             : {
    1655             :     for( iterator it = begin(), it_end = end(); it != it_end; ++it )
    1656             :     {
    1657             :         T& v = *it;
    1658             : 
    1659             :         if ( v == static_cast< T >( 0 ) )
    1660             :             v = std::numeric_limits< T >::max();
    1661             :         else
    1662             :             v = static_cast< T >( 1.0 ) / v;
    1663             :     }
    1664             : }
    1665             : 
    1666             : 
    1667             : 
    1668             : template< size_t M, typename T >
    1669             : template< typename TT >
    1670             : void
    1671             : vector< M, T >::cast_from( const vector< M, TT >& other )
    1672             : {
    1673             :     typedef vmml::vector< M, TT > vector_tt_type ;
    1674             :     typedef typename vector_tt_type::const_iterator tt_const_iterator;
    1675             : 
    1676             :     iterator it = begin(), it_end = end();
    1677             :     tt_const_iterator other_it = other.begin();
    1678             :     for( ; it != it_end; ++it, ++other_it )
    1679             :     {
    1680             :         *it = static_cast< T >( *other_it );
    1681             :     }
    1682             : }
    1683             : 
    1684             : template< size_t M, typename T >
    1685             : size_t
    1686             : vector< M, T >::nnz() const
    1687             : {
    1688             :     size_t counter = 0;
    1689             : 
    1690             :     const_iterator  it = begin(),
    1691             :     it_end = end();
    1692             :     for( ; it != it_end; ++it)
    1693             :     {
    1694             :         if ( *it != 0 ) {
    1695             :             ++counter;
    1696             :         }
    1697             :     }
    1698             : 
    1699             :     return counter;
    1700             : }
    1701             : 
    1702             : 
    1703             : template< size_t M, typename T >
    1704             : double
    1705           1 : vector< M, T >::norm( ) const
    1706             : {
    1707           1 :     double norm_v = 0.0;
    1708             : 
    1709           1 :     const_iterator it = begin(), it_end = end();
    1710           5 :     for( ; it != it_end; ++it )
    1711             :     {
    1712           4 :         norm_v += *it * *it;
    1713             :     }
    1714             : 
    1715           1 :     return std::sqrt(norm_v);
    1716             : }
    1717             : 
    1718             : template< size_t M, typename T >
    1719             : void
    1720             : vector< M, T >::set_random( int seed )
    1721             : {
    1722             :     if ( seed >= 0 )
    1723             :         srand( seed );
    1724             : 
    1725             :     for( size_t i = 0; i < M; ++i )
    1726             :     {
    1727             :         const double fillValue = double( rand( )) / double( RAND_MAX );
    1728             :         at( i ) = -1.0 + 2.0 * fillValue;
    1729             :     }
    1730             : }
    1731             : 
    1732             : 
    1733             : } // namespace vmml
    1734             : 
    1735             : #endif

Generated by: LCOV version 1.11