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
00505 void
00506 reshape(int arrayRows, int arrayColumns);
00507
00508
00516 inline Array1D<Type>
00517 row(size_t index) {return this->getRow(index);}
00518
00519
00527 const Array1D<Type>
00528 row(size_t index) const {return this->getRow(index);}
00529
00530
00541 iterator
00542 rowBegin(size_t rowIndex) {return m_dataPtr + rowIndex * m_columns;}
00543
00544
00555 const_iterator
00556 rowBegin(size_t rowIndex) const {
00557 return m_dataPtr + rowIndex * m_columns;
00558 }
00559
00560
00571 iterator
00572 rowEnd(size_t rowIndex) {
00573 return m_dataPtr + (rowIndex + 1) * m_columns;
00574 }
00575
00576
00587 const_iterator
00588 rowEnd(size_t rowIndex) const {
00589 return m_dataPtr + (rowIndex + 1) * m_columns;
00590 }
00591
00592
00600 size_t
00601 rows() const {return m_rows;}
00602
00603
00617 Type&
00618 setElement(size_t index0, const Type& value) {
00619 return this->operator()(index0) = value;
00620 }
00621
00622
00639 Type&
00640 setElement(size_t rowIndex, size_t columnIndex, const Type& value) {
00641 return this->operator()(rowIndex, columnIndex) = value;
00642 }
00643
00644
00653 Array1D<size_t>
00654 shape() const;
00655
00667 size_t
00668 shape(size_t axis) const;
00669
00676 size_t
00677 size() const {return m_size;}
00678
00685 Array2D<Type>
00686 transpose() const;
00687
00696 Array2D<Type>&
00697 operator=(const Array2D<Type>& source);
00698
00706 Array2D<Type>&
00707 operator=(Type value);
00708
00717 Type&
00718 operator()(size_t index) {
00719 this->checkBounds(index);
00720 return m_dataPtr[index];
00721 }
00722
00729 Type operator()(size_t index) const {
00730 this->checkBounds(index);
00731 return m_dataPtr[index];
00732 }
00733
00743 Type&
00744 operator()(size_t rowIndex, size_t columnIndex) {
00745 this->checkBounds(rowIndex, columnIndex);
00746 return m_dataPtr[columnIndex + rowIndex * m_columns];
00747 }
00748
00758 Type
00759 operator()(size_t rowIndex, size_t columnIndex) const {
00760 this->checkBounds(rowIndex, columnIndex);
00761 return m_dataPtr[columnIndex + rowIndex * m_columns];
00762 }
00763
00772 Type&
00773 operator[](size_t index) {return this->operator()(index);}
00774
00783 Type
00784 operator[](size_t index) const {return this->operator()(index);}
00785
00797 template <class Type2> Array2D<Type>&
00798 operator+=(const Array2D<Type2>& arg);
00799
00811 template <class Type2> Array2D<Type>&
00812 operator-=(const Array2D<Type2>& arg);
00813
00825 template <class Type2> Array2D<Type>&
00826 operator*=(const Array2D<Type2>& arg);
00827
00839 template <class Type2> Array2D<Type>&
00840 operator/=(const Array2D<Type2>& arg);
00841
00849 Array2D<Type>&
00850 operator+=(Type arg);
00851
00859 Array2D<Type>&
00860 operator-=(Type arg);
00861
00869 Array2D<Type>&
00870 operator*=(Type arg);
00871
00879 Array2D<Type>&
00880 operator/=(Type arg);
00881
00882 private:
00883
00884 void
00885 allocate();
00886
00887
00888
00889 inline void
00890 checkBounds(size_t index) const;
00891
00892
00893
00894 inline void
00895 checkBounds(size_t row, size_t column) const;
00896
00897 void
00898 deAllocate();
00899
00900
00901
00902
00903
00908 static const std::string& ioIntro();
00909
00914 static const std::string& ioOutro();
00915
00920 static const char ioOpening = '[';
00921
00926 static const char ioClosing = ']';
00927
00932 static const char ioSeparator = ',';
00933
00934
00935
00936 size_t m_rows;
00937 size_t m_columns;
00938 size_t m_size;
00939 Type* m_dataPtr;
00940 size_t* m_refCountPtr;
00941 bool m_isAllocated;
00942
00943 };
00944
00945
00946
00957 template <class Type>
00958 Array2D<Type>
00959 squareRoot(const Array2D<Type>& array0);
00960
00972 template <class Type>
00973 inline Array2D<Type>
00974 sqrt(const Array2D<Type>& array0);
00975
00989 template <class Type>
00990 Array2D<Type>
00991 operator+(const Array2D<Type>& array0,
00992 const Array2D<Type>& array1);
00993
01007 template <class Type>
01008 Array2D<Type>
01009 operator-(const Array2D<Type>& array0,
01010 const Array2D<Type>& array1);
01011
01025 template <class Type>
01026 Array2D<Type>
01027 operator*(const Array2D<Type>& array0,
01028 const Array2D<Type>& array1);
01029
01043 template <class Type>
01044 Array2D<Type>
01045 operator/(const Array2D<Type>& array0,
01046 const Array2D<Type>& array1);
01047
01059 template <class Type>
01060 Array2D<Type>
01061 operator+(const Array2D<Type>& array0, Type scalar);
01062
01074 template <class Type>
01075 Array2D<Type>
01076 operator-(const Array2D<Type>& array0, Type scalar);
01077
01089 template <class Type>
01090 Array2D<Type>
01091 operator*(const Array2D<Type>& array0, Type scalar);
01092
01104 template <class Type>
01105 Array2D<Type>
01106 operator/(const Array2D<Type>& array0, Type scalar);
01107
01119 template <class Type>
01120 inline Array2D<Type>
01121 operator+(Type scalar, const Array2D<Type>& array0);
01122
01123
01135 template <class Type>
01136 inline Array2D<Type>
01137 operator*(Type scalar, const Array2D<Type>& array0);
01138
01139
01151 template <class Type>
01152 Array2D<bool>
01153 operator==(const Array2D<Type>& array0, const Type arg);
01154
01155
01168 template <class Type>
01169 Array2D<bool>
01170 operator==(const Array2D<Type>& array0, const Array2D<Type>& array1);
01171
01172
01184 template <class Type>
01185 Array2D<bool>
01186 operator>(const Array2D<Type>& array0, Type arg);
01187
01188
01200 template <class Type>
01201 Array2D<bool>
01202 operator<(const Array2D<Type>& array0, Type arg);
01203
01204
01217 template <class Type>
01218 Array2D<bool>
01219 operator>=(const Array2D<Type>& array0, Type arg);
01220
01221
01234 template <class Type>
01235 Array2D<bool>
01236 operator<=(const Array2D<Type>& array0, Type arg);
01237
01238
01257 template <class Type>
01258 std::ostream&
01259 operator<<(std::ostream& stream, const Array2D<Type>& array0);
01260
01272 template <class Type>
01273 std::istream&
01274 operator>>(std::istream& stream, Array2D<Type>& array0);
01275
01276 }
01277
01278 }
01279
01280
01281
01282
01283 namespace dlr {
01284
01285 using numeric::Array2D;
01286
01287 }
01288
01289
01290
01291
01292
01293
01294
01295 #include <algorithm>
01296 #include <functional>
01297 #include <sstream>
01298 #include <vector>
01299 #include <dlrCommon/functional.h>
01300 #include <dlrCommon/inputStream.h>
01301 #include <dlrNumeric/numericTraits.h>
01302 #include <dlrNumeric/functional.h>
01303
01304 namespace dlr {
01305
01306 namespace numeric {
01307
01308
01309
01310 template <class Type>
01311 const std::string&
01312 Array2D<Type>::
01313 ioIntro()
01314 {
01315 static const std::string intro = "Array2D(";
01316 return intro;
01317 }
01318
01319
01320
01321 template <class Type>
01322 const std::string&
01323 Array2D<Type>::
01324 ioOutro()
01325 {
01326 static const std::string outro = ")";
01327 return outro;
01328 }
01329
01330
01331
01332 template <class Type>
01333 Array2D<Type>::
01334 Array2D()
01335 : m_rows(0),
01336 m_columns(0),
01337 m_size(0),
01338 m_dataPtr(0),
01339 m_refCountPtr(0),
01340 m_isAllocated(false)
01341 {
01342
01343 }
01344
01345
01346 template <class Type>
01347 Array2D<Type>::
01348 Array2D(size_t arrayRows, size_t arrayColumns)
01349 : m_rows(arrayRows),
01350 m_columns(arrayColumns),
01351 m_size(0),
01352 m_dataPtr(0),
01353 m_refCountPtr(0),
01354 m_isAllocated(false)
01355 {
01356 this->allocate();
01357 }
01358
01359
01360
01361 template <class Type>
01362 Array2D<Type>::
01363 Array2D(const std::string& inputString)
01364 : m_rows(0),
01365 m_columns(0),
01366 m_size(0),
01367 m_dataPtr(0),
01368 m_refCountPtr(0),
01369 m_isAllocated(false)
01370 {
01371
01372 std::istringstream inputStream(inputString);
01373
01374
01375 Array2D<Type> inputArray;
01376 inputStream >> inputArray;
01377 if(!inputStream) {
01378 std::ostringstream message;
01379 message << "Couldn't parse input string: \"" << inputString << "\".";
01380 DLR_THROW3(ValueException, "Array2D::Array2D(const std::string&)",
01381 message.str().c_str());
01382 }
01383
01384
01385 *this = inputArray;
01386 }
01387
01388
01389
01390
01391
01392 template <class Type>
01393 Array2D<Type>::
01394 Array2D(const Array2D<Type>& source)
01395 : m_rows(source.m_rows),
01396 m_columns(source.m_columns),
01397 m_size(source.m_size),
01398 m_dataPtr(source.m_dataPtr),
01399 m_refCountPtr(source.m_refCountPtr),
01400 m_isAllocated(source.m_isAllocated)
01401 {
01402 if(m_isAllocated) {
01403 ++(*m_refCountPtr);
01404 }
01405 }
01406
01407
01408
01409
01410 template <class Type>
01411 Array2D<Type>::
01412 Array2D(size_t arrayRows, size_t arrayColumns, Type* const dataPtr)
01413 : m_rows(arrayRows),
01414 m_columns(arrayColumns),
01415 m_size(arrayRows*arrayColumns),
01416 m_dataPtr(dataPtr),
01417 m_refCountPtr(0),
01418 m_isAllocated(false)
01419 {
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 size_t* referenceCountPtr)
01430 : m_rows(arrayRows),
01431 m_columns(arrayColumns),
01432 m_size(arrayRows*arrayColumns),
01433 m_dataPtr(dataPtr),
01434 m_refCountPtr(referenceCountPtr),
01435 m_isAllocated(true)
01436 {
01437 ++(*m_refCountPtr);
01438 }
01439
01440
01441 template <class Type>
01442 Array2D<Type>::
01443 ~Array2D()
01444 {
01445 deAllocate();
01446 }
01447
01448
01449 template <class Type>
01450 inline void Array2D<Type>::
01451 checkDimension(size_t arrayRows, size_t arrayColumns) const
01452 {
01453 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01454 if(arrayRows != this->rows()
01455 || arrayColumns != this->columns()) {
01456 std::ostringstream message;
01457 message << "Size mismatch: required dimension is ("
01458 << arrayRows << ", " << arrayColumns << ") "
01459 << " while *this has dimension "
01460 << this->rows() << ", " << this->columns() << ").";
01461 DLR_THROW(IndexException, "Array2D::checkDimension()",
01462 message.str().c_str());
01463 }
01464 #endif
01465 }
01466
01467
01468 template <class Type>
01469 Array2D<Type> Array2D<Type>::
01470 copy() const
01471 {
01472 Array2D<Type> newArray(m_rows, m_columns);
01473 newArray.copy(*this);
01474 return newArray;
01475 }
01476
01477
01478 template <class Type> template <class Type2>
01479 void Array2D<Type>::
01480 copy(const Array2D<Type2>& source)
01481 {
01482 if(source.size() != m_size) {
01483 std::ostringstream message;
01484 message << "Mismatched array sizes. Source array has "
01485 << source.size() << " elements, while destination array has "
01486 << m_size << " elements.";
01487 DLR_THROW3(ValueException, "Array2D::copy(const Array2D&)",
01488 message.str().c_str());
01489 }
01490 if(m_size != 0) {
01491 this->copy(source.data());
01492 }
01493 }
01494
01495
01496 template <class Type> template <class Type2>
01497 void Array2D<Type>::
01498 copy(const Type2* dataPtr)
01499 {
01500 if(dataPtr == 0) {
01501 DLR_THROW(ValueException, "Array2D::copy(const Type2*)",
01502 "Argument is a NULL pointer.");
01503 }
01504 std::transform(dataPtr, dataPtr + m_size, m_dataPtr,
01505 StaticCastFunctor<Type2, Type>());
01506 }
01507
01508
01509 template <class Type>
01510 Array1D<Type> Array2D<Type>::
01511 getRow(size_t index)
01512 {
01513 this->checkBounds(index, 0);
01514 return Array1D<Type>(this->columns(),
01515 m_dataPtr + (index * this->m_columns));
01516 }
01517
01518
01519 template <class Type>
01520 const Array1D<Type> Array2D<Type>::
01521 getRow(size_t index) const
01522 {
01523 this->checkBounds(index, 0);
01524 return Array1D<Type>(this->columns(),
01525 m_dataPtr + (index * this->m_columns));
01526 }
01527
01528
01529 template <class Type>
01530 const Array1D<Type> Array2D<Type>::
01531 ravel() const
01532 {
01533 if(m_isAllocated) {
01534 return Array1D<Type>(m_size, m_dataPtr, m_refCountPtr);
01535 }
01536 return Array1D<Type>(m_size, m_dataPtr);
01537 }
01538
01539 template <class Type>
01540 Array1D<Type> Array2D<Type>::
01541 ravel()
01542 {
01543 if(m_isAllocated) {
01544 return Array1D<Type>(m_size, m_dataPtr, m_refCountPtr);
01545 }
01546 return Array1D<Type>(m_size, m_dataPtr);
01547 }
01548
01549
01550 template <class Type>
01551 std::istream&
01552 Array2D<Type>::
01553 readFromStream(std::istream& inputStream)
01554 {
01555
01556 typedef typename NumericTraits<Type>::TextOutputType InputType;
01557
01558
01559 if (!inputStream){
01560 return inputStream;
01561 }
01562
01563
01564
01565
01566 std::ios_base::iostate oldExceptionState = inputStream.exceptions();
01567 inputStream.exceptions(
01568 std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit);
01569
01570
01571 try{
01572
01573
01574 InputStream stream(inputStream);
01575
01576
01577 stream.skipWhiteSpace();
01578
01579
01580
01581 bool foundIntro = false;
01582 if(stream.peek() == ioIntro()[0]) {
01583 foundIntro = true;
01584 stream.expect(ioIntro());
01585 }
01586
01587
01588
01589
01590 stream.expect(ioOpening);
01591
01592
01593
01594 Array1D<Type> inputValue;
01595 std::vector< Array1D<Type> > inputBuffer;
01596 while(1) {
01597
01598 stream >> inputValue;
01599 inputBuffer.push_back(inputValue);
01600
01601
01602 char inChar = 0;
01603 stream >> inChar;
01604 if(inChar == ioClosing) {
01605
01606 break;
01607 }
01608 if(inChar != ioSeparator) {
01609
01610 stream.clear(std::ios_base::failbit);
01611 }
01612 }
01613
01614
01615 if(foundIntro) {
01616 stream.expect(ioOutro());
01617 }
01618
01619
01620
01621 size_t arrayRows = inputBuffer.size();
01622 size_t arrayColumns = ((inputBuffer.size() != 0) ? inputBuffer[0].size() : 0);
01623 for(size_t index = 1; index < arrayRows; ++index) {
01624 if(inputBuffer[index].size() != arrayColumns) {
01625
01626 stream.clear(std::ios_base::failbit);
01627 }
01628 }
01629
01630
01631 this->reinit(arrayRows, arrayColumns);
01632 for(size_t index = 0; index < arrayRows; ++index) {
01633 std::copy(inputBuffer[index].begin(), inputBuffer[index].end(),
01634 this->begin() + (index * arrayColumns));
01635 }
01636 } catch(std::ios_base::failure) {
01637
01638 }
01639 inputStream.exceptions(oldExceptionState);
01640 return inputStream;
01641 }
01642
01643
01644 template <class Type>
01645 void Array2D<Type>::
01646 reinit(size_t arrayRows, size_t arrayColumns)
01647 {
01648 this->deAllocate();
01649 this->m_rows = arrayRows;
01650 this->m_columns = arrayColumns;
01651 this->allocate();
01652 }
01653
01654
01655
01656 template <class Type>
01657 void Array2D<Type>::
01658 reshape(int arrayRows, int arrayColumns)
01659 {
01660
01661
01662 if((arrayRows == -1) && (arrayColumns != 0)) {
01663 arrayRows = static_cast<int>(this->size()) / arrayColumns;
01664 } else
01665 if((arrayColumns == -1) && (arrayRows != 0)) {
01666 arrayColumns = static_cast<int>(this->size()) / arrayRows;
01667 }
01668 if((arrayRows * arrayColumns) != static_cast<int>(this->size())) {
01669 std::ostringstream message;
01670 message << "Can't reshape a(n) " << this->size()
01671 << " element array to have " << arrayRows << " rows and "
01672 << arrayColumns << " columns.";
01673 DLR_THROW(ValueException, "Array2D::reshape()", message.str().c_str());
01674 }
01675 m_rows = arrayRows;
01676 m_columns = arrayColumns;
01677 }
01678
01679
01680 template <class Type>
01681 Array1D<size_t> Array2D<Type>::
01682 shape() const
01683 {
01684 Array1D<size_t> rc(2);
01685 rc(0) = this->rows();
01686 rc(1) = this->columns();
01687 return rc;
01688 }
01689
01690
01691 template <class Type>
01692 size_t Array2D<Type>::
01693 shape(size_t axis) const
01694 {
01695 size_t result;
01696 switch(axis) {
01697 case 0:
01698 result = this->rows();
01699 break;
01700 case 1:
01701 result = this->columns();
01702 break;
01703 default:
01704 std::ostringstream message;
01705 message << "Invalid Axis: "<< axis << ".";
01706 DLR_THROW(ValueException, "Array2D::shape(size_t)",
01707 message.str().c_str());
01708 result = 0;
01709 break;
01710 }
01711 return result;
01712 }
01713
01714
01715 template <class Type>
01716 Array2D<Type>& Array2D<Type>::
01717 operator=(Type value)
01718 {
01719 std::fill(m_dataPtr, m_dataPtr + m_size, value);
01720 return *this;
01721 }
01722
01723
01724 template <class Type>
01725 Array2D<Type>& Array2D<Type>::
01726 operator=(const Array2D<Type>& source)
01727 {
01728
01729 if(&source != this) {
01730 this->deAllocate();
01731 m_rows = source.m_rows;
01732 m_columns = source.m_columns;
01733 m_size = source.m_size;
01734 m_dataPtr = source.m_dataPtr;
01735 m_refCountPtr = source.m_refCountPtr;
01736 m_isAllocated = source.m_isAllocated;
01737 if(m_isAllocated) {
01738 ++(*m_refCountPtr);
01739 }
01740 }
01741 return *this;
01742 }
01743
01744
01745 template <class Type> template <class Type2>
01746 Array2D<Type>&
01747 Array2D<Type>::
01748 operator+=(const Array2D<Type2>& arg)
01749 {
01750 if(m_size != arg.size()) {
01751 std::ostringstream message;
01752 message << "Mismatched array sizes. Argument array is "
01753 << arg.rows() << " x " << arg.columns()
01754 << ", while destination array is "
01755 << m_rows << " x " << m_columns << ".";
01756 DLR_THROW(ValueException, "Array2D::operator+=()",
01757 message.str().c_str());
01758 }
01759 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01760 std::plus<Type>());
01761 return *this;
01762 }
01763
01764
01765 template <class Type> template <class Type2>
01766 Array2D<Type>&
01767 Array2D<Type>::
01768 operator-=(const Array2D<Type2>& arg)
01769 {
01770 if(m_size != arg.size()) {
01771 std::ostringstream message;
01772 message << "Mismatched array sizes. Argument array is "
01773 << arg.rows() << " x " << arg.columns()
01774 << ", while destination array is "
01775 << m_rows << " x " << m_columns << ".";
01776 DLR_THROW(ValueException, "Array2D::operator-=()",
01777 message.str().c_str());
01778 }
01779 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01780 std::minus<Type>());
01781 return *this;
01782 }
01783
01784
01785 template <class Type> template <class Type2>
01786 Array2D<Type>&
01787 Array2D<Type>::
01788 operator*=(const Array2D<Type2>& arg)
01789 {
01790 if(m_size != arg.size()) {
01791 std::ostringstream message;
01792 message << "Mismatched array sizes. Argument array is "
01793 << arg.rows() << " x " << arg.columns()
01794 << ", while destination array is "
01795 << m_rows << " x " << m_columns << ".";
01796 DLR_THROW(ValueException, "Array2D::operator*=()",
01797 message.str().c_str());
01798 }
01799 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01800 std::multiplies<Type>());
01801 return *this;
01802 }
01803
01804
01805 template <class Type> template <class Type2>
01806 Array2D<Type>&
01807 Array2D<Type>::
01808 operator/=(const Array2D<Type2>& arg)
01809 {
01810 if(m_size != arg.size()) {
01811 std::ostringstream message;
01812 message << "Mismatched array sizes. Argument array is "
01813 << arg.rows() << " x " << arg.columns()
01814 << ", while destination array is "
01815 << m_rows << " x " << m_columns << ".";
01816 DLR_THROW(ValueException, "Array2D::operator/=()",
01817 message.str().c_str());
01818 }
01819 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01820 std::divides<Type>());
01821 return *this;
01822 }
01823
01824
01825 template <class Type>
01826 Array2D<Type>&
01827 Array2D<Type>::
01828 operator*=(Type arg)
01829 {
01830 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01831 std::bind2nd(std::multiplies<Type>(), arg));
01832 return *this;
01833 }
01834
01835
01836 template <class Type>
01837 Array2D<Type>&
01838 Array2D<Type>::
01839 operator/=(Type arg)
01840 {
01841 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01842 std::bind2nd(std::divides<Type>(), arg));
01843 return *this;
01844 }
01845
01846
01847 template <class Type>
01848 Array2D<Type>&
01849 Array2D<Type>::
01850 operator+=(Type arg)
01851 {
01852 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01853 std::bind2nd(std::plus<Type>(), arg));
01854 return *this;
01855 }
01856
01857
01858 template <class Type>
01859 Array2D<Type>&
01860 Array2D<Type>::
01861 operator-=(Type arg)
01862 {
01863 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01864 std::bind2nd(std::minus<Type>(), arg));
01865 return *this;
01866 }
01867
01868
01869 template <class Type>
01870 Array2D<Type> Array2D<Type>::
01871 transpose() const
01872 {
01873 Array2D<Type> newMx(m_columns, m_rows);
01874
01875
01876 Type *tPtr0 = newMx.m_dataPtr;
01877 for(size_t j = 0; j < m_columns; ++j) {
01878
01879 const Type *tPtr1 = this->data(j);
01880 for(size_t i = 0; i < m_rows; ++i) {
01881 *tPtr0 = *tPtr1;
01882 ++tPtr0;
01883 tPtr1 += m_columns;
01884 }
01885 }
01886 return newMx;
01887 }
01888
01889
01890 template <class Type>
01891 void Array2D<Type>::
01892 allocate()
01893 {
01894 m_size = m_rows * m_columns;
01895 if(m_rows > 0 && m_columns > 0) {
01896 m_dataPtr = new(Type[m_rows * m_columns]);
01897 m_refCountPtr = new size_t;
01898 *m_refCountPtr = 1;
01899 m_isAllocated = true;
01900 return;
01901 }
01902 m_dataPtr = 0;
01903 m_refCountPtr = 0;
01904 m_isAllocated = false;
01905 return;
01906 }
01907
01908
01909 template <class Type>
01910 inline void Array2D<Type>::
01911 checkBounds(size_t index) const
01912 {
01913 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01914 if(index >= m_size) {
01915 std::ostringstream message;
01916 message << "Index " << index << " is invalid for a(n) " << m_rows
01917 << " x " << m_columns << " array.";
01918 DLR_THROW(IndexException, "Array2D::checkBounds(size_t)",
01919 message.str().c_str());
01920 }
01921 #endif
01922 }
01923
01924
01925 template <class Type>
01926 inline void Array2D<Type>::
01927 checkBounds(size_t rowIndex, size_t columnIndex) const
01928 {
01929 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01930 if(rowIndex >= m_rows) {
01931 std::ostringstream message;
01932 message << "Row index " << rowIndex << " is invalid for a(n) "
01933 << m_rows << " x " << m_columns << " array.";
01934 DLR_THROW(IndexException, "Array2D::checkBounds(size_t, size_t)",
01935 message.str().c_str());
01936 }
01937 if(columnIndex >= m_columns) {
01938 std::ostringstream message;
01939 message << "Column index " << columnIndex << " is invalid for a(n) "
01940 << m_rows << " x " << m_columns << " array.";
01941 DLR_THROW(IndexException, "Array2D::checkBounds(size_t, size_t)",
01942 message.str().c_str());
01943 }
01944 #endif
01945 }
01946
01947
01948 template <class Type>
01949 void Array2D<Type>::
01950 deAllocate()
01951 {
01952 if(m_isAllocated == true) {
01953 if(--(*m_refCountPtr) == 0) {
01954 delete[] m_dataPtr;
01955 delete m_refCountPtr;
01956 m_isAllocated = false;
01957 m_dataPtr = 0;
01958 m_refCountPtr = 0;
01959 }
01960 } else {
01961 m_dataPtr = 0;
01962 m_refCountPtr = 0;
01963 }
01964 }
01965
01966
01967
01968 template <class Type>
01969 inline Array2D<Type>
01970 sqrt(const Array2D<Type>& array0)
01971 {
01972 return squareRoot(array0);
01973 }
01974
01975
01976
01977
01978 template <class Type>
01979 Array2D<Type>
01980 squareRoot(const Array2D<Type>& array0)
01981 {
01982 Array2D<Type> result(array0.rows(), array0.columns());
01983 std::transform(array0.begin(), array0.end(),
01984 result.begin(), SquareRootFunctor<Type>());
01985 return result;
01986 }
01987
01988 template <class Type>
01989 Array2D<Type> operator+(const Array2D<Type>& array0,
01990 const Array2D<Type>& array1)
01991 {
01992 if((array0.rows() != array1.rows())
01993 || (array0.columns() != array1.columns())) {
01994 std::ostringstream message;
01995 message << "Array sizes do not match. Array0 is " << array0.rows()
01996 << " x " << array0.columns() << ", while array1 is "
01997 << array1.rows() << " x " << array1.columns() << ".";
01998 DLR_THROW(ValueException, "Array2D::operator+()", message.str().c_str());
01999 }
02000 Array2D<Type> result(array0.rows(), array0.columns());
02001 std::transform(array0.begin(), array0.end(), array1.begin(),
02002 result.begin(), std::plus<Type>());
02003 return result;
02004 }
02005
02006 template <class Type>
02007 Array2D<Type> operator-(const Array2D<Type>& array0,
02008 const Array2D<Type>& array1)
02009 {
02010 if((array0.rows() != array1.rows())
02011 || (array0.columns() != array1.columns())) {
02012 std::ostringstream message;
02013 message << "Array sizes do not match. Array0 is " << array0.rows()
02014 << " x " << array0.columns() << ", while array1 is "
02015 << array1.rows() << " x " << array1.columns() << ".";
02016 DLR_THROW(ValueException, "Array2D::operator-()", message.str().c_str());
02017 }
02018 Array2D<Type> result(array0.rows(), array0.columns());
02019 std::transform(array0.begin(), array0.end(), array1.begin(),
02020 result.begin(), std::minus<Type>());
02021 return result;
02022 }
02023
02024 template <class Type>
02025 Array2D<Type> operator*(const Array2D<Type>& array0,
02026 const Array2D<Type>& array1)
02027 {
02028 if((array0.rows() != array1.rows())
02029 || (array0.columns() != array1.columns())) {
02030 std::ostringstream message;
02031 message << "Array sizes do not match. Array0 is " << array0.rows()
02032 << " x " << array0.columns() << ", while array1 is "
02033 << array1.rows() << " x " << array1.columns() << ".";
02034 DLR_THROW(ValueException, "Array2D::operator*()", message.str().c_str());
02035 }
02036 Array2D<Type> result(array0.rows(), array0.columns());
02037 std::transform(array0.begin(), array0.end(), array1.begin(),
02038 result.begin(), std::multiplies<Type>());
02039 return result;
02040 }
02041
02042 template <class Type>
02043 Array2D<Type> operator/(const Array2D<Type>& array0,
02044 const Array2D<Type>& array1)
02045 {
02046 if((array0.rows() != array1.rows())
02047 || (array0.columns() != array1.columns())) {
02048 std::ostringstream message;
02049 message << "Array sizes do not match. Array0 is " << array0.rows()
02050 << " x " << array0.columns() << ", while array1 is "
02051 << array1.rows() << " x " << array1.columns() << ".";
02052 DLR_THROW(ValueException, "Array2D::operator/()", message.str().c_str());
02053 }
02054 Array2D<Type> result(array0.rows(), array0.columns());
02055 std::transform(array0.begin(), array0.end(), array1.begin(),
02056 result.begin(), std::divides<Type>());
02057 return result;
02058 }
02059
02060 template <class Type>
02061 Array2D<Type> operator+(const Array2D<Type>& array0, Type scalar)
02062 {
02063 Array2D<Type> result(array0.rows(), array0.columns());
02064 std::transform(array0.begin(), array0.end(), result.begin(),
02065 std::bind2nd(std::plus<Type>(), scalar));
02066 return result;
02067 }
02068
02069 template <class Type>
02070 Array2D<Type> operator-(const Array2D<Type>& array0, Type scalar)
02071 {
02072 Array2D<Type> result(array0.rows(), array0.columns());
02073 std::transform(array0.begin(), array0.end(), result.begin(),
02074 std::bind2nd(std::minus<Type>(), scalar));
02075 return result;
02076 }
02077
02078 template <class Type>
02079 Array2D<Type> operator*(const Array2D<Type>& array0, Type scalar)
02080 {
02081 Array2D<Type> result(array0.rows(), array0.columns());
02082 std::transform(array0.begin(), array0.end(), result.begin(),
02083 std::bind2nd(std::multiplies<Type>(), scalar));
02084 return result;
02085 }
02086
02087 template <class Type>
02088 Array2D<Type> operator/(const Array2D<Type>& array0, Type scalar)
02089 {
02090 Array2D<Type> result(array0.rows(), array0.columns());
02091 std::transform(array0.begin(), array0.end(), result.begin(),
02092 std::bind2nd(std::divides<Type>(), scalar));
02093 return result;
02094 }
02095
02096 template <class Type>
02097 inline Array2D<Type> operator+(Type scalar, const Array2D<Type>& array0)
02098 {
02099 return array0 + scalar;
02100 }
02101
02102 template <class Type>
02103 inline Array2D<Type> operator*(Type scalar, const Array2D<Type>& array0)
02104 {
02105 return array0 * scalar;
02106 }
02107
02108
02109
02110 template <class Type>
02111 Array2D<bool>
02112 operator==(const Array2D<Type>& array0, const Type arg)
02113 {
02114 Array2D<bool> result(array0.rows(), array0.columns());
02115 std::transform(array0.begin(), array0.end(), result.data(),
02116 std::bind2nd(std::equal_to<Type>(), arg));
02117 return result;
02118 }
02119
02120
02121
02122 template <class Type>
02123 Array2D<bool>
02124 operator==(const Array2D<Type>& array0, const Array2D<Type>& array1)
02125 {
02126 array0.checkDimension(array1.rows(), array1.columns());
02127 Array2D<bool> result(array0.rows(), array0.columns());
02128 std::transform(array0.begin(), array0.end(), array1.begin(),
02129 result.begin(), std::equal_to<Type>());
02130 return result;
02131 }
02132
02133
02134 template <class Type>
02135 Array2D<bool> operator>(const Array2D<Type>& array0, Type arg)
02136 {
02137 Array2D<bool> result(array0.rows(), array0.columns());
02138 std::transform(array0.begin(), array0.end(), result.begin(),
02139 std::bind2nd(std::greater<Type>(), arg));
02140 return result;
02141 }
02142
02143 template <class Type>
02144 Array2D<bool> operator<(const Array2D<Type>& array0, Type arg)
02145 {
02146 Array2D<bool> result(array0.rows(), array0.columns());
02147 std::transform(array0.begin(), array0.end(), result.begin(),
02148 std::bind2nd(std::less<Type>(), arg));
02149 return result;
02150 }
02151
02152 template <class Type>
02153 Array2D<bool> operator>=(const Array2D<Type>& array0, Type arg)
02154 {
02155 Array2D<bool> result(array0.rows(), array0.columns());
02156 std::transform(array0.begin(), array0.end(), result.begin(),
02157 std::bind2nd(std::greater_equal<Type>(), arg));
02158 return result;
02159 }
02160
02161 template <class Type>
02162 Array2D<bool> operator<=(const Array2D<Type>& array0, Type arg)
02163 {
02164 Array2D<bool> result(array0.rows(), array0.columns());
02165 std::transform(array0.begin(), array0.end(), result.begin(),
02166 std::bind2nd(std::less_equal<Type>(), arg));
02167 return result;
02168 }
02169
02170 template <class Type>
02171 std::ostream& operator<<(std::ostream& stream, const Array2D<Type>& array0)
02172 {
02173
02174 typedef typename NumericTraits<Type>::TextOutputType OutputType;
02175
02176 stream << "Array2D([[";
02177 for(size_t row = 0; row < array0.rows(); ++row) {
02178 if (array0.columns() > 0) {
02179 for(size_t column = 0; column < array0.columns() - 1; ++column) {
02180 stream << static_cast<OutputType>(array0(row, column)) << ", ";
02181 }
02182 stream << static_cast<OutputType>(array0(row, array0.columns() - 1));
02183 if(row != array0.rows() - 1) {
02184 stream << "],\n";
02185 stream << " [";
02186 }
02187 }
02188 }
02189 stream << "]])";
02190 stream.flush();
02191 return stream;
02192 }
02193
02194
02195 template <class Type>
02196 std::istream& operator>>(std::istream& inputStream, Array2D<Type>& array0)
02197 {
02198 return array0.readFromStream(inputStream);
02199 }
02200
02201 }
02202
02203 }
02204
02205 #endif