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
00368 bool
00369 isAllocated() const {return m_isAllocated;}
00370
00371
00379 Array1D<Type>
00380 ravel();
00381
00389 const Array1D<Type>
00390 ravel() const;
00391
00404 std::istream&
00405 readFromStream(std::istream& inputStream);
00406
00407
00415 size_t*
00416 refCountPtr() const {return m_refCountPtr;}
00417
00418
00428 void
00429 reinit(size_t rows, size_t columns);
00430
00445 void
00446 reshape(int rows, int columns);
00447
00458 Array1D<Type>
00459 row(size_t index);
00460
00471 const Array1D<Type>
00472 row(size_t index) const;
00473
00474
00485 iterator
00486 rowBegin(size_t rowIndex) {return m_dataPtr + rowIndex * m_columns;}
00487
00488
00499 const_iterator
00500 rowBegin(size_t rowIndex) const {
00501 return m_dataPtr + rowIndex * m_columns;
00502 }
00503
00504
00515 iterator
00516 rowEnd(size_t rowIndex) {
00517 return m_dataPtr + (rowIndex + 1) * m_columns;
00518 }
00519
00520
00531 const_iterator
00532 rowEnd(size_t rowIndex) const {
00533 return m_dataPtr + (rowIndex + 1) * m_columns;
00534 }
00535
00536
00544 size_t
00545 rows() const {return m_rows;}
00546
00555 Array1D<size_t>
00556 shape() const;
00557
00569 size_t
00570 shape(size_t axis) const;
00571
00578 size_t
00579 size() const {return m_size;}
00580
00587 Array2D<Type>
00588 transpose() const;
00589
00598 Array2D<Type>&
00599 operator=(const Array2D<Type>& source);
00600
00608 Array2D<Type>&
00609 operator=(Type value);
00610
00619 Type&
00620 operator()(size_t index) {
00621 this->checkBounds(index);
00622 return m_dataPtr[index];
00623 }
00624
00631 Type operator()(size_t index) const {
00632 this->checkBounds(index);
00633 return m_dataPtr[index];
00634 }
00635
00645 Type&
00646 operator()(size_t row, size_t column) {
00647 this->checkBounds(row, column);
00648 return m_dataPtr[column + row * m_columns];
00649 }
00650
00660 Type
00661 operator()(size_t row, size_t column) const {
00662 this->checkBounds(row, column);
00663 return m_dataPtr[column + row * m_columns];
00664 }
00665
00674 Type&
00675 operator[](size_t index) {return this->operator()(index);}
00676
00685 Type
00686 operator[](size_t index) const {return this->operator()(index);}
00687
00699 template <class Type2> Array2D<Type>&
00700 operator+=(const Array2D<Type2>& arg);
00701
00713 template <class Type2> Array2D<Type>&
00714 operator-=(const Array2D<Type2>& arg);
00715
00727 template <class Type2> Array2D<Type>&
00728 operator*=(const Array2D<Type2>& arg);
00729
00741 template <class Type2> Array2D<Type>&
00742 operator/=(const Array2D<Type2>& arg);
00743
00751 Array2D<Type>&
00752 operator+=(Type arg);
00753
00761 Array2D<Type>&
00762 operator-=(Type arg);
00763
00771 Array2D<Type>&
00772 operator*=(Type arg);
00773
00781 Array2D<Type>&
00782 operator/=(Type arg);
00783
00784 private:
00785
00786 void
00787 allocate();
00788
00789
00790
00791 inline void
00792 checkBounds(size_t index) const;
00793
00794
00795
00796 inline void
00797 checkBounds(size_t row, size_t column) const;
00798
00799 void
00800 deAllocate();
00801
00802
00803
00804
00805
00810 static const std::string& ioIntro();
00811
00816 static const std::string& ioOutro();
00817
00822 static const char ioOpening = '[';
00823
00828 static const char ioClosing = ']';
00829
00834 static const char ioSeparator = ',';
00835
00836
00837
00838 size_t m_rows;
00839 size_t m_columns;
00840 size_t m_size;
00841 Type* m_dataPtr;
00842 size_t* m_refCountPtr;
00843 bool m_isAllocated;
00844
00845 };
00846
00847
00848
00859 template <class Type>
00860 Array2D<Type>
00861 squareRoot(const Array2D<Type>& array0);
00862
00874 template <class Type>
00875 inline Array2D<Type>
00876 sqrt(const Array2D<Type>& array0);
00877
00891 template <class Type>
00892 Array2D<Type>
00893 operator+(const Array2D<Type>& array0,
00894 const Array2D<Type>& array1);
00895
00909 template <class Type>
00910 Array2D<Type>
00911 operator-(const Array2D<Type>& array0,
00912 const Array2D<Type>& array1);
00913
00927 template <class Type>
00928 Array2D<Type>
00929 operator*(const Array2D<Type>& array0,
00930 const Array2D<Type>& array1);
00931
00945 template <class Type>
00946 Array2D<Type>
00947 operator/(const Array2D<Type>& array0,
00948 const Array2D<Type>& array1);
00949
00961 template <class Type>
00962 Array2D<Type>
00963 operator+(const Array2D<Type>& array0, Type scalar);
00964
00976 template <class Type>
00977 Array2D<Type>
00978 operator-(const Array2D<Type>& array0, Type scalar);
00979
00991 template <class Type>
00992 Array2D<Type>
00993 operator*(const Array2D<Type>& array0, Type scalar);
00994
01006 template <class Type>
01007 Array2D<Type>
01008 operator/(const Array2D<Type>& array0, Type scalar);
01009
01021 template <class Type>
01022 inline Array2D<Type>
01023 operator+(Type scalar, const Array2D<Type>& array0);
01024
01025
01037 template <class Type>
01038 inline Array2D<Type>
01039 operator*(Type scalar, const Array2D<Type>& array0);
01040
01041
01053 template <class Type>
01054 Array2D<bool>
01055 operator==(const Array2D<Type>& array0, const Type arg);
01056
01057
01070 template <class Type>
01071 Array2D<bool>
01072 operator==(const Array2D<Type>& array0, const Array2D<Type>& array1);
01073
01074
01086 template <class Type>
01087 Array2D<bool>
01088 operator>(const Array2D<Type>& array0, Type arg);
01089
01090
01102 template <class Type>
01103 Array2D<bool>
01104 operator<(const Array2D<Type>& array0, Type arg);
01105
01106
01119 template <class Type>
01120 Array2D<bool>
01121 operator>=(const Array2D<Type>& array0, Type arg);
01122
01123
01136 template <class Type>
01137 Array2D<bool>
01138 operator<=(const Array2D<Type>& array0, Type arg);
01139
01140
01159 template <class Type>
01160 std::ostream&
01161 operator<<(std::ostream& stream, const Array2D<Type>& array0);
01162
01174 template <class Type>
01175 std::istream&
01176 operator>>(std::istream& stream, Array2D<Type>& array0);
01177
01178 }
01179
01180 }
01181
01182
01183
01184
01185 namespace dlr {
01186
01187 using numeric::Array2D;
01188
01189 }
01190
01191
01192
01193
01194
01195
01196
01197 #include <algorithm>
01198 #include <functional>
01199 #include <sstream>
01200 #include <vector>
01201 #include <dlrCommon/functional.h>
01202 #include <dlrCommon/inputStream.h>
01203 #include <dlrNumeric/numericTraits.h>
01204 #include <dlrNumeric/functional.h>
01205
01206 namespace dlr {
01207
01208 namespace numeric {
01209
01210
01211
01212 template <class Type>
01213 const std::string&
01214 Array2D<Type>::
01215 ioIntro()
01216 {
01217 static const std::string intro = "Array2D(";
01218 return intro;
01219 }
01220
01221
01222
01223 template <class Type>
01224 const std::string&
01225 Array2D<Type>::
01226 ioOutro()
01227 {
01228 static const std::string outro = ")";
01229 return outro;
01230 }
01231
01232
01233
01234 template <class Type>
01235 Array2D<Type>::
01236 Array2D()
01237 : m_rows(0),
01238 m_columns(0),
01239 m_size(0),
01240 m_dataPtr(0),
01241 m_refCountPtr(0),
01242 m_isAllocated(false)
01243 {
01244
01245 }
01246
01247 template <class Type>
01248 Array2D<Type>::
01249 Array2D(size_t rows, size_t columns)
01250 : m_rows(rows),
01251 m_columns(columns),
01252 m_size(0),
01253 m_dataPtr(0),
01254 m_refCountPtr(0),
01255 m_isAllocated(false)
01256 {
01257 this->allocate();
01258 }
01259
01260
01261
01262 template <class Type>
01263 Array2D<Type>::
01264 Array2D(const std::string& inputString)
01265 : m_rows(0),
01266 m_columns(0),
01267 m_size(0),
01268 m_dataPtr(0),
01269 m_refCountPtr(0),
01270 m_isAllocated(false)
01271 {
01272
01273 std::istringstream inputStream(inputString);
01274
01275
01276 Array2D<Type> inputArray;
01277 inputStream >> inputArray;
01278 if(!inputStream) {
01279 std::ostringstream message;
01280 message << "Couldn't parse input string: \"" << inputString << "\".";
01281 DLR_THROW3(ValueException, "Array2D::Array2D(const std::string&)",
01282 message.str().c_str());
01283 }
01284
01285
01286 *this = inputArray;
01287 }
01288
01289
01290
01291
01292
01293 template <class Type>
01294 Array2D<Type>::
01295 Array2D(const Array2D<Type>& source)
01296 : m_rows(source.m_rows),
01297 m_columns(source.m_columns),
01298 m_size(source.m_size),
01299 m_dataPtr(source.m_dataPtr),
01300 m_refCountPtr(source.m_refCountPtr),
01301 m_isAllocated(source.m_isAllocated)
01302 {
01303 if(m_isAllocated) {
01304 ++(*m_refCountPtr);
01305 }
01306 }
01307
01308
01309
01310
01311 template <class Type>
01312 Array2D<Type>::
01313 Array2D(size_t rows, size_t columns, Type* const dataPtr)
01314 : m_rows(rows),
01315 m_columns(columns),
01316 m_size(rows*columns),
01317 m_dataPtr(dataPtr),
01318 m_refCountPtr(0),
01319 m_isAllocated(false)
01320 {
01321
01322 }
01323
01324
01325
01326
01327 template <class Type>
01328 Array2D<Type>::
01329 Array2D(size_t rows, size_t columns, Type* const dataPtr,
01330 size_t* refCountPtr)
01331 : m_rows(rows),
01332 m_columns(columns),
01333 m_size(rows*columns),
01334 m_dataPtr(dataPtr),
01335 m_refCountPtr(refCountPtr),
01336 m_isAllocated(true)
01337 {
01338 ++(*m_refCountPtr);
01339 }
01340
01341
01342 template <class Type>
01343 Array2D<Type>::
01344 ~Array2D()
01345 {
01346 deAllocate();
01347 }
01348
01349
01350 template <class Type>
01351 inline void Array2D<Type>::
01352 checkDimension(size_t rows, size_t columns) const
01353 {
01354 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01355 if(rows != this->rows()
01356 || columns != this->columns()) {
01357 std::ostringstream message;
01358 message << "Size mismatch: required dimension is ("
01359 << rows << ", " << columns << ") "
01360 << " while *this has dimension "
01361 << this->rows() << ", " << this->columns() << ").";
01362 DLR_THROW(IndexException, "Array2D::checkDimension()",
01363 message.str().c_str());
01364 }
01365 #endif
01366 }
01367
01368
01369 template <class Type>
01370 Array2D<Type> Array2D<Type>::
01371 copy() const
01372 {
01373 Array2D<Type> newArray(m_rows, m_columns);
01374 newArray.copy(*this);
01375 return newArray;
01376 }
01377
01378 template <class Type> template <class Type2>
01379 void Array2D<Type>::
01380 copy(const Array2D<Type2>& source)
01381 {
01382 if(source.size() != m_size) {
01383 std::ostringstream message;
01384 message << "Mismatched array sizes. Source array has "
01385 << source.size() << " elements, while destination array has "
01386 << m_size << " elements.";
01387 DLR_THROW3(ValueException, "Array2D::copy(const Array2D&)",
01388 message.str().c_str());
01389 }
01390 if(m_size != 0) {
01391 this->copy(source.data());
01392 }
01393 }
01394
01395 template <class Type> template <class Type2>
01396 void Array2D<Type>::
01397 copy(const Type2* dataPtr)
01398 {
01399 if(dataPtr == 0) {
01400 DLR_THROW(ValueException, "Array2D::copy(const Type2*)",
01401 "Argument is a NULL pointer.");
01402 }
01403 std::transform(dataPtr, dataPtr + m_size, m_dataPtr,
01404 StaticCastFunctor<Type2, Type>());
01405 }
01406
01407
01408 template <class Type>
01409 const Array1D<Type> Array2D<Type>::
01410 ravel() const
01411 {
01412 if(m_isAllocated) {
01413 return Array1D<Type>(m_size, m_dataPtr, m_refCountPtr);
01414 }
01415 return Array1D<Type>(m_size, m_dataPtr);
01416 }
01417
01418 template <class Type>
01419 Array1D<Type> Array2D<Type>::
01420 ravel()
01421 {
01422 if(m_isAllocated) {
01423 return Array1D<Type>(m_size, m_dataPtr, m_refCountPtr);
01424 }
01425 return Array1D<Type>(m_size, m_dataPtr);
01426 }
01427
01428
01429 template <class Type>
01430 std::istream&
01431 Array2D<Type>::
01432 readFromStream(std::istream& inputStream)
01433 {
01434
01435 typedef typename NumericTraits<Type>::TextOutputType InputType;
01436
01437
01438 if (!inputStream){
01439 return inputStream;
01440 }
01441
01442
01443
01444
01445 std::ios_base::iostate oldExceptionState = inputStream.exceptions();
01446 inputStream.exceptions(
01447 std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit);
01448
01449
01450 try{
01451
01452
01453 InputStream stream(inputStream);
01454
01455
01456 stream.skipWhiteSpace();
01457
01458
01459
01460 bool foundIntro = false;
01461 if(stream.peek() == ioIntro()[0]) {
01462 foundIntro = true;
01463 stream.expect(ioIntro());
01464 }
01465
01466
01467
01468
01469 stream.expect(ioOpening);
01470
01471
01472
01473 Array1D<Type> inputValue;
01474 std::vector< Array1D<Type> > inputBuffer;
01475 while(1) {
01476
01477 stream >> inputValue;
01478 inputBuffer.push_back(inputValue);
01479
01480
01481 char inChar = 0;
01482 stream >> inChar;
01483 if(inChar == ioClosing) {
01484
01485 break;
01486 }
01487 if(inChar != ioSeparator) {
01488
01489 stream.clear(std::ios_base::failbit);
01490 }
01491 }
01492
01493
01494 if(foundIntro) {
01495 stream.expect(ioOutro());
01496 }
01497
01498
01499
01500 size_t rows = inputBuffer.size();
01501 size_t columns = ((inputBuffer.size() != 0) ? inputBuffer[0].size() : 0);
01502 for(size_t index = 1; index < rows; ++index) {
01503 if(inputBuffer[index].size() != columns) {
01504
01505 stream.clear(std::ios_base::failbit);
01506 }
01507 }
01508
01509
01510 this->reinit(rows, columns);
01511 for(size_t index = 0; index < rows; ++index) {
01512 std::copy(inputBuffer[index].begin(), inputBuffer[index].end(),
01513 this->begin() + (index * columns));
01514 }
01515 } catch(std::ios_base::failure) {
01516
01517 }
01518 inputStream.exceptions(oldExceptionState);
01519 return inputStream;
01520 }
01521
01522
01523 template <class Type>
01524 void Array2D<Type>::
01525 reinit(size_t rows, size_t columns)
01526 {
01527 this->deAllocate();
01528 this->m_rows = rows;
01529 this->m_columns = columns;
01530 this->allocate();
01531 }
01532
01533
01534
01535 template <class Type>
01536 void Array2D<Type>::
01537 reshape(int rows, int columns)
01538 {
01539
01540
01541 if((rows == -1) && (columns != 0)) {
01542 rows = static_cast<int>(this->size()) / columns;
01543 } else
01544 if((columns == -1) && (rows != 0)) {
01545 columns = static_cast<int>(this->size()) / rows;
01546 }
01547 if((rows * columns) != static_cast<int>(this->size())) {
01548 std::ostringstream message;
01549 message << "Can't reshape a(n) " << this->size()
01550 << " element array to have " << rows << " rows and "
01551 << columns << " columns.";
01552 DLR_THROW(ValueException, "Array2D::reshape()", message.str().c_str());
01553 }
01554 m_rows = rows;
01555 m_columns = columns;
01556 }
01557
01558
01559 template <class Type>
01560 Array1D<Type> Array2D<Type>::
01561 row(size_t index)
01562 {
01563 this->checkBounds(index, 0);
01564 return Array1D<Type>(this->columns(),
01565 m_dataPtr + (index * this->m_columns));
01566 }
01567
01568
01569 template <class Type>
01570 const Array1D<Type> Array2D<Type>::
01571 row(size_t index) const
01572 {
01573 this->checkBounds(index, 0);
01574 return Array1D<Type>(this->columns(),
01575 m_dataPtr + (index * this->m_columns));
01576 }
01577
01578
01579 template <class Type>
01580 Array1D<size_t> Array2D<Type>::
01581 shape() const
01582 {
01583 Array1D<size_t> rc(2);
01584 rc(0) = this->rows();
01585 rc(1) = this->columns();
01586 return rc;
01587 }
01588
01589
01590 template <class Type>
01591 size_t Array2D<Type>::
01592 shape(size_t axis) const
01593 {
01594 size_t shape;
01595 switch(axis) {
01596 case 0:
01597 shape = this->rows();
01598 break;
01599 case 1:
01600 shape = this->columns();
01601 break;
01602 default:
01603 std::ostringstream message;
01604 message << "Invalid Axis: "<< axis << ".";
01605 DLR_THROW(ValueException, "Array2D::shape(size_t)",
01606 message.str().c_str());
01607 shape = 0;
01608 break;
01609 }
01610 return shape;
01611 }
01612
01613
01614 template <class Type>
01615 Array2D<Type>& Array2D<Type>::
01616 operator=(Type value)
01617 {
01618 std::fill(m_dataPtr, m_dataPtr + m_size, value);
01619 return *this;
01620 }
01621
01622
01623 template <class Type>
01624 Array2D<Type>& Array2D<Type>::
01625 operator=(const Array2D<Type>& source)
01626 {
01627
01628 if(&source != this) {
01629 this->deAllocate();
01630 m_rows = source.m_rows;
01631 m_columns = source.m_columns;
01632 m_size = source.m_size;
01633 m_dataPtr = source.m_dataPtr;
01634 m_refCountPtr = source.m_refCountPtr;
01635 m_isAllocated = source.m_isAllocated;
01636 if(m_isAllocated) {
01637 ++(*m_refCountPtr);
01638 }
01639 }
01640 return *this;
01641 }
01642
01643
01644 template <class Type> template <class Type2>
01645 Array2D<Type>&
01646 Array2D<Type>::
01647 operator+=(const Array2D<Type2>& arg)
01648 {
01649 if(m_size != arg.size()) {
01650 std::ostringstream message;
01651 message << "Mismatched array sizes. Argument array is "
01652 << arg.rows() << " x " << arg.columns()
01653 << ", while destination array is "
01654 << m_rows << " x " << m_columns << ".";
01655 DLR_THROW(ValueException, "Array2D::operator+=()",
01656 message.str().c_str());
01657 }
01658 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01659 std::plus<Type>());
01660 return *this;
01661 }
01662
01663
01664 template <class Type> template <class Type2>
01665 Array2D<Type>&
01666 Array2D<Type>::
01667 operator-=(const Array2D<Type2>& arg)
01668 {
01669 if(m_size != arg.size()) {
01670 std::ostringstream message;
01671 message << "Mismatched array sizes. Argument array is "
01672 << arg.rows() << " x " << arg.columns()
01673 << ", while destination array is "
01674 << m_rows << " x " << m_columns << ".";
01675 DLR_THROW(ValueException, "Array2D::operator-=()",
01676 message.str().c_str());
01677 }
01678 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01679 std::minus<Type>());
01680 return *this;
01681 }
01682
01683
01684 template <class Type> template <class Type2>
01685 Array2D<Type>&
01686 Array2D<Type>::
01687 operator*=(const Array2D<Type2>& arg)
01688 {
01689 if(m_size != arg.size()) {
01690 std::ostringstream message;
01691 message << "Mismatched array sizes. Argument array is "
01692 << arg.rows() << " x " << arg.columns()
01693 << ", while destination array is "
01694 << m_rows << " x " << m_columns << ".";
01695 DLR_THROW(ValueException, "Array2D::operator*=()",
01696 message.str().c_str());
01697 }
01698 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01699 std::multiplies<Type>());
01700 return *this;
01701 }
01702
01703
01704 template <class Type> template <class Type2>
01705 Array2D<Type>&
01706 Array2D<Type>::
01707 operator/=(const Array2D<Type2>& arg)
01708 {
01709 if(m_size != arg.size()) {
01710 std::ostringstream message;
01711 message << "Mismatched array sizes. Argument array is "
01712 << arg.rows() << " x " << arg.columns()
01713 << ", while destination array is "
01714 << m_rows << " x " << m_columns << ".";
01715 DLR_THROW(ValueException, "Array2D::operator/=()",
01716 message.str().c_str());
01717 }
01718 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01719 std::divides<Type>());
01720 return *this;
01721 }
01722
01723
01724 template <class Type>
01725 Array2D<Type>&
01726 Array2D<Type>::
01727 operator*=(Type arg)
01728 {
01729 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01730 std::bind2nd(std::multiplies<Type>(), arg));
01731 return *this;
01732 }
01733
01734
01735 template <class Type>
01736 Array2D<Type>&
01737 Array2D<Type>::
01738 operator/=(Type arg)
01739 {
01740 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01741 std::bind2nd(std::divides<Type>(), arg));
01742 return *this;
01743 }
01744
01745
01746 template <class Type>
01747 Array2D<Type>&
01748 Array2D<Type>::
01749 operator+=(Type arg)
01750 {
01751 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01752 std::bind2nd(std::plus<Type>(), arg));
01753 return *this;
01754 }
01755
01756
01757 template <class Type>
01758 Array2D<Type>&
01759 Array2D<Type>::
01760 operator-=(Type arg)
01761 {
01762 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01763 std::bind2nd(std::minus<Type>(), arg));
01764 return *this;
01765 }
01766
01767
01768 template <class Type>
01769 Array2D<Type> Array2D<Type>::
01770 transpose() const
01771 {
01772 Array2D<Type> newMx(m_columns, m_rows);
01773
01774
01775 Type *tPtr0 = newMx.m_dataPtr;
01776 for(size_t j = 0; j < m_columns; ++j) {
01777
01778 const Type *tPtr1 = this->data(j);
01779 for(size_t i = 0; i < m_rows; ++i) {
01780 *tPtr0 = *tPtr1;
01781 ++tPtr0;
01782 tPtr1 += m_columns;
01783 }
01784 }
01785 return newMx;
01786 }
01787
01788
01789 template <class Type>
01790 void Array2D<Type>::
01791 allocate()
01792 {
01793 m_size = m_rows * m_columns;
01794 if(m_rows > 0 && m_columns > 0) {
01795 m_dataPtr = new(Type[m_rows * m_columns]);
01796 m_refCountPtr = new size_t;
01797 *m_refCountPtr = 1;
01798 m_isAllocated = true;
01799 return;
01800 }
01801 m_dataPtr = 0;
01802 m_refCountPtr = 0;
01803 m_isAllocated = false;
01804 return;
01805 }
01806
01807
01808 template <class Type>
01809 inline void Array2D<Type>::
01810 checkBounds(size_t index) const
01811 {
01812 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01813 if(index < 0 || index >= m_size) {
01814 std::ostringstream message;
01815 message << "Index " << index << " is invalid for a(n) " << m_rows
01816 << " x " << m_columns << " array.";
01817 DLR_THROW(IndexException, "Array2D::checkBounds(size_t)",
01818 message.str().c_str());
01819 }
01820 #endif
01821 }
01822
01823
01824 template <class Type>
01825 inline void Array2D<Type>::
01826 checkBounds(size_t row, size_t column) const
01827 {
01828 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01829 if(row < 0 || row >= m_rows) {
01830 std::ostringstream message;
01831 message << "Row index " << row << " is invalid for a(n) "
01832 << m_rows << " x " << m_columns << " array.";
01833 DLR_THROW(IndexException, "Array2D::checkBounds(size_t, size_t)",
01834 message.str().c_str());
01835 }
01836 if(column < 0 || column >= m_columns) {
01837 std::ostringstream message;
01838 message << "Column index " << column << " is invalid for a(n) "
01839 << m_rows << " x " << m_columns << " array.";
01840 DLR_THROW(IndexException, "Array2D::checkBounds(size_t, size_t)",
01841 message.str().c_str());
01842 }
01843 #endif
01844 }
01845
01846
01847 template <class Type>
01848 void Array2D<Type>::
01849 deAllocate()
01850 {
01851 if(m_isAllocated == true) {
01852 if(--(*m_refCountPtr) == 0) {
01853 delete[] m_dataPtr;
01854 delete m_refCountPtr;
01855 m_isAllocated = false;
01856 m_dataPtr = 0;
01857 m_refCountPtr = 0;
01858 }
01859 } else {
01860 m_dataPtr = 0;
01861 m_refCountPtr = 0;
01862 }
01863 }
01864
01865
01866
01867 template <class Type>
01868 inline Array2D<Type>
01869 sqrt(const Array2D<Type>& array0)
01870 {
01871 return squareRoot(array0);
01872 }
01873
01874
01875
01876
01877 template <class Type>
01878 Array2D<Type>
01879 squareRoot(const Array2D<Type>& array0)
01880 {
01881 Array2D<Type> result(array0.rows(), array0.columns());
01882 std::transform(array0.begin(), array0.end(),
01883 result.begin(), SquareRootFunctor<Type>());
01884 return result;
01885 }
01886
01887 template <class Type>
01888 Array2D<Type> operator+(const Array2D<Type>& array0,
01889 const Array2D<Type>& array1)
01890 {
01891 if((array0.rows() != array1.rows())
01892 || (array0.columns() != array1.columns())) {
01893 std::ostringstream message;
01894 message << "Array sizes do not match. Array0 is " << array0.rows()
01895 << " x " << array0.columns() << ", while array1 is "
01896 << array1.rows() << " x " << array1.columns() << ".";
01897 DLR_THROW(ValueException, "Array2D::operator+()", message.str().c_str());
01898 }
01899 Array2D<Type> result(array0.rows(), array0.columns());
01900 std::transform(array0.begin(), array0.end(), array1.begin(),
01901 result.begin(), std::plus<Type>());
01902 return result;
01903 }
01904
01905 template <class Type>
01906 Array2D<Type> operator-(const Array2D<Type>& array0,
01907 const Array2D<Type>& array1)
01908 {
01909 if((array0.rows() != array1.rows())
01910 || (array0.columns() != array1.columns())) {
01911 std::ostringstream message;
01912 message << "Array sizes do not match. Array0 is " << array0.rows()
01913 << " x " << array0.columns() << ", while array1 is "
01914 << array1.rows() << " x " << array1.columns() << ".";
01915 DLR_THROW(ValueException, "Array2D::operator-()", message.str().c_str());
01916 }
01917 Array2D<Type> result(array0.rows(), array0.columns());
01918 std::transform(array0.begin(), array0.end(), array1.begin(),
01919 result.begin(), std::minus<Type>());
01920 return result;
01921 }
01922
01923 template <class Type>
01924 Array2D<Type> operator*(const Array2D<Type>& array0,
01925 const Array2D<Type>& array1)
01926 {
01927 if((array0.rows() != array1.rows())
01928 || (array0.columns() != array1.columns())) {
01929 std::ostringstream message;
01930 message << "Array sizes do not match. Array0 is " << array0.rows()
01931 << " x " << array0.columns() << ", while array1 is "
01932 << array1.rows() << " x " << array1.columns() << ".";
01933 DLR_THROW(ValueException, "Array2D::operator*()", message.str().c_str());
01934 }
01935 Array2D<Type> result(array0.rows(), array0.columns());
01936 std::transform(array0.begin(), array0.end(), array1.begin(),
01937 result.begin(), std::multiplies<Type>());
01938 return result;
01939 }
01940
01941 template <class Type>
01942 Array2D<Type> operator/(const Array2D<Type>& array0,
01943 const Array2D<Type>& array1)
01944 {
01945 if((array0.rows() != array1.rows())
01946 || (array0.columns() != array1.columns())) {
01947 std::ostringstream message;
01948 message << "Array sizes do not match. Array0 is " << array0.rows()
01949 << " x " << array0.columns() << ", while array1 is "
01950 << array1.rows() << " x " << array1.columns() << ".";
01951 DLR_THROW(ValueException, "Array2D::operator/()", message.str().c_str());
01952 }
01953 Array2D<Type> result(array0.rows(), array0.columns());
01954 std::transform(array0.begin(), array0.end(), array1.begin(),
01955 result.begin(), std::divides<Type>());
01956 return result;
01957 }
01958
01959 template <class Type>
01960 Array2D<Type> operator+(const Array2D<Type>& array0, Type scalar)
01961 {
01962 Array2D<Type> result(array0.rows(), array0.columns());
01963 std::transform(array0.begin(), array0.end(), result.begin(),
01964 std::bind2nd(std::plus<Type>(), scalar));
01965 return result;
01966 }
01967
01968 template <class Type>
01969 Array2D<Type> operator-(const Array2D<Type>& array0, Type scalar)
01970 {
01971 Array2D<Type> result(array0.rows(), array0.columns());
01972 std::transform(array0.begin(), array0.end(), result.begin(),
01973 std::bind2nd(std::minus<Type>(), scalar));
01974 return result;
01975 }
01976
01977 template <class Type>
01978 Array2D<Type> operator*(const Array2D<Type>& array0, Type scalar)
01979 {
01980 Array2D<Type> result(array0.rows(), array0.columns());
01981 std::transform(array0.begin(), array0.end(), result.begin(),
01982 std::bind2nd(std::multiplies<Type>(), scalar));
01983 return result;
01984 }
01985
01986 template <class Type>
01987 Array2D<Type> operator/(const Array2D<Type>& array0, Type scalar)
01988 {
01989 Array2D<Type> result(array0.rows(), array0.columns());
01990 std::transform(array0.begin(), array0.end(), result.begin(),
01991 std::bind2nd(std::divides<Type>(), scalar));
01992 return result;
01993 }
01994
01995 template <class Type>
01996 inline Array2D<Type> operator+(Type scalar, const Array2D<Type>& array0)
01997 {
01998 return array0 + scalar;
01999 }
02000
02001 template <class Type>
02002 inline Array2D<Type> operator*(Type scalar, const Array2D<Type>& array0)
02003 {
02004 return array0 * scalar;
02005 }
02006
02007
02008
02009 template <class Type>
02010 Array2D<bool>
02011 operator==(const Array2D<Type>& array0, const Type arg)
02012 {
02013 Array2D<bool> result(array0.rows(), array0.columns());
02014 std::transform(array0.begin(), array0.end(), result.data(),
02015 std::bind2nd(std::equal_to<Type>(), arg));
02016 return result;
02017 }
02018
02019
02020
02021 template <class Type>
02022 Array2D<bool>
02023 operator==(const Array2D<Type>& array0, const Array2D<Type>& array1)
02024 {
02025 array0.checkDimension(array1.rows(), array1.columns());
02026 Array2D<bool> result(array0.rows(), array0.columns());
02027 std::transform(array0.begin(), array0.end(), array1.begin(),
02028 result.begin(), std::equal_to<Type>());
02029 return result;
02030 }
02031
02032
02033 template <class Type>
02034 Array2D<bool> operator>(const Array2D<Type>& array0, Type arg)
02035 {
02036 Array2D<bool> result(array0.rows(), array0.columns());
02037 std::transform(array0.begin(), array0.end(), result.begin(),
02038 std::bind2nd(std::greater<Type>(), arg));
02039 return result;
02040 }
02041
02042 template <class Type>
02043 Array2D<bool> operator<(const Array2D<Type>& array0, Type arg)
02044 {
02045 Array2D<bool> result(array0.rows(), array0.columns());
02046 std::transform(array0.begin(), array0.end(), result.begin(),
02047 std::bind2nd(std::less<Type>(), arg));
02048 return result;
02049 }
02050
02051 template <class Type>
02052 Array2D<bool> operator>=(const Array2D<Type>& array0, Type arg)
02053 {
02054 Array2D<bool> result(array0.rows(), array0.columns());
02055 std::transform(array0.begin(), array0.end(), result.begin(),
02056 std::bind2nd(std::greater_equal<Type>(), arg));
02057 return result;
02058 }
02059
02060 template <class Type>
02061 Array2D<bool> operator<=(const Array2D<Type>& array0, Type arg)
02062 {
02063 Array2D<bool> result(array0.rows(), array0.columns());
02064 std::transform(array0.begin(), array0.end(), result.begin(),
02065 std::bind2nd(std::less_equal<Type>(), arg));
02066 return result;
02067 }
02068
02069 template <class Type>
02070 std::ostream& operator<<(std::ostream& stream, const Array2D<Type>& array0)
02071 {
02072
02073 typedef typename NumericTraits<Type>::TextOutputType OutputType;
02074
02075 stream << "Array2D([[";
02076 for(size_t row = 0; row < array0.rows(); ++row) {
02077 if (array0.columns() > 0) {
02078 for(size_t column = 0; column < array0.columns() - 1; ++column) {
02079 stream << static_cast<OutputType>(array0(row, column)) << ", ";
02080 }
02081 stream << static_cast<OutputType>(array0(row, array0.columns() - 1));
02082 if(row != array0.rows() - 1) {
02083 stream << "],\n";
02084 stream << " [";
02085 }
02086 }
02087 }
02088 stream << "]])";
02089 stream.flush();
02090 return stream;
02091 }
02092
02093
02094 template <class Type>
02095 std::istream& operator>>(std::istream& inputStream, Array2D<Type>& array0)
02096 {
02097 return array0.readFromStream(inputStream);
02098 }
02099
02100 }
02101
02102 }
02103
02104 #endif // #ifdef _DLR_ARRAY2D_H_