ISIS Core Library 0.7.2 (api 3.0.0)

/scr/tee1/isis/lib/Core/CoreUtils/vector.hpp

Go to the documentation of this file.
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