00001
00015 #ifndef _DLR_ARRAY3D_H_
00016 #define _DLR_ARRAY3D_H_
00017
00018 #include <iostream>
00019 #include <dlrNumeric/array1D.h>
00020 #include <dlrNumeric/array2D.h>
00021 #include <dlrCommon/exception.h>
00022
00023 namespace dlr {
00024
00025 namespace numeric {
00026
00049 template <class Type>
00050 class Array3D {
00051 public:
00052
00053
00057 typedef Type value_type;
00058
00062 typedef Type* iterator;
00063
00068 typedef const Type* const_iterator;
00069
00070
00071
00075 Array3D();
00076
00094 Array3D(size_t arrayShape0, size_t arrayShape1, size_t arrayShape2);
00095
00111 explicit
00112 Array3D(const std::string& inputString);
00113
00120 Array3D(const Array3D<Type> &source);
00121
00138 Array3D(size_t arrayShape0, size_t arrayShape1, size_t arrayShape2, Type* const dataPtr);
00139
00144 virtual
00145 ~Array3D();
00146
00152 iterator
00153 begin() {return m_dataPtr;}
00154
00161 const_iterator
00162 begin() const {return m_dataPtr;}
00163
00168 void
00169 clear() {this->reinit(0, 0, 0);}
00170
00171
00183 inline void
00184 checkDimension(size_t arrayShape0, size_t arrayShape1, size_t arrayShape2) const;
00185
00186
00192 Array3D<Type>
00193 copy() const;
00194
00203 template <class Type2>
00204 void
00205 copy(const Array3D<Type2>& source);
00206
00213 template <class Type2>
00214 void
00215 copy(const Type2* dataPtr);
00216
00226 Type*
00227 data() {return m_dataPtr;}
00228
00235 const Type*
00236 data() const {return m_dataPtr;}
00237
00247 Type*
00248 data(size_t index) {
00249 checkBounds(index);
00250 return m_dataPtr + index;
00251 }
00252
00261 const Type*
00262 data(size_t index) const {
00263 checkBounds(index);
00264 return m_dataPtr+index;
00265 }
00266
00276 Type*
00277 data(size_t index0, size_t index1, size_t index2) {
00278 checkBounds(index0, index1, index2);
00279 return (m_dataPtr + index2 + (index1 * m_shape2)
00280 + (index0 * m_shape1Times2));
00281 }
00282
00292 const Type*
00293 data(size_t index0, size_t index1, size_t index2) const {
00294 checkBounds(index0, index1, index2);
00295 return (m_dataPtr + index2 + (index1 * m_shape2)
00296 + (index0 * m_shape1Times2));
00297 }
00298
00299
00307 bool
00308 empty() const {return this->size() == 0;}
00309
00310
00317 iterator
00318 end() {return m_dataPtr + m_size;}
00319
00326 const_iterator
00327 end() const {return m_dataPtr + m_size;}
00328
00329
00339 inline Type
00340 getElement(size_t index0) const {return this->operator()(index0);}
00341
00342
00358 Type
00359 getElement(size_t index0, size_t index1, size_t index2) const {
00360 return this->operator()(index0, index1, index2);
00361 }
00362
00363
00375 std::istream&
00376 readFromStream(std::istream& inputStream);
00377
00388 void
00389 reinit(size_t arrayShape0, size_t arrayShape1, size_t arrayShape2);
00390
00391
00403 inline void
00404 reinitIfNecessary(size_t arrayShape0, size_t arrayShape1,
00405 size_t arrayShape2);
00406
00407
00419 void
00420 reshape(int arrayShape0, int arrayShape1, int arrayShape2);
00421
00422
00436 Type&
00437 setElement(size_t index0, const Type& value) {
00438 return this->operator()(index0) = value;
00439 }
00440
00441
00461 Type&
00462 setElement(size_t index0, size_t index1, size_t index2,
00463 const Type& value) {
00464 return this->operator()(index0, index1, index2) = value;
00465 }
00466
00467
00476 Array1D<size_t>
00477 shape() const;
00478
00487 size_t
00488 shape(size_t axis) const;
00489
00496 size_t
00497 shape0() const {return m_shape0;}
00498
00505 size_t
00506 shape1() const {return m_shape1;}
00507
00514 size_t
00515 shape2() const {return m_shape2;}
00516
00523 size_t
00524 size() const {return m_size;}
00525
00534 Array2D<Type>
00535 slice(size_t index);
00536
00545 const Array2D<Type>
00546 slice(size_t index) const;
00547
00555 Array3D<Type>&
00556 operator=(const Array3D<Type>& source);
00557
00564 Array3D<Type>&
00565 operator=(Type value);
00566
00574 inline Type&
00575 operator()(size_t index) {
00576 checkBounds(index);
00577 return m_dataPtr[index];
00578 }
00579
00587 inline Type
00588 operator()(size_t index) const {
00589 checkBounds(index);
00590 return m_dataPtr[index];
00591 }
00592
00606 inline Type&
00607 operator()(size_t index0, size_t index1, size_t index2) {
00608 checkBounds(index0, index1, index2);
00609 return m_dataPtr[index2 + (index1 * m_shape2)
00610 + (index0 * m_shape1Times2)];
00611 }
00612
00626 inline Type
00627 operator()(size_t index0, size_t index1, size_t index2) const {
00628 checkBounds(index0, index1, index2);
00629 return m_dataPtr[index2 + (index1 * m_shape2)
00630 + (index0 * m_shape1Times2)];
00631 }
00632
00640 inline Type&
00641 operator[](size_t index) {return this->operator()(index);}
00642
00650 inline Type
00651 operator[](size_t index) const {return this->operator()(index);}
00652
00661 template <class Type2>
00662 Array3D<Type>&
00663 operator*=(const Array3D<Type2>& arg);
00664
00673 template <class Type2>
00674 Array3D<Type>&
00675 operator/=(const Array3D<Type2>& arg);
00676
00685 template <class Type2>
00686 Array3D<Type>&
00687 operator+=(const Array3D<Type2>& arg);
00688
00697 template <class Type2>
00698 Array3D<Type>&
00699 operator-=(const Array3D<Type2>& arg);
00700
00707 Array3D<Type>&
00708 operator+=(const Type arg);
00709
00716 Array3D<Type>&
00717 operator-=(const Type arg);
00718
00725 Array3D<Type>&
00726 operator*=(const Type arg);
00727
00734 Array3D<Type>&
00735 operator/=(const Type arg);
00736
00737 private:
00738
00739 void allocate();
00740
00741
00742
00743 inline void
00744 checkBounds(size_t index) const;
00745
00746
00747
00748 inline void
00749 checkBounds(size_t index0, size_t index1, size_t index2) const;
00750
00751 void deAllocate();
00752
00753
00754
00755
00756
00761 static const std::string& ioIntro();
00762
00767 static const std::string& ioOutro();
00768
00773 static const char ioOpening = '[';
00774
00779 static const char ioClosing = ']';
00780
00785 static const char ioSeparator = ',';
00786
00787
00788 size_t m_shape0;
00789 size_t m_shape1;
00790 size_t m_shape2;
00791 size_t m_shape1Times2;
00792 size_t m_size;
00793 Type* m_dataPtr;
00794 size_t* m_refCountPtr;
00795 bool m_isAllocated;
00796
00797 };
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00858 template <class Type>
00859 Array3D<Type>
00860 operator+(const Array3D<Type>& array0, const Array3D<Type>& array1);
00861
00862
00876 template <class Type>
00877 Array3D<Type>
00878 operator-(const Array3D<Type>& array0, const Array3D<Type>& array1);
00879
00880
00894 template <class Type>
00895 Array3D<Type>
00896 operator*(const Array3D<Type>& array0, const Array3D<Type>& array1);
00897
00898
00912 template <class Type>
00913 Array3D<Type>
00914 operator/(const Array3D<Type>& array0, const Array3D<Type>& array1);
00915
00916
00928 template <class Type>
00929 Array3D<Type>
00930 operator+(const Array3D<Type>& array0, Type scalar);
00931
00932
00944 template <class Type>
00945 Array3D<Type>
00946 operator-(const Array3D<Type>& array0, Type scalar);
00947
00948
00960 template <class Type>
00961 Array3D<Type>
00962 operator*(const Array3D<Type>& array0, Type scalar);
00963
00964
00976 template <class Type>
00977 Array3D<Type>
00978 operator/(const Array3D<Type>& array0, Type scalar);
00979
00980
00992 template <class Type>
00993 inline Array3D<Type>
00994 operator+(Type scalar, const Array3D<Type>& array0);
00995
00996
01008 template <class Type>
01009 inline Array3D<Type>
01010 operator*(Type scalar, const Array3D<Type>& array0);
01011
01012
01024 template <class Type>
01025 Array3D<bool>
01026 operator==(const Array3D<Type>& array0, const Type arg);
01027
01028
01041 template <class Type>
01042 Array3D<bool>
01043 operator==(const Array3D<Type>& array0, const Array3D<Type>& array1);
01044
01045
01056 template <class Type>
01057 Array3D<bool>
01058 operator<(const Array3D<Type>& array0, Type arg);
01059
01060
01071 template <class Type>
01072 Array3D<bool>
01073 operator<=(const Array3D<Type>& array0, Type arg);
01074
01075
01086 template <class Type>
01087 Array3D<bool>
01088 operator>(const Array3D<Type>& array0, Type arg);
01089
01090
01101 template <class Type>
01102 Array3D<bool>
01103 operator>=(const Array3D<Type>& array0, Type arg);
01104
01105
01126 template <class Type>
01127 std::ostream& operator<<(std::ostream& stream, const Array3D<Type>& array0);
01128
01129
01141 template <class Type>
01142 std::istream&
01143 operator>>(std::istream& stream, Array3D<Type>& array0);
01144
01145 }
01146
01147 }
01148
01149
01150
01151
01152 namespace dlr {
01153
01154 using numeric::Array3D;
01155
01156 }
01157
01158
01159
01160
01161
01162
01163
01164 #include <algorithm>
01165 #include <sstream>
01166 #include <numeric>
01167 #include <functional>
01168 #include <dlrNumeric/numericTraits.h>
01169
01170 namespace dlr {
01171
01172 namespace numeric {
01173
01174
01175
01176 template <class Type>
01177 const std::string&
01178 Array3D<Type>::
01179 ioIntro()
01180 {
01181 static const std::string intro = "Array3D(";
01182 return intro;
01183 }
01184
01185
01186
01187
01188 template <class Type>
01189 const std::string&
01190 Array3D<Type>::
01191 ioOutro()
01192 {
01193 static const std::string outro = ")";
01194 return outro;
01195 }
01196
01197
01198
01199 template <class Type>
01200 Array3D<Type>::
01201 Array3D()
01202 : m_shape0(0),
01203 m_shape1(0),
01204 m_shape2(0),
01205 m_shape1Times2(0),
01206 m_size(0),
01207 m_dataPtr(0),
01208 m_refCountPtr(0),
01209 m_isAllocated(false)
01210 {
01211
01212 }
01213
01214
01215 template <class Type>
01216 Array3D<Type>::
01217 Array3D(size_t arrayShape0, size_t arrayShape1, size_t arrayShape2)
01218 : m_shape0(arrayShape0),
01219 m_shape1(arrayShape1),
01220 m_shape2(arrayShape2),
01221 m_shape1Times2(0),
01222 m_size(0),
01223 m_dataPtr(0),
01224 m_refCountPtr(0),
01225 m_isAllocated(false)
01226 {
01227 this->allocate();
01228 }
01229
01230
01231
01232 template <class Type>
01233 Array3D<Type>::
01234 Array3D(const std::string& inputString)
01235 : m_shape0(0),
01236 m_shape1(0),
01237 m_shape2(0),
01238 m_shape1Times2(0),
01239 m_size(0),
01240 m_dataPtr(0),
01241 m_refCountPtr(0),
01242 m_isAllocated(false)
01243 {
01244
01245 std::istringstream inputStream(inputString);
01246
01247
01248 Array3D<Type> inputArray;
01249 inputStream >> inputArray;
01250 if(!inputStream) {
01251 std::ostringstream message;
01252 message << "Couldn't parse input string: \"" << inputString << "\".";
01253 DLR_THROW3(ValueException, "Array3D::Array3D(const std::string&)",
01254 message.str().c_str());
01255 }
01256
01257
01258 *this = inputArray;
01259 }
01260
01261
01262
01263
01264
01265
01266 template <class Type>
01267 Array3D<Type>::
01268 Array3D(const Array3D<Type>& source)
01269 : m_shape0(source.m_shape0),
01270 m_shape1(source.m_shape1),
01271 m_shape2(source.m_shape2),
01272 m_shape1Times2(source.m_shape1 * source.m_shape2),
01273 m_size(source.m_size),
01274 m_dataPtr(source.m_dataPtr),
01275 m_refCountPtr(source.m_refCountPtr),
01276 m_isAllocated(source.m_isAllocated)
01277 {
01278 if(m_isAllocated) {
01279 ++(*m_refCountPtr);
01280 }
01281 }
01282
01283
01284
01285
01286 template <class Type>
01287 Array3D<Type>::
01288 Array3D(size_t arrayShape0, size_t arrayShape1, size_t arrayShape2, Type* const dataPtr)
01289 : m_shape0(arrayShape0),
01290 m_shape1(arrayShape1),
01291 m_shape2(arrayShape2),
01292 m_shape1Times2(arrayShape1 * arrayShape2),
01293 m_size(arrayShape0 * arrayShape1 * arrayShape2),
01294 m_dataPtr(dataPtr),
01295 m_refCountPtr(0),
01296 m_isAllocated(false)
01297 {
01298
01299 }
01300
01301
01302 template <class Type>
01303 Array3D<Type>::
01304 ~Array3D()
01305 {
01306 deAllocate();
01307 }
01308
01309
01310 template <class Type>
01311 inline void Array3D<Type>::
01312 checkDimension(size_t arrayShape0, size_t arrayShape1, size_t arrayShape2) const
01313 {
01314 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01315 if(arrayShape0 != this->shape0()
01316 || arrayShape1 != this->shape1()
01317 || arrayShape2 != this->shape2()){
01318 std::ostringstream message;
01319 message << "Size mismatch: required dimension is ("
01320 << arrayShape0 << ", " << arrayShape1 << ", " << arrayShape2 << ") "
01321 << " while *this has dimension "
01322 << this->shape0() << ", " << this->shape1() << ", "
01323 << this->shape2() << ") ";
01324 DLR_THROW(IndexException, "Array3D::checkDimension()",
01325 message.str().c_str());
01326 }
01327 #endif
01328 }
01329
01330
01331 template <class Type>
01332 Array3D<Type> Array3D<Type>::
01333 copy() const
01334 {
01335 Array3D<Type> newArray(m_shape0, m_shape1, m_shape2);
01336 newArray.copy(*this);
01337 return newArray;
01338 }
01339
01340
01341 template <class Type> template <class Type2>
01342 void Array3D<Type>::
01343 copy(const Array3D<Type2>& source)
01344 {
01345 if(source.size() != m_size) {
01346 std::ostringstream message;
01347 message << "Mismatched array sizes. Source array has "
01348 << source.size() << " elements, while destination array has "
01349 << m_size << " elements.";
01350 DLR_THROW3(ValueException, "Array3D::copy(const Array3D&)",
01351 message.str().c_str());
01352 }
01353 if(m_size != 0) {
01354 this->copy(source.data());
01355 }
01356 }
01357
01358
01359 template <class Type> template <class Type2>
01360 void Array3D<Type>::
01361 copy(const Type2* dataPtr)
01362 {
01363 if (dataPtr == 0) {
01364 DLR_THROW(ValueException, "Array3D::copy(const Type2*)",
01365 "Argument is a NULL pointer.");
01366 }
01367 std::copy(dataPtr, dataPtr + m_size, m_dataPtr);
01368 }
01369
01370
01371
01372
01373 template <class Type>
01374 std::istream&
01375 Array3D<Type>::
01376 readFromStream(std::istream& inputStream)
01377 {
01378
01379 typedef typename NumericTraits<Type>::TextOutputType InputType;
01380
01381
01382 if (!inputStream){
01383 return inputStream;
01384 }
01385
01386
01387
01388
01389 std::ios_base::iostate oldExceptionState = inputStream.exceptions();
01390 inputStream.exceptions(
01391 std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit);
01392
01393
01394 try{
01395
01396
01397 InputStream stream(inputStream);
01398
01399
01400
01401 bool foundIntro = false;
01402 if(stream.peek() == ioIntro()[0]) {
01403 foundIntro = true;
01404 stream.expect(ioIntro());
01405 }
01406
01407
01408
01409
01410 stream.expect(ioOpening);
01411
01412
01413
01414 Array2D<Type> inputValue;
01415 std::vector< Array2D<Type> > inputBuffer;
01416 while(1) {
01417
01418 stream >> inputValue;
01419 inputBuffer.push_back(inputValue);
01420
01421
01422 char inChar = 0;
01423 stream >> inChar;
01424 if(inChar == ioClosing) {
01425
01426 break;
01427 }
01428 if(inChar != ioSeparator) {
01429
01430 stream.clear(std::ios_base::failbit);
01431 }
01432 }
01433
01434
01435 if(foundIntro) {
01436 stream.expect(ioOutro());
01437 }
01438
01439
01440
01441 size_t arrayShape0 = inputBuffer.size();
01442 size_t arrayShape1 = ((arrayShape0 != 0) ? inputBuffer[0].rows() : 0);
01443 size_t arrayShape2 = ((arrayShape0 != 0) ? inputBuffer[0].columns() : 0);
01444 for(size_t index = 1; index < arrayShape0; ++index) {
01445 if((inputBuffer[index].rows() != arrayShape1)
01446 || (inputBuffer[index].columns() != arrayShape2)) {
01447
01448 stream.clear(std::ios_base::failbit);
01449 }
01450 }
01451
01452
01453 size_t sliceSize = arrayShape1 * arrayShape2;
01454 this->reinit(arrayShape0, arrayShape1, arrayShape2);
01455 for(size_t index = 0; index < arrayShape0; ++index) {
01456 std::copy(inputBuffer[index].begin(), inputBuffer[index].end(),
01457 this->begin() + (index * sliceSize));
01458 }
01459 } catch(std::ios_base::failure) {
01460
01461 }
01462 inputStream.exceptions(oldExceptionState);
01463 return inputStream;
01464 }
01465
01466
01467 template <class Type>
01468 void Array3D<Type>::
01469 reinit(size_t arrayShape0, size_t arrayShape1, size_t arrayShape2)
01470 {
01471 this->deAllocate();
01472 this->m_shape0 = arrayShape0;
01473 this->m_shape1 = arrayShape1;
01474 this->m_shape2 = arrayShape2;
01475 this->allocate();
01476 }
01477
01478
01479 template <class Type>
01480 void Array3D<Type>::
01481 reinitIfNecessary(size_t arrayShape0, size_t arrayShape1,
01482 size_t arrayShape2)
01483 {
01484 if(this->size() != arrayShape0 * arrayShape1 * arrayShape2) {
01485 this->reinit(arrayShape0, arrayShape1, arrayShape2);
01486 } else {
01487 if(this->shape0() != arrayShape0
01488 || this->shape1() != arrayShape1) {
01489 this->reshape(arrayShape0, arrayShape1, arrayShape2);
01490 }
01491 }
01492 }
01493
01494
01495 template <class Type>
01496 void Array3D<Type>::
01497 reshape(int arrayShape0, int arrayShape1, int arrayShape2)
01498 {
01499 if ((arrayShape0 * arrayShape1 * arrayShape2 != 0)){
01500
01501
01502 if((arrayShape0 == -1) && (arrayShape1 != -1) && (arrayShape2 != -1)) {
01503 arrayShape0 = static_cast<int>(this->size()) / (arrayShape1 * arrayShape2);
01504 } else if((arrayShape1 == -1) && (arrayShape0 != -1) && (arrayShape2 != -1)) {
01505 arrayShape1 = static_cast<int>(this->size()) / (arrayShape0 * arrayShape2);
01506 } else if((arrayShape2 == -1) && (arrayShape1 != -1) && (arrayShape0 != -1)) {
01507 arrayShape2 = static_cast<int>(this->size()) / (arrayShape1 * arrayShape0);
01508 }
01509 }
01510 if((arrayShape0 * arrayShape1 * arrayShape2) != static_cast<int>(this->size())) {
01511 std::ostringstream message;
01512 message << "Can't reshape a(n) " << this->size()
01513 << " element array to be " << arrayShape0 << " x " << arrayShape1
01514 << " x " << arrayShape2 << ".";
01515 DLR_THROW(ValueException, "Array3D::reshape()", message.str().c_str());
01516 }
01517
01518 m_shape0 = static_cast<size_t>(arrayShape0);
01519 m_shape1 = static_cast<size_t>(arrayShape1);
01520 m_shape2 = static_cast<size_t>(arrayShape2);
01521 m_shape1Times2 = arrayShape1 * arrayShape2;
01522 }
01523
01524
01525 template <class Type>
01526 Array1D<size_t> Array3D<Type>::
01527 shape() const
01528 {
01529 Array1D<size_t> rc(3);
01530 rc(0) = this->shape0();
01531 rc(1) = this->shape1();
01532 rc(2) = this->shape2();
01533 return rc;
01534 }
01535
01536
01537 template <class Type>
01538 size_t Array3D<Type>::
01539 shape(size_t axis) const
01540 {
01541 switch(axis) {
01542 case 0:
01543 return this->shape0();
01544 break;
01545 case 1:
01546 return this->shape1();
01547 break;
01548 case 2:
01549 return this->shape2();
01550 break;
01551 default:
01552 std::ostringstream message;
01553 message << "Invalid Axis: "<< axis << ".";
01554 DLR_THROW(ValueException, "Array3D::shape(size_t)",
01555 message.str().c_str());
01556 break;
01557 }
01558 return 0;
01559 }
01560
01561
01562 template <class Type>
01563 Array2D<Type>
01564 Array3D<Type>::
01565 slice(size_t index0)
01566 {
01567 this->checkBounds(index0, 0, 0);
01568 return Array2D<Type>(
01569 m_shape1, m_shape2, m_dataPtr + (index0 * m_shape1Times2));
01570 }
01571
01572
01573 template <class Type>
01574 const Array2D<Type>
01575 Array3D<Type>::
01576 slice(size_t index0) const
01577 {
01578 this->checkBounds(index0, 0, 0);
01579 return Array2D<Type>(
01580 m_shape1, m_shape2, m_dataPtr + (index0 * m_shape1Times2));
01581 }
01582
01583
01584 template <class Type>
01585 Array3D<Type>& Array3D<Type>::
01586 operator=(const Array3D<Type>& source)
01587 {
01588
01589 if(&source != this) {
01590 this->deAllocate();
01591 m_shape0 = source.m_shape0;
01592 m_shape1 = source.m_shape1;
01593 m_shape2 = source.m_shape2;
01594 m_shape1Times2 = source.m_shape1Times2;
01595 m_size = source.m_size;
01596 m_dataPtr = source.m_dataPtr;
01597 m_refCountPtr = source.m_refCountPtr;
01598 m_isAllocated = source.m_isAllocated;
01599 if(m_isAllocated) {
01600 ++(*m_refCountPtr);
01601 }
01602 }
01603 return *this;
01604 }
01605
01606
01607 template <class Type>
01608 Array3D<Type>& Array3D<Type>::
01609 operator=(Type value)
01610 {
01611 std::fill(m_dataPtr, m_dataPtr + m_size, value);
01612 return *this;
01613 }
01614
01615
01616 template <class Type> template <class Type2>
01617 Array3D<Type>& Array3D<Type>::
01618 operator*=(const Array3D<Type2>& arg)
01619 {
01620 if(m_size != arg.size()) {
01621 std::ostringstream message;
01622 message << "Mismatched array sizes. Argument array has "
01623 << arg.size() << " elements, while destination array has "
01624 << m_size << " elements.";
01625 DLR_THROW(ValueException, "Array3D::operator*=()",
01626 message.str().c_str());
01627 }
01628 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01629 std::multiplies<Type>());
01630 return *this;
01631 }
01632
01633
01634 template <class Type> template <class Type2>
01635 Array3D<Type>& Array3D<Type>::
01636 operator/=(const Array3D<Type2>& arg)
01637 {
01638 if(m_size != arg.size()) {
01639 std::ostringstream message;
01640 message << "Mismatched array sizes. Argument array has "
01641 << arg.size() << " elements, while destination array has "
01642 << m_size << " elements.";
01643 DLR_THROW(ValueException, "Array3D::operator/=()",
01644 message.str().c_str());
01645 }
01646 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01647 std::divides<Type>());
01648 return *this;
01649 }
01650
01651
01652 template <class Type> template <class Type2>
01653 Array3D<Type>& Array3D<Type>::
01654 operator+=(const Array3D<Type2>& arg)
01655 {
01656 if(m_size != arg.size()) {
01657 std::ostringstream message;
01658 message << "Mismatched array sizes. Argument array has "
01659 << arg.size() << " elements, while destination array has "
01660 << m_size << " elements.";
01661 DLR_THROW(ValueException, "Array3D::operator+=()",
01662 message.str().c_str());
01663 }
01664 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01665 std::plus<Type>());
01666 return *this;
01667 }
01668
01669
01670 template <class Type> template <class Type2>
01671 Array3D<Type>& Array3D<Type>::
01672 operator-=(const Array3D<Type2>& arg)
01673 {
01674 if(m_size != arg.size()) {
01675 std::ostringstream message;
01676 message << "Mismatched array sizes. Argument array has "
01677 << arg.size() << " elements, while destination array has "
01678 << m_size << " elements.";
01679 DLR_THROW(ValueException, "Array3D::operator-=()",
01680 message.str().c_str());
01681 }
01682 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01683 std::minus<Type>());
01684 return *this;
01685 }
01686
01687
01688 template <class Type>
01689 Array3D<Type>& Array3D<Type>::
01690 operator+=(const Type arg)
01691 {
01692 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01693 std::bind2nd(std::plus<Type>(), arg));
01694 return *this;
01695 }
01696
01697
01698 template <class Type>
01699 Array3D<Type>& Array3D<Type>::
01700 operator-=(const Type arg)
01701 {
01702 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01703 std::bind2nd(std::minus<Type>(), arg));
01704 return *this;
01705 }
01706
01707
01708 template <class Type>
01709 Array3D<Type>& Array3D<Type>::
01710 operator*=(const Type arg)
01711 {
01712 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01713 std::bind2nd(std::multiplies<Type>(), arg));
01714 return *this;
01715 }
01716
01717
01718 template <class Type>
01719 Array3D<Type>& Array3D<Type>::
01720 operator/=(const Type arg)
01721 {
01722 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01723 std::bind2nd(std::divides<Type>(), arg));
01724 return *this;
01725 }
01726
01727
01728 template <class Type>
01729 void Array3D<Type>::
01730 allocate()
01731 {
01732 m_shape1Times2 = m_shape1 * m_shape2;
01733 m_size = m_shape0 * m_shape1 * m_shape2;
01734 if(m_shape0 > 0 && m_shape1 > 0 && m_shape2 > 0) {
01735 m_dataPtr = new(Type[m_size]);
01736 m_refCountPtr = new size_t;
01737 *m_refCountPtr = 1;
01738 m_isAllocated = true;
01739 return;
01740 }
01741 m_dataPtr = 0;
01742 m_refCountPtr = 0;
01743 m_isAllocated = false;
01744 return;
01745 }
01746
01747
01748 template <class Type>
01749 inline void Array3D<Type>::
01750 checkBounds(size_t index) const
01751 {
01752 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01753 if(index >= m_size) {
01754 std::ostringstream message;
01755 message << "Index " << index << " is invalid for a(n) " << m_size
01756 << " element array.";
01757 DLR_THROW(IndexException, "Array3D::checkBounds(size_t)",
01758 message.str().c_str());
01759 }
01760 #endif
01761 }
01762
01763
01764 template <class Type>
01765 inline void Array3D<Type>::
01766 checkBounds(size_t index0, size_t index1, size_t index2) const
01767 {
01768 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01769 if(index0 >= m_shape0) {
01770 std::ostringstream message;
01771 message << "index0 should be less than " << m_shape0
01772 << ", but is actually " << index0 << ".";
01773 DLR_THROW3(IndexException, "Array3D::checkBounds()",
01774 message.str().c_str());
01775 }
01776 if(index1 >= m_shape1) {
01777 std::ostringstream message;
01778 message << "index1 should be less than " << m_shape1
01779 << ", but is actually " << index1 << ".";
01780 DLR_THROW3(IndexException, "Array3D::checkBounds()",
01781 message.str().c_str());
01782 }
01783 if(index2 >= m_shape2) {
01784 std::ostringstream message;
01785 message << "index2 should be less than " << m_shape2
01786 << ", but is actually " << index2 << ".";
01787 DLR_THROW3(IndexException, "Array3D::checkBounds()",
01788 message.str().c_str());
01789 }
01790 #endif
01791 }
01792
01793
01794 template <class Type>
01795 void Array3D<Type>::
01796 deAllocate()
01797 {
01798 if(m_isAllocated == true) {
01799 if(--(*m_refCountPtr) == 0) {
01800 delete[] m_dataPtr;
01801 delete m_refCountPtr;
01802 m_isAllocated = false;
01803 m_dataPtr = 0;
01804 m_refCountPtr = 0;
01805 }
01806 } else {
01807 m_dataPtr = 0;
01808 m_refCountPtr = 0;
01809 }
01810 }
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833 template <class Type>
01834 Array3D<Type> operator+(const Array3D<Type>& array0,
01835 const Array3D<Type>& array1)
01836 {
01837 if((array0.shape0() != array1.shape0())
01838 || (array0.shape1() != array1.shape1())
01839 || (array0.shape2() != array1.shape2())) {
01840 std::ostringstream message;
01841 message << "Array sizes do not match. Array0 is "
01842 << array0.shape0() << " x " << array0.shape1()
01843 << " x " << array0.shape2()
01844 << ", while array1 is "
01845 << array1.shape0() << " x " << array1.shape1()
01846 << " x " << array1.shape2() << ".";
01847 DLR_THROW(ValueException, "Array3D::operator+()", message.str().c_str());
01848 }
01849 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01850 std::transform(array0.begin(), array0.end(), array1.begin(),
01851 result.begin(), std::plus<Type>());
01852 return result;
01853 }
01854
01855
01856 template <class Type>
01857 Array3D<Type> operator-(const Array3D<Type>& array0,
01858 const Array3D<Type>& array1)
01859 {
01860 if((array0.shape0() != array1.shape0())
01861 || (array0.shape1() != array1.shape1())
01862 || (array0.shape2() != array1.shape2())) {
01863 std::ostringstream message;
01864 message << "Array sizes do not match. Array0 is "
01865 << array0.shape0() << " x " << array0.shape1()
01866 << " x " << array0.shape2()
01867 << ", while array1 is "
01868 << array1.shape0() << " x " << array1.shape1()
01869 << " x " << array1.shape2() << ".";
01870 DLR_THROW(ValueException, "Array3D::operator-()", message.str().c_str());
01871 }
01872 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01873 std::transform(array0.begin(), array0.end(), array1.begin(),
01874 result.begin(), std::minus<Type>());
01875 return result;
01876 }
01877
01878
01879 template <class Type>
01880 Array3D<Type> operator*(const Array3D<Type>& array0,
01881 const Array3D<Type>& array1)
01882 {
01883 if((array0.shape0() != array1.shape0())
01884 || (array0.shape1() != array1.shape1())
01885 || (array0.shape2() != array1.shape2())) {
01886 std::ostringstream message;
01887 message << "Array sizes do not match. Array0 is "
01888 << array0.shape0() << " x " << array0.shape1()
01889 << " x " << array0.shape2()
01890 << ", while array1 is "
01891 << array1.shape0() << " x " << array1.shape1()
01892 << " x " << array1.shape2() << ".";
01893 DLR_THROW(ValueException, "Array3D::operator*()", message.str().c_str());
01894 }
01895 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01896 std::transform(array0.begin(), array0.end(), array1.begin(),
01897 result.begin(), std::multiplies<Type>());
01898 return result;
01899 }
01900
01901
01902 template <class Type>
01903 Array3D<Type> operator/(const Array3D<Type>& array0,
01904 const Array3D<Type>& array1)
01905 {
01906 if((array0.shape0() != array1.shape0())
01907 || (array0.shape1() != array1.shape1())
01908 || (array0.shape2() != array1.shape2())) {
01909 std::ostringstream message;
01910 message << "Array sizes do not match. Array0 is "
01911 << array0.shape0() << " x " << array0.shape1()
01912 << " x " << array0.shape2()
01913 << ", while array1 is "
01914 << array1.shape0() << " x " << array1.shape1()
01915 << " x " << array1.shape2() << ".";
01916 DLR_THROW(ValueException, "Array3D::operator/()", message.str().c_str());
01917 }
01918 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01919 std::transform(array0.begin(), array0.end(), array1.begin(), result.begin(),
01920 std::divides<Type>());
01921 return result;
01922 }
01923
01924
01925 template <class Type>
01926 Array3D<Type> operator+(const Array3D<Type>& array0, Type scalar)
01927 {
01928 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01929 std::transform(array0.begin(), array0.end(), result.begin(),
01930 std::bind2nd(std::plus<Type>(), scalar));
01931 return result;
01932 }
01933
01934
01935 template <class Type>
01936 Array3D<Type> operator-(const Array3D<Type>& array0, Type scalar)
01937 {
01938 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01939 std::transform(array0.begin(), array0.end(), result.begin(),
01940 std::bind2nd(std::minus<Type>(), scalar));
01941 return result;
01942 }
01943
01944
01945 template <class Type>
01946 Array3D<Type> operator*(const Array3D<Type>& array0, Type scalar)
01947 {
01948 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01949 std::transform(array0.begin(), array0.end(), result.begin(),
01950 std::bind2nd(std::multiplies<Type>(), scalar));
01951 return result;
01952 }
01953
01954
01955 template <class Type>
01956 Array3D<Type> operator/(const Array3D<Type>& array0, Type scalar)
01957 {
01958 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01959 std::transform(array0.begin(), array0.end(), result.begin(),
01960 std::bind2nd(std::divides<Type>(), scalar));
01961 return result;
01962 }
01963
01964
01965 template <class Type>
01966 inline Array3D<Type> operator+(Type scalar, const Array3D<Type>& array0)
01967 {
01968 return array0 + scalar;
01969 }
01970
01971
01972 template <class Type>
01973 inline Array3D<Type> operator*(Type scalar, const Array3D<Type>& array0)
01974 {
01975 return array0 * scalar;
01976 }
01977
01978
01979
01980 template <class Type>
01981 Array3D<bool>
01982 operator==(const Array3D<Type>& array0, const Type arg)
01983 {
01984 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
01985 std::transform(array0.begin(), array0.end(), result.data(),
01986 std::bind2nd(std::equal_to<Type>(), arg));
01987 return result;
01988 }
01989
01990
01991
01992 template <class Type>
01993 Array3D<bool>
01994 operator==(const Array3D<Type>& array0, const Array3D<Type>& array1)
01995 {
01996 array0.checkDimension(array1.shape0(), array1.shape1(), array1.shape2());
01997 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
01998 std::transform(array0.begin(), array0.end(), array1.begin(),
01999 result.begin(), std::equal_to<Type>());
02000 return result;
02001 }
02002
02003
02004 template <class Type>
02005 Array3D<bool> operator>(const Array3D<Type>& array0, Type arg)
02006 {
02007 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
02008 std::transform(array0.begin(), array0.end(), result.begin(),
02009 std::bind2nd(std::greater<Type>(), arg));
02010 return result;
02011 }
02012
02013
02014 template <class Type>
02015 Array3D<bool> operator<(const Array3D<Type>& array0, Type arg)
02016 {
02017 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
02018 std::transform(array0.begin(), array0.end(), result.begin(),
02019 std::bind2nd(std::less<Type>(), arg));
02020 return result;
02021 }
02022
02023
02024 template <class Type>
02025 Array3D<bool> operator>=(const Array3D<Type>& array0, Type arg)
02026 {
02027 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
02028 std::transform(array0.begin(), array0.end(), result.begin(),
02029 std::bind2nd(std::greater_equal<Type>(), arg));
02030 return result;
02031 }
02032
02033
02034 template <class Type>
02035 Array3D<bool> operator<=(const Array3D<Type>& array0, Type arg)
02036 {
02037 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
02038 std::transform(array0.begin(), array0.end(), result.begin(),
02039 std::bind2nd(std::less_equal<Type>(), arg));
02040 return result;
02041 }
02042
02043
02044
02045
02046 template <class Type>
02047 std::ostream& operator<<(std::ostream& stream, const Array3D<Type>& array0)
02048 {
02049
02050 typedef typename NumericTraits<Type>::TextOutputType OutputType;
02051
02052 size_t index0, index1, index2;
02053 stream << "Array3D([";
02054 for(index0 = 0; index0 < array0.shape0(); ++index0) {
02055 if(index0 != 0) {
02056 stream << " ";
02057 }
02058 stream << "[";
02059 for(index1 = 0; index1 < array0.shape1(); ++index1) {
02060 if(index1 != 0) {
02061 stream << " ";
02062 }
02063 stream << "[";
02064 for(index2 = 0; index2 < array0.shape2(); ++index2) {
02065 stream << static_cast<OutputType>(array0(index0, index1, index2));
02066 if(index2 != array0.shape2() - 1) {
02067 stream << ", ";
02068 }
02069 }
02070 stream << "]";
02071 if(index1 != array0.shape1() - 1) {
02072 stream << ",\n";
02073 }
02074 }
02075 stream << "]";
02076 if(index0 != array0.shape0() - 1) {
02077 stream << ",\n";
02078 }
02079 }
02080 stream << "])\n";
02081 stream.flush();
02082 return stream;
02083 }
02084
02085
02086 template <class Type>
02087 std::istream&
02088 operator>>(std::istream& inputStream, Array3D<Type>& array0)
02089 {
02090 return array0.readFromStream(inputStream);
02091 }
02092
02093 }
02094
02095 }
02096
02097 #endif