stencil2D.h

Go to the documentation of this file.
00001 
00015 #ifndef _DLRNUMERIC_STENCIL2D_H_
00016 #define _DLRNUMERIC_STENCIL2D_H_
00017 
00018 #include <vector>
00019 #include <dlrNumeric/array2D.h>
00020 #include <dlrNumeric/index2D.h>
00021 
00022 namespace dlr {
00023 
00024   namespace numeric {
00025     
00034     template <class Type, int Size>
00035     class StencilIterator
00036     {
00037     public:
00038 
00054       StencilIterator(Type* ptr, int* incrementPtr, size_t position=0)
00055         : m_incrementPtr(incrementPtr),
00056           m_position(position),
00057           m_ptr(ptr) {}
00058 
00069       bool
00070       operator!=(const StencilIterator<Type, Size>& other) {
00071         return m_ptr != other.m_ptr;
00072       }
00073 
00074     
00085       bool
00086       operator==(const StencilIterator<Type, Size>& other) {
00087         return m_ptr == other.m_ptr;
00088       }
00089 
00090     
00097       StencilIterator<Type, Size>&
00098       operator++() {m_ptr += m_incrementPtr[m_position++]; return *this;}
00099 
00100     
00108       StencilIterator<Type, Size>
00109       operator++(int) {
00110         StencilIterator<Type, Size> result(*this);
00111         ++(*this);
00112         return result;
00113       }
00114 
00115 
00122       StencilIterator<Type, Size>&
00123       operator--() {m_ptr += m_incrementPtr[--m_position]; return *this;}
00124 
00125     
00133       StencilIterator<Type, Size>
00134       operator--(int) {
00135         StencilIterator<Type, Size> result(*this);
00136         --(*this);
00137         return result;
00138       }
00139 
00140 
00154       Type&
00155       operator*() {return *m_ptr;}
00156 
00157     
00170       Type* operator->() {return m_ptr;}
00171 
00172     private:
00173       int* m_incrementPtr;
00174       size_t m_position;
00175       Type* m_ptr;
00176     };
00177 
00178 
00200     template <class Type, int Size>
00201     class Stencil2D {
00202     public:
00206       Stencil2D();
00207 
00208 
00218       Stencil2D(size_t rows, size_t columns);
00219     
00220 
00233       Stencil2D(const Array2D<bool>& pattern);
00234 
00235 
00247       Stencil2D(const std::vector<Index2D>& pattern);
00248     
00249 
00253       ~Stencil2D() {}
00254 
00255 
00262       inline void
00263       advance() {++m_ptr;}
00264     
00265 
00274       StencilIterator<Type, Size>
00275       begin() {return StencilIterator<Type, Size>(
00276                  m_ptr + m_offsetArray[0], m_incrementArray, 0);}
00277 
00278 
00288       StencilIterator<Type, Size>
00289       end() {return StencilIterator<Type, Size>(
00290                m_ptr + m_targetSize, m_incrementArray, m_numberOfElements);}
00291     
00292 
00304       inline Type&
00305       getReference(size_t elementNumber);
00306 
00307 
00318       inline Type
00319       getValue(size_t elementNumber) const;
00320 
00321 
00330       inline void
00331       goTo(size_t index);
00332 
00333 
00345       inline void
00346       goTo(size_t row, size_t column);
00347 
00348 
00358       void
00359       setPattern(const Array2D<bool>& pattern);
00360 
00361 
00369       template <class Type2>
00370       void
00371       setTarget(const Array2D<Type2>& target);
00372 
00373 
00381       template <class Type2>
00382       void
00383       setTarget(Array2D<Type2>& target);
00384     
00385       // private:
00386 
00387       inline void
00388       checkBounds(size_t elementNumber) const;
00389 
00390 
00391       // Data members to allow moving around in the target array.
00392       Type* m_basePtr;
00393       size_t m_rows;
00394       size_t m_columns;
00395 
00396       // Data members to allow bounds checking.
00397       int m_targetSize;
00398 
00399       // Data members which actually do the work.
00400       size_t m_numberOfElements;
00401       Type* m_ptr;
00402       int m_offsetArray[Size];
00403       int m_incrementArray[Size];
00404       Index2D m_patternArray[Size];
00405     };
00406 
00407   } // namespace numeric
00408 
00409 } // namespace dlr
00410 
00411 
00412 /* ======= Declarations to maintain compatibility with legacy code. ======= */
00413 
00414 namespace dlr {
00415 
00416   using numeric::StencilIterator;
00417   using numeric::Stencil2D;
00418 
00419 } // namespace dlr
00420 
00421 
00422 /* ============ Definitions of inline & template functions ============ */
00423 
00424 
00425 #include <cmath>
00426 
00427 namespace dlr {
00428 
00429   namespace numeric {
00430     
00431     template <class Type, int Size>
00432     Stencil2D<Type, Size>::
00433     Stencil2D()
00434       : m_basePtr(0),
00435         m_rows(0),
00436         m_columns(0),
00437         m_targetSize(0),
00438         m_numberOfElements(0),
00439         m_ptr(0),
00440         m_offsetArray(),
00441         m_incrementArray(),
00442         m_patternArray()
00443     {
00444       for(size_t elementIndex = 0; elementIndex < Size; ++elementIndex) {
00445         m_offsetArray[elementIndex] = 0;
00446         m_incrementArray[elementIndex] = 0;
00447         m_patternArray[elementIndex] = Index2D(0, 0);
00448       }
00449     }
00450 
00451 
00452     template <class Type, int Size>
00453     Stencil2D<Type, Size>::
00454     Stencil2D(size_t rows, size_t columns)
00455       : m_basePtr(0),
00456         m_rows(0),
00457         m_columns(0),
00458         m_targetSize(0),
00459         m_numberOfElements(rows * columns),
00460         m_ptr(0),
00461         m_offsetArray(),
00462         m_incrementArray(),
00463         m_patternArray()
00464     {
00465       if(rows * columns > Size) {
00466         std::ostringstream message;
00467         message << "Requested size, (" << rows << ", " << columns << ") "
00468                 << "is too big for a " << Size << " element stencil.";
00469         DLR_THROW(ValueException, "Stencil2D::Stencil2D()",
00470                   message.str().c_str());
00471       }
00472 
00473       // Record the rows x columns ROI.
00474       size_t index0 = 0;
00475       for(int row = 0; row < static_cast<int>(rows); ++row) {
00476         for(int column = 0; column < static_cast<int>(columns); ++column) {
00477           m_offsetArray[index0] = 0;
00478           m_incrementArray[index0] = 0;
00479           m_patternArray[index0] = Index2D(row, column);
00480           ++index0;
00481         }
00482       }
00483 
00484       // Fill in any unused elements with zeros.
00485       while(index0 < Size) {
00486         m_offsetArray[index0] = 0;
00487         m_incrementArray[index0] = 0;
00488         m_patternArray[index0] = Index2D(0, 0);
00489         ++index0;
00490       }
00491     }
00492   
00493     
00494     template <class Type, int Size>
00495     Stencil2D<Type, Size>::
00496     Stencil2D(const Array2D<bool>& pattern)
00497       : m_basePtr(0),
00498         m_rows(0),
00499         m_columns(0),
00500         m_targetSize(0),
00501         m_numberOfElements(0),
00502         m_ptr(0),
00503         m_offsetArray(),
00504         m_incrementArray(),
00505         m_patternArray()
00506     {
00507       this->setPattern(pattern);
00508     }
00509 
00510 
00511     template <class Type, int Size>
00512     Stencil2D<Type, Size>::
00513     Stencil2D(const std::vector<Index2D>& pattern)
00514       : m_basePtr(0),
00515         m_rows(0),
00516         m_columns(0),
00517         m_targetSize(0),
00518         m_numberOfElements(pattern.size()),
00519         m_ptr(0),
00520         m_offsetArray(),
00521         m_incrementArray(),
00522         m_patternArray()
00523     {
00524       if(pattern.size() > Size) {
00525         std::ostringstream message;
00526         message << "Requested pattern has too many elements for a "
00527                 << Size << " element stencil.";
00528         DLR_THROW(ValueException, "Stencil2D::Stencil2D()",
00529                   message.str().c_str());
00530       }
00531       std::fill(m_offsetArray.begin(), m_offsetArray.end(), 0);
00532       std::fill(m_incrementArray.begin(), m_incrementArray.end(), 0);
00533       std::copy(pattern.begin(), pattern.end(), m_patternArray.begin());
00534       for(size_t index0 = pattern.size(); index0 < Size; ++index0) {
00535         m_patternArray[index0] = Index2D(0, 0);
00536       }
00537     }
00538 
00539   
00540     template <class Type, int Size>
00541     Type&
00542     Stencil2D<Type, Size>::
00543     getReference(size_t elementNumber)
00544     {
00545       this->checkBounds(elementNumber);
00546       return *(m_ptr + m_offsetArray[elementNumber]);
00547     }
00548       
00549 
00550     template <class Type, int Size>
00551     Type
00552     Stencil2D<Type, Size>::
00553     getValue(size_t elementNumber) const
00554     {
00555       this->checkBounds(elementNumber);
00556       return *(m_ptr + m_offsetArray[elementNumber]);
00557     }
00558 
00559 
00560     template <class Type, int Size>
00561     void
00562     Stencil2D<Type, Size>::
00563     goTo(size_t index)
00564     {
00565       m_ptr = m_basePtr + index;
00566     }
00567 
00568 
00569     template <class Type, int Size>
00570     void
00571     Stencil2D<Type, Size>::
00572     goTo(size_t row, size_t column)
00573     {
00574       m_ptr = m_basePtr + row * m_columns + column;
00575     }
00576 
00577 
00578     template <class Type, int Size>
00579     void
00580     Stencil2D<Type, Size>::
00581     setPattern(const Array2D<bool>& pattern)
00582     {
00583       // Record which of the elements in pattern are true.
00584       size_t index0 = 0;
00585       for(int row = 0; row < static_cast<int>(pattern.rows()); ++row) {
00586         for(int column = 0; column < static_cast<int>(pattern.columns());
00587             ++column) {
00588           if(pattern(row, column)) {
00589             if(index0 >= Size) {
00590               std::ostringstream message;
00591               message << "Requested pattern has too many elements for a "
00592                       << Size << " element stencil.";
00593               DLR_THROW(ValueException, "Stencil2D::Stencil2D()",
00594                         message.str().c_str());
00595             }
00596             m_offsetArray[index0] = 0;
00597             m_incrementArray[index0] = 0;
00598             m_patternArray[index0] = Index2D(row, column);
00599             ++index0;
00600           }
00601         }
00602       }
00603       m_numberOfElements = index0;
00604 
00605       // Fill in any unused elements with zeros.
00606       while(index0 < Size) {
00607         m_offsetArray[index0] = 0;
00608         m_incrementArray[index0] = 0;
00609         m_patternArray[index0] = Index2D(0, 0);
00610         ++index0;
00611       }
00612     }
00613 
00614     
00615     template <class Type, int Size> template <class Type2>
00616     void
00617     Stencil2D<Type, Size>::
00618     setTarget(const Array2D<Type2>& target)
00619     {
00620       m_basePtr = target.data();
00621       m_rows = target.rows();
00622       m_columns = target.columns();
00623       m_targetSize = static_cast<int>(target.size());
00624       m_ptr = m_basePtr;
00625 
00626       for(size_t elementIndex = 0; elementIndex < m_numberOfElements;
00627           ++elementIndex) {
00628         Index2D targetIndex = m_patternArray[elementIndex];
00629         m_offsetArray[elementIndex] =
00630           static_cast<int>(targetIndex.getColumn() + targetIndex.getRow() * m_columns);
00631       }
00632       for(size_t elementIndex = 0; elementIndex < m_numberOfElements - 1;
00633           ++elementIndex) {
00634         m_incrementArray[elementIndex] =
00635           m_offsetArray[elementIndex + 1] - m_offsetArray[elementIndex];
00636       }
00637       m_incrementArray[m_numberOfElements - 1] =
00638         m_targetSize - m_offsetArray[m_numberOfElements - 1];
00639     }
00640 
00641 
00642     template <class Type, int Size> template <class Type2>
00643     void
00644     Stencil2D<Type, Size>::
00645     setTarget(Array2D<Type2>& target)
00646     {
00647       m_basePtr = target.data();
00648       m_rows = target.rows();
00649       m_columns = target.columns();
00650       m_targetSize = target.size();
00651       m_ptr = m_basePtr;
00652 
00653       for(size_t elementIndex = 0; elementIndex < m_numberOfElements;
00654           ++elementIndex) {
00655         Index2D targetIndex = m_patternArray[elementIndex];
00656         m_offsetArray[elementIndex] =
00657           targetIndex.getColumn() + targetIndex.getRow() * m_columns;
00658       }
00659       for(size_t elementIndex = 0; elementIndex < m_numberOfElements - 1;
00660           ++elementIndex) {
00661         m_incrementArray[elementIndex] =
00662           m_offsetArray[elementIndex + 1] - m_offsetArray[elementIndex];
00663       }
00664       m_incrementArray[m_numberOfElements - 1] =
00665         m_targetSize - m_offsetArray[m_numberOfElements - 1];
00666     }
00667 
00668 
00669     template <class Type, int Size>
00670     inline void
00671     Stencil2D<Type, Size>::
00672     checkBounds(size_t elementNumber) const
00673     {
00674 #ifdef _DLRNUMERIC_CHECKBOUNDS_
00675       if(elementNumber >= m_numberOfElements) {
00676         std::ostringstream message;
00677         message << "Element number " << elementNumber
00678                 << " is invalid for a(n) " << m_numberOfElements
00679                 << " element stencil. ";
00680         DLR_THROW(IndexException, "Stencil2D::checkBounds(size_t)",
00681                   message.str().c_str());
00682       }
00683 
00684       Type* resultPtr = m_ptr + this->m_offsetArray[elementNumber];
00685       if(resultPtr < m_basePtr) {
00686         DLR_THROW(IndexException, "Stencil2D::checkBounds(size_t)",
00687                   "Pointer has retreated too far.  "
00688                   "Stencil no longer addresses valid memory.");
00689       }
00690 
00691       if(resultPtr >= m_basePtr + m_targetSize) {
00692         DLR_THROW(IndexException, "Stencil2D::checkBounds(size_t)",
00693                   "Pointer has advanced too far.  "
00694                   "Stencil no longer addresses valid memory.");
00695       }
00696 #endif 
00697     }
00698   
00699   } // namespace numeric
00700 
00701 } // namespace dlr
00702 
00703 #endif /* #ifndef _DLRNUMERIC_STENCIL2D_H_ */

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