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
00386
00387 inline void
00388 checkBounds(size_t elementNumber) const;
00389
00390
00391
00392 Type* m_basePtr;
00393 size_t m_rows;
00394 size_t m_columns;
00395
00396
00397 int m_targetSize;
00398
00399
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 }
00408
00409 }
00410
00411
00412
00413
00414 namespace dlr {
00415
00416 using numeric::StencilIterator;
00417 using numeric::Stencil2D;
00418
00419 }
00420
00421
00422
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
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
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
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
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 }
00700
00701 }
00702
00703 #endif