00001
00015 #ifndef _DLR_ARRAY2D_H_
00016 #define _DLR_ARRAY2D_H_
00017
00018
00019 #include <algorithm>
00020
00021 #include <iostream>
00022 #include <dlrCommon/exception.h>
00023 #include <dlrNumeric/array1D.h>
00024
00025 namespace dlr {
00026
00027 namespace numeric {
00028
00051 template <class Type>
00052 class Array2D {
00053 public:
00054
00055
00056
00060 typedef Type value_type;
00061
00065 typedef Type* iterator;
00066
00071 typedef const Type* const_iterator;
00072
00073
00074
00078 Array2D();
00079
00080
00090 Array2D(size_t arrayRows, size_t arrayColumns);
00091
00092
00106 explicit
00107 Array2D(const std::string& inputString);
00108
00115 Array2D(const Array2D<Type> &source);
00116
00132 Array2D(size_t arrayRows, size_t arrayColumns, Type* const dataPtr);
00133
00134
00156 Array2D(size_t arrayRows, size_t arrayColumns, Type* const dataPtr,
00157 size_t* referenceCountPtr);
00158
00163 virtual
00164 ~Array2D();
00165
00171 iterator
00172 begin() {return m_dataPtr;}
00173
00180 const_iterator
00181 begin() const {return m_dataPtr;}
00182
00187 void
00188 clear() {this->reinit(0, 0);}
00189
00197 size_t
00198 columns() const {return m_columns;}
00199
00200
00209 inline void
00210 checkDimension(size_t arrayRows, size_t arrayColumns) const;
00211
00212
00218 Array2D<Type>
00219 copy() const;
00220
00231 template <class Type2> void
00232 copy(const Array2D<Type2>& source);
00233
00240 template <class Type2> void
00241 copy(const Type2* dataPtr);
00242
00252 Type*
00253 data() {return m_dataPtr;}
00254
00261 const Type*
00262 data() const {return m_dataPtr;}
00263
00274 Type*
00275 data(size_t index) {
00276 this->checkBounds(index);
00277 return m_dataPtr + index;
00278 }
00279
00289 const Type*
00290 data(size_t index) const {
00291 this->checkBounds(index);
00292 return m_dataPtr+index;
00293 }
00294
00307 Type*
00308 data(size_t rowIndex, size_t columnIndex) {
00309 this->checkBounds(rowIndex, columnIndex);
00310 return m_dataPtr + columnIndex + (rowIndex * m_columns);
00311 }
00312
00324 const Type*
00325 data(size_t rowIndex, size_t columnIndex) const {
00326 this->checkBounds(rowIndex, columnIndex);
00327 return m_dataPtr + columnIndex + (rowIndex * m_columns);
00328 }
00329
00330
00338 bool
00339 empty() const {return this->size() == 0;}
00340
00341
00348 iterator
00349 end() {return m_dataPtr + m_size;}
00350
00351
00358 const_iterator
00359 end() const {return m_dataPtr + m_size;}
00360
00361
00371 inline Type
00372 getElement(size_t index0) const {return this->operator()(index0);}
00373
00374
00387 Type
00388 getElement(size_t rowIndex, size_t columnIndex) const {
00389 return this->operator()(rowIndex, columnIndex);
00390 }
00391
00392
00403 Array1D<Type>
00404 getRow(size_t index);
00405
00416 const Array1D<Type>
00417 getRow(size_t index) const;
00418
00419
00428 bool
00429 isAllocated() const {return m_isAllocated;}
00430
00431
00439 Array1D<Type>
00440 ravel();
00441
00449 const Array1D<Type>
00450 ravel() const;
00451
00464 std::istream&
00465 readFromStream(std::istream& inputStream);
00466
00467
00475 size_t*
00476 refCountPtr() const {return m_refCountPtr;}
00477
00478
00488 void
00489 reinit(size_t arrayRows, size_t arrayColumns);
00490
00491
00503 inline void
00504 reinitIfNecessary(size_t arrayRows, size_t arrayColumns);
00505
00506
00521 void
00522 reshape(int arrayRows, int arrayColumns);
00523
00524
00532 inline Array1D<Type>
00533 row(size_t index) {return this->getRow(index);}
00534
00535
00543 const Array1D<Type>
00544 row(size_t index) const {return this->getRow(index);}
00545
00546
00557 iterator
00558 rowBegin(size_t rowIndex) {return m_dataPtr + rowIndex * m_columns;}
00559
00560
00571 const_iterator
00572 rowBegin(size_t rowIndex) const {
00573 return m_dataPtr + rowIndex * m_columns;
00574 }
00575
00576
00587 iterator
00588 rowEnd(size_t rowIndex) {
00589 return m_dataPtr + (rowIndex + 1) * m_columns;
00590 }
00591
00592
00603 const_iterator
00604 rowEnd(size_t rowIndex) const {
00605 return m_dataPtr + (rowIndex + 1) * m_columns;
00606 }
00607
00608
00616 size_t
00617 rows() const {return m_rows;}
00618
00619
00633 Type&
00634 setElement(size_t index0, const Type& value) {
00635 return this->operator()(index0) = value;
00636 }
00637
00638
00655 Type&
00656 setElement(size_t rowIndex, size_t columnIndex, const Type& value) {
00657 return this->operator()(rowIndex, columnIndex) = value;
00658 }
00659
00660
00669 Array1D<size_t>
00670 shape() const;
00671
00683 size_t
00684 shape(size_t axis) const;
00685
00692 size_t
00693 size() const {return m_size;}
00694
00701 Array2D<Type>
00702 transpose() const;
00703
00712 Array2D<Type>&
00713 operator=(const Array2D<Type>& source);
00714
00722 Array2D<Type>&
00723 operator=(Type value);
00724
00733 Type&
00734 operator()(size_t index) {
00735 this->checkBounds(index);
00736 return m_dataPtr[index];
00737 }
00738
00745 Type operator()(size_t index) const {
00746 this->checkBounds(index);
00747 return m_dataPtr[index];
00748 }
00749
00759 Type&
00760 operator()(size_t rowIndex, size_t columnIndex) {
00761 this->checkBounds(rowIndex, columnIndex);
00762 return m_dataPtr[columnIndex + rowIndex * m_columns];
00763 }
00764
00774 Type
00775 operator()(size_t rowIndex, size_t columnIndex) const {
00776 this->checkBounds(rowIndex, columnIndex);
00777 return m_dataPtr[columnIndex + rowIndex * m_columns];
00778 }
00779
00788 Type&
00789 operator[](size_t index) {return this->operator()(index);}
00790
00799 Type
00800 operator[](size_t index) const {return this->operator()(index);}
00801
00813 template <class Type2> Array2D<Type>&
00814 operator+=(const Array2D<Type2>& arg);
00815
00827 template <class Type2> Array2D<Type>&
00828 operator-=(const Array2D<Type2>& arg);
00829
00841 template <class Type2> Array2D<Type>&
00842 operator*=(const Array2D<Type2>& arg);
00843
00855 template <class Type2> Array2D<Type>&
00856 operator/=(const Array2D<Type2>& arg);
00857
00865 Array2D<Type>&
00866 operator+=(Type arg);
00867
00875 Array2D<Type>&
00876 operator-=(Type arg);
00877
00885 Array2D<Type>&
00886 operator*=(Type arg);
00887
00895 Array2D<Type>&
00896 operator/=(Type arg);
00897
00898 private:
00899
00900 void
00901 allocate();
00902
00903
00904
00905 inline void
00906 checkBounds(size_t index) const;
00907
00908
00909
00910 inline void
00911 checkBounds(size_t row, size_t column) const;
00912
00913 void
00914 deAllocate();
00915
00916
00917
00918
00919
00924 static const std::string& ioIntro();
00925
00930 static const std::string& ioOutro();
00931
00936 static const char ioOpening = '[';
00937
00942 static const char ioClosing = ']';
00943
00948 static const char ioSeparator = ',';
00949
00950
00951
00952 size_t m_rows;
00953 size_t m_columns;
00954 size_t m_size;
00955 Type* m_dataPtr;
00956 size_t* m_refCountPtr;
00957 bool m_isAllocated;
00958
00959 };
00960
00961
00962
00973 template <class Type>
00974 Array2D<Type>
00975 squareRoot(const Array2D<Type>& array0);
00976
00988 template <class Type>
00989 inline Array2D<Type>
00990 sqrt(const Array2D<Type>& array0);
00991
01005 template <class Type>
01006 Array2D<Type>
01007 operator+(const Array2D<Type>& array0,
01008 const Array2D<Type>& array1);
01009
01023 template <class Type>
01024 Array2D<Type>
01025 operator-(const Array2D<Type>& array0,
01026 const Array2D<Type>& array1);
01027
01041 template <class Type>
01042 Array2D<Type>
01043 operator*(const Array2D<Type>& array0,
01044 const Array2D<Type>& array1);
01045
01059 template <class Type>
01060 Array2D<Type>
01061 operator/(const Array2D<Type>& array0,
01062 const Array2D<Type>& array1);
01063
01075 template <class Type>
01076 Array2D<Type>
01077 operator+(const Array2D<Type>& array0, Type scalar);
01078
01090 template <class Type>
01091 Array2D<Type>
01092 operator-(const Array2D<Type>& array0, Type scalar);
01093
01105 template <class Type>
01106 Array2D<Type>
01107 operator*(const Array2D<Type>& array0, Type scalar);
01108
01120 template <class Type>
01121 Array2D<Type>
01122 operator/(const Array2D<Type>& array0, Type scalar);
01123
01135 template <class Type>
01136 inline Array2D<Type>
01137 operator+(Type scalar, const Array2D<Type>& array0);
01138
01139
01151 template <class Type>
01152 inline Array2D<Type>
01153 operator*(Type scalar, const Array2D<Type>& array0);
01154
01155
01167 template <class Type>
01168 Array2D<bool>
01169 operator==(const Array2D<Type>& array0, const Type arg);
01170
01171
01184 template <class Type>
01185 Array2D<bool>
01186 operator==(const Array2D<Type>& array0, const Array2D<Type>& array1);
01187
01188
01200 template <class Type>
01201 Array2D<bool>
01202 operator>(const Array2D<Type>& array0, Type arg);
01203
01204
01216 template <class Type>
01217 Array2D<bool>
01218 operator<(const Array2D<Type>& array0, Type arg);
01219
01220
01233 template <class Type>
01234 Array2D<bool>
01235 operator>=(const Array2D<Type>& array0, Type arg);
01236
01237
01250 template <class Type>
01251 Array2D<bool>
01252 operator<=(const Array2D<Type>& array0, Type arg);
01253
01254
01273 template <class Type>
01274 std::ostream&
01275 operator<<(std::ostream& stream, const Array2D<Type>& array0);
01276
01288 template <class Type>
01289 std::istream&
01290 operator>>(std::istream& stream, Array2D<Type>& array0);
01291
01292 }
01293
01294 }
01295
01296
01297
01298
01299 namespace dlr {
01300
01301 using numeric::Array2D;
01302
01303 }
01304
01305
01306
01307
01308
01309
01310
01311 #include <algorithm>
01312 #include <functional>
01313 #include <sstream>
01314 #include <vector>
01315 #include <dlrCommon/functional.h>
01316 #include <dlrCommon/inputStream.h>
01317 #include <dlrNumeric/numericTraits.h>
01318 #include <dlrNumeric/functional.h>
01319
01320 namespace dlr {
01321
01322 namespace numeric {
01323
01324
01325
01326 template <class Type>
01327 const std::string&
01328 Array2D<Type>::
01329 ioIntro()
01330 {
01331 static const std::string intro = "Array2D(";
01332 return intro;
01333 }
01334
01335
01336
01337 template <class Type>
01338 const std::string&
01339 Array2D<Type>::
01340 ioOutro()
01341 {
01342 static const std::string outro = ")";
01343 return outro;
01344 }
01345
01346
01347
01348 template <class Type>
01349 Array2D<Type>::
01350 Array2D()
01351 : m_rows(0),
01352 m_columns(0),
01353 m_size(0),
01354 m_dataPtr(0),
01355 m_refCountPtr(0),
01356 m_isAllocated(false)
01357 {
01358
01359 }
01360
01361
01362 template <class Type>
01363 Array2D<Type>::
01364 Array2D(size_t arrayRows, size_t arrayColumns)
01365 : m_rows(arrayRows),
01366 m_columns(arrayColumns),
01367 m_size(0),
01368 m_dataPtr(0),
01369 m_refCountPtr(0),
01370 m_isAllocated(false)
01371 {
01372 this->allocate();
01373 }
01374
01375
01376
01377 template <class Type>
01378 Array2D<Type>::
01379 Array2D(const std::string& inputString)
01380 : m_rows(0),
01381 m_columns(0),
01382 m_size(0),
01383 m_dataPtr(0),
01384 m_refCountPtr(0),
01385 m_isAllocated(false)
01386 {
01387
01388 std::istringstream inputStream(inputString);
01389
01390
01391 Array2D<Type> inputArray;
01392 inputStream >> inputArray;
01393 if(!inputStream) {
01394 std::ostringstream message;
01395 message << "Couldn't parse input string: \"" << inputString << "\".";
01396 DLR_THROW3(ValueException, "Array2D::Array2D(const std::string&)",
01397 message.str().c_str());
01398 }
01399
01400
01401 *this = inputArray;
01402 }
01403
01404
01405
01406
01407
01408 template <class Type>
01409 Array2D<Type>::
01410 Array2D(const Array2D<Type>& source)
01411 : m_rows(source.m_rows),
01412 m_columns(source.m_columns),
01413 m_size(source.m_size),
01414 m_dataPtr(source.m_dataPtr),
01415 m_refCountPtr(source.m_refCountPtr),
01416 m_isAllocated(source.m_isAllocated)
01417 {
01418 if(m_isAllocated) {
01419 ++(*m_refCountPtr);
01420 }
01421 }
01422
01423
01424
01425
01426 template <class Type>
01427 Array2D<Type>::
01428 Array2D(size_t arrayRows, size_t arrayColumns, Type* const dataPtr)
01429 : m_rows(arrayRows),
01430 m_columns(arrayColumns),
01431 m_size(arrayRows*arrayColumns),
01432 m_dataPtr(dataPtr),
01433 m_refCountPtr(0),
01434 m_isAllocated(false)
01435 {
01436
01437 }
01438
01439
01440
01441
01442 template <class Type>
01443 Array2D<Type>::
01444 Array2D(size_t arrayRows, size_t arrayColumns, Type* const dataPtr,
01445 size_t* referenceCountPtr)
01446 : m_rows(arrayRows),
01447 m_columns(arrayColumns),
01448 m_size(arrayRows*arrayColumns),
01449 m_dataPtr(dataPtr),
01450 m_refCountPtr(referenceCountPtr),
01451 m_isAllocated(true)
01452 {
01453 ++(*m_refCountPtr);
01454 }
01455
01456
01457 template <class Type>
01458 Array2D<Type>::
01459 ~Array2D()
01460 {
01461 deAllocate();
01462 }
01463
01464
01465 template <class Type>
01466 inline void Array2D<Type>::
01467 checkDimension(size_t arrayRows, size_t arrayColumns) const
01468 {
01469 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01470 if(arrayRows != this->rows()
01471 || arrayColumns != this->columns()) {
01472 std::ostringstream message;
01473 message << "Size mismatch: required dimension is ("
01474 << arrayRows << ", " << arrayColumns << ") "
01475 << " while *this has dimension "
01476 << this->rows() << ", " << this->columns() << ").";
01477 DLR_THROW(IndexException, "Array2D::checkDimension()",
01478 message.str().c_str());
01479 }
01480 #endif
01481 }
01482
01483
01484 template <class Type>
01485 Array2D<Type> Array2D<Type>::
01486 copy() const
01487 {
01488 Array2D<Type> newArray(m_rows, m_columns);
01489 newArray.copy(*this);
01490 return newArray;
01491 }
01492
01493
01494 template <class Type> template <class Type2>
01495 void Array2D<Type>::
01496 copy(const Array2D<Type2>& source)
01497 {
01498 if(source.size() != m_size) {
01499 std::ostringstream message;
01500 message << "Mismatched array sizes. Source array has "
01501 << source.size() << " elements, while destination array has "
01502 << m_size << " elements.";
01503 DLR_THROW3(ValueException, "Array2D::copy(const Array2D&)",
01504 message.str().c_str());
01505 }
01506 if(m_size != 0) {
01507 this->copy(source.data());
01508 }
01509 }
01510
01511
01512 template <class Type> template <class Type2>
01513 void Array2D<Type>::
01514 copy(const Type2* dataPtr)
01515 {
01516 if(dataPtr == 0) {
01517 DLR_THROW(ValueException, "Array2D::copy(const Type2*)",
01518 "Argument is a NULL pointer.");
01519 }
01520 std::transform(dataPtr, dataPtr + m_size, m_dataPtr,
01521 StaticCastFunctor<Type2, Type>());
01522 }
01523
01524
01525 template <class Type>
01526 Array1D<Type> Array2D<Type>::
01527 getRow(size_t index)
01528 {
01529 this->checkBounds(index, 0);
01530 return Array1D<Type>(this->columns(),
01531 m_dataPtr + (index * this->m_columns));
01532 }
01533
01534
01535 template <class Type>
01536 const Array1D<Type> Array2D<Type>::
01537 getRow(size_t index) const
01538 {
01539 this->checkBounds(index, 0);
01540 return Array1D<Type>(this->columns(),
01541 m_dataPtr + (index * this->m_columns));
01542 }
01543
01544
01545 template <class Type>
01546 const Array1D<Type> Array2D<Type>::
01547 ravel() const
01548 {
01549 if(m_isAllocated) {
01550 return Array1D<Type>(m_size, m_dataPtr, m_refCountPtr);
01551 }
01552 return Array1D<Type>(m_size, m_dataPtr);
01553 }
01554
01555 template <class Type>
01556 Array1D<Type> Array2D<Type>::
01557 ravel()
01558 {
01559 if(m_isAllocated) {
01560 return Array1D<Type>(m_size, m_dataPtr, m_refCountPtr);
01561 }
01562 return Array1D<Type>(m_size, m_dataPtr);
01563 }
01564
01565
01566 template <class Type>
01567 std::istream&
01568 Array2D<Type>::
01569 readFromStream(std::istream& inputStream)
01570 {
01571
01572 typedef typename NumericTraits<Type>::TextOutputType InputType;
01573
01574
01575 if (!inputStream){
01576 return inputStream;
01577 }
01578
01579
01580
01581
01582 std::ios_base::iostate oldExceptionState = inputStream.exceptions();
01583 inputStream.exceptions(
01584 std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit);
01585
01586
01587 try{
01588
01589
01590 InputStream stream(inputStream);
01591
01592
01593 stream.skipWhiteSpace();
01594
01595
01596
01597 bool foundIntro = false;
01598 if(stream.peek() == ioIntro()[0]) {
01599 foundIntro = true;
01600 stream.expect(ioIntro());
01601 }
01602
01603
01604
01605
01606 stream.expect(ioOpening);
01607
01608
01609
01610 Array1D<Type> inputValue;
01611 std::vector< Array1D<Type> > inputBuffer;
01612 while(1) {
01613
01614 stream >> inputValue;
01615 inputBuffer.push_back(inputValue);
01616
01617
01618 char inChar = 0;
01619 stream >> inChar;
01620 if(inChar == ioClosing) {
01621
01622 break;
01623 }
01624 if(inChar != ioSeparator) {
01625
01626 stream.clear(std::ios_base::failbit);
01627 }
01628 }
01629
01630
01631 if(foundIntro) {
01632 stream.expect(ioOutro());
01633 }
01634
01635
01636
01637 size_t arrayRows = inputBuffer.size();
01638 size_t arrayColumns = ((inputBuffer.size() != 0) ? inputBuffer[0].size() : 0);
01639 for(size_t index = 1; index < arrayRows; ++index) {
01640 if(inputBuffer[index].size() != arrayColumns) {
01641
01642 stream.clear(std::ios_base::failbit);
01643 }
01644 }
01645
01646
01647 this->reinit(arrayRows, arrayColumns);
01648 for(size_t index = 0; index < arrayRows; ++index) {
01649 std::copy(inputBuffer[index].begin(), inputBuffer[index].end(),
01650 this->begin() + (index * arrayColumns));
01651 }
01652 } catch(std::ios_base::failure) {
01653
01654 }
01655 inputStream.exceptions(oldExceptionState);
01656 return inputStream;
01657 }
01658
01659
01660 template <class Type>
01661 void Array2D<Type>::
01662 reinit(size_t arrayRows, size_t arrayColumns)
01663 {
01664 this->deAllocate();
01665 this->m_rows = arrayRows;
01666 this->m_columns = arrayColumns;
01667 this->allocate();
01668 }
01669
01670
01671 template <class Type>
01672 void Array2D<Type>::
01673 reinitIfNecessary(size_t arrayRows, size_t arrayColumns)
01674 {
01675 if(this->size() != arrayRows * arrayColumns) {
01676 this->reinit(arrayRows, arrayColumns);
01677 } else {
01678 if(this->rows() != arrayRows) {
01679 this->reshape(arrayRows, arrayColumns);
01680 }
01681 }
01682 }
01683
01684
01685
01686 template <class Type>
01687 void Array2D<Type>::
01688 reshape(int arrayRows, int arrayColumns)
01689 {
01690
01691
01692 if((arrayRows == -1) && (arrayColumns != 0)) {
01693 arrayRows = static_cast<int>(this->size()) / arrayColumns;
01694 } else
01695 if((arrayColumns == -1) && (arrayRows != 0)) {
01696 arrayColumns = static_cast<int>(this->size()) / arrayRows;
01697 }
01698 if((arrayRows * arrayColumns) != static_cast<int>(this->size())) {
01699 std::ostringstream message;
01700 message << "Can't reshape a(n) " << this->size()
01701 << " element array to have " << arrayRows << " rows and "
01702 << arrayColumns << " columns.";
01703 DLR_THROW(ValueException, "Array2D::reshape()", message.str().c_str());
01704 }
01705 m_rows = arrayRows;
01706 m_columns = arrayColumns;
01707 }
01708
01709
01710 template <class Type>
01711 Array1D<size_t> Array2D<Type>::
01712 shape() const
01713 {
01714 Array1D<size_t> rc(2);
01715 rc(0) = this->rows();
01716 rc(1) = this->columns();
01717 return rc;
01718 }
01719
01720
01721 template <class Type>
01722 size_t Array2D<Type>::
01723 shape(size_t axis) const
01724 {
01725 size_t result;
01726 switch(axis) {
01727 case 0:
01728 result = this->rows();
01729 break;
01730 case 1:
01731 result = this->columns();
01732 break;
01733 default:
01734 std::ostringstream message;
01735 message << "Invalid Axis: "<< axis << ".";
01736 DLR_THROW(ValueException, "Array2D::shape(size_t)",
01737 message.str().c_str());
01738 result = 0;
01739 break;
01740 }
01741 return result;
01742 }
01743
01744
01745 template <class Type>
01746 Array2D<Type>& Array2D<Type>::
01747 operator=(Type value)
01748 {
01749 std::fill(m_dataPtr, m_dataPtr + m_size, value);
01750 return *this;
01751 }
01752
01753
01754 template <class Type>
01755 Array2D<Type>& Array2D<Type>::
01756 operator=(const Array2D<Type>& source)
01757 {
01758
01759 if(&source != this) {
01760 this->deAllocate();
01761 m_rows = source.m_rows;
01762 m_columns = source.m_columns;
01763 m_size = source.m_size;
01764 m_dataPtr = source.m_dataPtr;
01765 m_refCountPtr = source.m_refCountPtr;
01766 m_isAllocated = source.m_isAllocated;
01767 if(m_isAllocated) {
01768 ++(*m_refCountPtr);
01769 }
01770 }
01771 return *this;
01772 }
01773
01774
01775 template <class Type> template <class Type2>
01776 Array2D<Type>&
01777 Array2D<Type>::
01778 operator+=(const Array2D<Type2>& arg)
01779 {
01780 if(m_size != arg.size()) {
01781 std::ostringstream message;
01782 message << "Mismatched array sizes. Argument array is "
01783 << arg.rows() << " x " << arg.columns()
01784 << ", while destination array is "
01785 << m_rows << " x " << m_columns << ".";
01786 DLR_THROW(ValueException, "Array2D::operator+=()",
01787 message.str().c_str());
01788 }
01789 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01790 std::plus<Type>());
01791 return *this;
01792 }
01793
01794
01795 template <class Type> template <class Type2>
01796 Array2D<Type>&
01797 Array2D<Type>::
01798 operator-=(const Array2D<Type2>& arg)
01799 {
01800 if(m_size != arg.size()) {
01801 std::ostringstream message;
01802 message << "Mismatched array sizes. Argument array is "
01803 << arg.rows() << " x " << arg.columns()
01804 << ", while destination array is "
01805 << m_rows << " x " << m_columns << ".";
01806 DLR_THROW(ValueException, "Array2D::operator-=()",
01807 message.str().c_str());
01808 }
01809 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01810 std::minus<Type>());
01811 return *this;
01812 }
01813
01814
01815 template <class Type> template <class Type2>
01816 Array2D<Type>&
01817 Array2D<Type>::
01818 operator*=(const Array2D<Type2>& arg)
01819 {
01820 if(m_size != arg.size()) {
01821 std::ostringstream message;
01822 message << "Mismatched array sizes. Argument array is "
01823 << arg.rows() << " x " << arg.columns()
01824 << ", while destination array is "
01825 << m_rows << " x " << m_columns << ".";
01826 DLR_THROW(ValueException, "Array2D::operator*=()",
01827 message.str().c_str());
01828 }
01829 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01830 std::multiplies<Type>());
01831 return *this;
01832 }
01833
01834
01835 template <class Type> template <class Type2>
01836 Array2D<Type>&
01837 Array2D<Type>::
01838 operator/=(const Array2D<Type2>& arg)
01839 {
01840 if(m_size != arg.size()) {
01841 std::ostringstream message;
01842 message << "Mismatched array sizes. Argument array is "
01843 << arg.rows() << " x " << arg.columns()
01844 << ", while destination array is "
01845 << m_rows << " x " << m_columns << ".";
01846 DLR_THROW(ValueException, "Array2D::operator/=()",
01847 message.str().c_str());
01848 }
01849 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01850 std::divides<Type>());
01851 return *this;
01852 }
01853
01854
01855 template <class Type>
01856 Array2D<Type>&
01857 Array2D<Type>::
01858 operator*=(Type arg)
01859 {
01860 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01861 std::bind2nd(std::multiplies<Type>(), arg));
01862 return *this;
01863 }
01864
01865
01866 template <class Type>
01867 Array2D<Type>&
01868 Array2D<Type>::
01869 operator/=(Type arg)
01870 {
01871 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01872 std::bind2nd(std::divides<Type>(), arg));
01873 return *this;
01874 }
01875
01876
01877 template <class Type>
01878 Array2D<Type>&
01879 Array2D<Type>::
01880 operator+=(Type arg)
01881 {
01882 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01883 std::bind2nd(std::plus<Type>(), arg));
01884 return *this;
01885 }
01886
01887
01888 template <class Type>
01889 Array2D<Type>&
01890 Array2D<Type>::
01891 operator-=(Type arg)
01892 {
01893 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01894 std::bind2nd(std::minus<Type>(), arg));
01895 return *this;
01896 }
01897
01898
01899 template <class Type>
01900 Array2D<Type> Array2D<Type>::
01901 transpose() const
01902 {
01903 Array2D<Type> newMx(m_columns, m_rows);
01904
01905
01906 Type *tPtr0 = newMx.m_dataPtr;
01907 for(size_t j = 0; j < m_columns; ++j) {
01908
01909 const Type *tPtr1 = this->data(j);
01910 for(size_t i = 0; i < m_rows; ++i) {
01911 *tPtr0 = *tPtr1;
01912 ++tPtr0;
01913 tPtr1 += m_columns;
01914 }
01915 }
01916 return newMx;
01917 }
01918
01919
01920 template <class Type>
01921 void Array2D<Type>::
01922 allocate()
01923 {
01924 m_size = m_rows * m_columns;
01925 if(m_rows > 0 && m_columns > 0) {
01926 m_dataPtr = new(Type[m_rows * m_columns]);
01927 m_refCountPtr = new size_t;
01928 *m_refCountPtr = 1;
01929 m_isAllocated = true;
01930 return;
01931 }
01932 m_dataPtr = 0;
01933 m_refCountPtr = 0;
01934 m_isAllocated = false;
01935 return;
01936 }
01937
01938
01939 template <class Type>
01940 inline void Array2D<Type>::
01941 checkBounds(size_t index) const
01942 {
01943 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01944 if(index >= m_size) {
01945 std::ostringstream message;
01946 message << "Index " << index << " is invalid for a(n) " << m_rows
01947 << " x " << m_columns << " array.";
01948 DLR_THROW(IndexException, "Array2D::checkBounds(size_t)",
01949 message.str().c_str());
01950 }
01951 #endif
01952 }
01953
01954
01955 template <class Type>
01956 inline void Array2D<Type>::
01957 checkBounds(size_t rowIndex, size_t columnIndex) const
01958 {
01959 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01960 if(rowIndex >= m_rows) {
01961 std::ostringstream message;
01962 message << "Row index " << rowIndex << " is invalid for a(n) "
01963 << m_rows << " x " << m_columns << " array.";
01964 DLR_THROW(IndexException, "Array2D::checkBounds(size_t, size_t)",
01965 message.str().c_str());
01966 }
01967 if(columnIndex >= m_columns) {
01968 std::ostringstream message;
01969 message << "Column index " << columnIndex << " is invalid for a(n) "
01970 << m_rows << " x " << m_columns << " array.";
01971 DLR_THROW(IndexException, "Array2D::checkBounds(size_t, size_t)",
01972 message.str().c_str());
01973 }
01974 #endif
01975 }
01976
01977
01978 template <class Type>
01979 void Array2D<Type>::
01980 deAllocate()
01981 {
01982 if(m_isAllocated == true) {
01983 if(--(*m_refCountPtr) == 0) {
01984 delete[] m_dataPtr;
01985 delete m_refCountPtr;
01986 m_isAllocated = false;
01987 m_dataPtr = 0;
01988 m_refCountPtr = 0;
01989 }
01990 } else {
01991 m_dataPtr = 0;
01992 m_refCountPtr = 0;
01993 }
01994 }
01995
01996
01997
01998 template <class Type>
01999 inline Array2D<Type>
02000 sqrt(const Array2D<Type>& array0)
02001 {
02002 return squareRoot(array0);
02003 }
02004
02005
02006
02007
02008 template <class Type>
02009 Array2D<Type>
02010 squareRoot(const Array2D<Type>& array0)
02011 {
02012 Array2D<Type> result(array0.rows(), array0.columns());
02013 std::transform(array0.begin(), array0.end(),
02014 result.begin(), SquareRootFunctor<Type>());
02015 return result;
02016 }
02017
02018 template <class Type>
02019 Array2D<Type> operator+(const Array2D<Type>& array0,
02020 const Array2D<Type>& array1)
02021 {
02022 if((array0.rows() != array1.rows())
02023 || (array0.columns() != array1.columns())) {
02024 std::ostringstream message;
02025 message << "Array sizes do not match. Array0 is " << array0.rows()
02026 << " x " << array0.columns() << ", while array1 is "
02027 << array1.rows() << " x " << array1.columns() << ".";
02028 DLR_THROW(ValueException, "Array2D::operator+()", message.str().c_str());
02029 }
02030 Array2D<Type> result(array0.rows(), array0.columns());
02031 std::transform(array0.begin(), array0.end(), array1.begin(),
02032 result.begin(), std::plus<Type>());
02033 return result;
02034 }
02035
02036 template <class Type>
02037 Array2D<Type> operator-(const Array2D<Type>& array0,
02038 const Array2D<Type>& array1)
02039 {
02040 if((array0.rows() != array1.rows())
02041 || (array0.columns() != array1.columns())) {
02042 std::ostringstream message;
02043 message << "Array sizes do not match. Array0 is " << array0.rows()
02044 << " x " << array0.columns() << ", while array1 is "
02045 << array1.rows() << " x " << array1.columns() << ".";
02046 DLR_THROW(ValueException, "Array2D::operator-()", message.str().c_str());
02047 }
02048 Array2D<Type> result(array0.rows(), array0.columns());
02049 std::transform(array0.begin(), array0.end(), array1.begin(),
02050 result.begin(), std::minus<Type>());
02051 return result;
02052 }
02053
02054 template <class Type>
02055 Array2D<Type> operator*(const Array2D<Type>& array0,
02056 const Array2D<Type>& array1)
02057 {
02058 if((array0.rows() != array1.rows())
02059 || (array0.columns() != array1.columns())) {
02060 std::ostringstream message;
02061 message << "Array sizes do not match. Array0 is " << array0.rows()
02062 << " x " << array0.columns() << ", while array1 is "
02063 << array1.rows() << " x " << array1.columns() << ".";
02064 DLR_THROW(ValueException, "Array2D::operator*()", message.str().c_str());
02065 }
02066 Array2D<Type> result(array0.rows(), array0.columns());
02067 std::transform(array0.begin(), array0.end(), array1.begin(),
02068 result.begin(), std::multiplies<Type>());
02069 return result;
02070 }
02071
02072 template <class Type>
02073 Array2D<Type> operator/(const Array2D<Type>& array0,
02074 const Array2D<Type>& array1)
02075 {
02076 if((array0.rows() != array1.rows())
02077 || (array0.columns() != array1.columns())) {
02078 std::ostringstream message;
02079 message << "Array sizes do not match. Array0 is " << array0.rows()
02080 << " x " << array0.columns() << ", while array1 is "
02081 << array1.rows() << " x " << array1.columns() << ".";
02082 DLR_THROW(ValueException, "Array2D::operator/()", message.str().c_str());
02083 }
02084 Array2D<Type> result(array0.rows(), array0.columns());
02085 std::transform(array0.begin(), array0.end(), array1.begin(),
02086 result.begin(), std::divides<Type>());
02087 return result;
02088 }
02089
02090 template <class Type>
02091 Array2D<Type> operator+(const Array2D<Type>& array0, Type scalar)
02092 {
02093 Array2D<Type> result(array0.rows(), array0.columns());
02094 std::transform(array0.begin(), array0.end(), result.begin(),
02095 std::bind2nd(std::plus<Type>(), scalar));
02096 return result;
02097 }
02098
02099 template <class Type>
02100 Array2D<Type> operator-(const Array2D<Type>& array0, Type scalar)
02101 {
02102 Array2D<Type> result(array0.rows(), array0.columns());
02103 std::transform(array0.begin(), array0.end(), result.begin(),
02104 std::bind2nd(std::minus<Type>(), scalar));
02105 return result;
02106 }
02107
02108 template <class Type>
02109 Array2D<Type> operator*(const Array2D<Type>& array0, Type scalar)
02110 {
02111 Array2D<Type> result(array0.rows(), array0.columns());
02112 std::transform(array0.begin(), array0.end(), result.begin(),
02113 std::bind2nd(std::multiplies<Type>(), scalar));
02114 return result;
02115 }
02116
02117 template <class Type>
02118 Array2D<Type> operator/(const Array2D<Type>& array0, Type scalar)
02119 {
02120 Array2D<Type> result(array0.rows(), array0.columns());
02121 std::transform(array0.begin(), array0.end(), result.begin(),
02122 std::bind2nd(std::divides<Type>(), scalar));
02123 return result;
02124 }
02125
02126 template <class Type>
02127 inline Array2D<Type> operator+(Type scalar, const Array2D<Type>& array0)
02128 {
02129 return array0 + scalar;
02130 }
02131
02132 template <class Type>
02133 inline Array2D<Type> operator*(Type scalar, const Array2D<Type>& array0)
02134 {
02135 return array0 * scalar;
02136 }
02137
02138
02139
02140 template <class Type>
02141 Array2D<bool>
02142 operator==(const Array2D<Type>& array0, const Type arg)
02143 {
02144 Array2D<bool> result(array0.rows(), array0.columns());
02145 std::transform(array0.begin(), array0.end(), result.data(),
02146 std::bind2nd(std::equal_to<Type>(), arg));
02147 return result;
02148 }
02149
02150
02151
02152 template <class Type>
02153 Array2D<bool>
02154 operator==(const Array2D<Type>& array0, const Array2D<Type>& array1)
02155 {
02156 array0.checkDimension(array1.rows(), array1.columns());
02157 Array2D<bool> result(array0.rows(), array0.columns());
02158 std::transform(array0.begin(), array0.end(), array1.begin(),
02159 result.begin(), std::equal_to<Type>());
02160 return result;
02161 }
02162
02163
02164 template <class Type>
02165 Array2D<bool> operator>(const Array2D<Type>& array0, Type arg)
02166 {
02167 Array2D<bool> result(array0.rows(), array0.columns());
02168 std::transform(array0.begin(), array0.end(), result.begin(),
02169 std::bind2nd(std::greater<Type>(), arg));
02170 return result;
02171 }
02172
02173 template <class Type>
02174 Array2D<bool> operator<(const Array2D<Type>& array0, Type arg)
02175 {
02176 Array2D<bool> result(array0.rows(), array0.columns());
02177 std::transform(array0.begin(), array0.end(), result.begin(),
02178 std::bind2nd(std::less<Type>(), arg));
02179 return result;
02180 }
02181
02182 template <class Type>
02183 Array2D<bool> operator>=(const Array2D<Type>& array0, Type arg)
02184 {
02185 Array2D<bool> result(array0.rows(), array0.columns());
02186 std::transform(array0.begin(), array0.end(), result.begin(),
02187 std::bind2nd(std::greater_equal<Type>(), arg));
02188 return result;
02189 }
02190
02191 template <class Type>
02192 Array2D<bool> operator<=(const Array2D<Type>& array0, Type arg)
02193 {
02194 Array2D<bool> result(array0.rows(), array0.columns());
02195 std::transform(array0.begin(), array0.end(), result.begin(),
02196 std::bind2nd(std::less_equal<Type>(), arg));
02197 return result;
02198 }
02199
02200 template <class Type>
02201 std::ostream& operator<<(std::ostream& stream, const Array2D<Type>& array0)
02202 {
02203
02204 typedef typename NumericTraits<Type>::TextOutputType OutputType;
02205
02206 stream << "Array2D([[";
02207 for(size_t row = 0; row < array0.rows(); ++row) {
02208 if (array0.columns() > 0) {
02209 for(size_t column = 0; column < array0.columns() - 1; ++column) {
02210 stream << static_cast<OutputType>(array0(row, column)) << ", ";
02211 }
02212 stream << static_cast<OutputType>(array0(row, array0.columns() - 1));
02213 if(row != array0.rows() - 1) {
02214 stream << "],\n";
02215 stream << " [";
02216 }
02217 }
02218 }
02219 stream << "]])";
02220 stream.flush();
02221 return stream;
02222 }
02223
02224
02225 template <class Type>
02226 std::istream& operator>>(std::istream& inputStream, Array2D<Type>& array0)
02227 {
02228 return array0.readFromStream(inputStream);
02229 }
02230
02231 }
02232
02233 }
02234
02235 #endif