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 shape0, size_t shape1, size_t shape2);
00095
00111 explicit
00112 Array3D(const std::string& inputString);
00113
00120 Array3D(const Array3D<Type> &source);
00121
00138 Array3D(size_t shape0, size_t shape1, size_t shape2, 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 shape0, size_t shape1, size_t shape2) 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
00387 void
00388 reinit(size_t shape0, size_t shape1, size_t shape2);
00389
00401 void
00402 reshape(int shape0, int shape1, int shape2);
00403
00404
00418 Type&
00419 setElement(size_t index0, const Type& value) {
00420 return this->operator()(index0) = value;
00421 }
00422
00423
00443 Type&
00444 setElement(size_t index0, size_t index1, size_t index2,
00445 const Type& value) {
00446 return this->operator()(index0, index1, index2) = value;
00447 }
00448
00449
00458 Array1D<size_t>
00459 shape() const;
00460
00469 size_t
00470 shape(size_t axis) const;
00471
00478 size_t
00479 shape0() const {return m_shape0;}
00480
00487 size_t
00488 shape1() const {return m_shape1;}
00489
00496 size_t
00497 shape2() const {return m_shape2;}
00498
00505 size_t
00506 size() const {return m_size;}
00507
00516 Array2D<Type>
00517 slice(size_t index);
00518
00527 const Array2D<Type>
00528 slice(size_t index) const;
00529
00537 Array3D<Type>&
00538 operator=(const Array3D<Type>& source);
00539
00546 Array3D<Type>&
00547 operator=(Type value);
00548
00556 Type&
00557 operator()(size_t index) {
00558 checkBounds(index);
00559 return m_dataPtr[index];
00560 }
00561
00569 Type
00570 operator()(size_t index) const {
00571 checkBounds(index);
00572 return m_dataPtr[index];
00573 }
00574
00588 Type&
00589 operator()(size_t index0, size_t index1, size_t index2) {
00590 checkBounds(index0, index1, index2);
00591 return m_dataPtr[index2 + (index1 * m_shape2)
00592 + (index0 * m_shape1Times2)];
00593 }
00594
00608 Type
00609 operator()(size_t index0, size_t index1, size_t index2) const {
00610 checkBounds(index0, index1, index2);
00611 return m_dataPtr[index2 + (index1 * m_shape2)
00612 + (index0 * m_shape1Times2)];
00613 }
00614
00622 Type&
00623 operator[](size_t index) {return this->operator()(index);}
00624
00632 Type
00633 operator[](size_t index) const {return this->operator()(index);}
00634
00643 template <class Type2>
00644 Array3D<Type>&
00645 operator*=(const Array3D<Type2>& arg);
00646
00655 template <class Type2>
00656 Array3D<Type>&
00657 operator/=(const Array3D<Type2>& arg);
00658
00667 template <class Type2>
00668 Array3D<Type>&
00669 operator+=(const Array3D<Type2>& arg);
00670
00679 template <class Type2>
00680 Array3D<Type>&
00681 operator-=(const Array3D<Type2>& arg);
00682
00689 Array3D<Type>&
00690 operator+=(const Type arg);
00691
00698 Array3D<Type>&
00699 operator-=(const Type arg);
00700
00707 Array3D<Type>&
00708 operator*=(const Type arg);
00709
00716 Array3D<Type>&
00717 operator/=(const Type arg);
00718
00719 private:
00720
00721 void allocate();
00722
00723
00724
00725 inline void
00726 checkBounds(size_t index) const;
00727
00728
00729
00730 inline void
00731 checkBounds(size_t index0, size_t index1, size_t index2) const;
00732
00733 void deAllocate();
00734
00735
00736
00737
00738
00743 static const std::string& ioIntro();
00744
00749 static const std::string& ioOutro();
00750
00755 static const char ioOpening = '[';
00756
00761 static const char ioClosing = ']';
00762
00767 static const char ioSeparator = ',';
00768
00769
00770 size_t m_shape0;
00771 size_t m_shape1;
00772 size_t m_shape2;
00773 size_t m_shape1Times2;
00774 size_t m_size;
00775 Type* m_dataPtr;
00776 size_t* m_refCountPtr;
00777 bool m_isAllocated;
00778
00779 };
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
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
00840 template <class Type>
00841 Array3D<Type>
00842 operator+(const Array3D<Type>& array0, const Array3D<Type>& array1);
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
00910 template <class Type>
00911 Array3D<Type>
00912 operator+(const Array3D<Type>& array0, Type scalar);
00913
00914
00926 template <class Type>
00927 Array3D<Type>
00928 operator-(const Array3D<Type>& array0, Type scalar);
00929
00930
00942 template <class Type>
00943 Array3D<Type>
00944 operator*(const Array3D<Type>& array0, Type scalar);
00945
00946
00958 template <class Type>
00959 Array3D<Type>
00960 operator/(const Array3D<Type>& array0, Type scalar);
00961
00962
00974 template <class Type>
00975 inline Array3D<Type>
00976 operator+(Type scalar, const Array3D<Type>& array0);
00977
00978
00990 template <class Type>
00991 inline Array3D<Type>
00992 operator*(Type scalar, const Array3D<Type>& array0);
00993
00994
01006 template <class Type>
01007 Array3D<bool>
01008 operator==(const Array3D<Type>& array0, const Type arg);
01009
01010
01023 template <class Type>
01024 Array3D<bool>
01025 operator==(const Array3D<Type>& array0, const Array3D<Type>& array1);
01026
01027
01038 template <class Type>
01039 Array3D<bool>
01040 operator<(const Array3D<Type>& array0, Type arg);
01041
01042
01053 template <class Type>
01054 Array3D<bool>
01055 operator<=(const Array3D<Type>& array0, Type arg);
01056
01057
01068 template <class Type>
01069 Array3D<bool>
01070 operator>(const Array3D<Type>& array0, Type arg);
01071
01072
01083 template <class Type>
01084 Array3D<bool>
01085 operator>=(const Array3D<Type>& array0, Type arg);
01086
01087
01108 template <class Type>
01109 std::ostream& operator<<(std::ostream& stream, const Array3D<Type>& array0);
01110
01111
01123 template <class Type>
01124 std::istream&
01125 operator>>(std::istream& stream, Array3D<Type>& array0);
01126
01127 }
01128
01129 }
01130
01131
01132
01133
01134 namespace dlr {
01135
01136 using numeric::Array3D;
01137
01138 }
01139
01140
01141
01142
01143
01144
01145
01146 #include <algorithm>
01147 #include <sstream>
01148 #include <numeric>
01149 #include <functional>
01150 #include <dlrNumeric/numericTraits.h>
01151
01152 namespace dlr {
01153
01154 namespace numeric {
01155
01156
01157
01158 template <class Type>
01159 const std::string&
01160 Array3D<Type>::
01161 ioIntro()
01162 {
01163 static const std::string intro = "Array3D(";
01164 return intro;
01165 }
01166
01167
01168
01169
01170 template <class Type>
01171 const std::string&
01172 Array3D<Type>::
01173 ioOutro()
01174 {
01175 static const std::string outro = ")";
01176 return outro;
01177 }
01178
01179
01180
01181 template <class Type>
01182 Array3D<Type>::
01183 Array3D()
01184 : m_shape0(0),
01185 m_shape1(0),
01186 m_shape2(0),
01187 m_shape1Times2(0),
01188 m_size(0),
01189 m_dataPtr(0),
01190 m_refCountPtr(0),
01191 m_isAllocated(false)
01192 {
01193
01194 }
01195
01196
01197 template <class Type>
01198 Array3D<Type>::
01199 Array3D(size_t shape0, size_t shape1, size_t shape2)
01200 : m_shape0(shape0),
01201 m_shape1(shape1),
01202 m_shape2(shape2),
01203 m_shape1Times2(0),
01204 m_size(0),
01205 m_dataPtr(0),
01206 m_refCountPtr(0),
01207 m_isAllocated(false)
01208 {
01209 this->allocate();
01210 }
01211
01212
01213
01214 template <class Type>
01215 Array3D<Type>::
01216 Array3D(const std::string& inputString)
01217 : m_shape0(0),
01218 m_shape1(0),
01219 m_shape2(0),
01220 m_shape1Times2(0),
01221 m_size(0),
01222 m_dataPtr(0),
01223 m_refCountPtr(0),
01224 m_isAllocated(false)
01225 {
01226
01227 std::istringstream inputStream(inputString);
01228
01229
01230 Array3D<Type> inputArray;
01231 inputStream >> inputArray;
01232 if(!inputStream) {
01233 std::ostringstream message;
01234 message << "Couldn't parse input string: \"" << inputString << "\".";
01235 DLR_THROW3(ValueException, "Array3D::Array3D(const std::string&)",
01236 message.str().c_str());
01237 }
01238
01239
01240 *this = inputArray;
01241 }
01242
01243
01244
01245
01246
01247
01248 template <class Type>
01249 Array3D<Type>::
01250 Array3D(const Array3D<Type>& source)
01251 : m_shape0(source.m_shape0),
01252 m_shape1(source.m_shape1),
01253 m_shape2(source.m_shape2),
01254 m_shape1Times2(source.m_shape1 * source.m_shape2),
01255 m_size(source.m_size),
01256 m_dataPtr(source.m_dataPtr),
01257 m_refCountPtr(source.m_refCountPtr),
01258 m_isAllocated(source.m_isAllocated)
01259 {
01260 if(m_isAllocated) {
01261 ++(*m_refCountPtr);
01262 }
01263 }
01264
01265
01266
01267
01268 template <class Type>
01269 Array3D<Type>::
01270 Array3D(size_t shape0, size_t shape1, size_t shape2, Type* const dataPtr)
01271 : m_shape0(shape0),
01272 m_shape1(shape1),
01273 m_shape2(shape2),
01274 m_shape1Times2(shape1 * shape2),
01275 m_size(shape0 * shape1 * shape2),
01276 m_dataPtr(dataPtr),
01277 m_refCountPtr(0),
01278 m_isAllocated(false)
01279 {
01280
01281 }
01282
01283
01284 template <class Type>
01285 Array3D<Type>::
01286 ~Array3D()
01287 {
01288 deAllocate();
01289 }
01290
01291
01292 template <class Type>
01293 inline void Array3D<Type>::
01294 checkDimension(size_t shape0, size_t shape1, size_t shape2) const
01295 {
01296 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01297 if(shape0 != this->shape0()
01298 || shape1 != this->shape1()
01299 || shape2 != this->shape2()){
01300 std::ostringstream message;
01301 message << "Size mismatch: required dimension is ("
01302 << shape0 << ", " << shape1 << ", " << shape2 << ") "
01303 << " while *this has dimension "
01304 << this->shape0() << ", " << this->shape1() << ", "
01305 << this->shape2() << ") ";
01306 DLR_THROW(IndexException, "Array3D::checkDimension()",
01307 message.str().c_str());
01308 }
01309 #endif
01310 }
01311
01312
01313 template <class Type>
01314 Array3D<Type> Array3D<Type>::
01315 copy() const
01316 {
01317 Array3D<Type> newArray(m_shape0, m_shape1, m_shape2);
01318 newArray.copy(*this);
01319 return newArray;
01320 }
01321
01322
01323 template <class Type> template <class Type2>
01324 void Array3D<Type>::
01325 copy(const Array3D<Type2>& source)
01326 {
01327 if(source.size() != m_size) {
01328 std::ostringstream message;
01329 message << "Mismatched array sizes. Source array has "
01330 << source.size() << " elements, while destination array has "
01331 << m_size << " elements.";
01332 DLR_THROW3(ValueException, "Array3D::copy(const Array3D&)",
01333 message.str().c_str());
01334 }
01335 if(m_size != 0) {
01336 this->copy(source.data());
01337 }
01338 }
01339
01340
01341 template <class Type> template <class Type2>
01342 void Array3D<Type>::
01343 copy(const Type2* dataPtr)
01344 {
01345 if (dataPtr == 0) {
01346 DLR_THROW(ValueException, "Array3D::copy(const Type2*)",
01347 "Argument is a NULL pointer.");
01348 }
01349 std::copy(dataPtr, dataPtr + m_size, m_dataPtr);
01350 }
01351
01352
01353
01354
01355 template <class Type>
01356 std::istream&
01357 Array3D<Type>::
01358 readFromStream(std::istream& inputStream)
01359 {
01360
01361 typedef typename NumericTraits<Type>::TextOutputType InputType;
01362
01363
01364 if (!inputStream){
01365 return inputStream;
01366 }
01367
01368
01369
01370
01371 std::ios_base::iostate oldExceptionState = inputStream.exceptions();
01372 inputStream.exceptions(
01373 std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit);
01374
01375
01376 try{
01377
01378
01379 InputStream stream(inputStream);
01380
01381
01382
01383 bool foundIntro = false;
01384 if(stream.peek() == ioIntro()[0]) {
01385 foundIntro = true;
01386 stream.expect(ioIntro());
01387 }
01388
01389
01390
01391
01392 stream.expect(ioOpening);
01393
01394
01395
01396 Array2D<Type> inputValue;
01397 std::vector< Array2D<Type> > inputBuffer;
01398 while(1) {
01399
01400 stream >> inputValue;
01401 inputBuffer.push_back(inputValue);
01402
01403
01404 char inChar = 0;
01405 stream >> inChar;
01406 if(inChar == ioClosing) {
01407
01408 break;
01409 }
01410 if(inChar != ioSeparator) {
01411
01412 stream.clear(std::ios_base::failbit);
01413 }
01414 }
01415
01416
01417 if(foundIntro) {
01418 stream.expect(ioOutro());
01419 }
01420
01421
01422
01423 size_t shape0 = inputBuffer.size();
01424 size_t shape1 = ((shape0 != 0) ? inputBuffer[0].rows() : 0);
01425 size_t shape2 = ((shape0 != 0) ? inputBuffer[0].columns() : 0);
01426 for(size_t index = 1; index < shape0; ++index) {
01427 if((inputBuffer[index].rows() != shape1)
01428 || (inputBuffer[index].columns() != shape2)) {
01429
01430 stream.clear(std::ios_base::failbit);
01431 }
01432 }
01433
01434
01435 size_t sliceSize = shape1 * shape2;
01436 this->reinit(shape0, shape1, shape2);
01437 for(size_t index = 0; index < shape0; ++index) {
01438 std::copy(inputBuffer[index].begin(), inputBuffer[index].end(),
01439 this->begin() + (index * sliceSize));
01440 }
01441 } catch(std::ios_base::failure) {
01442
01443 }
01444 inputStream.exceptions(oldExceptionState);
01445 return inputStream;
01446 }
01447
01448
01449 template <class Type>
01450 void Array3D<Type>::
01451 reinit(size_t shape0, size_t shape1, size_t shape2)
01452 {
01453 this->deAllocate();
01454 this->m_shape0 = shape0;
01455 this->m_shape1 = shape1;
01456 this->m_shape2 = shape2;
01457 this->allocate();
01458 }
01459
01460
01461 template <class Type>
01462 void Array3D<Type>::
01463 reshape(int shape0, int shape1, int shape2)
01464 {
01465 if ((shape0 * shape1 * shape2 != 0)){
01466
01467
01468 if((shape0 == -1) && (shape1 != -1) && (shape2 != -1)) {
01469 shape0 = static_cast<int>(this->size()) / (shape1 * shape2);
01470 } else if((shape1 == -1) && (shape0 != -1) && (shape2 != -1)) {
01471 shape1 = static_cast<int>(this->size()) / (shape0 * shape2);
01472 } else if((shape2 == -1) && (shape1 != -1) && (shape0 != -1)) {
01473 shape2 = static_cast<int>(this->size()) / (shape1 * shape0);
01474 }
01475 }
01476 if((shape0 * shape1 * shape2) != static_cast<int>(this->size())) {
01477 std::ostringstream message;
01478 message << "Can't reshape a(n) " << this->size()
01479 << " element array to be " << shape0 << " x " << shape1
01480 << " x " << shape2 << ".";
01481 DLR_THROW(ValueException, "Array3D::reshape()", message.str().c_str());
01482 }
01483
01484 m_shape0 = static_cast<size_t>(shape0);
01485 m_shape1 = static_cast<size_t>(shape1);
01486 m_shape2 = static_cast<size_t>(shape2);
01487 m_shape1Times2 = shape1 * shape2;
01488 }
01489
01490
01491 template <class Type>
01492 Array1D<size_t> Array3D<Type>::
01493 shape() const
01494 {
01495 Array1D<size_t> rc(3);
01496 rc(0) = this->shape0();
01497 rc(1) = this->shape1();
01498 rc(2) = this->shape2();
01499 return rc;
01500 }
01501
01502
01503 template <class Type>
01504 size_t Array3D<Type>::
01505 shape(size_t axis) const
01506 {
01507 switch(axis) {
01508 case 0:
01509 return this->shape0();
01510 break;
01511 case 1:
01512 return this->shape1();
01513 break;
01514 case 2:
01515 return this->shape2();
01516 break;
01517 default:
01518 std::ostringstream message;
01519 message << "Invalid Axis: "<< axis << ".";
01520 DLR_THROW(ValueException, "Array3D::shape(size_t)",
01521 message.str().c_str());
01522 break;
01523 }
01524 return 0;
01525 }
01526
01527
01528 template <class Type>
01529 Array2D<Type>
01530 Array3D<Type>::
01531 slice(size_t index0)
01532 {
01533 this->checkBounds(index0, 0, 0);
01534 return Array2D<Type>(
01535 m_shape1, m_shape2, m_dataPtr + (index0 * m_shape1Times2));
01536 }
01537
01538
01539 template <class Type>
01540 const Array2D<Type>
01541 Array3D<Type>::
01542 slice(size_t index0) const
01543 {
01544 this->checkBounds(index0, 0, 0);
01545 return Array2D<Type>(
01546 m_shape1, m_shape2, m_dataPtr + (index0 * m_shape1Times2));
01547 }
01548
01549
01550 template <class Type>
01551 Array3D<Type>& Array3D<Type>::
01552 operator=(const Array3D<Type>& source)
01553 {
01554
01555 if(&source != this) {
01556 this->deAllocate();
01557 m_shape0 = source.m_shape0;
01558 m_shape1 = source.m_shape1;
01559 m_shape2 = source.m_shape2;
01560 m_shape1Times2 = source.m_shape1Times2;
01561 m_size = source.m_size;
01562 m_dataPtr = source.m_dataPtr;
01563 m_refCountPtr = source.m_refCountPtr;
01564 m_isAllocated = source.m_isAllocated;
01565 if(m_isAllocated) {
01566 ++(*m_refCountPtr);
01567 }
01568 }
01569 return *this;
01570 }
01571
01572
01573 template <class Type>
01574 Array3D<Type>& Array3D<Type>::
01575 operator=(Type value)
01576 {
01577 std::fill(m_dataPtr, m_dataPtr + m_size, value);
01578 return *this;
01579 }
01580
01581
01582 template <class Type> template <class Type2>
01583 Array3D<Type>& Array3D<Type>::
01584 operator*=(const Array3D<Type2>& arg)
01585 {
01586 if(m_size != arg.size()) {
01587 std::ostringstream message;
01588 message << "Mismatched array sizes. Argument array has "
01589 << arg.size() << " elements, while destination array has "
01590 << m_size << " elements.";
01591 DLR_THROW(ValueException, "Array3D::operator*=()",
01592 message.str().c_str());
01593 }
01594 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01595 std::multiplies<Type>());
01596 return *this;
01597 }
01598
01599
01600 template <class Type> template <class Type2>
01601 Array3D<Type>& Array3D<Type>::
01602 operator/=(const Array3D<Type2>& arg)
01603 {
01604 if(m_size != arg.size()) {
01605 std::ostringstream message;
01606 message << "Mismatched array sizes. Argument array has "
01607 << arg.size() << " elements, while destination array has "
01608 << m_size << " elements.";
01609 DLR_THROW(ValueException, "Array3D::operator/=()",
01610 message.str().c_str());
01611 }
01612 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01613 std::divides<Type>());
01614 return *this;
01615 }
01616
01617
01618 template <class Type> template <class Type2>
01619 Array3D<Type>& Array3D<Type>::
01620 operator+=(const Array3D<Type2>& arg)
01621 {
01622 if(m_size != arg.size()) {
01623 std::ostringstream message;
01624 message << "Mismatched array sizes. Argument array has "
01625 << arg.size() << " elements, while destination array has "
01626 << m_size << " elements.";
01627 DLR_THROW(ValueException, "Array3D::operator+=()",
01628 message.str().c_str());
01629 }
01630 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01631 std::plus<Type>());
01632 return *this;
01633 }
01634
01635
01636 template <class Type> template <class Type2>
01637 Array3D<Type>& Array3D<Type>::
01638 operator-=(const Array3D<Type2>& arg)
01639 {
01640 if(m_size != arg.size()) {
01641 std::ostringstream message;
01642 message << "Mismatched array sizes. Argument array has "
01643 << arg.size() << " elements, while destination array has "
01644 << m_size << " elements.";
01645 DLR_THROW(ValueException, "Array3D::operator-=()",
01646 message.str().c_str());
01647 }
01648 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01649 std::minus<Type>());
01650 return *this;
01651 }
01652
01653
01654 template <class Type>
01655 Array3D<Type>& Array3D<Type>::
01656 operator+=(const Type arg)
01657 {
01658 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01659 std::bind2nd(std::plus<Type>(), arg));
01660 return *this;
01661 }
01662
01663
01664 template <class Type>
01665 Array3D<Type>& Array3D<Type>::
01666 operator-=(const Type arg)
01667 {
01668 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01669 std::bind2nd(std::minus<Type>(), arg));
01670 return *this;
01671 }
01672
01673
01674 template <class Type>
01675 Array3D<Type>& Array3D<Type>::
01676 operator*=(const Type arg)
01677 {
01678 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01679 std::bind2nd(std::multiplies<Type>(), arg));
01680 return *this;
01681 }
01682
01683
01684 template <class Type>
01685 Array3D<Type>& Array3D<Type>::
01686 operator/=(const Type arg)
01687 {
01688 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01689 std::bind2nd(std::divides<Type>(), arg));
01690 return *this;
01691 }
01692
01693
01694 template <class Type>
01695 void Array3D<Type>::
01696 allocate()
01697 {
01698 m_shape1Times2 = m_shape1 * m_shape2;
01699 m_size = m_shape0 * m_shape1 * m_shape2;
01700 if(m_shape0 > 0 && m_shape1 > 0 && m_shape2 > 0) {
01701 m_dataPtr = new(Type[m_size]);
01702 m_refCountPtr = new size_t;
01703 *m_refCountPtr = 1;
01704 m_isAllocated = true;
01705 return;
01706 }
01707 m_dataPtr = 0;
01708 m_refCountPtr = 0;
01709 m_isAllocated = false;
01710 return;
01711 }
01712
01713
01714 template <class Type>
01715 inline void Array3D<Type>::
01716 checkBounds(size_t index) const
01717 {
01718 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01719 if(index >= m_size) {
01720 std::ostringstream message;
01721 message << "Index " << index << " is invalid for a(n) " << m_size
01722 << " element array.";
01723 DLR_THROW(IndexException, "Array3D::checkBounds(size_t)",
01724 message.str().c_str());
01725 }
01726 #endif
01727 }
01728
01729
01730 template <class Type>
01731 inline void Array3D<Type>::
01732 checkBounds(size_t index0, size_t index1, size_t index2) const
01733 {
01734 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01735 if(index0 >= m_shape0) {
01736 std::ostringstream message;
01737 message << "index0 should be less than " << m_shape0
01738 << ", but is actually " << index0 << ".";
01739 DLR_THROW3(IndexException, "Array3D::checkBounds()",
01740 message.str().c_str());
01741 }
01742 if(index1 >= m_shape1) {
01743 std::ostringstream message;
01744 message << "index1 should be less than " << m_shape1
01745 << ", but is actually " << index1 << ".";
01746 DLR_THROW3(IndexException, "Array3D::checkBounds()",
01747 message.str().c_str());
01748 }
01749 if(index2 >= m_shape2) {
01750 std::ostringstream message;
01751 message << "index2 should be less than " << m_shape2
01752 << ", but is actually " << index2 << ".";
01753 DLR_THROW3(IndexException, "Array3D::checkBounds()",
01754 message.str().c_str());
01755 }
01756 #endif
01757 }
01758
01759
01760 template <class Type>
01761 void Array3D<Type>::
01762 deAllocate()
01763 {
01764 if(m_isAllocated == true) {
01765 if(--(*m_refCountPtr) == 0) {
01766 delete[] m_dataPtr;
01767 delete m_refCountPtr;
01768 m_isAllocated = false;
01769 m_dataPtr = 0;
01770 m_refCountPtr = 0;
01771 }
01772 } else {
01773 m_dataPtr = 0;
01774 m_refCountPtr = 0;
01775 }
01776 }
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799 template <class Type>
01800 Array3D<Type> operator+(const Array3D<Type>& array0,
01801 const Array3D<Type>& array1)
01802 {
01803 if((array0.shape0() != array1.shape0())
01804 || (array0.shape1() != array1.shape1())
01805 || (array0.shape2() != array1.shape2())) {
01806 std::ostringstream message;
01807 message << "Array sizes do not match. Array0 is "
01808 << array0.shape0() << " x " << array0.shape1()
01809 << " x " << array0.shape2()
01810 << ", while array1 is "
01811 << array1.shape0() << " x " << array1.shape1()
01812 << " x " << array1.shape2() << ".";
01813 DLR_THROW(ValueException, "Array3D::operator+()", message.str().c_str());
01814 }
01815 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01816 std::transform(array0.begin(), array0.end(), array1.begin(),
01817 result.begin(), std::plus<Type>());
01818 return result;
01819 }
01820
01821
01822 template <class Type>
01823 Array3D<Type> operator-(const Array3D<Type>& array0,
01824 const Array3D<Type>& array1)
01825 {
01826 if((array0.shape0() != array1.shape0())
01827 || (array0.shape1() != array1.shape1())
01828 || (array0.shape2() != array1.shape2())) {
01829 std::ostringstream message;
01830 message << "Array sizes do not match. Array0 is "
01831 << array0.shape0() << " x " << array0.shape1()
01832 << " x " << array0.shape2()
01833 << ", while array1 is "
01834 << array1.shape0() << " x " << array1.shape1()
01835 << " x " << array1.shape2() << ".";
01836 DLR_THROW(ValueException, "Array3D::operator-()", message.str().c_str());
01837 }
01838 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01839 std::transform(array0.begin(), array0.end(), array1.begin(),
01840 result.begin(), std::minus<Type>());
01841 return result;
01842 }
01843
01844
01845 template <class Type>
01846 Array3D<Type> operator*(const Array3D<Type>& array0,
01847 const Array3D<Type>& array1)
01848 {
01849 if((array0.shape0() != array1.shape0())
01850 || (array0.shape1() != array1.shape1())
01851 || (array0.shape2() != array1.shape2())) {
01852 std::ostringstream message;
01853 message << "Array sizes do not match. Array0 is "
01854 << array0.shape0() << " x " << array0.shape1()
01855 << " x " << array0.shape2()
01856 << ", while array1 is "
01857 << array1.shape0() << " x " << array1.shape1()
01858 << " x " << array1.shape2() << ".";
01859 DLR_THROW(ValueException, "Array3D::operator*()", message.str().c_str());
01860 }
01861 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01862 std::transform(array0.begin(), array0.end(), array1.begin(),
01863 result.begin(), std::multiplies<Type>());
01864 return result;
01865 }
01866
01867
01868 template <class Type>
01869 Array3D<Type> operator/(const Array3D<Type>& array0,
01870 const Array3D<Type>& array1)
01871 {
01872 if((array0.shape0() != array1.shape0())
01873 || (array0.shape1() != array1.shape1())
01874 || (array0.shape2() != array1.shape2())) {
01875 std::ostringstream message;
01876 message << "Array sizes do not match. Array0 is "
01877 << array0.shape0() << " x " << array0.shape1()
01878 << " x " << array0.shape2()
01879 << ", while array1 is "
01880 << array1.shape0() << " x " << array1.shape1()
01881 << " x " << array1.shape2() << ".";
01882 DLR_THROW(ValueException, "Array3D::operator/()", message.str().c_str());
01883 }
01884 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01885 std::transform(array0.begin(), array0.end(), array1.begin(), result.begin(),
01886 std::divides<Type>());
01887 return result;
01888 }
01889
01890
01891 template <class Type>
01892 Array3D<Type> operator+(const Array3D<Type>& array0, Type scalar)
01893 {
01894 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01895 std::transform(array0.begin(), array0.end(), result.begin(),
01896 std::bind2nd(std::plus<Type>(), scalar));
01897 return result;
01898 }
01899
01900
01901 template <class Type>
01902 Array3D<Type> operator-(const Array3D<Type>& array0, Type scalar)
01903 {
01904 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01905 std::transform(array0.begin(), array0.end(), result.begin(),
01906 std::bind2nd(std::minus<Type>(), scalar));
01907 return result;
01908 }
01909
01910
01911 template <class Type>
01912 Array3D<Type> operator*(const Array3D<Type>& array0, Type scalar)
01913 {
01914 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01915 std::transform(array0.begin(), array0.end(), result.begin(),
01916 std::bind2nd(std::multiplies<Type>(), scalar));
01917 return result;
01918 }
01919
01920
01921 template <class Type>
01922 Array3D<Type> operator/(const Array3D<Type>& array0, Type scalar)
01923 {
01924 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01925 std::transform(array0.begin(), array0.end(), result.begin(),
01926 std::bind2nd(std::divides<Type>(), scalar));
01927 return result;
01928 }
01929
01930
01931 template <class Type>
01932 inline Array3D<Type> operator+(Type scalar, const Array3D<Type>& array0)
01933 {
01934 return array0 + scalar;
01935 }
01936
01937
01938 template <class Type>
01939 inline Array3D<Type> operator*(Type scalar, const Array3D<Type>& array0)
01940 {
01941 return array0 * scalar;
01942 }
01943
01944
01945
01946 template <class Type>
01947 Array3D<bool>
01948 operator==(const Array3D<Type>& array0, const Type arg)
01949 {
01950 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
01951 std::transform(array0.begin(), array0.end(), result.data(),
01952 std::bind2nd(std::equal_to<Type>(), arg));
01953 return result;
01954 }
01955
01956
01957
01958 template <class Type>
01959 Array3D<bool>
01960 operator==(const Array3D<Type>& array0, const Array3D<Type>& array1)
01961 {
01962 array0.checkDimension(array1.shape0(), array1.shape1(), array1.shape2());
01963 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
01964 std::transform(array0.begin(), array0.end(), array1.begin(),
01965 result.begin(), std::equal_to<Type>());
01966 return result;
01967 }
01968
01969
01970 template <class Type>
01971 Array3D<bool> operator>(const Array3D<Type>& array0, Type arg)
01972 {
01973 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
01974 std::transform(array0.begin(), array0.end(), result.begin(),
01975 std::bind2nd(std::greater<Type>(), arg));
01976 return result;
01977 }
01978
01979
01980 template <class Type>
01981 Array3D<bool> operator<(const Array3D<Type>& array0, Type arg)
01982 {
01983 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
01984 std::transform(array0.begin(), array0.end(), result.begin(),
01985 std::bind2nd(std::less<Type>(), arg));
01986 return result;
01987 }
01988
01989
01990 template <class Type>
01991 Array3D<bool> operator>=(const Array3D<Type>& array0, Type arg)
01992 {
01993 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
01994 std::transform(array0.begin(), array0.end(), result.begin(),
01995 std::bind2nd(std::greater_equal<Type>(), arg));
01996 return result;
01997 }
01998
01999
02000 template <class Type>
02001 Array3D<bool> operator<=(const Array3D<Type>& array0, Type arg)
02002 {
02003 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
02004 std::transform(array0.begin(), array0.end(), result.begin(),
02005 std::bind2nd(std::less_equal<Type>(), arg));
02006 return result;
02007 }
02008
02009
02010
02011
02012 template <class Type>
02013 std::ostream& operator<<(std::ostream& stream, const Array3D<Type>& array0)
02014 {
02015
02016 typedef typename NumericTraits<Type>::TextOutputType OutputType;
02017
02018 size_t index0, index1, index2;
02019 stream << "Array3D([";
02020 for(index0 = 0; index0 < array0.shape0(); ++index0) {
02021 if(index0 != 0) {
02022 stream << " ";
02023 }
02024 stream << "[";
02025 for(index1 = 0; index1 < array0.shape1(); ++index1) {
02026 if(index1 != 0) {
02027 stream << " ";
02028 }
02029 stream << "[";
02030 for(index2 = 0; index2 < array0.shape2(); ++index2) {
02031 stream << static_cast<OutputType>(array0(index0, index1, index2));
02032 if(index2 != array0.shape2() - 1) {
02033 stream << ", ";
02034 }
02035 }
02036 stream << "]";
02037 if(index1 != array0.shape1() - 1) {
02038 stream << ",\n";
02039 }
02040 }
02041 stream << "]";
02042 if(index0 != array0.shape0() - 1) {
02043 stream << ",\n";
02044 }
02045 }
02046 stream << "])\n";
02047 stream.flush();
02048 return stream;
02049 }
02050
02051
02052 template <class Type>
02053 std::istream&
02054 operator>>(std::istream& inputStream, Array3D<Type>& array0)
02055 {
02056 return array0.readFromStream(inputStream);
02057 }
02058
02059 }
02060
02061 }
02062
02063 #endif