OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
WValue.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WVALUE_H
26 #define WVALUE_H
27 
28 #include <algorithm>
29 #include <cmath>
30 #include <vector>
31 
32 #include "../WAssert.h"
33 #include "../WStringUtils.h"
34 #include "linearAlgebra/WLinearAlgebra.h"
35 
36 /**
37  * Base class for all higher level values like tensors, vectors, matrices and so on.
38  */
39 template< typename T > class WValue
40 {
41 template< typename S > friend class WValue; //!< All WValues are friends of each other.
42 
43 // We exclude this from doxygen since they are documented already as functions and I don't want to duplicate that documentation
44 // \cond Suppress_Doxygen
45 template< typename U > friend std::ostream& operator<<( std::ostream& os, const WValue< U > &rhs );
46 template< typename U > friend std::istream& operator>>( std::istream& in, WValue< U >& rhs );
47 // \endcond
48 public:
49  /**
50  * Create a WValue with the given number of components.
51  * The components will be set to zero if T is a type representing numbers.
52  * \param nbComponents Number of elements the WValue consists of.
53  */
54  explicit WValue( size_t nbComponents )
55  : m_components( nbComponents )
56  {
57  }
58 
59  /**
60  * Create a WValue as copy of the one given as parameter.
61  * \param newValue The WValue to be copied.
62  */
63  WValue( const WValue& newValue )
64  : m_components( newValue.m_components )
65  {
66  }
67 
68  /**
69  * Create a WValue as copy of the one given as parameter but with another template type.
70  * \param newValue The WValue to be copied.
71  */
72  template< typename S > explicit WValue( const WValue< S >& newValue )
73  {
74  m_components.resize( newValue.m_components.size() );
75  for( size_t i = 0; i < m_components.size(); ++i )
76  {
77  m_components[i] = newValue.m_components[i];
78  }
79  }
80 
81  /**
82  * Create a WValue from the given WVector_2.
83  * \param newValues The WVector_2 with the values..
84  */
85  explicit WValue( const WVector_2& newValues )
86  : m_components( static_cast< std::size_t >( newValues.size() ) )
87  {
88  for( std::size_t i = 0; i < m_components.size(); ++i )
89  {
90  m_components[ i ] = static_cast< T >( newValues( i ) );
91  }
92  }
93 
94  /**
95  * Get number of components the value consists of.
96  * \return The number of components the value consists of.
97  */
98  size_t size() const
99  {
100  return m_components.size();
101  }
102 
103  /**
104  * Returns a reference to the i-th component in order
105  * to provide access to the component.
106  * \param i element id
107  * \return A reference to the desired component.
108  */
109  T& operator[]( size_t i )
110  {
111  WAssert( i < m_components.size(), "Index out of bounds." );
112  return m_components[i];
113  }
114 
115  /**
116  * Returns a CONST reference to the i-th component in order
117  * to provide read-only access to the component.
118  * \param i element id
119  * \return A CONST reference to the desired component
120  */
121  const T& operator[]( size_t i ) const
122  {
123  WAssert( i < m_components.size(), "Index out of bounds." );
124  return m_components[i];
125  }
126 
127  /**
128  * Compares two WValues and returns true if they contain the same data.
129  * \param rhs The right hand side of the comparison
130  * \return The answer to whether both WValues contain the same data.
131  */
132  bool operator==( const WValue& rhs ) const
133  {
134  return ( m_components == rhs.m_components );
135  }
136 
137  /**
138  * Compares two WValues and returns true if they contain the different data.
139  * \param rhs The right hand side of the comparison
140  * \return The answer to whether both WValues do NOT contain the same data.
141  */
142  bool operator!=( const WValue& rhs ) const
143  {
144  return ( m_components != rhs.m_components );
145  }
146 
147  /**
148  * Assigns the contents of its argument to the contents of this WValue.
149  * \param rhs The right hand side of the assignment
150  * \return A reference to the left hand side of the assignment (i.e. the current object).
151  */
152  WValue& operator=( const WValue& rhs )
153  {
155  return *this;
156  }
157 
158  /**
159  * Adds a the argument component-wise to the components of this WValue
160  * \param rhs The right hand side of the assignment
161  * \return A reference to the left hand side of the assignment (i.e. the current object).
162  */
163  WValue& operator+=( const WValue& rhs )
164  {
165  WAssert( m_components.size() == rhs.m_components.size(), "Incompatible sizes of lhs and rhs of operator." );
166  for( unsigned int i = 0; i < m_components.size(); ++i )
167  m_components[i] += rhs.m_components[i];
168  return *this;
169  }
170 
171  /**
172  * Subtracts the argument component-wise from the components of this WValue
173  * \param rhs The right hand side of the assignment
174  * \return A reference to the left hand side of the assignment (i.e. the current object).
175  */
176  WValue& operator-=( const WValue& rhs )
177  {
178  WAssert( m_components.size() == rhs.m_components.size(), "Incompatible sizes of lhs and rhs of operator." );
179  for( unsigned int i = 0; i < m_components.size(); ++i )
180  m_components[i] -= rhs.m_components[i];
181  return *this;
182  }
183 
184  /**
185  * Scales each component of this WValue with the given scalar argument
186  * \param rhs The right hand side of the assignment
187  * \return A reference to the left hand side of the assignment (i.e. the (scaled) current object).
188  */
189  WValue& operator*=( double rhs )
190  {
191  for( unsigned int i = 0; i < m_components.size(); ++i )
192  m_components[i] *= rhs;
193  return *this;
194  }
195 
196  /**
197  * Scales each component of this WValue with the corresponding
198  * component of the given argument WValue
199  * \param rhs The right hand side of the assignment
200  * \return A reference to the left hand side of the assignment (i.e. the current (scaled) object).
201  */
202  WValue& operator*=( const WValue& rhs )
203  {
204  WAssert( m_components.size() == rhs.m_components.size(), "Incompatible sizes of lhs and rhs of operator." );
205  for( unsigned int i = 0; i < m_components.size(); ++i )
206  m_components[i] *= rhs.m_components[i];
207  return *this;
208  }
209 
210  /**
211  * Scales each component of this WValue with the given scalar argument
212  * \param rhs The right hand side of the assignment
213  * \return A reference to the left hand side of the assignment (i.e. the current (scaled) object).
214  */
215  WValue& operator/=( const double rhs )
216  {
217  for( unsigned int i = 0; i < m_components.size(); ++i )
218  m_components[i] /= rhs;
219  return *this;
220  }
221 
222 
223  /**
224  * Component-wise addition.
225  * \param summand2 The right hand side of the summation
226  * \result The sum of the WValues.
227  */
228  const WValue operator+( const WValue& summand2 ) const
229  {
230  WAssert( m_components.size() == summand2.m_components.size(), "Incompatible sizes of summands." );
231  WValue result( *this );
232  result += summand2;
233  return result;
234  }
235 
236  /**
237  * Component-wise subtraction.
238  * \param subtrahend The right hand side of the subtraction
239  * \result The difference of the WValues.
240  */
241  const WValue operator-( const WValue& subtrahend ) const
242  {
243  WAssert( m_components.size() == subtrahend.m_components.size(), "Incompatible sizes of subtrahend and minuend." );
244  WValue result( *this );
245  result -= subtrahend;
246  return result;
247  }
248 
249  /**
250  * Component-wise multiplication.
251  * \param factor2 The right hand side of the product
252  * \return The vector of the product of the components.
253  */
254  const WValue operator*( const WValue& factor2 ) const
255  {
256  WAssert( m_components.size() == factor2.m_components.size(), "Incompatible sizes of factors." );
257  WValue result( *this );
258  result *= factor2;
259  return result;
260  }
261 
262  /**
263  * Square root of sum of squares of elements.
264  * This function returns double instead of T
265  * because norm includes a square root and thus
266  * its computation automatically results in a
267  * floating point number.
268  * \return Double-precision norm of the WValue.
269  */
270  double norm() const
271  {
272  return sqrt( this->normSquare() );
273  }
274 
275  /**
276  * Sum of squares of elements.
277  * This function returns double instead of T
278  * because normSquare includes many squares and thus
279  * might return large values that might not fit into
280  * T's range of values. Double prevents an overflow.
281  * Additionally this is consistent with norm().
282  * \return Double-precision squared norm of the WValue.
283  */
284  double normSquare() const
285  {
286  double normSquare = 0.0;
287 
288  for( unsigned int i = 0; i < m_components.size(); ++i )
289  {
290  normSquare += m_components[i] * m_components[i];
291  }
292 
293  return normSquare;
294  }
295 
296  /**
297  * Make the norm of this WValue be 1 by dividing by WValue::norm()
298  */
299  void normalize()
300  {
301  double currentNorm = norm();
302  for( unsigned int i = 0; i < m_components.size(); ++i )
303  {
304  WAssert( currentNorm > 0.0, "Norm is non-positive!" );
305  m_components[i] /= currentNorm;
306  }
307  }
308 
309  /**
310  * Return a normalized version of the current WValue without modifying it.
311  * \return Normalized version of the current WValue object.
312  */
314  {
315  WValue result = *this;
316  result.normalize();
317  return result;
318  }
319 
320  /**
321  * Returns the mean value of all values stored in this WValue.
322  * \return Mean of the WValues components.
323  */
324  T mean() const
325  {
326  WAssert( !m_components.empty(), "WValue has no entries." );
327  T sum = 0;
328  for( typename std::vector< T >::const_iterator it = m_components.begin(); it != m_components.end(); it++ )
329  {
330  sum += ( *it );
331  }
332  return ( sum / static_cast< T >( m_components.size() ) );
333  }
334 
335  /**
336  * Returns the median of all values stored in this WValue.
337  * \return Median of the WValues components.
338  */
339  T median() const
340  {
341  WAssert( !m_components.empty(), "WValue has no entries. " );
342  std::vector< T > components( m_components );
343  std::sort( components.begin(), components.end() );
344  return components[ components.size() / 2 ];
345  }
346 
347  /**
348  * Changes the number of scalars held by this WValue.
349  * \param size The number of scalars stored in the WValue.
350  */
351  void resize( size_t size )
352  {
353  m_components.resize( size );
354  }
355 
356  /**
357  * Returns this WValue as WVector_2.
358  * \return The WValue as WVector_2.
359  */
360  WVector_2 toWVector()
361  {
362  WVector_2 result( m_components.size() );
363  for( size_t i = 0; i < m_components.size(); ++i )
364  {
365  result( i ) = static_cast<double>( m_components[ i ] );
366  }
367  return result;
368  }
369 
370 protected:
371 private:
372  /**
373  * The components the value is composed of. This contains the actual data
374  */
375  std::vector< T > m_components;
376 };
377 
378 /**
379  * Multiplies a WValue with a scalar
380  * \param lhs left hand side of product
381  * \param rhs right hand side of product
382  * \return product of WValue with scalar
383  */
384 template< typename T > inline const WValue< T > operator*( const WValue< T >& lhs, double rhs )
385 {
386  WValue< T > result( lhs );
387  result *= rhs;
388  return result;
389 }
390 
391 /**
392  * This functions only exists to make scalar multiplication commutative
393  * \param lhs left hand side of product
394  * \param rhs right hand side of product
395  * \return product of WValue with scalar
396  */
397 template< typename T > inline const WValue< T > operator*( double lhs, const WValue< T >& rhs )
398 {
399  WValue< T > result( rhs );
400  result *= lhs;
401  return result;
402 }
403 
404 /**
405  * Divides a WValue by a scalar
406  * \param lhs left hand side of division
407  * \param rhs right hand side of division
408  * \return Quotien of WValue with scalar
409  */
410 template< typename T > inline const WValue< T > operator/( const WValue< T >& lhs, double rhs )
411 {
412  WValue< T > result( lhs );
413  result /= rhs;
414  return result;
415 }
416 
417 /**
418  * Writes a meaningful representation of that object to the given stream.
419  *
420  * \param os The operator will write to this stream.
421  * \param rhs This will be written to the stream.
422  *
423  * \return the output stream
424  */
425 template< typename U > inline std::ostream& operator<<( std::ostream& os, const WValue< U > &rhs )
426 {
427  return string_utils::operator<<( os, rhs.m_components );
428 }
429 
430 /**
431  * Write an input stream into a WValue.
432  *
433  * \param in the input stream
434  * \param rhs the value to where to write the stream
435  *
436  * \return the input stream
437  */
438 template< typename U > inline std::istream& operator>>( std::istream& in, WValue< U >& rhs )
439 {
440  return string_utils::operator>>( in, rhs.m_components );
441 }
442 
443 #endif // WVALUE_H