subArray1D.h

Go to the documentation of this file.
00001 
00016 #ifndef _DLR_SUBARRAY1D_H_
00017 #define _DLR_SUBARRAY1D_H_
00018 
00019 #include <dlrNumeric/array1D.h>
00020 #include <dlrNumeric/slice.h>
00021 
00022 namespace dlr {
00023 
00024   namespace numeric {
00025     
00036     template <class Type>
00037     class SubArray1D {
00038     public:
00039 
00046       SubArray1D(const Array1D<Type>& source);
00047 
00048     
00060       SubArray1D(const Array1D<Type>& source, const Slice& slice0);
00061 
00062     
00071       SubArray1D(const SubArray1D<Type> &other);
00072 
00073     
00077       virtual
00078       ~SubArray1D() {}
00079 
00080     
00089       operator Array1D<Type>() const;
00090 
00091     
00099       inline size_t
00100       size() const {return this->m_size;}
00101 
00102     
00111       inline size_t
00112       start() const {return this->m_start;}
00113 
00114 
00123       inline size_t
00124       stride() const {return this->m_stride;}
00125 
00126     
00135       inline Array1D<Type>
00136       getArray() const {return this->m_source;}
00137   
00138 
00150       SubArray1D<Type>&
00151       operator=(const SubArray1D<Type>& other);
00152 
00153     
00165       SubArray1D<Type>&
00166       operator=(Type value);
00167 
00179       SubArray1D<Type>&
00180       operator+=(const SubArray1D<Type>& other);
00181 
00193       SubArray1D<Type>&
00194       operator-=(const SubArray1D<Type>& other);
00195 
00196     private:
00205       inline int
00206       abs(int argument) {return (argument >= 0) ? argument : -argument;}
00207 
00208       inline void
00209       checkArray1DSize(const Array1D<Type>& other) const;
00210 
00211       inline void
00212       checkSubArray1DSize(const SubArray1D<Type>& other) const;
00213 
00214       SubArray1D<Type>&
00215       copy(const SubArray1D<Type>& other);
00216 
00217       Array1D<Type> m_source;
00218       int m_start;
00219       int m_stop;
00220       int m_stride;
00221       size_t m_size;
00222     };
00223 
00224 
00225     /* Non-member functions */
00226 
00238     template <class Type>
00239     inline SubArray1D<Type>
00240     subArray(const Array1D<Type>& source) {return SubArray1D<Type>(source);}
00241 
00242   
00262     template <class Type>
00263     inline SubArray1D<Type>
00264     subArray(const Array1D<Type>& source,
00265              const Slice& rowSlice) {
00266       return SubArray1D<Type>(source, rowSlice);
00267     }
00268 
00269   
00280     template <class Type>
00281     std::ostream&
00282     operator<<(std::ostream& stream, const SubArray1D<Type>& subArray0);
00283 
00284   } // namespace numeric
00285 
00286 } // namespace dlr
00287 
00288 
00289 /* ======= Declarations to maintain compatibility with legacy code. ======= */
00290 
00291 namespace dlr {
00292 
00293   using numeric::SubArray1D;
00294   using numeric::subArray;
00295 
00296 } // namespace dlr
00297 
00298 
00299 /*******************************************************************
00300  * Function definitions follow.  This would be a .C file
00301  * if SubArray1D weren't templated.
00302  *******************************************************************/
00303 
00304 #include <cmath>
00305 #include <dlrCommon/stridedPointer.h>
00306 
00307 namespace dlr {
00308 
00309   namespace numeric {
00310     
00311     template <class Type>
00312     SubArray1D<Type>::
00313     SubArray1D(const Array1D<Type>& source)
00314       : m_source(source),
00315         m_start(0),
00316         m_stop(source.size()),
00317         m_stride(1),
00318         m_size(source.size())
00319     {
00320       // Empty
00321     }
00322 
00323     template <class Type>
00324     SubArray1D<Type>::
00325     SubArray1D(const Array1D<Type>& source, const Slice& slice0)
00326       : m_source(source),
00327         m_start(slice0.start()),
00328         m_stop(slice0.stop()),
00329         m_stride(slice0.stride()),
00330         m_size(0)
00331     {
00332       // It's convenient to be able to specify "last element" somehow.
00333       // Setting the stop value to zero will wrap to source.size()
00334       // if appropriate.
00335       if((this->m_stop == 0) && (this->m_stride > 0)) {
00336         this->m_stop = source.size();
00337       }
00338     
00339       // Negative indexing is also super-convenient
00340       while(this->m_start < 0) {
00341         this->m_start += source.size();
00342       }
00343       while(this->m_stop < 0) {
00344         this->m_stop += source.size();
00345       }
00346 
00347       // Now compute sizes (yuck).
00348       this->m_size = ((this->m_stop - this->m_start)
00349                       / this->m_stride); // integer division
00350       if(this->m_size < 0) {
00351         this->m_size = 0; 
00352       } else {
00353         // Can't think of a better way to do this.
00354         if(this->abs(this->m_size * this->m_stride)
00355            < this->abs(this->m_stop - this->m_start)) {
00356           ++this->m_size;
00357         }
00358       }
00359 
00360       // Make sure we won't read/write outside of the array.
00361       this->checkArray1DSize(source);
00362     }
00363 
00364   
00365     template <class Type>
00366     SubArray1D<Type>::
00367     SubArray1D(const SubArray1D<Type> &other)
00368       : m_source(other.m_source),
00369         m_start(other.m_start),
00370         m_stop(other.m_stop),
00371         m_stride(other.m_stride),
00372         m_size(other.m_size)
00373     {
00374       // Empty
00375     }
00376 
00377   
00378     template <class Type>
00379     SubArray1D<Type>::operator Array1D<Type>() const
00380     {
00381       Array1D<Type> returnVal(this->size());
00382       subArray(returnVal) = *this;
00383       return returnVal;
00384     }
00385 
00386   
00387     template <class Type>
00388     SubArray1D<Type>& SubArray1D<Type>::
00389     operator=(const SubArray1D<Type>& other)
00390     {
00391       this->checkSubArray1DSize(other);
00392       return this->copy(other);
00393     }
00394 
00395   
00396     template <class Type>
00397     SubArray1D<Type>& SubArray1D<Type>::
00398     operator=(Type value)
00399     {
00400       StridedPointer<Type> outPtr0(this->m_source.data(m_start), this->m_stride);
00401       StridedPointer<Type> outPtr1 = outPtr0 + this->size();
00402       std::fill(outPtr0, outPtr1, value);
00403       return *this;
00404     }
00405 
00406   
00407     template <class Type>
00408     SubArray1D<Type>& SubArray1D<Type>::
00409     operator+=(const SubArray1D<Type>& other)
00410     {
00411       this->checkSubArray1DSize(other);
00412       StridedPointer<Type> thisDataPtr0(this->m_source.data(this->m_start),
00413                                         this->m_stride);
00414       StridedPointer<Type> thisDataPtr1 = thisDataPtr0 + this->size();
00415       StridedPointer<const Type>
00416         otherDataPtr0(other.m_source.data(other.m_start), other.m_stride);
00417       std::transform(thisDataPtr0, thisDataPtr1, otherDataPtr0, thisDataPtr0,
00418                      std::plus<Type>());
00419       return *this;
00420     }
00421 
00422   
00423     template <class Type>
00424     SubArray1D<Type>& SubArray1D<Type>::
00425     operator-=(const SubArray1D<Type>& other)
00426     {
00427       this->checkSubArray1DSize(other);
00428       StridedPointer<Type> thisDataPtr0(this->m_source.data(this->m_start),
00429                                         this->m_stride);
00430       StridedPointer<Type> thisDataPtr1 = thisDataPtr0 + this->size();
00431       StridedPointer<const Type>
00432         otherDataPtr0(other.m_source.data(other.m_start), other.m_stride);
00433       std::transform(thisDataPtr0, thisDataPtr1, otherDataPtr0, thisDataPtr0,
00434                      std::minus<Type>());
00435       return *this;
00436     }
00437   
00438     template <class Type>
00439     inline void SubArray1D<Type>::
00440     checkArray1DSize(const Array1D<Type>& other) const
00441     {
00442 #ifdef _DLRNUMERIC_CHECKBOUNDS_
00443       if((m_start < 0) || (m_start >= static_cast<int>(other.size()))) {
00444         std::ostringstream message;
00445         message << "Invalid start index: " << m_start << std::endl;
00446         DLR_THROW(IndexException, "SubArray1D::checkArray1DSize()",
00447                   message.str().c_str());
00448       }
00449       if(m_stride > 0) {
00450         if(m_stop > static_cast<int>(other.size())) {
00451           std::ostringstream message;
00452           message << "Invalid stop index: " << m_stop << std::endl;
00453           DLR_THROW(IndexException, "SubArray1D::checkArray1DSize()",
00454                     message.str().c_str());
00455         }
00456       } else if(m_stride < 0) {
00457         if(m_stop < -1) {
00458           std::ostringstream message;
00459           message << "Invalid stop index: " << m_stop << std::endl;
00460           DLR_THROW(IndexException, "SubArray1D::checkArray1DSize()",
00461                     message.str().c_str());
00462         }
00463       } else {
00464         // m_stride == 0
00465         DLR_THROW(IndexException, "SubArray1D::checkArray1DSize()",
00466                   "Invalid stride: 0");
00467       }
00468 #endif
00469     }
00470 
00471   
00472     template <class Type>
00473     inline void SubArray1D<Type>::
00474     checkSubArray1DSize(const SubArray1D<Type>& other) const
00475     {
00476 #ifdef _DLRNUMERIC_CHECKBOUNDS_
00477       if(other.size() != this->size()) {
00478         std::ostringstream message;
00479         message << "Size mismatch: " << other.size() << " vs. "
00480                 << this->size() << std::endl;
00481         DLR_THROW(IndexException, "SubArray1D::checkSubArray1DSize()",
00482                   message.str().c_str());
00483       }
00484 #endif
00485     }
00486 
00487   
00488     template <class Type>
00489     SubArray1D<Type>& SubArray1D<Type>::
00490     copy(const SubArray1D<Type>& other)
00491     {
00492       StridedPointer<const Type>
00493         inPtr0(other.m_source.data(other.m_start), other.stride());
00494       StridedPointer<const Type> inPtr1 = inPtr0 + other.size();
00495       StridedPointer<Type>
00496         outPtr0(this->m_source.data(this->m_start), this->m_stride);
00497       std::copy(inPtr0, inPtr1, outPtr0);
00498       return *this;
00499     }
00500 
00501     /* Non-member functions */
00502 
00503     template <class Type>
00504     std::ostream& operator<<(std::ostream& stream,
00505                              const SubArray1D<Type>& subArray)
00506     {
00507       Array1D<Type> array(subArray.size());
00508       subArray1D(array) = subArray;
00509       stream << "SubArray1D([";
00510       for(int index0 = 0; index < array.size() - 1; ++index0) {
00511         stream << array(index0) << ", ";
00512       }
00513       stream << array(array.size() - 1) << "])";
00514       stream.flush();
00515       return stream;
00516     }
00517 
00518   } // namespace numeric
00519 
00520 } // namespace dlr
00521 
00522 #endif // #ifdef _DLR_SUBARRAY1D_H_
00523 

Generated on Wed Nov 25 00:42:43 2009 for dlrUtilities Utility Library by  doxygen 1.5.8