00001
00015 #ifndef _DLR_SUBARRAY2D_H_
00016 #define _DLR_SUBARRAY2D_H_
00017
00018 #include <dlrNumeric/array2D.h>
00019 #include <dlrNumeric/slice.h>
00020
00021 namespace dlr {
00022
00023 namespace numeric {
00024
00039 template <class Type>
00040 class SubArray2D {
00041 public:
00048 SubArray2D(const Array2D<Type>& source);
00049
00065 SubArray2D(const Array2D<Type>& source, const Slice& rowSlice,
00066 const Slice& columnSlice);
00067
00076 SubArray2D(const SubArray2D<Type> &other);
00077
00081 virtual
00082 ~SubArray2D() {}
00083
00092 operator Array2D<Type>() const;
00093
00101 inline size_t
00102 rows() const {return this->m_rows;}
00103
00112 inline size_t
00113 columns() const {return this->m_columns;}
00114
00123 inline size_t
00124 startRow() const {return this->m_startRow;}
00125
00134 inline size_t
00135 startColumn() const {return this->m_startColumn;}
00136
00144 inline size_t
00145 rowStride() const {return this->m_rowStride;}
00146
00155 inline size_t
00156 columnStride() const {return this->m_columnStride;}
00157
00166 inline Array2D<Type>
00167 getArray() const {return this->m_source;}
00168
00179 SubArray2D<Type>&
00180 operator=(const SubArray2D<Type>& other);
00181
00192 SubArray2D<Type>& operator=(Type value);
00193
00204 SubArray2D<Type>&
00205 operator+=(const SubArray2D<Type>& other);
00206
00217 SubArray2D<Type>&
00218 operator-=(const SubArray2D<Type>& other);
00219
00220 private:
00221
00230 inline int
00231 abs(int argument) {return (argument >= 0) ? argument : -argument;}
00232
00233 inline void
00234 checkArray2DSize(const Array2D<Type>& other) const;
00235
00236 inline void
00237 checkSubArray2DSize(const SubArray2D<Type>& other) const;
00238
00239 SubArray2D<Type>&
00240 copyColumnMajor(const SubArray2D<Type>& other);
00241
00242 SubArray2D<Type>&
00243 copyRowMajor(const SubArray2D<Type>& other);
00244
00245 Array2D<Type> m_source;
00246 int m_startRow;
00247 int m_stopRow;
00248 int m_rowStride;
00250 size_t m_rows;
00251 int m_startColumn;
00252 int m_stopColumn;
00253 int m_columnStride;
00255 size_t m_columns;
00256 };
00257
00258
00259
00260
00275 template <class Type>
00276 inline SubArray2D<Type>
00277 subArray(const Array2D<Type>& source) {return SubArray2D<Type>(source);}
00278
00279
00300 template <class Type>
00301 inline SubArray2D<Type>
00302 subArray(const Array2D<Type>& source,
00303 const Slice& rowSlice,
00304 const Slice& columnSlice) {
00305 return SubArray2D<Type>(source, rowSlice, columnSlice);
00306 }
00307
00308
00328 template <class Type>
00329 inline SubArray2D<Type>
00330 subArray(const Array2D<Type>& source,
00331 const int row,
00332 const Slice& columnSlice) {
00333 return SubArray2D<Type>(source, Slice(row, row+1), columnSlice);
00334 }
00335
00336
00356 template <class Type>
00357 inline SubArray2D<Type>
00358 subArray(const Array2D<Type>& source,
00359 const Slice& rowSlice,
00360 int column) {
00361 return SubArray2D<Type>(source, rowSlice, Slice(column, column + 1));
00362 }
00363
00364
00373 template <class Type>
00374 std::ostream&
00375 operator<<(std::ostream& stream, const SubArray2D<Type>& subArray0);
00376
00377 }
00378
00379 }
00380
00381
00382
00383
00384 namespace dlr {
00385
00386 using numeric::SubArray2D;
00387 using numeric::subArray;
00388
00389 }
00390
00391
00392
00393
00394
00395
00396
00397 #include <cmath>
00398 #include <dlrCommon/stridedPointer.h>
00399
00400 namespace dlr {
00401
00402 namespace numeric {
00403
00404 template <class Type>
00405 SubArray2D<Type>::
00406 SubArray2D(const Array2D<Type>& source)
00407 : m_source(source),
00408 m_startRow(0),
00409 m_stopRow(source.rows()),
00410 m_rowStride(1),
00411 m_rows(source.rows()),
00412 m_startColumn(0),
00413 m_stopColumn(source.columns()),
00414 m_columnStride(1),
00415 m_columns(source.columns())
00416 {
00417
00418 }
00419
00420 template <class Type>
00421 SubArray2D<Type>::
00422 SubArray2D(const Array2D<Type>& source, const Slice& rowSlice,
00423 const Slice& columnSlice)
00424 : m_source(source),
00425 m_startRow(rowSlice.start()),
00426 m_stopRow(rowSlice.stop()),
00427 m_rowStride(rowSlice.stride()),
00428 m_rows(0),
00429 m_startColumn(columnSlice.start()),
00430 m_stopColumn(columnSlice.stop()),
00431 m_columnStride(columnSlice.stride()),
00432 m_columns(0)
00433 {
00434
00435
00436
00437 if((this->m_stopRow == 0) && (this->m_rowStride > 0)) {
00438 this->m_stopRow = static_cast<int>(source.rows());
00439 }
00440 if((this->m_stopColumn == 0) && (this->m_columnStride > 0)) {
00441 this->m_stopColumn = static_cast<int>(source.columns());
00442 }
00443
00444
00445 while(this->m_startRow < 0) {
00446 this->m_startRow += static_cast<int>(source.rows());
00447 }
00448 while(this->m_stopRow < 0) {
00449 this->m_stopRow += static_cast<int>(source.rows());
00450 }
00451 while(this->m_startColumn < 0) {
00452 this->m_startColumn += static_cast<int>(source.columns());
00453 }
00454 while(this->m_stopColumn < 0) {
00455 this->m_stopColumn += static_cast<int>(source.columns());
00456 }
00457
00458
00459 this->m_rows = ((this->m_stopRow - this->m_startRow)
00460 / this->m_rowStride);
00461 if(this->m_rows < 0) {
00462 this->m_rows = 0;
00463 } else {
00464
00465 if(this->abs(static_cast<int>(this->m_rows) * this->m_rowStride)
00466 < this->abs(this->m_stopRow - this->m_startRow)) {
00467 ++this->m_rows;
00468 }
00469 }
00470 this->m_columns = ((this->m_stopColumn - this->m_startColumn)
00471 / this->m_columnStride);
00472 if(this->m_columns < 0) {
00473 this->m_columns = 0;
00474 } else {
00475
00476 if(this->abs(static_cast<int>(this->m_columns) * this->m_columnStride)
00477 < this->abs(this->m_stopColumn - this->m_startColumn)) {
00478 ++this->m_columns;
00479 }
00480 }
00481
00482 this->checkArray2DSize(source);
00483 }
00484
00485 template <class Type>
00486 SubArray2D<Type>::
00487 SubArray2D(const SubArray2D<Type> &other)
00488 : m_source(other.m_source),
00489 m_startRow(other.m_startRow),
00490 m_stopRow(other.m_stopRow),
00491 m_rowStride(other.m_rowStride),
00492 m_rows(other.m_rows),
00493 m_startColumn(other.m_startColumn),
00494 m_stopColumn(other.m_stopColumn),
00495 m_columnStride(other.m_columnStride),
00496 m_columns(other.m_columns)
00497 {
00498
00499 }
00500
00501 template <class Type>
00502 SubArray2D<Type>::operator Array2D<Type>() const
00503 {
00504 Array2D<Type> returnVal(this->rows(), this->columns());
00505 subArray(returnVal) = *this;
00506 return returnVal;
00507 }
00508
00509 template <class Type>
00510 SubArray2D<Type>& SubArray2D<Type>::
00511 operator=(const SubArray2D<Type>& other)
00512 {
00513 this->checkSubArray2DSize(other);
00514
00515 if(1) {
00516 return this->copyRowMajor(other);
00517 } else {
00518 return this->copyColumnMajor(other);
00519 }
00520 }
00521
00522 template <class Type>
00523 SubArray2D<Type>& SubArray2D<Type>::
00524 operator=(Type value)
00525 {
00526 int outRow = m_startRow;
00527 while(outRow < m_stopRow) {
00528 StridedPointer<Type>
00529 outPtr0(this->m_source.data(outRow, this->m_startColumn),
00530 this->m_columnStride);
00531 StridedPointer<Type> outPtr1 = outPtr0 + this->columns();
00532 std::fill(outPtr0, outPtr1, value);
00533 outRow += this->m_rowStride;
00534 }
00535 return *this;
00536 }
00537
00538 template <class Type>
00539 SubArray2D<Type>& SubArray2D<Type>::
00540 operator+=(const SubArray2D<Type>& other)
00541 {
00542 this->checkSubArray2DSize(other);
00543 int inRow = other.m_startRow;
00544 int outRow = this->m_startRow;
00545 while(inRow < other.m_stopRow) {
00546 StridedPointer<Type>
00547 thisDataPtr0(this->m_source.data(outRow, this->m_startColumn),
00548 this->m_columnStride);
00549 StridedPointer<Type> thisDataPtr1 = thisDataPtr0 + this->columns();
00550 StridedPointer<const Type>
00551 otherDataPtr0(other.m_source.data(inRow, other.m_startColumn),
00552 other.m_columnStride);
00553 std::transform(thisDataPtr0, thisDataPtr1, otherDataPtr0, thisDataPtr0,
00554 std::plus<Type>());
00555 inRow += other.m_rowStride;
00556 outRow += this->m_rowStride;
00557 }
00558 return *this;
00559 }
00560
00561 template <class Type>
00562 SubArray2D<Type>& SubArray2D<Type>::
00563 operator-=(const SubArray2D<Type>& other)
00564 {
00565 this->checkSubArray2DSize(other);
00566 int inRow = other.m_startRow;
00567 int outRow = this->m_startRow;
00568 while(inRow < other.m_stopRow) {
00569 StridedPointer<Type>
00570 thisDataPtr0(this->m_source.data(outRow, this->m_startColumn),
00571 this->m_columnStride);
00572 StridedPointer<Type> thisDataPtr1 = thisDataPtr0 + this->columns();
00573 StridedPointer<const Type>
00574 otherDataPtr0(other.m_source.data(inRow, other.m_startColumn),
00575 other.m_columnStride);
00576 std::transform(thisDataPtr0, thisDataPtr1, otherDataPtr0, thisDataPtr0,
00577 std::minus<Type>());
00578 inRow += other.m_rowStride;
00579 outRow += this->m_rowStride;
00580 }
00581 return *this;
00582 }
00583
00584 template <class Type>
00585 inline void SubArray2D<Type>::
00586 checkArray2DSize(const Array2D<Type>& other) const
00587 {
00588 #ifdef _DLRNUMERIC_CHECKBOUNDS_
00589 if((m_startRow < 0) || (m_startRow >= static_cast<int>(other.rows()))) {
00590 std::ostringstream message;
00591 message << "Invalid start row: " << m_startRow << std::endl;
00592 DLR_THROW(IndexException, "SubArray2D::checkArray2DSize()",
00593 message.str().c_str());
00594 }
00595 if(m_rowStride > 0) {
00596 if(m_stopRow > static_cast<int>(other.rows())) {
00597 std::ostringstream message;
00598 message << "Invalid stop row: " << m_stopRow << std::endl;
00599 DLR_THROW(IndexException, "SubArray2D::checkArray2DSize()",
00600 message.str().c_str());
00601 }
00602 } else if(m_rowStride < 0) {
00603 if(m_stopRow < -1) {
00604 std::ostringstream message;
00605 message << "Invalid stop row: " << m_stopRow << std::endl;
00606 DLR_THROW(IndexException, "SubArray2D::checkArray2DSize()",
00607 message.str().c_str());
00608 }
00609 } else {
00610
00611 DLR_THROW(IndexException, "SubArray2D::checkArray2DSize()",
00612 "Invalid row stride: 0\n");
00613 }
00614 if((m_startColumn < 0)
00615 || (m_startColumn >= static_cast<int>(other.columns()))) {
00616 std::ostringstream message;
00617 message << "Invalid start column: " << m_startColumn << std::endl;
00618 DLR_THROW(IndexException, "SubArray2D::checkArray2DSize()",
00619 message.str().c_str());
00620 }
00621 if(m_columnStride > 0) {
00622 if(m_stopColumn > static_cast<int>(other.columns())) {
00623 std::ostringstream message;
00624 message << "Invalid stop column: " << m_stopColumn << std::endl;
00625 DLR_THROW(IndexException, "SubArray2D::checkArray2DSize()",
00626 message.str().c_str());
00627 }
00628 } else if(m_columnStride < 0) {
00629 if(m_stopColumn < -1) {
00630 std::ostringstream message;
00631 message << "Invalid stop column: " << m_stopColumn << std::endl;
00632 DLR_THROW(IndexException, "SubArray2D::checkArray2DSize()",
00633 message.str().c_str());
00634 }
00635 } else {
00636
00637 DLR_THROW(IndexException, "SubArray2D::checkArray2DSize()",
00638 "Invalid column stride: 0\n");
00639 }
00640 #endif
00641 }
00642
00643 template <class Type>
00644 inline void SubArray2D<Type>::
00645 checkSubArray2DSize(const SubArray2D<Type>& other) const
00646 {
00647 #ifdef _DLRNUMERIC_CHECKBOUNDS_
00648 if(other.rows() != this->rows()) {
00649 std::ostringstream message;
00650 message << "Row mismatch: " << other.rows() << " vs. "
00651 << this->rows() << std::endl;
00652 DLR_THROW(IndexException, "SubArray2D::checkSubArray2DSize()",
00653 message.str().c_str());
00654 }
00655 if(other.columns() != this->columns()) {
00656 std::ostringstream message;
00657 message << "Column mismatch: " << other.columns() << " vs. "
00658 << this->columns() << std::endl;
00659 DLR_THROW(IndexException, "SubArray2D::checkSubArray2DSize()",
00660 message.str().c_str());
00661 }
00662 #endif
00663 }
00664
00665 template <class Type>
00666 SubArray2D<Type>& SubArray2D<Type>::
00667 copyColumnMajor(const SubArray2D<Type>& other)
00668 {
00669 int inColumn = other.m_startColumn;
00670 int outColumn = this->m_startColumn;
00671 while(inColumn < other.m_stopColumn) {
00672 StridedPointer<const Type>
00673 inPtr0(other.m_source.data(other.m_startRow, inColumn),
00674 other.m_rowStride * other.m_source.columns());
00675 StridedPointer<const Type> inPtr1 = inPtr0 + other.rows();
00676 StridedPointer<Type>
00677 outPtr0(this->m_source.data(this->m_startRow, outColumn),
00678 this->m_rowStride * this->m_source.columns());
00679 std::copy(inPtr0, inPtr1, outPtr0);
00680 inColumn += other.m_columnStride;
00681 outColumn += this->m_columnStride;
00682 }
00683 return *this;
00684 }
00685
00686 template <class Type>
00687 SubArray2D<Type>& SubArray2D<Type>::
00688 copyRowMajor(const SubArray2D<Type>& other)
00689 {
00690 int inRow = other.m_startRow;
00691 int outRow = this->m_startRow;
00692 while(inRow < other.m_stopRow) {
00693 StridedPointer<const Type>
00694 inPtr0(other.m_source.data(inRow, other.m_startColumn),
00695 other.m_columnStride);
00696 StridedPointer<const Type> inPtr1 = inPtr0 + other.columns();
00697 StridedPointer<Type>
00698 outPtr0(this->m_source.data(outRow, this->m_startColumn),
00699 this->m_columnStride);
00700 std::copy(inPtr0, inPtr1, outPtr0);
00701 inRow += other.m_rowStride;
00702 outRow += this->m_rowStride;
00703 }
00704 return *this;
00705 }
00706
00707
00708
00709 template <class Type>
00710 std::ostream& operator<<(std::ostream& stream,
00711 const SubArray2D<Type>& subArray)
00712 {
00713 Array2D<Type> array(subArray.rows(), subArray.columns());
00714 subArray2D(array) = subArray;
00715 stream << "SubArray2D([[";
00716 for(int row = 0; row < array.rows(); ++row) {
00717 for(int column = 0; column < array.columns() - 1; ++column) {
00718 stream << array(row, column) << ", ";
00719 }
00720 stream << array(row, array.columns() - 1) << "],\n";
00721 if(row != array.rows() - 1) {
00722 stream << " ";
00723 }
00724 }
00725 stream.flush();
00726 return stream;
00727 }
00728
00729 }
00730
00731 }
00732
00733 #endif // #ifdef _DLR_SUBARRAY2D_H_
00734