OpenWalnut  1.4.0
WValue.h
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WVALUE_H
00026 #define WVALUE_H
00027 
00028 #include <algorithm>
00029 #include <cmath>
00030 #include <vector>
00031 
00032 #include <Eigen/Core>
00033 
00034 #include "../WAssert.h"
00035 #include "../WStringUtils.h"
00036 
00037 /**
00038  * Base class for all higher level values like tensors, vectors, matrices and so on.
00039  */
00040 template< typename T > class WValue
00041 {
00042 template< typename S > friend class WValue; //!< All WValues are friends of each other.
00043 
00044 // We exclude this from doxygen since they are documented already as functions and I don't want to duplicate that documentation
00045 // \cond Suppress_Doxygen
00046 template< typename U > friend std::ostream& operator<<( std::ostream& os, const WValue< U > &rhs );
00047 template< typename U > friend std::istream& operator>>( std::istream& in, WValue< U >& rhs );
00048 // \endcond
00049 public:
00050     /**
00051      * Create a WValue with the given number of components.
00052      * The components will be set to zero if T is a type representing numbers.
00053      * \param nbComponents Number of elements the WValue consists of.
00054      */
00055     explicit WValue( size_t nbComponents )
00056         : m_components( nbComponents )
00057     {
00058     }
00059 
00060     /**
00061      * Create a WValue as copy of the one given as parameter.
00062      * \param newValue The WValue to be copied.
00063      */
00064     WValue( const WValue& newValue )
00065         : m_components( newValue.m_components )
00066     {
00067     }
00068 
00069     /**
00070      * Create a WValue as copy of the one given as parameter but with another template type.
00071      * \param newValue The WValue to be copied.
00072      */
00073     template< typename S > explicit WValue( const WValue< S >& newValue )
00074     {
00075         m_components.resize( newValue.m_components.size() );
00076         for( size_t i = 0; i < m_components.size(); ++i )
00077         {
00078             m_components[i] = newValue.m_components[i];
00079         }
00080     }
00081 
00082     /**
00083      * Create a WValue from the given Eigen::VectorXd.
00084      * \param newValues The Eigen::VectorXd with the values..
00085      */
00086     explicit WValue( const Eigen::VectorXd& newValues )
00087         : m_components( static_cast< std::size_t >( newValues.size() ) )
00088     {
00089         copyFromEigenVector( newValues );
00090     }
00091 
00092     /**
00093      * Create a WValue from the given Eigen::VectorXf.
00094      * \param newValues The Eigen::VectorXf with the values..
00095      */
00096     explicit WValue( const Eigen::VectorXf& newValues )
00097         : m_components( static_cast< std::size_t >( newValues.size() ) )
00098     {
00099         copyFromEigenVector( newValues );
00100     }
00101 
00102     /**
00103      * Create a WValue from the given Eigen::VectorXi.
00104      * \param newValues The Eigen::VectorXi with the values..
00105      */
00106     explicit WValue( const Eigen::VectorXi& newValues )
00107         : m_components( static_cast< std::size_t >( newValues.size() ) )
00108     {
00109         copyFromEigenVector( newValues );
00110     }
00111 
00112     /**
00113      * Get number of components the value consists of.
00114      * \return The number of components the value consists of.
00115      */
00116     size_t size() const
00117     {
00118         return m_components.size();
00119     }
00120 
00121     /**
00122      * Returns a reference to the i-th component in order
00123      * to provide access to the component.
00124      * \param i element id
00125      * \return A reference to the desired component.
00126      */
00127     T& operator[]( size_t i )
00128     {
00129         WAssert( i <  m_components.size(), "Index out of bounds." );
00130         return m_components[i];
00131     }
00132 
00133     /**
00134      * Returns a CONST reference to the i-th component in order
00135      * to provide read-only access to the component.
00136      * \param i element id
00137      * \return A CONST reference to the desired component
00138      */
00139     const T& operator[]( size_t i ) const
00140     {
00141         WAssert( i <  m_components.size(), "Index out of bounds." );
00142         return m_components[i];
00143     }
00144 
00145     /**
00146      * Compares two WValues and returns true if they contain the same data.
00147      * \param rhs The right hand side of the comparison
00148      * \return The answer to whether both WValues contain the same data.
00149      */
00150     bool operator==( const WValue& rhs ) const
00151     {
00152         return ( m_components == rhs.m_components );
00153     }
00154 
00155     /**
00156      * Compares two WValues and returns true if they contain the different data.
00157      * \param rhs The right hand side of the comparison
00158      * \return The answer to whether both WValues do NOT contain the same data.
00159      */
00160     bool operator!=( const WValue& rhs ) const
00161     {
00162         return ( m_components != rhs.m_components );
00163     }
00164 
00165     /**
00166      * Assigns the contents of its argument to the contents of this WValue.
00167      * \param rhs The right hand side of the assignment
00168      * \return A reference to the left hand side of the assignment (i.e. the current object).
00169      */
00170     WValue& operator=( const WValue& rhs )
00171     {
00172         m_components = rhs.m_components;
00173         return *this;
00174     }
00175 
00176     /**
00177      * Adds a the argument component-wise to the components of this WValue
00178      * \param rhs The right hand side of the assignment
00179      * \return A reference to the left hand side of the assignment (i.e. the current object).
00180      */
00181     WValue& operator+=( const WValue& rhs )
00182     {
00183         WAssert( m_components.size() == rhs.m_components.size(), "Incompatible sizes of lhs and rhs of operator." );
00184         for( unsigned int i = 0; i < m_components.size(); ++i )
00185             m_components[i] += rhs.m_components[i];
00186         return *this;
00187     }
00188 
00189     /**
00190      * Subtracts the argument component-wise from the components of this WValue
00191      * \param rhs The right hand side of the assignment
00192      * \return A reference to the left hand side of the assignment (i.e. the current object).
00193      */
00194     WValue& operator-=( const WValue& rhs )
00195     {
00196         WAssert( m_components.size() == rhs.m_components.size(), "Incompatible sizes of lhs and rhs of operator." );
00197         for( unsigned int i = 0; i < m_components.size(); ++i )
00198             m_components[i] -= rhs.m_components[i];
00199         return *this;
00200     }
00201 
00202     /**
00203      * Scales each component of this WValue with the given scalar argument
00204      * \param rhs The right hand side of the assignment
00205      * \return A reference to the left hand side of the assignment (i.e. the (scaled) current object).
00206      */
00207     WValue& operator*=( double rhs )
00208     {
00209         for( unsigned int i = 0; i < m_components.size(); ++i )
00210             m_components[i] *= rhs;
00211         return *this;
00212     }
00213 
00214     /**
00215      * Scales each component of this WValue with the corresponding
00216      * component of the given argument WValue
00217      * \param rhs The right hand side of the assignment
00218      * \return A reference to the left hand side of the assignment (i.e. the current (scaled) object).
00219      */
00220     WValue& operator*=( const WValue& rhs )
00221     {
00222         WAssert( m_components.size() == rhs.m_components.size(), "Incompatible sizes of lhs and rhs of operator." );
00223         for( unsigned int i = 0; i < m_components.size(); ++i )
00224             m_components[i] *= rhs.m_components[i];
00225         return *this;
00226     }
00227 
00228     /**
00229      * Scales each component of this WValue with the given scalar argument
00230      * \param rhs The right hand side of the assignment
00231      * \return A reference to the left hand side of the assignment (i.e. the current (scaled) object).
00232      */
00233     WValue& operator/=( const double rhs )
00234     {
00235         for( unsigned int i = 0; i < m_components.size(); ++i )
00236             m_components[i] /= rhs;
00237         return *this;
00238     }
00239 
00240 
00241     /**
00242      * Component-wise addition.
00243      * \param summand2 The right hand side of the summation
00244      * \result The sum of the WValues.
00245      */
00246     const WValue operator+( const WValue& summand2 ) const
00247     {
00248         WAssert( m_components.size() == summand2.m_components.size(), "Incompatible sizes of summands." );
00249         WValue result( *this );
00250         result += summand2;
00251         return result;
00252     }
00253 
00254     /**
00255      * Component-wise subtraction.
00256      * \param subtrahend The right hand side of the subtraction
00257      * \result The difference of the WValues.
00258      */
00259     const WValue operator-( const WValue& subtrahend ) const
00260     {
00261         WAssert( m_components.size() == subtrahend.m_components.size(), "Incompatible sizes of subtrahend and minuend." );
00262         WValue result( *this );
00263         result -= subtrahend;
00264         return result;
00265     }
00266 
00267     /**
00268      * Component-wise multiplication.
00269      * \param factor2 The right hand side of the product
00270      * \return The vector of the product of the components.
00271      */
00272     const WValue operator*( const WValue& factor2 ) const
00273     {
00274         WAssert( m_components.size() == factor2.m_components.size(), "Incompatible sizes of factors." );
00275         WValue result( *this );
00276         result *= factor2;
00277         return result;
00278     }
00279 
00280     /**
00281      * Square root of sum of squares of elements.
00282      * This function returns double instead of T
00283      * because norm includes a square root and thus
00284      * its computation automatically results in a
00285      * floating point number.
00286      * \return Double-precision norm of the WValue.
00287      */
00288     double norm() const
00289     {
00290         return sqrt( this->normSquare() );
00291     }
00292 
00293     /**
00294      * Sum of squares of elements.
00295      * This function returns double instead of T
00296      * because normSquare includes many squares and thus
00297      * might return large values that might not fit into
00298      * T's range of values. Double prevents an overflow.
00299      * Additionally this is consistent with norm().
00300      * \return Double-precision squared norm of the WValue.
00301      */
00302     double normSquare() const
00303     {
00304         double normSquare = 0.0;
00305 
00306         for( unsigned int i = 0; i < m_components.size(); ++i )
00307         {
00308             normSquare += m_components[i] * m_components[i];
00309         }
00310 
00311         return normSquare;
00312     }
00313 
00314     /**
00315      * Make the norm of this WValue be 1 by dividing by WValue::norm()
00316      */
00317     void normalize()
00318     {
00319         double currentNorm = norm();
00320         for( unsigned int i = 0; i < m_components.size(); ++i )
00321         {
00322             WAssert( currentNorm > 0.0, "Norm is non-positive!" );
00323             m_components[i] /= currentNorm;
00324         }
00325     }
00326 
00327     /**
00328      * Return a normalized version of the current WValue without modifying it.
00329      * \return Normalized version of the current WValue object.
00330      */
00331     WValue normalized() const
00332     {
00333         WValue result = *this;
00334         result.normalize();
00335         return result;
00336     }
00337 
00338     /**
00339      * Returns the mean value of all values stored in this WValue.
00340      * \return Mean of the WValues components.
00341      */
00342     T mean() const
00343     {
00344         WAssert( !m_components.empty(), "WValue has no entries." );
00345         T sum = 0;
00346         for( typename std::vector< T >::const_iterator it = m_components.begin(); it != m_components.end(); it++  )
00347         {
00348             sum += ( *it );
00349         }
00350         return ( sum / static_cast< T >( m_components.size() ) );
00351     }
00352 
00353     /**
00354      * Returns the median of all values stored in this WValue.
00355      * \return Median of the WValues components.
00356      */
00357     T median() const
00358     {
00359         WAssert( !m_components.empty(), "WValue has no entries. " );
00360         std::vector< T > components( m_components );
00361         std::sort( components.begin(), components.end() );
00362         return components[ components.size() / 2 ];
00363     }
00364 
00365     /**
00366      * Changes the number of scalars held by this WValue.
00367      * \param size The number of scalars stored in the WValue.
00368      */
00369     void resize( size_t size )
00370     {
00371         m_components.resize( size );
00372     }
00373 
00374 protected:
00375 private:
00376     /**
00377      * This function is used by the constructors that have the different Eigen::MatrixX types as parameter.
00378      * \tparam EigenDataType The data type which is used by the Eigen::VectorX.
00379      * \param newValues The source Eigen::VectorX.
00380      */
00381     template< typename EigenDataType >
00382     void copyFromEigenVector( const Eigen::Matrix< EigenDataType, Eigen::Dynamic, 1 >& newValues )
00383     {
00384         for( std::size_t i = 0; i < m_components.size(); ++i )
00385         {
00386             m_components[ i ] = static_cast< T >( newValues( i ) );
00387         }
00388     }
00389 
00390    /**
00391      * The components the value is composed of. This contains the actual data
00392      */
00393     std::vector< T > m_components;
00394 };
00395 
00396 /**
00397  * Multiplies a WValue with a scalar
00398  * \param lhs left hand side of product
00399  * \param rhs right hand side of product
00400  * \return product of WValue with scalar
00401  */
00402 template< typename T > inline const WValue< T > operator*( const WValue< T >& lhs, double rhs )
00403 {
00404     WValue< T > result( lhs );
00405     result *= rhs;
00406     return result;
00407 }
00408 
00409 /**
00410  * This functions only exists to make scalar multiplication commutative
00411  * \param lhs left hand side of product
00412  * \param rhs right hand side of product
00413  * \return product of WValue with scalar
00414  */
00415 template< typename T > inline const WValue< T > operator*( double lhs, const WValue< T >& rhs )
00416 {
00417     WValue< T > result( rhs );
00418     result *= lhs;
00419     return result;
00420 }
00421 
00422 /**
00423  * Divides a WValue by a scalar
00424  * \param lhs left hand side of division
00425  * \param rhs right hand side of division
00426  * \return Quotien of WValue with scalar
00427  */
00428 template< typename T > inline const WValue< T > operator/( const WValue< T >& lhs, double rhs )
00429 {
00430     WValue< T > result( lhs );
00431     result /= rhs;
00432     return result;
00433 }
00434 
00435 /**
00436  * Writes a meaningful representation of that object to the given stream.
00437  *
00438  * \param os The operator will write to this stream.
00439  * \param rhs This will be written to the stream.
00440  *
00441  * \return the output stream
00442  */
00443 template< typename U > inline std::ostream& operator<<( std::ostream& os, const WValue< U > &rhs )
00444 {
00445     return string_utils::operator<<( os, rhs.m_components );
00446 }
00447 
00448 /**
00449  * Write an input stream into a WValue.
00450  *
00451  * \param in the input stream
00452  * \param rhs the value to where to write the stream
00453  *
00454  * \return the input stream
00455  */
00456 template< typename U > inline std::istream& operator>>( std::istream& in, WValue< U >& rhs )
00457 {
00458     return string_utils::operator>>( in, rhs.m_components );
00459 }
00460 
00461 #endif  // WVALUE_H