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
00089 Array2D(size_t rows, size_t columns);
00090
00104 explicit
00105 Array2D(const std::string& inputString);
00106
00113 Array2D(const Array2D<Type> &source);
00114
00130 Array2D(size_t rows, size_t columns, Type* const dataPtr);
00131
00132
00154 Array2D(size_t rows, size_t columns, Type* const dataPtr,
00155 size_t* refCountPtr);
00156
00161 virtual
00162 ~Array2D();
00163
00169 iterator
00170 begin() {return m_dataPtr;}
00171
00178 const_iterator
00179 begin() const {return m_dataPtr;}
00180
00185 void
00186 clear() {this->reinit(0, 0);}
00187
00195 size_t
00196 columns() const {return m_columns;}
00197
00198
00207 inline void
00208 checkDimension(size_t rows, size_t columns) const;
00209
00210
00216 Array2D<Type>
00217 copy() const;
00218
00229 template <class Type2> void
00230 copy(const Array2D<Type2>& source);
00231
00238 template <class Type2> void
00239 copy(const Type2* dataPtr);
00240
00250 Type*
00251 data() {return m_dataPtr;}
00252
00259 const Type*
00260 data() const {return m_dataPtr;}
00261
00272 Type*
00273 data(size_t index) {
00274 this->checkBounds(index);
00275 return m_dataPtr + index;
00276 }
00277
00287 const Type*
00288 data(size_t index) const {
00289 this->checkBounds(index);
00290 return m_dataPtr+index;
00291 }
00292
00305 Type*
00306 data(size_t row, size_t column) {
00307 this->checkBounds(row, column);
00308 return m_dataPtr + column + (row * m_columns);
00309 }
00310
00322 const Type*
00323 data(size_t row, size_t column) const {
00324 this->checkBounds(row, column);
00325 return m_dataPtr + column + (row * m_columns);
00326 }
00327
00328
00336 bool
00337 empty() const {return this->size() == 0;}
00338
00339
00346 iterator
00347 end() {return m_dataPtr + m_size;}
00348
00349
00356 const_iterator
00357 end() const {return m_dataPtr + m_size;}
00358
00359
00369 inline Type
00370 getElement(size_t index0) const {return this->operator()(index0);}
00371
00372
00385 Type
00386 getElement(size_t row, size_t column) const {
00387 return this->operator()(row, column);
00388 }
00389
00390
00399 bool
00400 isAllocated() const {return m_isAllocated;}
00401
00402
00410 Array1D<Type>
00411 ravel();
00412
00420 const Array1D<Type>
00421 ravel() const;
00422
00435 std::istream&
00436 readFromStream(std::istream& inputStream);
00437
00438
00446 size_t*
00447 refCountPtr() const {return m_refCountPtr;}
00448
00449
00459 void
00460 reinit(size_t rows, size_t columns);
00461
00476 void
00477 reshape(int rows, int columns);
00478
00489 Array1D<Type>
00490 row(size_t index);
00491
00502 const Array1D<Type>
00503 row(size_t index) const;
00504
00505
00516 iterator
00517 rowBegin(size_t rowIndex) {return m_dataPtr + rowIndex * m_columns;}
00518
00519
00530 const_iterator
00531 rowBegin(size_t rowIndex) const {
00532 return m_dataPtr + rowIndex * m_columns;
00533 }
00534
00535
00546 iterator
00547 rowEnd(size_t rowIndex) {
00548 return m_dataPtr + (rowIndex + 1) * m_columns;
00549 }
00550
00551
00562 const_iterator
00563 rowEnd(size_t rowIndex) const {
00564 return m_dataPtr + (rowIndex + 1) * m_columns;
00565 }
00566
00567
00575 size_t
00576 rows() const {return m_rows;}
00577
00578
00592 Type&
00593 setElement(size_t index0, const Type& value) {
00594 return this->operator()(index0) = value;
00595 }
00596
00597
00614 Type&
00615 setElement(size_t row, size_t column, const Type& value) {
00616 return this->operator()(row, column) = value;
00617 }
00618
00619
00628 Array1D<size_t>
00629 shape() const;
00630
00642 size_t
00643 shape(size_t axis) const;
00644
00651 size_t
00652 size() const {return m_size;}
00653
00660 Array2D<Type>
00661 transpose() const;
00662
00671 Array2D<Type>&
00672 operator=(const Array2D<Type>& source);
00673
00681 Array2D<Type>&
00682 operator=(Type value);
00683
00692 Type&
00693 operator()(size_t index) {
00694 this->checkBounds(index);
00695 return m_dataPtr[index];
00696 }
00697
00704 Type operator()(size_t index) const {
00705 this->checkBounds(index);
00706 return m_dataPtr[index];
00707 }
00708
00718 Type&
00719 operator()(size_t row, size_t column) {
00720 this->checkBounds(row, column);
00721 return m_dataPtr[column + row * m_columns];
00722 }
00723
00733 Type
00734 operator()(size_t row, size_t column) const {
00735 this->checkBounds(row, column);
00736 return m_dataPtr[column + row * m_columns];
00737 }
00738
00747 Type&
00748 operator[](size_t index) {return this->operator()(index);}
00749
00758 Type
00759 operator[](size_t index) const {return this->operator()(index);}
00760
00772 template <class Type2> Array2D<Type>&
00773 operator+=(const Array2D<Type2>& arg);
00774
00786 template <class Type2> Array2D<Type>&
00787 operator-=(const Array2D<Type2>& arg);
00788
00800 template <class Type2> Array2D<Type>&
00801 operator*=(const Array2D<Type2>& arg);
00802
00814 template <class Type2> Array2D<Type>&
00815 operator/=(const Array2D<Type2>& arg);
00816
00824 Array2D<Type>&
00825 operator+=(Type arg);
00826
00834 Array2D<Type>&
00835 operator-=(Type arg);
00836
00844 Array2D<Type>&
00845 operator*=(Type arg);
00846
00854 Array2D<Type>&
00855 operator/=(Type arg);
00856
00857 private:
00858
00859 void
00860 allocate();
00861
00862
00863
00864 inline void
00865 checkBounds(size_t index) const;
00866
00867
00868
00869 inline void
00870 checkBounds(size_t row, size_t column) const;
00871
00872 void
00873 deAllocate();
00874
00875
00876
00877
00878
00883 static const std::string& ioIntro();
00884
00889 static const std::string& ioOutro();
00890
00895 static const char ioOpening = '[';
00896
00901 static const char ioClosing = ']';
00902
00907 static const char ioSeparator = ',';
00908
00909
00910
00911 size_t m_rows;
00912 size_t m_columns;
00913 size_t m_size;
00914 Type* m_dataPtr;
00915 size_t* m_refCountPtr;
00916 bool m_isAllocated;
00917
00918 };
00919
00920
00921
00932 template <class Type>
00933 Array2D<Type>
00934 squareRoot(const Array2D<Type>& array0);
00935
00947 template <class Type>
00948 inline Array2D<Type>
00949 sqrt(const Array2D<Type>& array0);
00950
00964 template <class Type>
00965 Array2D<Type>
00966 operator+(const Array2D<Type>& array0,
00967 const Array2D<Type>& array1);
00968
00982 template <class Type>
00983 Array2D<Type>
00984 operator-(const Array2D<Type>& array0,
00985 const Array2D<Type>& array1);
00986
01000 template <class Type>
01001 Array2D<Type>
01002 operator*(const Array2D<Type>& array0,
01003 const Array2D<Type>& array1);
01004
01018 template <class Type>
01019 Array2D<Type>
01020 operator/(const Array2D<Type>& array0,
01021 const Array2D<Type>& array1);
01022
01034 template <class Type>
01035 Array2D<Type>
01036 operator+(const Array2D<Type>& array0, Type scalar);
01037
01049 template <class Type>
01050 Array2D<Type>
01051 operator-(const Array2D<Type>& array0, Type scalar);
01052
01064 template <class Type>
01065 Array2D<Type>
01066 operator*(const Array2D<Type>& array0, Type scalar);
01067
01079 template <class Type>
01080 Array2D<Type>
01081 operator/(const Array2D<Type>& array0, Type scalar);
01082
01094 template <class Type>
01095 inline Array2D<Type>
01096 operator+(Type scalar, const Array2D<Type>& array0);
01097
01098
01110 template <class Type>
01111 inline Array2D<Type>
01112 operator*(Type scalar, const Array2D<Type>& array0);
01113
01114
01126 template <class Type>
01127 Array2D<bool>
01128 operator==(const Array2D<Type>& array0, const Type arg);
01129
01130
01143 template <class Type>
01144 Array2D<bool>
01145 operator==(const Array2D<Type>& array0, const Array2D<Type>& array1);
01146
01147
01159 template <class Type>
01160 Array2D<bool>
01161 operator>(const Array2D<Type>& array0, Type arg);
01162
01163
01175 template <class Type>
01176 Array2D<bool>
01177 operator<(const Array2D<Type>& array0, Type arg);
01178
01179
01192 template <class Type>
01193 Array2D<bool>
01194 operator>=(const Array2D<Type>& array0, Type arg);
01195
01196
01209 template <class Type>
01210 Array2D<bool>
01211 operator<=(const Array2D<Type>& array0, Type arg);
01212
01213
01232 template <class Type>
01233 std::ostream&
01234 operator<<(std::ostream& stream, const Array2D<Type>& array0);
01235
01247 template <class Type>
01248 std::istream&
01249 operator>>(std::istream& stream, Array2D<Type>& array0);
01250
01251 }
01252
01253 }
01254
01255
01256
01257
01258 namespace dlr {
01259
01260 using numeric::Array2D;
01261
01262 }
01263
01264
01265
01266
01267
01268
01269
01270 #include <algorithm>
01271 #include <functional>
01272 #include <sstream>
01273 #include <vector>
01274 #include <dlrCommon/functional.h>
01275 #include <dlrCommon/inputStream.h>
01276 #include <dlrNumeric/numericTraits.h>
01277 #include <dlrNumeric/functional.h>
01278
01279 namespace dlr {
01280
01281 namespace numeric {
01282
01283
01284
01285 template <class Type>
01286 const std::string&
01287 Array2D<Type>::
01288 ioIntro()
01289 {
01290 static const std::string intro = "Array2D(";
01291 return intro;
01292 }
01293
01294
01295
01296 template <class Type>
01297 const std::string&
01298 Array2D<Type>::
01299 ioOutro()
01300 {
01301 static const std::string outro = ")";
01302 return outro;
01303 }
01304
01305
01306
01307 template <class Type>
01308 Array2D<Type>::
01309 Array2D()
01310 : m_rows(0),
01311 m_columns(0),
01312 m_size(0),
01313 m_dataPtr(0),
01314 m_refCountPtr(0),
01315 m_isAllocated(false)
01316 {
01317
01318 }
01319
01320 template <class Type>
01321 Array2D<Type>::
01322 Array2D(size_t rows, size_t columns)
01323 : m_rows(rows),
01324 m_columns(columns),
01325 m_size(0),
01326 m_dataPtr(0),
01327 m_refCountPtr(0),
01328 m_isAllocated(false)
01329 {
01330 this->allocate();
01331 }
01332
01333
01334
01335 template <class Type>
01336 Array2D<Type>::
01337 Array2D(const std::string& inputString)
01338 : m_rows(0),
01339 m_columns(0),
01340 m_size(0),
01341 m_dataPtr(0),
01342 m_refCountPtr(0),
01343 m_isAllocated(false)
01344 {
01345
01346 std::istringstream inputStream(inputString);
01347
01348
01349 Array2D<Type> inputArray;
01350 inputStream >> inputArray;
01351 if(!inputStream) {
01352 std::ostringstream message;
01353 message << "Couldn't parse input string: \"" << inputString << "\".";
01354 DLR_THROW3(ValueException, "Array2D::Array2D(const std::string&)",
01355 message.str().c_str());
01356 }
01357
01358
01359 *this = inputArray;
01360 }
01361
01362
01363
01364
01365
01366 template <class Type>
01367 Array2D<Type>::
01368 Array2D(const Array2D<Type>& source)
01369 : m_rows(source.m_rows),
01370 m_columns(source.m_columns),
01371 m_size(source.m_size),
01372 m_dataPtr(source.m_dataPtr),
01373 m_refCountPtr(source.m_refCountPtr),
01374 m_isAllocated(source.m_isAllocated)
01375 {
01376 if(m_isAllocated) {
01377 ++(*m_refCountPtr);
01378 }
01379 }
01380
01381
01382
01383
01384 template <class Type>
01385 Array2D<Type>::
01386 Array2D(size_t rows, size_t columns, Type* const dataPtr)
01387 : m_rows(rows),
01388 m_columns(columns),
01389 m_size(rows*columns),
01390 m_dataPtr(dataPtr),
01391 m_refCountPtr(0),
01392 m_isAllocated(false)
01393 {
01394
01395 }
01396
01397
01398
01399
01400 template <class Type>
01401 Array2D<Type>::
01402 Array2D(size_t rows, size_t columns, Type* const dataPtr,
01403 size_t* refCountPtr)
01404 : m_rows(rows),
01405 m_columns(columns),
01406 m_size(rows*columns),
01407 m_dataPtr(dataPtr),
01408 m_refCountPtr(refCountPtr),
01409 m_isAllocated(true)
01410 {
01411 ++(*m_refCountPtr);
01412 }
01413
01414
01415 template <class Type>
01416 Array2D<Type>::
01417 ~Array2D()
01418 {
01419 deAllocate();
01420 }
01421
01422
01423 template <class Type>
01424 inline void Array2D<Type>::
01425 checkDimension(size_t rows, size_t columns) const
01426 {
01427 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01428 if(rows != this->rows()
01429 || columns != this->columns()) {
01430 std::ostringstream message;
01431 message << "Size mismatch: required dimension is ("
01432 << rows << ", " << columns << ") "
01433 << " while *this has dimension "
01434 << this->rows() << ", " << this->columns() << ").";
01435 DLR_THROW(IndexException, "Array2D::checkDimension()",
01436 message.str().c_str());
01437 }
01438 #endif
01439 }
01440
01441
01442 template <class Type>
01443 Array2D<Type> Array2D<Type>::
01444 copy() const
01445 {
01446 Array2D<Type> newArray(m_rows, m_columns);
01447 newArray.copy(*this);
01448 return newArray;
01449 }
01450
01451 template <class Type> template <class Type2>
01452 void Array2D<Type>::
01453 copy(const Array2D<Type2>& source)
01454 {
01455 if(source.size() != m_size) {
01456 std::ostringstream message;
01457 message << "Mismatched array sizes. Source array has "
01458 << source.size() << " elements, while destination array has "
01459 << m_size << " elements.";
01460 DLR_THROW3(ValueException, "Array2D::copy(const Array2D&)",
01461 message.str().c_str());
01462 }
01463 if(m_size != 0) {
01464 this->copy(source.data());
01465 }
01466 }
01467
01468 template <class Type> template <class Type2>
01469 void Array2D<Type>::
01470 copy(const Type2* dataPtr)
01471 {
01472 if(dataPtr == 0) {
01473 DLR_THROW(ValueException, "Array2D::copy(const Type2*)",
01474 "Argument is a NULL pointer.");
01475 }
01476 std::transform(dataPtr, dataPtr + m_size, m_dataPtr,
01477 StaticCastFunctor<Type2, Type>());
01478 }
01479
01480
01481 template <class Type>
01482 const Array1D<Type> Array2D<Type>::
01483 ravel() const
01484 {
01485 if(m_isAllocated) {
01486 return Array1D<Type>(m_size, m_dataPtr, m_refCountPtr);
01487 }
01488 return Array1D<Type>(m_size, m_dataPtr);
01489 }
01490
01491 template <class Type>
01492 Array1D<Type> Array2D<Type>::
01493 ravel()
01494 {
01495 if(m_isAllocated) {
01496 return Array1D<Type>(m_size, m_dataPtr, m_refCountPtr);
01497 }
01498 return Array1D<Type>(m_size, m_dataPtr);
01499 }
01500
01501
01502 template <class Type>
01503 std::istream&
01504 Array2D<Type>::
01505 readFromStream(std::istream& inputStream)
01506 {
01507
01508 typedef typename NumericTraits<Type>::TextOutputType InputType;
01509
01510
01511 if (!inputStream){
01512 return inputStream;
01513 }
01514
01515
01516
01517
01518 std::ios_base::iostate oldExceptionState = inputStream.exceptions();
01519 inputStream.exceptions(
01520 std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit);
01521
01522
01523 try{
01524
01525
01526 InputStream stream(inputStream);
01527
01528
01529 stream.skipWhiteSpace();
01530
01531
01532
01533 bool foundIntro = false;
01534 if(stream.peek() == ioIntro()[0]) {
01535 foundIntro = true;
01536 stream.expect(ioIntro());
01537 }
01538
01539
01540
01541
01542 stream.expect(ioOpening);
01543
01544
01545
01546 Array1D<Type> inputValue;
01547 std::vector< Array1D<Type> > inputBuffer;
01548 while(1) {
01549
01550 stream >> inputValue;
01551 inputBuffer.push_back(inputValue);
01552
01553
01554 char inChar = 0;
01555 stream >> inChar;
01556 if(inChar == ioClosing) {
01557
01558 break;
01559 }
01560 if(inChar != ioSeparator) {
01561
01562 stream.clear(std::ios_base::failbit);
01563 }
01564 }
01565
01566
01567 if(foundIntro) {
01568 stream.expect(ioOutro());
01569 }
01570
01571
01572
01573 size_t rows = inputBuffer.size();
01574 size_t columns = ((inputBuffer.size() != 0) ? inputBuffer[0].size() : 0);
01575 for(size_t index = 1; index < rows; ++index) {
01576 if(inputBuffer[index].size() != columns) {
01577
01578 stream.clear(std::ios_base::failbit);
01579 }
01580 }
01581
01582
01583 this->reinit(rows, columns);
01584 for(size_t index = 0; index < rows; ++index) {
01585 std::copy(inputBuffer[index].begin(), inputBuffer[index].end(),
01586 this->begin() + (index * columns));
01587 }
01588 } catch(std::ios_base::failure) {
01589
01590 }
01591 inputStream.exceptions(oldExceptionState);
01592 return inputStream;
01593 }
01594
01595
01596 template <class Type>
01597 void Array2D<Type>::
01598 reinit(size_t rows, size_t columns)
01599 {
01600 this->deAllocate();
01601 this->m_rows = rows;
01602 this->m_columns = columns;
01603 this->allocate();
01604 }
01605
01606
01607
01608 template <class Type>
01609 void Array2D<Type>::
01610 reshape(int rows, int columns)
01611 {
01612
01613
01614 if((rows == -1) && (columns != 0)) {
01615 rows = static_cast<int>(this->size()) / columns;
01616 } else
01617 if((columns == -1) && (rows != 0)) {
01618 columns = static_cast<int>(this->size()) / rows;
01619 }
01620 if((rows * columns) != static_cast<int>(this->size())) {
01621 std::ostringstream message;
01622 message << "Can't reshape a(n) " << this->size()
01623 << " element array to have " << rows << " rows and "
01624 << columns << " columns.";
01625 DLR_THROW(ValueException, "Array2D::reshape()", message.str().c_str());
01626 }
01627 m_rows = rows;
01628 m_columns = columns;
01629 }
01630
01631
01632 template <class Type>
01633 Array1D<Type> Array2D<Type>::
01634 row(size_t index)
01635 {
01636 this->checkBounds(index, 0);
01637 return Array1D<Type>(this->columns(),
01638 m_dataPtr + (index * this->m_columns));
01639 }
01640
01641
01642 template <class Type>
01643 const Array1D<Type> Array2D<Type>::
01644 row(size_t index) const
01645 {
01646 this->checkBounds(index, 0);
01647 return Array1D<Type>(this->columns(),
01648 m_dataPtr + (index * this->m_columns));
01649 }
01650
01651
01652 template <class Type>
01653 Array1D<size_t> Array2D<Type>::
01654 shape() const
01655 {
01656 Array1D<size_t> rc(2);
01657 rc(0) = this->rows();
01658 rc(1) = this->columns();
01659 return rc;
01660 }
01661
01662
01663 template <class Type>
01664 size_t Array2D<Type>::
01665 shape(size_t axis) const
01666 {
01667 size_t shape;
01668 switch(axis) {
01669 case 0:
01670 shape = this->rows();
01671 break;
01672 case 1:
01673 shape = this->columns();
01674 break;
01675 default:
01676 std::ostringstream message;
01677 message << "Invalid Axis: "<< axis << ".";
01678 DLR_THROW(ValueException, "Array2D::shape(size_t)",
01679 message.str().c_str());
01680 shape = 0;
01681 break;
01682 }
01683 return shape;
01684 }
01685
01686
01687 template <class Type>
01688 Array2D<Type>& Array2D<Type>::
01689 operator=(Type value)
01690 {
01691 std::fill(m_dataPtr, m_dataPtr + m_size, value);
01692 return *this;
01693 }
01694
01695
01696 template <class Type>
01697 Array2D<Type>& Array2D<Type>::
01698 operator=(const Array2D<Type>& source)
01699 {
01700
01701 if(&source != this) {
01702 this->deAllocate();
01703 m_rows = source.m_rows;
01704 m_columns = source.m_columns;
01705 m_size = source.m_size;
01706 m_dataPtr = source.m_dataPtr;
01707 m_refCountPtr = source.m_refCountPtr;
01708 m_isAllocated = source.m_isAllocated;
01709 if(m_isAllocated) {
01710 ++(*m_refCountPtr);
01711 }
01712 }
01713 return *this;
01714 }
01715
01716
01717 template <class Type> template <class Type2>
01718 Array2D<Type>&
01719 Array2D<Type>::
01720 operator+=(const Array2D<Type2>& arg)
01721 {
01722 if(m_size != arg.size()) {
01723 std::ostringstream message;
01724 message << "Mismatched array sizes. Argument array is "
01725 << arg.rows() << " x " << arg.columns()
01726 << ", while destination array is "
01727 << m_rows << " x " << m_columns << ".";
01728 DLR_THROW(ValueException, "Array2D::operator+=()",
01729 message.str().c_str());
01730 }
01731 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01732 std::plus<Type>());
01733 return *this;
01734 }
01735
01736
01737 template <class Type> template <class Type2>
01738 Array2D<Type>&
01739 Array2D<Type>::
01740 operator-=(const Array2D<Type2>& arg)
01741 {
01742 if(m_size != arg.size()) {
01743 std::ostringstream message;
01744 message << "Mismatched array sizes. Argument array is "
01745 << arg.rows() << " x " << arg.columns()
01746 << ", while destination array is "
01747 << m_rows << " x " << m_columns << ".";
01748 DLR_THROW(ValueException, "Array2D::operator-=()",
01749 message.str().c_str());
01750 }
01751 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01752 std::minus<Type>());
01753 return *this;
01754 }
01755
01756
01757 template <class Type> template <class Type2>
01758 Array2D<Type>&
01759 Array2D<Type>::
01760 operator*=(const Array2D<Type2>& arg)
01761 {
01762 if(m_size != arg.size()) {
01763 std::ostringstream message;
01764 message << "Mismatched array sizes. Argument array is "
01765 << arg.rows() << " x " << arg.columns()
01766 << ", while destination array is "
01767 << m_rows << " x " << m_columns << ".";
01768 DLR_THROW(ValueException, "Array2D::operator*=()",
01769 message.str().c_str());
01770 }
01771 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01772 std::multiplies<Type>());
01773 return *this;
01774 }
01775
01776
01777 template <class Type> template <class Type2>
01778 Array2D<Type>&
01779 Array2D<Type>::
01780 operator/=(const Array2D<Type2>& arg)
01781 {
01782 if(m_size != arg.size()) {
01783 std::ostringstream message;
01784 message << "Mismatched array sizes. Argument array is "
01785 << arg.rows() << " x " << arg.columns()
01786 << ", while destination array is "
01787 << m_rows << " x " << m_columns << ".";
01788 DLR_THROW(ValueException, "Array2D::operator/=()",
01789 message.str().c_str());
01790 }
01791 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01792 std::divides<Type>());
01793 return *this;
01794 }
01795
01796
01797 template <class Type>
01798 Array2D<Type>&
01799 Array2D<Type>::
01800 operator*=(Type arg)
01801 {
01802 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01803 std::bind2nd(std::multiplies<Type>(), arg));
01804 return *this;
01805 }
01806
01807
01808 template <class Type>
01809 Array2D<Type>&
01810 Array2D<Type>::
01811 operator/=(Type arg)
01812 {
01813 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01814 std::bind2nd(std::divides<Type>(), arg));
01815 return *this;
01816 }
01817
01818
01819 template <class Type>
01820 Array2D<Type>&
01821 Array2D<Type>::
01822 operator+=(Type arg)
01823 {
01824 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01825 std::bind2nd(std::plus<Type>(), arg));
01826 return *this;
01827 }
01828
01829
01830 template <class Type>
01831 Array2D<Type>&
01832 Array2D<Type>::
01833 operator-=(Type arg)
01834 {
01835 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01836 std::bind2nd(std::minus<Type>(), arg));
01837 return *this;
01838 }
01839
01840
01841 template <class Type>
01842 Array2D<Type> Array2D<Type>::
01843 transpose() const
01844 {
01845 Array2D<Type> newMx(m_columns, m_rows);
01846
01847
01848 Type *tPtr0 = newMx.m_dataPtr;
01849 for(size_t j = 0; j < m_columns; ++j) {
01850
01851 const Type *tPtr1 = this->data(j);
01852 for(size_t i = 0; i < m_rows; ++i) {
01853 *tPtr0 = *tPtr1;
01854 ++tPtr0;
01855 tPtr1 += m_columns;
01856 }
01857 }
01858 return newMx;
01859 }
01860
01861
01862 template <class Type>
01863 void Array2D<Type>::
01864 allocate()
01865 {
01866 m_size = m_rows * m_columns;
01867 if(m_rows > 0 && m_columns > 0) {
01868 m_dataPtr = new(Type[m_rows * m_columns]);
01869 m_refCountPtr = new size_t;
01870 *m_refCountPtr = 1;
01871 m_isAllocated = true;
01872 return;
01873 }
01874 m_dataPtr = 0;
01875 m_refCountPtr = 0;
01876 m_isAllocated = false;
01877 return;
01878 }
01879
01880
01881 template <class Type>
01882 inline void Array2D<Type>::
01883 checkBounds(size_t index) const
01884 {
01885 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01886 if(index < 0 || index >= m_size) {
01887 std::ostringstream message;
01888 message << "Index " << index << " is invalid for a(n) " << m_rows
01889 << " x " << m_columns << " array.";
01890 DLR_THROW(IndexException, "Array2D::checkBounds(size_t)",
01891 message.str().c_str());
01892 }
01893 #endif
01894 }
01895
01896
01897 template <class Type>
01898 inline void Array2D<Type>::
01899 checkBounds(size_t row, size_t column) const
01900 {
01901 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01902 if(row < 0 || row >= m_rows) {
01903 std::ostringstream message;
01904 message << "Row index " << row << " is invalid for a(n) "
01905 << m_rows << " x " << m_columns << " array.";
01906 DLR_THROW(IndexException, "Array2D::checkBounds(size_t, size_t)",
01907 message.str().c_str());
01908 }
01909 if(column < 0 || column >= m_columns) {
01910 std::ostringstream message;
01911 message << "Column index " << column << " is invalid for a(n) "
01912 << m_rows << " x " << m_columns << " array.";
01913 DLR_THROW(IndexException, "Array2D::checkBounds(size_t, size_t)",
01914 message.str().c_str());
01915 }
01916 #endif
01917 }
01918
01919
01920 template <class Type>
01921 void Array2D<Type>::
01922 deAllocate()
01923 {
01924 if(m_isAllocated == true) {
01925 if(--(*m_refCountPtr) == 0) {
01926 delete[] m_dataPtr;
01927 delete m_refCountPtr;
01928 m_isAllocated = false;
01929 m_dataPtr = 0;
01930 m_refCountPtr = 0;
01931 }
01932 } else {
01933 m_dataPtr = 0;
01934 m_refCountPtr = 0;
01935 }
01936 }
01937
01938
01939
01940 template <class Type>
01941 inline Array2D<Type>
01942 sqrt(const Array2D<Type>& array0)
01943 {
01944 return squareRoot(array0);
01945 }
01946
01947
01948
01949
01950 template <class Type>
01951 Array2D<Type>
01952 squareRoot(const Array2D<Type>& array0)
01953 {
01954 Array2D<Type> result(array0.rows(), array0.columns());
01955 std::transform(array0.begin(), array0.end(),
01956 result.begin(), SquareRootFunctor<Type>());
01957 return result;
01958 }
01959
01960 template <class Type>
01961 Array2D<Type> operator+(const Array2D<Type>& array0,
01962 const Array2D<Type>& array1)
01963 {
01964 if((array0.rows() != array1.rows())
01965 || (array0.columns() != array1.columns())) {
01966 std::ostringstream message;
01967 message << "Array sizes do not match. Array0 is " << array0.rows()
01968 << " x " << array0.columns() << ", while array1 is "
01969 << array1.rows() << " x " << array1.columns() << ".";
01970 DLR_THROW(ValueException, "Array2D::operator+()", message.str().c_str());
01971 }
01972 Array2D<Type> result(array0.rows(), array0.columns());
01973 std::transform(array0.begin(), array0.end(), array1.begin(),
01974 result.begin(), std::plus<Type>());
01975 return result;
01976 }
01977
01978 template <class Type>
01979 Array2D<Type> operator-(const Array2D<Type>& array0,
01980 const Array2D<Type>& array1)
01981 {
01982 if((array0.rows() != array1.rows())
01983 || (array0.columns() != array1.columns())) {
01984 std::ostringstream message;
01985 message << "Array sizes do not match. Array0 is " << array0.rows()
01986 << " x " << array0.columns() << ", while array1 is "
01987 << array1.rows() << " x " << array1.columns() << ".";
01988 DLR_THROW(ValueException, "Array2D::operator-()", message.str().c_str());
01989 }
01990 Array2D<Type> result(array0.rows(), array0.columns());
01991 std::transform(array0.begin(), array0.end(), array1.begin(),
01992 result.begin(), std::minus<Type>());
01993 return result;
01994 }
01995
01996 template <class Type>
01997 Array2D<Type> operator*(const Array2D<Type>& array0,
01998 const Array2D<Type>& array1)
01999 {
02000 if((array0.rows() != array1.rows())
02001 || (array0.columns() != array1.columns())) {
02002 std::ostringstream message;
02003 message << "Array sizes do not match. Array0 is " << array0.rows()
02004 << " x " << array0.columns() << ", while array1 is "
02005 << array1.rows() << " x " << array1.columns() << ".";
02006 DLR_THROW(ValueException, "Array2D::operator*()", message.str().c_str());
02007 }
02008 Array2D<Type> result(array0.rows(), array0.columns());
02009 std::transform(array0.begin(), array0.end(), array1.begin(),
02010 result.begin(), std::multiplies<Type>());
02011 return result;
02012 }
02013
02014 template <class Type>
02015 Array2D<Type> operator/(const Array2D<Type>& array0,
02016 const Array2D<Type>& array1)
02017 {
02018 if((array0.rows() != array1.rows())
02019 || (array0.columns() != array1.columns())) {
02020 std::ostringstream message;
02021 message << "Array sizes do not match. Array0 is " << array0.rows()
02022 << " x " << array0.columns() << ", while array1 is "
02023 << array1.rows() << " x " << array1.columns() << ".";
02024 DLR_THROW(ValueException, "Array2D::operator/()", message.str().c_str());
02025 }
02026 Array2D<Type> result(array0.rows(), array0.columns());
02027 std::transform(array0.begin(), array0.end(), array1.begin(),
02028 result.begin(), std::divides<Type>());
02029 return result;
02030 }
02031
02032 template <class Type>
02033 Array2D<Type> operator+(const Array2D<Type>& array0, Type scalar)
02034 {
02035 Array2D<Type> result(array0.rows(), array0.columns());
02036 std::transform(array0.begin(), array0.end(), result.begin(),
02037 std::bind2nd(std::plus<Type>(), scalar));
02038 return result;
02039 }
02040
02041 template <class Type>
02042 Array2D<Type> operator-(const Array2D<Type>& array0, Type scalar)
02043 {
02044 Array2D<Type> result(array0.rows(), array0.columns());
02045 std::transform(array0.begin(), array0.end(), result.begin(),
02046 std::bind2nd(std::minus<Type>(), scalar));
02047 return result;
02048 }
02049
02050 template <class Type>
02051 Array2D<Type> operator*(const Array2D<Type>& array0, Type scalar)
02052 {
02053 Array2D<Type> result(array0.rows(), array0.columns());
02054 std::transform(array0.begin(), array0.end(), result.begin(),
02055 std::bind2nd(std::multiplies<Type>(), scalar));
02056 return result;
02057 }
02058
02059 template <class Type>
02060 Array2D<Type> operator/(const Array2D<Type>& array0, Type scalar)
02061 {
02062 Array2D<Type> result(array0.rows(), array0.columns());
02063 std::transform(array0.begin(), array0.end(), result.begin(),
02064 std::bind2nd(std::divides<Type>(), scalar));
02065 return result;
02066 }
02067
02068 template <class Type>
02069 inline Array2D<Type> operator+(Type scalar, const Array2D<Type>& array0)
02070 {
02071 return array0 + scalar;
02072 }
02073
02074 template <class Type>
02075 inline Array2D<Type> operator*(Type scalar, const Array2D<Type>& array0)
02076 {
02077 return array0 * scalar;
02078 }
02079
02080
02081
02082 template <class Type>
02083 Array2D<bool>
02084 operator==(const Array2D<Type>& array0, const Type arg)
02085 {
02086 Array2D<bool> result(array0.rows(), array0.columns());
02087 std::transform(array0.begin(), array0.end(), result.data(),
02088 std::bind2nd(std::equal_to<Type>(), arg));
02089 return result;
02090 }
02091
02092
02093
02094 template <class Type>
02095 Array2D<bool>
02096 operator==(const Array2D<Type>& array0, const Array2D<Type>& array1)
02097 {
02098 array0.checkDimension(array1.rows(), array1.columns());
02099 Array2D<bool> result(array0.rows(), array0.columns());
02100 std::transform(array0.begin(), array0.end(), array1.begin(),
02101 result.begin(), std::equal_to<Type>());
02102 return result;
02103 }
02104
02105
02106 template <class Type>
02107 Array2D<bool> operator>(const Array2D<Type>& array0, Type arg)
02108 {
02109 Array2D<bool> result(array0.rows(), array0.columns());
02110 std::transform(array0.begin(), array0.end(), result.begin(),
02111 std::bind2nd(std::greater<Type>(), arg));
02112 return result;
02113 }
02114
02115 template <class Type>
02116 Array2D<bool> operator<(const Array2D<Type>& array0, Type arg)
02117 {
02118 Array2D<bool> result(array0.rows(), array0.columns());
02119 std::transform(array0.begin(), array0.end(), result.begin(),
02120 std::bind2nd(std::less<Type>(), arg));
02121 return result;
02122 }
02123
02124 template <class Type>
02125 Array2D<bool> operator>=(const Array2D<Type>& array0, Type arg)
02126 {
02127 Array2D<bool> result(array0.rows(), array0.columns());
02128 std::transform(array0.begin(), array0.end(), result.begin(),
02129 std::bind2nd(std::greater_equal<Type>(), arg));
02130 return result;
02131 }
02132
02133 template <class Type>
02134 Array2D<bool> operator<=(const Array2D<Type>& array0, Type arg)
02135 {
02136 Array2D<bool> result(array0.rows(), array0.columns());
02137 std::transform(array0.begin(), array0.end(), result.begin(),
02138 std::bind2nd(std::less_equal<Type>(), arg));
02139 return result;
02140 }
02141
02142 template <class Type>
02143 std::ostream& operator<<(std::ostream& stream, const Array2D<Type>& array0)
02144 {
02145
02146 typedef typename NumericTraits<Type>::TextOutputType OutputType;
02147
02148 stream << "Array2D([[";
02149 for(size_t row = 0; row < array0.rows(); ++row) {
02150 if (array0.columns() > 0) {
02151 for(size_t column = 0; column < array0.columns() - 1; ++column) {
02152 stream << static_cast<OutputType>(array0(row, column)) << ", ";
02153 }
02154 stream << static_cast<OutputType>(array0(row, array0.columns() - 1));
02155 if(row != array0.rows() - 1) {
02156 stream << "],\n";
02157 stream << " [";
02158 }
02159 }
02160 }
02161 stream << "]])";
02162 stream.flush();
02163 return stream;
02164 }
02165
02166
02167 template <class Type>
02168 std::istream& operator>>(std::istream& inputStream, Array2D<Type>& array0)
02169 {
02170 return array0.readFromStream(inputStream);
02171 }
02172
02173 }
02174
02175 }
02176
02177 #endif