ISIS Core Library 0.7.2 (api 3.0.0)
|
00001 // 00002 // C++ Interface: vector 00003 // 00004 // Description: 00005 // 00006 // 00007 // Author: Enrico Reimer<reimer@cbs.mpg.de>, (C) 2009 00008 // 00009 // Copyright: See COPYING file that comes with this distribution 00010 // 00011 // 00012 00013 #ifndef VECTOR_HPP 00014 #define VECTOR_HPP 00015 00016 #ifdef _MSC_VER 00017 #pragma warning(disable:4290) 00018 #endif 00019 00020 #include "common.hpp" 00021 #include <algorithm> 00022 #include <ostream> 00023 #include <numeric> 00024 #include <cmath> 00025 00026 #include <boost/numeric/ublas/vector.hpp> 00027 00028 namespace isis 00029 { 00030 namespace util 00031 { 00033 namespace _internal 00034 { 00035 template<typename TYPE, size_t SIZE> class array 00036 { 00037 protected: 00038 TYPE cont[SIZE]; 00039 typedef TYPE *iterator; 00040 typedef const TYPE *const_iterator; 00041 iterator begin() {return cont;} 00042 const_iterator begin()const {return cont;} 00043 iterator end() {return cont + SIZE;} 00044 const_iterator end()const {return cont + SIZE;} 00045 }; 00046 } 00048 00049 template < typename TYPE, size_t SIZE, typename CONTAINER = _internal::array<TYPE, SIZE> > 00050 class FixedVector: protected CONTAINER 00051 { 00052 public: 00053 typedef typename CONTAINER::iterator iterator; 00054 typedef typename CONTAINER::const_iterator const_iterator; 00055 typedef FixedVector<TYPE, SIZE, CONTAINER> this_class; 00056 typedef CONTAINER container_type; 00057 typedef TYPE value_type; 00058 protected: 00060 template<typename OP> this_class binaryOp ( const this_class &src )const { 00061 this_class ret; 00062 std::transform( CONTAINER::begin(), CONTAINER::end(), src.begin(), ret.begin(), OP() ); 00063 return ret; 00064 } 00065 template<typename OP> this_class binaryOp( const TYPE &src )const { 00066 this_class ret; 00067 iterator dst = ret.begin(); 00068 const OP op = OP(); 00069 00070 for ( const_iterator i = CONTAINER::begin(); i != CONTAINER::end(); i++, dst++ ) 00071 *dst = op( *i, src ); 00072 00073 return ret; 00074 } 00075 template<typename OP> this_class unaryOp()const { 00076 this_class ret; 00077 std::transform( CONTAINER::begin(), CONTAINER::end(), ret.begin(), OP() ); 00078 return ret; 00079 } 00080 public: 00082 // Contructor stuff 00084 00088 FixedVector() {fill( TYPE() ); } 00089 00093 FixedVector( const TYPE src[SIZE] ) { 00094 std::copy( src, src + SIZE, CONTAINER::begin() ); 00095 } 00096 00098 void fill( const TYPE &val ) { 00099 std::fill( CONTAINER::begin(), CONTAINER::end(), val ); 00100 } 00101 size_t getBiggestVecElemAbs( ) const { 00102 size_t biggestVecElem = 0; 00103 TYPE tmpValue = 0; 00104 00105 for ( size_t vecElem = 0; vecElem < SIZE; vecElem++ ) { 00106 if ( fabs( operator[]( vecElem ) ) > fabs( tmpValue ) ) { 00107 biggestVecElem = vecElem; 00108 tmpValue = operator[]( vecElem ); 00109 } 00110 } 00111 00112 return biggestVecElem; 00113 } 00115 // Accessors 00117 const TYPE &operator []( size_t idx )const { 00118 LOG_IF( idx >= SIZE, Debug, error ) << "Index " << idx << " exceeds the size of the vector (" << SIZE << ")"; 00119 return CONTAINER::begin()[idx]; 00120 } 00121 TYPE &operator []( size_t idx ) { 00122 LOG_IF( idx >= SIZE, Debug, error ) << "Index " << idx << " exceeds the size of the vector (" << SIZE << ")"; 00123 return CONTAINER::begin()[idx]; 00124 } 00125 00127 // Comparison 00130 bool lexical_less( const this_class &src )const { 00131 const_iterator they = src.begin(); 00132 const_iterator me = CONTAINER::begin(); 00133 00134 while ( me != CONTAINER::end() ) { 00135 if ( *they < *me ) return false; 00136 else if ( *me < *they ) return true; 00137 00138 me++; 00139 they++; 00140 } 00141 00142 return false; 00143 } 00145 bool lexical_less_reverse( const this_class &src )const { 00146 const_iterator they = src.end(); 00147 const_iterator me = CONTAINER::end(); 00148 00149 while ( me != CONTAINER::begin() ) { 00150 me--; 00151 they--; 00152 00153 if ( *they < *me ) return false; 00154 else if ( *me < *they ) return true; 00155 } 00156 00157 return false; 00158 } 00160 bool operator==( const this_class &src )const {return std::equal( CONTAINER::begin(), CONTAINER::end(), src.begin() );} 00162 bool operator!=( const this_class &src )const { 00163 return !operator==( src ); 00164 } 00172 bool fuzzyEqual( const this_class &other, unsigned short scale = 10 )const { 00173 const_iterator b = other.begin(); 00174 00175 for ( const_iterator a = CONTAINER::begin(); a != CONTAINER::end(); ++a, ++b ) { 00176 if ( ! util::fuzzyEqual( *a, *b, scale ) ) 00177 return false; 00178 } 00179 00180 return true; 00181 } 00182 00183 00184 00186 // Arithmetic operations 00188 this_class operator-( const this_class &src )const {return binaryOp<std::minus<TYPE> >( src );} 00189 this_class operator+( const this_class &src )const {return binaryOp<std::plus<TYPE> >( src );} 00190 this_class operator*( const this_class &src )const {return binaryOp<std::multiplies<TYPE> >( src );} 00191 this_class operator/( const this_class &src )const {return binaryOp<std::divides<TYPE> >( src );} 00192 00193 this_class operator-( const TYPE &src )const {return binaryOp<std::minus<TYPE> >( src );} 00194 this_class operator+( const TYPE &src )const {return binaryOp<std::plus<TYPE> >( src );} 00195 this_class operator*( const TYPE &src )const {return binaryOp<std::multiplies<TYPE> >( src );} 00196 this_class operator/( const TYPE &src )const {return binaryOp<std::divides<TYPE> >( src );} 00197 00199 // applying Arithmetic operations 00201 this_class operator-=( const this_class &src ) {return *this = *this - src;} 00202 this_class operator+=( const this_class &src ) {return *this = *this + src;} 00203 this_class operator*=( const this_class &src ) {return *this = *this * src;} 00204 this_class operator/=( const this_class &src ) {return *this = *this / src;} 00205 00206 this_class operator-=( const TYPE &src ) {return *this = *this - src;} 00207 this_class operator+=( const TYPE &src ) {return *this = *this + src;} 00208 this_class operator*=( const TYPE &src ) {return *this = *this * src;} 00209 this_class operator/=( const TYPE &src ) {return *this = *this / src;} 00210 00212 const this_class negate()const { 00213 return unaryOp<std::negate<float> >(); 00214 } 00215 00220 TYPE dot( const this_class &vect )const {return std::inner_product( CONTAINER::begin(), CONTAINER::end(), vect.begin(), TYPE() );} 00225 TYPE sqlen()const {return dot( *this );} 00230 TYPE len()const {return std::sqrt( sqlen() );} 00231 00242 const this_class &norm()throw( std::invalid_argument ) { 00243 const TYPE d = len(); 00244 00245 if ( d == 0 )throw( std::invalid_argument( "Trying to normalize a vector of length 0" ) ); 00246 else *this = *this / d; 00247 00248 return *this; 00249 } 00250 00255 TYPE product()const { 00256 TYPE ret = 1; 00257 00258 for ( const_iterator i = CONTAINER::begin(); i != CONTAINER::end(); i++ ) 00259 ret *= *i; 00260 00261 return ret; 00262 } 00263 00268 TYPE sum() { 00269 TYPE ret = 0; 00270 00271 for ( iterator i = CONTAINER::begin(); i != CONTAINER::end(); i++ ) 00272 ret += *i; 00273 00274 return ret; 00275 } 00276 00277 boost::numeric::ublas::vector<TYPE> getBoostVector() const { 00278 boost::numeric::ublas::vector<TYPE> ret = boost::numeric::ublas::vector<TYPE>( SIZE ); 00279 00280 for( size_t i = 0; i < SIZE; i++ ) { 00281 ret( i ) = operator[]( i ); 00282 } 00283 00284 return ret; 00285 } 00286 00288 // copy stuff 00291 template<class OutputIterator> void copyTo( OutputIterator out )const { 00292 std::copy( CONTAINER::begin(), CONTAINER::end(), out ); 00293 } 00294 00296 template<class InputIterator> void copyFrom( InputIterator iter_start, InputIterator iter_end ) { 00297 LOG_IF( size_t( std::distance( iter_start, iter_end ) ) > SIZE, Runtime, error ) 00298 << "Copying " << std::distance( iter_start, iter_end ) << " Elements into a vector of the size " << SIZE; 00299 std::copy( iter_start, iter_end, CONTAINER::begin() ); 00300 } 00301 template<typename TYPE2, typename CONTAINER2> FixedVector( const FixedVector<TYPE2, SIZE, CONTAINER2> &src ) { 00302 src.copyTo( CONTAINER::begin() ); 00303 } 00304 00306 template<typename charT, typename traits> void writeTo( std::basic_ostream<charT, traits> &out )const { 00307 util::listToOStream( CONTAINER::begin(), CONTAINER::end(), out, "|", "<", ">" ); 00308 } 00309 00310 iterator begin() {return CONTAINER::begin();} 00311 iterator end() {return CONTAINER::end();} 00312 const_iterator begin()const {return CONTAINER::begin();} 00313 const_iterator end()const {return CONTAINER::end();} 00314 }; 00315 00316 template<typename TYPE> 00317 class vector4 : public FixedVector<TYPE, 4> 00318 { 00319 public: 00320 vector4() {} 00321 template<typename TYPE2, typename CONTAINER2> vector4( const FixedVector<TYPE2, 4, CONTAINER2> &src ) : FixedVector< TYPE, 4> ( src ) {} 00322 vector4( const TYPE src[4] ): FixedVector< TYPE, 4>( src ) {} 00323 vector4( TYPE first, TYPE second, TYPE third = 0, TYPE fourth = 0 ) { 00324 this->operator[]( 3 ) = fourth; 00325 this->operator[]( 2 ) = third; 00326 this->operator[]( 1 ) = second; 00327 this->operator[]( 0 ) = first; 00328 } 00329 }; 00330 00331 template<typename TYPE> 00332 class vector3 : public FixedVector<TYPE, 3> 00333 { 00334 public: 00335 vector3() {} 00336 template<typename TYPE2, typename CONTAINER2> vector3( const FixedVector<TYPE2, 3, CONTAINER2> &src ) : FixedVector< TYPE, 3> ( src ) {} 00337 vector3( const TYPE src[3] ): FixedVector< TYPE, 3>( src ) {} 00338 vector3( TYPE first, TYPE second, TYPE third = 0 ) { 00339 this->operator[]( 2 ) = third; 00340 this->operator[]( 1 ) = second; 00341 this->operator[]( 0 ) = first; 00342 } 00343 }; 00344 00345 template<typename TYPE, size_t SIZE, typename CONTAINER1, typename CONTAINER2> 00346 FixedVector<TYPE, SIZE> maxVector( const FixedVector<TYPE, SIZE, CONTAINER1> &first, const FixedVector<TYPE, SIZE, CONTAINER2> &second ) 00347 { 00348 FixedVector<TYPE, SIZE> ret( first ); 00349 00350 for ( size_t i = 0; i < SIZE; i++ ) 00351 if ( ret[i] < second[i] )ret[i] = second[i]; 00352 00353 return ret; 00354 } 00355 template<typename TYPE, size_t SIZE, typename CONTAINER1, typename CONTAINER2> 00356 FixedVector<TYPE, SIZE> minVector( const FixedVector<TYPE, SIZE, CONTAINER1> &first, const FixedVector<TYPE, SIZE, CONTAINER2> &second ) 00357 { 00358 FixedVector<TYPE, SIZE> ret( first ); 00359 00360 for ( size_t i = 0; i < SIZE; i++ ) 00361 if ( ret[i] > second[i] )ret[i] = second[i]; 00362 00363 return ret; 00364 } 00365 00366 typedef vector4<float> fvector4; 00367 typedef vector4<double> dvector4; 00368 typedef vector3<float> fvector3; 00369 typedef vector3<double> dvector3; 00370 typedef vector4<int32_t> ivector4; 00371 } 00372 } 00373 00374 template<typename TYPE, size_t SIZE, typename CONTAINER > 00375 ::isis::util::FixedVector<TYPE, SIZE, CONTAINER> operator-( const ::isis::util::FixedVector<TYPE, SIZE, CONTAINER>& s ) 00376 { 00377 return s.negate(); 00378 } 00379 00381 namespace std 00382 { 00383 00384 template<typename charT, typename traits, typename TYPE, size_t SIZE, typename CONTAINER > basic_ostream<charT, traits>& 00385 operator<<( basic_ostream<charT, traits> &out, const ::isis::util::FixedVector<TYPE, SIZE, CONTAINER>& s ) 00386 { 00387 s.writeTo( out ); 00388 return out; 00389 } 00390 } 00391 #endif //VECTOR_HPP