LCOV - code coverage report
Current view: top level - vmmlib - vector.hpp (source / functions) Hit Total Coverage
Test: vmmlib Lines: 298 309 96.4 %
Date: 2017-05-16 00:10:45 Functions: 158 205 77.1 %

          Line data    Source code
       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         116 :     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             : 
     216             :     /** @return the product of all elements of this vector */
     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             : 
     223             :     /** @return the sub vector of the given length at the given offset. */
     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             : 
     227             :     /** Set the sub vector of the given length at the given offset. */
     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           0 :     friend std::ostream& operator<< ( std::ostream& os, const vector& vector_ )
     288             :     {
     289           0 :         os << "[ ";
     290           0 :         for( size_t index = 0; index < M; ++index )
     291           0 :             os << vector_.at( index ) << " ";
     292           0 :         return os << "]";
     293             :     }
     294             : 
     295             :     /** @name Convenience presets for 3 and 4 component vectors */
     296             :     //@{
     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();
     307             :     //@}
     308             : 
     309             :     T array[ M ];    //!< storage
     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           1 : static vector< M, T > operator* ( T factor, const vector< M, T >& vector_ )
     325             : {
     326           1 :     return vector_ * factor;
     327             : }
     328             : 
     329             : template< size_t M, typename T >
     330           3 : inline T dot( const vector< M, T >& first, const vector< M, T >& second )
     331             : {
     332           3 :     return first.dot( second );
     333             : }
     334             : 
     335             : template< size_t M, typename T >
     336          10 : inline vector< M, T > cross( vector< M, T > a, const vector< M, T >& b )
     337             : {
     338          10 :     return a.cross( b );
     339             : }
     340             : 
     341             : template< size_t M, typename T >
     342           1 : 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           1 :     const vector< M, T > u = b - a;
     347           1 :     const vector< M, T > v = c - a;
     348           1 :     vector< M, T > w = cross( u, v );
     349           1 :     w.normalize();
     350           1 :     return w;
     351             : }
     352             : 
     353             : template< typename T >
     354           2 : vector< 3, T > rotate( vector< 3, T > vec, const T theta,
     355             :                        const vector< 3, T >& axis )
     356             : {
     357           2 :     return vec.rotate( theta, axis );
     358             : }
     359             : 
     360             : 
     361             : template< size_t M, typename T >
     362           2 : inline vector< M, T > normalize( vector< M, T > vector_ )
     363             : {
     364           2 :     vector_.normalize();
     365           2 :     return vector_;
     366             : }
     367             : 
     368             : template< typename T >
     369           6 : 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           6 :     const vector< 3, T > cb = b - c;
     374           6 :     const vector< 3, T > ba = a - b;
     375             : 
     376           6 :     vector< 4, T > plane = vector< 4, T >( cross( cb, ba ));
     377           6 :     plane.normalize();
     378           6 :     plane.w() = -plane.x() * a.x() - plane.y() * a.y() - plane.z() * a.z();
     379           6 :     return plane;
     380             : }
     381             : 
     382             : template< size_t M, typename T >
     383           7 : vector< M, T >::vector( const T& _a )
     384             : {
     385          29 :     for( iterator it = begin(), it_end = end(); it != it_end; ++it )
     386             :     {
     387          22 :         *it = _a;
     388             :     }
     389           7 : }
     390             : 
     391             : template< size_t M, typename T >
     392           1 : vector< M, T >::vector( const T& _x, const T& _y )
     393             : {
     394           1 :     array[ 0 ] = _x;
     395           1 :     array[ 1 ] = _y;
     396           1 : }
     397             : 
     398             : template< size_t M, typename T >
     399          74 : vector< M, T >::vector( const T& _x, const T& _y, const T& _z )
     400             : {
     401          74 :     array[ 0 ] = _x;
     402          74 :     array[ 1 ] = _y;
     403          74 :     array[ 2 ] = _z;
     404          74 : }
     405             : 
     406             : template< size_t M, typename T >
     407          26 : vector< M, T >::vector( const T& _x, const T& _y, const T& _z, const T& _w )
     408             : {
     409          26 :     array[ 0 ] = _x;
     410          26 :     array[ 1 ] = _y;
     411          26 :     array[ 2 ] = _z;
     412          26 :     array[ 3 ] = _w;
     413          26 : }
     414             : 
     415             : template< size_t M, typename T >
     416          26 : vector< M, T >::vector( const T* values )
     417             : {
     418          26 :     memcpy( array, values, M * sizeof( T ));
     419          26 : }
     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           1 : vector< M, T >::vector( const vector< M-1, TT >& vector_, T last_,
     437             :                         typename enable_if< M == 4, TT >::type* )
     438             : {
     439           1 :     array[0] = vector_.array[0];
     440           1 :     array[1] = vector_.array[1];
     441           1 :     array[2] = vector_.array[2];
     442           1 :     array[3] = last_;
     443           1 : }
     444             : #endif
     445             : 
     446             : // to-homogenous-coordinates ctor
     447             : template< size_t M, typename T > template< typename TT >
     448          47 : vector< M, T >::vector( const vector< 3, TT >& source_,
     449             :                         typename enable_if< M == 4, TT >::type* )
     450             : {
     451          47 :     std::copy( source_.begin(), source_.end(), begin() );
     452          47 :     at( M - 1 ) = static_cast< T >( 1.0 );
     453          47 : }
     454             : 
     455             : // from-homogenous-coordinates ctor
     456             : template< size_t M, typename T > template< typename TT >
     457           2 : vector< M, T >::vector( const vector< 4, TT >& source_,
     458             :                         typename enable_if< M == 3, TT >::type* )
     459             : {
     460           2 :     const T w_reci = static_cast< T >( 1.0 ) / source_( M );
     461           2 :     iterator it = begin(), it_end = end();
     462           8 :     for( size_t index = 0; it != it_end; ++it, ++index )
     463           6 :         *it = source_( index ) * w_reci;
     464           2 : }
     465             : 
     466             : template< size_t M, typename T >
     467             : template< typename U >
     468           1 : vector< M, T >::vector( const vector< M, U >& source_ )
     469             : {
     470           1 :     (*this) = source_;
     471           1 : }
     472             : 
     473             : namespace
     474             : {
     475             : template< size_t M, typename T >
     476           8 : vector< M, T > _createVector( const T x, const T y, const T z,
     477             :                               typename enable_if< M == 3 >::type* = nullptr )
     478             : {
     479           8 :     return vector< M, T >( x, y, z );
     480             : }
     481             : 
     482             : template< size_t M, typename T >
     483           1 : vector< M, T > _createVector( const T x, const T y, const T z,
     484             :                               typename enable_if< M == 4 >::type* = nullptr )
     485             : {
     486           1 :     return vector< M, T >( x, y, z, 1 );
     487             : }
     488             : }
     489             : 
     490           1 : template< size_t M, typename T > vector< M, T > vector< M, T >::zero()
     491             : {
     492           1 :     return _createVector< M, T >( 0, 0, 0 );
     493             : }
     494             : 
     495           3 : template< size_t M, typename T > vector< M, T > vector< M, T >::forward()
     496             : {
     497           3 :     return _createVector< M, T >( 0, 0, -1 );
     498             : }
     499             : 
     500           1 : template< size_t M, typename T > vector< M, T > vector< M, T >::backward()
     501             : {
     502           1 :     return _createVector< M, T >( 0, 0, 1 );
     503             : }
     504             : 
     505           2 : template< size_t M, typename T > vector< M, T > vector< M, T >::up()
     506             : {
     507           2 :     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           2 : template< size_t M, typename T > vector< M, T > vector< M, T >::left()
     516             : {
     517           2 :     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           1 : template< size_t M, typename T > void vector< M, T >::set( T _a )
     541             : {
     542           5 :     for( iterator it = begin(), it_end = end(); it != it_end; ++it )
     543           4 :         *it = _a;
     544           1 : }
     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           1 : void vector< M, T >::set( T _x, T _y, T _z, T _w )
     571             : {
     572           1 :     array[ 0 ] = _x;
     573           1 :     array[ 1 ] = _y;
     574           1 :     array[ 2 ] = _z;
     575           1 :     array[ 3 ] = _w;
     576           1 : }
     577             : 
     578             : template< size_t M, typename T >
     579             : inline T&
     580          26 : vector< M, T >::operator()( size_t index )
     581             : {
     582          26 :     return at( index );
     583             : }
     584             : 
     585             : template< size_t M, typename T >
     586             : inline const T&
     587          48 : vector< M, T >::operator()( size_t index ) const
     588             : {
     589          48 :     return at( index );
     590             : }
     591             : 
     592             : template< size_t M, typename T >
     593             : inline T&
     594         527 : vector< M, T >::at( size_t index )
     595             : {
     596         527 :     if( index >= M )
     597           0 :         throw std::runtime_error( "at() - index out of bounds" );
     598         527 :     return array[ index ];
     599             : }
     600             : 
     601             : template< size_t M, typename T >
     602             : inline const T&
     603         865 : vector< M, T >::at( size_t index ) const
     604             : {
     605         865 :     if ( index >= M )
     606           0 :         throw std::runtime_error( "at() - index out of bounds" );
     607         865 :     return array[ index ];
     608             : }
     609             : 
     610             : template< size_t M, typename T >
     611           0 : vector< M, T >::operator T*()
     612             : {
     613           0 :     return array;
     614             : }
     615             : 
     616             : template< size_t M, typename T >
     617         111 : vector< M, T >::operator const T*() const
     618             : {
     619         111 :     return array;
     620             : }
     621             : 
     622             : template< size_t M, typename T >
     623             : vector< M, T >
     624           1 : vector< M, T >::operator*( const vector< M, T >& other ) const
     625             : {
     626           1 :     vector< M, T > result;
     627           5 :     for( size_t index = 0; index < M; ++index )
     628           4 :         result.at( index ) = at( index ) * other.at( index );
     629           1 :     return result;
     630             : }
     631             : 
     632             : template< size_t M, typename T >
     633             : vector< M, T >
     634           1 : vector< M, T >::operator/( const vector< M, T >& other ) const
     635             : {
     636           1 :     vector< M, T > result;
     637           5 :     for( size_t index = 0; index < M; ++index )
     638           4 :         result.at( index ) = at( index ) / other.at( index );
     639           1 :     return result;
     640             : }
     641             : 
     642             : template< size_t M, typename T >
     643             : vector< M, T >
     644          19 : vector< M, T >::operator+( const vector< M, T >& other ) const
     645             : {
     646          19 :     vector< M, T > result;
     647          80 :     for( size_t index = 0; index < M; ++index )
     648          61 :         result.at( index ) = at( index ) + other.at( index );
     649          19 :     return result;
     650             : }
     651             : 
     652             : template< size_t M, typename T >
     653             : vector< M, T >
     654          34 : vector< M, T >::operator-( const vector< M, T >& other ) const
     655             : {
     656          34 :     vector< M, T > result;
     657         140 :     for( size_t index = 0; index < M; ++index )
     658         106 :         result.at( index ) = at( index ) - other.at( index );
     659          34 :     return result;
     660             : }
     661             : 
     662             : template< size_t M, typename T >
     663             : void
     664           1 : vector< M, T >::operator*=( const vector< M, T >& other )
     665             : {
     666           5 :     for( size_t index = 0; index < M; ++index )
     667           4 :         at( index ) *= other.at( index );
     668           1 : }
     669             : 
     670             : template< size_t M, typename T >
     671             : void
     672           1 : vector< M, T >::operator/=( const vector< M, T >& other )
     673             : {
     674           5 :     for( size_t index = 0; index < M; ++index )
     675           4 :         at( index ) /= other.at( index );
     676           1 : }
     677             : 
     678             : template< size_t M, typename T >
     679             : void
     680           1 : vector< M, T >::operator+=( const vector< M, T >& other )
     681             : {
     682           5 :     for( size_t index = 0; index < M; ++index )
     683           4 :         at( index ) += other.at( index );
     684           1 : }
     685             : 
     686             : template< size_t M, typename T >
     687             : void
     688           1 : vector< M, T >::operator-=( const vector< M, T >& other )
     689             : {
     690           5 :     for( size_t index = 0; index < M; ++index )
     691           4 :         at( index ) -= other.at( index );
     692           1 : }
     693             : 
     694             : template< size_t M, typename T >
     695             : vector< M, T >
     696          27 : vector< M, T >::operator*( const T other ) const
     697             : {
     698          27 :     vector< M, T > result;
     699         110 :     for( size_t index = 0; index < M; ++index )
     700          83 :         result.at( index ) = at( index ) * other;
     701          27 :     return result;
     702             : }
     703             : 
     704             : template< size_t M, typename T >
     705             : vector< M, T >
     706           1 : vector< M, T >::operator/( const T other ) const
     707             : {
     708           1 :     vector< M, T > result;
     709           5 :     for( size_t index = 0; index < M; ++index )
     710           4 :         result.at( index ) = at( index ) / other;
     711           1 :     return result;
     712             : }
     713             : 
     714             : template< size_t M, typename T >
     715             : vector< M, T >
     716           1 : vector< M, T >::operator+( const T other ) const
     717             : {
     718           1 :     vector< M, T > result;
     719           5 :     for( size_t index = 0; index < M; ++index )
     720           4 :         result.at( index ) = at( index ) + other;
     721           1 :     return result;
     722             : }
     723             : 
     724             : template< size_t M, typename T >
     725             : vector< M, T >
     726           1 : vector< M, T >::operator-( const T other ) const
     727             : {
     728           1 :     vector< M, T > result;
     729           5 :     for( size_t index = 0; index < M; ++index )
     730           4 :         result.at( index ) = at( index ) - other;
     731           1 :     return result;
     732             : }
     733             : 
     734             : template< size_t M, typename T >
     735             : void
     736          20 : vector< M, T >::operator*=( const T other )
     737             : {
     738          88 :     for( size_t index = 0; index < M; ++index )
     739          68 :         at( index ) *= other;
     740          20 : }
     741             : 
     742             : template< size_t M, typename T >
     743             : void
     744           1 : vector< M, T >::operator/=( const T other )
     745             : {
     746           5 :     for( size_t index = 0; index < M; ++index )
     747           4 :         at( index ) /= other;
     748           1 : }
     749             : 
     750             : template< size_t M, typename T >
     751             : void
     752           1 : vector< M, T >::operator+=( const T other )
     753             : {
     754           5 :     for( size_t index = 0; index < M; ++index )
     755           4 :         at( index ) += other;
     756           1 : }
     757             : 
     758             : template< size_t M, typename T >
     759             : void
     760           1 : vector< M, T >::operator-=( const T other )
     761             : {
     762           5 :     for( size_t index = 0; index < M; ++index )
     763           4 :         at( index ) -= other;
     764           1 : }
     765             : 
     766             : template< size_t M, typename T >
     767             : vector< M, T >
     768           2 : vector< M, T >::operator-() const
     769             : {
     770           2 :     vector< M, T > v( *this );
     771           2 :     return v.negate();
     772             : }
     773             : 
     774             : template< size_t M, typename T >
     775             : const vector< M, T >&
     776           2 : vector< M, T >::negate()
     777             : {
     778           8 :     for( size_t index = 0; index < M; ++index )
     779           6 :         array[ index ] = -array[ index ];
     780           2 :     return *this;
     781             : }
     782             : 
     783             : template< size_t M, typename T >
     784             : inline T&
     785          98 : vector< M, T >::x()
     786             : {
     787          98 :     return array[ 0 ];
     788             : }
     789             : 
     790             : template< size_t M, typename T >
     791             : inline T&
     792          99 : vector< M, T >::y()
     793             : {
     794          99 :     return array[ 1 ];
     795             : }
     796             : 
     797             : template< size_t M, typename T >
     798             : inline T&
     799          94 : vector< M, T >::z()
     800             : {
     801          94 :     return array[ 2 ];
     802             : }
     803             : 
     804             : template< size_t M, typename T >
     805             : inline T&
     806          13 : vector< M, T >::w()
     807             : {
     808          13 :     return array[ 3 ];
     809             : }
     810             : 
     811             : template< size_t M, typename T >
     812             : inline const T&
     813         199 : vector< M, T >::x() const
     814             : {
     815         199 :     return array[ 0 ];
     816             : }
     817             : 
     818             : template< size_t M, typename T >
     819             : inline const T&
     820         193 : vector< M, T >::y() const
     821             : {
     822         193 :     return array[ 1 ];
     823             : }
     824             : 
     825             : template< size_t M, typename T >
     826             : inline const T&
     827         191 : vector< M, T >::z() const
     828             : {
     829         191 :     return array[ 2 ];
     830             : }
     831             : 
     832             : template< size_t M, typename T >
     833             : inline const T&
     834         100 : vector< M, T >::w() const
     835             : {
     836         100 :     return array[ 3 ];
     837             : }
     838             : 
     839             : template< size_t M, typename T >
     840             : inline T&
     841             : vector< M, T >::r()
     842             : {
     843             :     return array[ 0 ];
     844             : }
     845             : 
     846             : template< size_t M, typename T >
     847             : inline T&
     848             : vector< M, T >::g()
     849             : {
     850             :     return array[ 1 ];
     851             : }
     852             : 
     853             : template< size_t M, typename T >
     854             : inline T&
     855             : vector< M, T >::b()
     856             : {
     857             :     return array[ 2 ];
     858             : }
     859             : 
     860             : template< size_t M, typename T >
     861             : inline T&
     862             : vector< M, T >::a()
     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 >
     896          11 : vector< M, T >& vector< M, T >::cross( const vector< M, TT >& rhs,
     897             :                                        typename enable_if< M == 3, TT >::type* )
     898             : {
     899          11 :     const T x_ = y() * rhs.z() - z() * rhs.y();
     900          11 :     const T y_ = z() * rhs.x() - x() * rhs.z();
     901          11 :     const T z_ = x() * rhs.y() - y() * rhs.x();
     902          11 :     x() = x_;
     903          11 :     y() = y_;
     904          11 :     z() = z_;
     905          11 :     return *this;
     906             : }
     907             : 
     908             : template< size_t M, typename T >
     909          44 : inline T vector< M, T >::dot( const vector< M, T >& other ) const
     910             : {
     911          44 :     T tmp = 0.0;
     912         216 :     for( size_t index = 0; index < M; ++index )
     913         172 :         tmp += at( index ) * other.at( index );
     914             : 
     915          44 :     return tmp;
     916             : }
     917             : 
     918          19 : template< size_t M, typename T > inline T vector< M, T >::normalize()
     919             : {
     920          19 :     const T len = length();
     921          19 :     if ( len <= std::numeric_limits< T >::epsilon( ))
     922           0 :         return 0;
     923             : 
     924          19 :     const T tmp = 1.0 / len;
     925          19 :     (*this) *= tmp;
     926          19 :     return len;
     927             : }
     928             : 
     929             : template< size_t M, typename T >
     930          27 : inline T vector< M, T >::length() const
     931             : {
     932          27 :     return std::sqrt( squared_length() );
     933             : }
     934             : 
     935             : template< size_t M, typename T >
     936          28 : inline T vector< M, T >::squared_length() const
     937             : {
     938          28 :     T _squared_length = 0.0;
     939         122 :     for( const_iterator it = begin(), it_end = end(); it != it_end; ++it )
     940          94 :         _squared_length += (*it) * (*it);
     941             : 
     942          28 :     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           2 : template< size_t M, typename T > inline T vector< M, T >::product() const
     961             : {
     962           2 :     T result = at( 0 );
     963           6 :     for( size_t i = 1; i < M; ++i )
     964           4 :         result *= at( i );
     965           2 :     return result;
     966             : }
     967             : 
     968             : template< size_t M, typename T > template< typename TT >
     969           3 : vector< 3, T >& vector< M, T >::rotate( const T theta, vector< M, TT > axis,
     970             :                                         typename enable_if< M==3, TT >::type* )
     971             : {
     972           3 :     const T costheta = std::cos( theta );
     973           3 :     const T sintheta = std::sin( theta );
     974             : 
     975           3 :     axis.normalize();
     976           6 :     return *this = vector< 3, T >(
     977           6 :         (costheta + ( 1 - costheta ) * axis.x() * axis.x() ) * x()    +
     978           9 :         (( 1 - costheta ) * axis.x() * axis.y() - axis.z() * sintheta ) * y() +
     979           3 :         (( 1 - costheta ) * axis.x() * axis.z() + axis.y() * sintheta ) * z(),
     980             : 
     981           6 :         (( 1 - costheta ) * axis.x() * axis.y() + axis.z() * sintheta ) * x() +
     982           9 :         ( costheta + ( 1 - costheta ) * axis.y() * axis.y() ) * y() +
     983           3 :         (( 1 - costheta ) * axis.y() * axis.z() - axis.x() * sintheta ) * z(),
     984             : 
     985           6 :         (( 1 - costheta ) * axis.x() * axis.z() - axis.y() * sintheta ) * x() +
     986           9 :         (( 1 - costheta ) * axis.y() * axis.z() + axis.x() * sintheta ) * y() +
     987           9 :         ( 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 >
     992             : vector< M, T >::project_point_onto_sphere( const vector< 3, TT >& point,
     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
    1006             : vector< M, T >::distance_to_sphere( const vector< 3, TT >& point,
    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 >
    1015           7 : vector< N, T > vector< M, T >::get_sub_vector(
    1016             :     typename enable_if< M >= N+O >::type* ) const
    1017             : {
    1018           7 :     return vector< N, T >( array + O );
    1019             : }
    1020             : 
    1021             : template< size_t M, typename T > template< size_t N, size_t O >
    1022           1 : void vector< M, T >::set_sub_vector( const vector< N, T >& sub,
    1023             :                                      typename enable_if< M >= N+O >::type* )
    1024             : {
    1025           1 :     ::memcpy( array + O, sub.array, N * sizeof( T ));
    1026           1 : }
    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 >
    1039             : vector< M, T >::project_point_onto_plane( const vector< 3, TT >& point,
    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          30 : bool vector< M, T >::operator==( const vector< M, T >& other ) const
    1048             : {
    1049          30 :     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           2 : bool vector< M, T >::equals( const vector< M, T >& other, T tolerance ) const
    1060             : {
    1061           8 :     for( size_t index = 0; index < M; ++index )
    1062           6 :         if( fabs( at( index ) - other( index ) ) >= tolerance )
    1063           0 :             return false;
    1064           2 :     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 >
    1089          40 : vector< M, T >& vector< M, T >::operator=( const vector< M, T >& other )
    1090             : {
    1091          40 :     if( this != &other )
    1092          40 :         memcpy( array, other.array, M * sizeof( T ) );
    1093          40 :     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           2 : void vector< M, T >::operator=( const vector< M, U >& source_ )
    1099             : {
    1100             :     typedef typename vector< M, U >::const_iterator u_c_iter;
    1101           2 :     u_c_iter it = source_.begin(), it_end = source_.end();
    1102           8 :     for( iterator my_it = begin(); it != it_end; ++it, ++my_it )
    1103           6 :         *my_it = static_cast< T >( *it );
    1104           2 : }
    1105             : 
    1106             : template< size_t M, typename T >
    1107             : template< typename input_iterator_t >
    1108             : void
    1109           4 : vector< M, T >::iter_set( input_iterator_t begin_, input_iterator_t end_ )
    1110             : {
    1111           4 :     input_iterator_t in_it = begin_;
    1112           4 :     iterator it = begin(), it_end = end();
    1113          34 :     for( ; it != it_end && in_it != end_; ++it, ++in_it )
    1114          15 :         (*it) = static_cast< T >( *in_it );
    1115           4 : }
    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
    1131             : vector< M, T >::size()
    1132             : {
    1133             :     return M;
    1134             : }
    1135             : 
    1136             : template< size_t M, typename T >
    1137             : size_t
    1138           2 : vector< M, T >::find_min_index() const
    1139             : {
    1140           2 :     return std::min_element( begin(), end() ) - begin();
    1141             : }
    1142             : 
    1143             : template< size_t M, typename T >
    1144             : size_t
    1145           2 : vector< M, T >::find_max_index() const
    1146             : {
    1147           2 :     return std::max_element( begin(), end() ) - begin();
    1148             : }
    1149             : 
    1150             : template< size_t M, typename T >
    1151             : T&
    1152           2 : vector< M, T >::find_min()
    1153             : {
    1154           2 :     return *std::min_element( begin(), end() );
    1155             : }
    1156             : 
    1157             : template< size_t M, typename T >
    1158             : const T&
    1159             : vector< M, T >::find_min() const
    1160             : {
    1161             :     return *std::min_element( begin(), end() );
    1162             : }
    1163             : 
    1164             : template< size_t M, typename T >
    1165             : T&
    1166           2 : vector< M, T >::find_max()
    1167             : {
    1168           2 :     return *std::max_element( begin(), end() );
    1169             : }
    1170             : 
    1171             : template< size_t M, typename T >
    1172             : const T&
    1173             : vector< M, T >::find_max() const
    1174             : {
    1175             :     return *std::max_element( begin(), end() );
    1176             : }
    1177             : 
    1178             : template< size_t M, typename T >
    1179             : inline typename vector< M, T >::iterator
    1180          71 : vector< M, T >::begin()
    1181             : {
    1182          71 :     return array;
    1183             : }
    1184             : 
    1185             : template< size_t M, typename T >
    1186             : inline typename vector< M, T >::iterator
    1187          21 : vector< M, T >::end()
    1188             : {
    1189          21 :     return array + M; ;
    1190             : }
    1191             : 
    1192             : template< size_t M, typename T >
    1193             : inline typename vector< M, T >::const_iterator
    1194          86 : vector< M, T >::begin() const
    1195             : {
    1196          86 :     return array;
    1197             : }
    1198             : 
    1199             : template< size_t M, typename T >
    1200             : inline typename vector< M, T >::const_iterator
    1201          82 : vector< M, T >::end() const
    1202             : {
    1203          82 :     return array + M; ;
    1204             : }
    1205             : 
    1206             : template< size_t M, typename T >
    1207             : inline typename vector< M, T >::reverse_iterator
    1208             : vector< M, T >::rbegin()
    1209             : {
    1210             :     return array + M - 1;
    1211             : }
    1212             : 
    1213             : template< size_t M, typename T >
    1214             : inline typename vector< M, T >::reverse_iterator
    1215             : vector< M, T >::rend()
    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
    1236             : vector< M, T >::is_unit_vector() const
    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
    1269           1 : vector< M, T >::sqrt_elementwise()
    1270             : {
    1271           5 :     for( iterator it = begin(), it_end = end(); it != it_end; ++it )
    1272             :     {
    1273           4 :         (*it) = std::sqrt(*it);
    1274             :     }
    1275           1 : }
    1276             : 
    1277           1 : template< size_t M, typename T > void vector< M, T >::reciprocal()
    1278             : {
    1279           5 :     for( iterator it = begin(), it_end = end(); it != it_end; ++it )
    1280           4 :         (*it) = static_cast< T >( 1 ) / (*it);
    1281           1 : }
    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
    1299             : vector< M, T >::cast_from( const vector< M, TT >& other )
    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           1 : vector< M, T >::norm( ) const
    1333             : {
    1334           1 :     double norm_v = 0.0;
    1335             : 
    1336           1 :     const_iterator it = begin(), it_end = end();
    1337           9 :     for( ; it != it_end; ++it )
    1338             :     {
    1339           4 :         norm_v += *it * *it;
    1340             :     }
    1341             : 
    1342           1 :     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

Generated by: LCOV version 1.11