openModeller  Version 1.4.0
Sample.cpp
Go to the documentation of this file.
00001 
00002 #include <Sample.hh>
00003 
00004 // check for malloc.h or stdlib.h
00005 #ifdef HAVE_MALLOC_H
00006 #include <malloc.h>
00007 #else
00008 #include <stdlib.h>
00009 #endif
00010 
00011 // cmath is included for std::sqrt
00012 #include <cmath>
00013 
00014 // String stream is included for the dump method
00015 #include <sstream>
00016 
00017 // Algorithm is included for std::min and std::max.
00018 #include <algorithm>
00019 
00020 // vector is used in a temporary variable in operator>>
00021 #include <vector>
00022 
00023 // iterator is needed for istream_iterator
00024 #include <iterator>
00025 
00026 // FIXME - SampleExpr.hh needs to be included after <vector>
00027 #include <SampleExpr.hh>
00028 
00029 // Log is included for the dump method
00030 #include <openmodeller/Log.hh>
00031 
00032 // To throw an out of memory exception
00033 #include <openmodeller/Exceptions.hh>
00034 
00035 
00036 using namespace std;
00037 
00038 Sample::Sample() :
00039   size_( 0 ),
00040   value_( 0 ),
00041   start_( 0 )
00042 { }
00043 
00044 Sample::Sample( size_t size ) :
00045   size_( 0 ),
00046   value_( 0 ),
00047   start_( 0 )
00048 {
00049   if ( size == 0 ) {
00050     return;
00051   }
00052 
00053   alloc( size );
00054   Scalar *v = value_;
00055 
00056   for ( size_t i = 0; i < size; ++i, ++v ) {
00057     *v = Scalar(0);
00058   }
00059 }
00060 
00061 Sample::Sample( std::size_t size, Scalar value ) :
00062   size_( 0 ),
00063   value_( 0 ),
00064   start_( 0 )
00065 {
00066   if ( size == 0 ) {
00067     return;
00068   }
00069   alloc( size );
00070 
00071   Scalar *v = value_;
00072   for( size_t i = 0; i<size; ++i ) {
00073     *v++ = value;
00074   }
00075 }
00076 
00077 Sample::Sample( size_t size, Scalar const * values ) :
00078   size_( 0 ),
00079   value_( 0 ),
00080   start_( 0 )
00081 {
00082   if ( size == 0 ) {
00083     return;
00084   }
00085   alloc( size );
00086   copy( size, values );
00087 }
00088 
00089 Sample::Sample( std::vector<Scalar> values ) :
00090   size_( 0 ),
00091   value_( 0 ),
00092   start_( 0 )
00093 {
00094   size_ = values.size();
00095   if ( size_ == 0 ) {
00096     return;
00097   }
00098 
00099   alloc( size_ );
00100 
00101   std::vector<Scalar>::const_iterator it = values.begin();
00102   std::vector<Scalar>::const_iterator end = values.end();
00103 
00104   Scalar *v = value_;
00105   while (it != end) {
00106     *v = (*it);
00107     ++v;
00108     ++it;
00109   }
00110 }
00111 
00112 Sample::Sample( const Sample & rhs ) :
00113   size_( 0 ),
00114   value_( 0 ),
00115   start_( 0 )
00116 {
00117   if ( rhs.size_ == 0 ) {
00118     return;
00119   }
00120   alloc( rhs.size_ );
00121   copy( rhs.size_, rhs.value_ );
00122 }
00123 
00124 Sample::~Sample()
00125 {
00126   if ( value_ ) {
00127     free( value_ );
00128   }
00129 }
00130 
00131 Sample&
00132 Sample::operator=( const Sample & rhs )
00133 {
00134   if ( this == &rhs ) {
00135     return *this;
00136   }
00137 
00138   if ( this->size_ != rhs.size_ ) {
00139     if ( value_ ) {
00140       free( value_ );
00141     }
00142     alloc( rhs.size_ );
00143   }
00144 
00145   copy( rhs.size_, rhs.value_ );
00146 
00147   start_ = rhs.start_;
00148 
00149   return *this;
00150 }
00151 
00152 void
00153 Sample::resize( size_t size )
00154 {
00155   // Do the easy case first.
00156   // The size hasn't changed, then just return.
00157   if ( size == this->size_ ) {
00158     return;
00159   }
00160 
00161   // Now check if the size is changing to 0.
00162   if ( size == 0 ) {
00163     // Since above, we tested for size == this->size,
00164     // we know that this->size != 0, and therefore
00165     // value_ != NULL;
00166     free( value_ );
00167     value_ = 0;
00168     this->size_ = 0;
00169     this->start_ = 0;
00170     return;
00171   }
00172 
00173   // Use realloc to make new space and copy.
00174   value_ = (Scalar*)realloc( value_, size*sizeof(Scalar) );
00175 
00176   // Now we need to loop through the new values, and initialize
00177   for ( Scalar *v = value_ + this->size_;
00178   v < value_ + size;
00179   ++v ) {
00180     *v = Scalar(0);
00181   }
00182 
00183   // Finally, update this->size.
00184   this->size_ = size;
00185 
00186   this->start_ = min( size, this->start_ );
00187 }
00188 
00189 
00190 void
00191 Sample::setCategoricalThreshold( std::size_t index )
00192 {
00193   index = max( (std::size_t)0, index ); // avoid negative values
00194   start_ = min( index, size_ ); // avoid values greater than the size
00195 }
00196 
00197 
00198 void
00199 Sample::alloc( size_t size )
00200 {
00201   this->size_ = size;
00202   this->start_ = 0;
00203   value_ = (Scalar*)malloc( size * sizeof( Scalar ) );
00204 
00205   if ( ! value_ ) {
00206 
00207     throw MemoryException( "Out of memory during Sample alloc" );
00208   }
00209 }
00210 
00211 void
00212 Sample::copy( size_t size, Scalar const * values )
00213 {
00214   Scalar *v = value_;
00215   for( size_t i = 0; i<size; ++i ) {
00216     *v++ = *values++;
00217   }
00218 }
00219 
00220 Scalar& 
00221 Sample::operator[]( std::size_t index ) 
00222 {
00223   if ( index >= size_ ) {
00224 
00225     ostringstream ss;
00226     ss << "Sample index (" << index << ") out of bounds (" << size_ << ")";
00227 
00228     throw MemoryException( ss.str().c_str() );
00229   }
00230  
00231   return value_[index]; 
00232 }
00233 
00234 Scalar 
00235 Sample::operator[]( std::size_t index ) const 
00236 {
00237   if ( index >= size_ ) {
00238 
00239     ostringstream ss;
00240     ss << "Sample index (" << index << ") out of bounds (" << size_ << ")";
00241 
00242     throw MemoryException( ss.str().c_str() );
00243   }
00244  
00245   return value_[index]; 
00246 }
00247 
00248 bool
00249 Sample::equals( const Sample& rhs ) const
00250 {
00251   // Zero vectors are equal.
00252   if ( size_ == 0 && rhs.size_ == 0 )
00253     return true;
00254 
00255   // If sizes are different, Samples must be different.
00256   if ( size_ != rhs.size_ )
00257     return false;
00258 
00259   // Check each value in Sample.
00260   Scalar *l = value_;
00261   Scalar *r = rhs.value_;
00262   for( size_t i = 0; i < size_; ++i ) {
00263     // If they are not equal, then Samples not equal
00264     if ( *l != *r )
00265       return false;
00266     ++l;
00267     ++r;
00268   }
00269 
00270   return true;
00271 }
00272 
00273 void
00274 Sample::dump() const
00275 {
00276   ostringstream ss;
00277   ss << "[";
00278   Scalar *vl = value_;
00279   size_t count = size_;
00280   for( size_t i = 0; i < count; ++i ) {
00281     ss << *vl++;
00282     if ( i < count-1 )
00283       ss << ", ";
00284   }
00285   ss << "]";
00286   Log::instance()->info( "Sample %s\n", ss.str().c_str() );
00287 }
00288 
00289 Sample&
00290 Sample::operator+=( const Sample& rhs )
00291 {
00292   Scalar *vl = value_;
00293   Scalar *vr = rhs.value_;
00294   size_t count = min( size_, rhs.size_);
00295   for( size_t i = 0; i < count; ++i,*vl++,*vr++ ) {
00296     if ( i >= start_ ) {
00297       *vl += *vr;
00298     }
00299   }
00300   (void) vr; // avoid unused var warning
00301   return *this;
00302 }
00303 
00304 Sample&
00305 Sample::operator+=( const Scalar& rhs )
00306 {
00307   iterator it = begin();
00308   for( size_t i = 0; it != end() ; ++it,++i ) {
00309     if ( i >= start_ ) {
00310       *it += rhs;
00311     }
00312   }
00313   return *this;
00314 }
00315 
00316 Sample&
00317 Sample::operator-=( const Sample& rhs )
00318 {
00319   Scalar *vl = value_;
00320   Scalar *vr = rhs.value_;
00321   size_t count = min( size_, rhs.size_);
00322   for( size_t i = 0; i < count; ++i,*vl++,*vr++ ) {
00323     if ( i >= start_ ) {
00324       *vl -= *vr;
00325     }
00326   }
00327   return *this;
00328 }
00329 
00330 Sample&
00331 Sample::operator-=( const Scalar& rhs )
00332 {
00333   iterator it = begin();
00334   for( size_t i = 0; it != end() ; ++it,++i ) {
00335     if ( i >= start_ ) {
00336       *it -= rhs;
00337     }
00338   }
00339   return *this;
00340 }
00341 
00342 Sample&
00343 Sample::operator*=( const Sample& rhs )
00344 {
00345   Scalar *vl = value_;
00346   Scalar *vr = rhs.value_;
00347   size_t count = min( size_, rhs.size_);
00348   for( size_t i = 0; i < count; ++i,*vl++,*vr++ ) {
00349     if ( i >= start_ ) {
00350       *vl *= *vr;
00351     }
00352   }
00353   return *this;
00354 }
00355 
00356 Sample&
00357 Sample::operator*=( const Scalar& rhs )
00358 {
00359   Scalar *vl = value_;
00360   size_t count = size_;
00361   for( size_t i = 0; i < count; ++i,*vl++ ) {
00362     if ( i >= start_ ) {
00363       *vl *= rhs;
00364     }
00365   }
00366   return *this;
00367 }
00368 
00369 Sample&
00370 Sample::operator/=( const Sample& rhs )
00371 {
00372   Scalar *vl = value_;
00373   Scalar *vr = rhs.value_;
00374   size_t count = min( size_, rhs.size_);
00375   for( size_t i = 0; i < count; ++i,*vl++,*vr++ ) {
00376     if ( i >= start_ ) {
00377       *vl /= *vr;
00378     }
00379   }
00380   return *this;
00381 }
00382 
00383 Sample&
00384 Sample::operator/=( const Scalar& rhs )
00385 {
00386   Scalar *vl = value_;
00387   size_t count = size_;
00388   for( size_t i = start_; i < count; ++i,*vl++ ) {
00389     if ( i >= start_ ) {
00390      *vl /= rhs;
00391     }
00392   }
00393   return *this;
00394 }
00395 
00396 Sample&
00397 Sample::operator&=( const Sample& rhs )
00398 {
00399   Scalar *vl = value_;
00400   Scalar *vr = rhs.value_;
00401   size_t count = min( size_, rhs.size_);
00402   for( size_t i = 0; i < count; ++i,vl++,vr++ ) {
00403     // The increments are not in the min() statement
00404     // because gcc has problems producing good code
00405     // when using -fno-inline.  For safety sake
00406     // the increments are explicitly after the min.
00407     if ( i >= start_ ) {
00408       *vl = min(*vl,*vr);
00409     }
00410   }
00411   return *this;
00412 }
00413 
00414 Sample&
00415 Sample::operator|=( const Sample& rhs )
00416 {
00417   Scalar *vl = value_;
00418   Scalar *vr = rhs.value_;
00419   size_t count = min( size_, rhs.size_);
00420   for( size_t i = start_; i < count; ++i,vl++,vr++ ) {
00421     // The increments are not in the max() statement
00422     // because gcc has problems producing good code
00423     // when using -fno-inline.  For safety sake
00424     // the increments are explicitly after the max.
00425     if ( i >= start_ ) {
00426       *vl = max(*vl,*vr);
00427     }
00428   }
00429   return *this;
00430 }
00431 
00432 Sample&
00433 Sample::sqr()
00434 {
00435   iterator it = begin();
00436   for( size_t i = 0; it != end() ; ++it,++i ) {
00437     if ( i >= start_ ) {
00438       *it = (*it) * (*it);
00439     }
00440   }
00441   return *this;
00442 }
00443 
00444 Sample&
00445 Sample::sqrt()
00446 {
00447   iterator it = begin();
00448   for( size_t i = 0; it != end() ; ++it,++i ) {
00449     if ( i >= start_ ) {
00450       *it = std::sqrt( *it );
00451     }
00452   }
00453   return *this;
00454 }
00455 
00456 Scalar
00457 Sample::norm() const
00458 {
00459   Scalar norm = 0.0;
00460   const_iterator it = begin();
00461   for( size_t i = 0; it != end() ; ++it,++i ) {
00462     if ( i >= start_ ) {
00463       norm += *it* *it;
00464     }
00465   }
00466   return std::sqrt(norm);
00467 }
00468 
00469 Scalar
00470 Sample::dotProduct( const Sample& rhs ) const
00471 {
00472   Scalar norm = 0.0;
00473   const_iterator lhs_it = begin();
00474   const_iterator rhs_it = rhs.begin();
00475   for( size_t i = 0; lhs_it != end() && rhs_it != rhs.end() ; ++lhs_it, ++rhs_it, ++i ) {
00476     if ( i >= start_ ) {
00477       norm += *lhs_it* *rhs_it;
00478     }
00479   }
00480   return std::sqrt(norm);
00481 }
00482 
00483 ostream&
00484 operator<<( ostream& os, const Sample& value )
00485 {
00486   if ( value.size() == 0 )
00487     return os;
00488 
00489   int oldprecision = os.precision(25);
00490 
00491   copy( value.begin(), value.end(),
00492   ostream_iterator<Scalar>(os," ") );
00493 
00494   os.precision( oldprecision );
00495   return os;
00496 }
00497 
00498 istream&
00499 operator>>( istream& is, Sample& value )
00500 {
00501   // Temporarily spool values into a vector<double>
00502   vector<double>v;
00503 
00504   copy( istream_iterator<double>(is),
00505   istream_iterator<double>(),
00506   back_inserter( v ) );
00507 
00508   // Copy from temporary vector<double> into value
00509   value.resize( v.size() );
00510 
00511   copy( v.begin(),
00512   v.end(),
00513   value.begin() );
00514 
00515   return is;
00516 
00517 }