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
00340 std::istream&
00341 readFromStream(std::istream& inputStream);
00342
00352 void
00353 reinit(size_t shape0, size_t shape1, size_t shape2);
00354
00366 void
00367 reshape(int shape0, int shape1, int shape2);
00368
00377 Array1D<size_t>
00378 shape() const;
00379
00388 size_t
00389 shape(size_t axis) const;
00390
00397 size_t
00398 shape0() const {return m_shape0;}
00399
00406 size_t
00407 shape1() const {return m_shape1;}
00408
00415 size_t
00416 shape2() const {return m_shape2;}
00417
00424 size_t
00425 size() const {return m_size;}
00426
00435 Array2D<Type>
00436 slice(size_t index);
00437
00446 const Array2D<Type>
00447 slice(size_t index) const;
00448
00456 Array3D<Type>&
00457 operator=(const Array3D<Type>& source);
00458
00465 Array3D<Type>&
00466 operator=(Type value);
00467
00475 Type&
00476 operator()(size_t index) {
00477 checkBounds(index);
00478 return m_dataPtr[index];
00479 }
00480
00488 Type
00489 operator()(size_t index) const {
00490 checkBounds(index);
00491 return m_dataPtr[index];
00492 }
00493
00507 Type&
00508 operator()(size_t index0, size_t index1, size_t index2) {
00509 checkBounds(index0, index1, index2);
00510 return m_dataPtr[index2 + (index1 * m_shape2)
00511 + (index0 * m_shape1Times2)];
00512 }
00513
00527 Type
00528 operator()(size_t index0, size_t index1, size_t index2) const {
00529 checkBounds(index0, index1, index2);
00530 return m_dataPtr[index2 + (index1 * m_shape2)
00531 + (index0 * m_shape1Times2)];
00532 }
00533
00541 Type&
00542 operator[](size_t index) {return this->operator()(index);}
00543
00551 Type
00552 operator[](size_t index) const {return this->operator()(index);}
00553
00562 template <class Type2>
00563 Array3D<Type>&
00564 operator*=(const Array3D<Type2>& arg);
00565
00574 template <class Type2>
00575 Array3D<Type>&
00576 operator/=(const Array3D<Type2>& arg);
00577
00586 template <class Type2>
00587 Array3D<Type>&
00588 operator+=(const Array3D<Type2>& arg);
00589
00598 template <class Type2>
00599 Array3D<Type>&
00600 operator-=(const Array3D<Type2>& arg);
00601
00608 Array3D<Type>&
00609 operator+=(const Type arg);
00610
00617 Array3D<Type>&
00618 operator-=(const Type arg);
00619
00626 Array3D<Type>&
00627 operator*=(const Type arg);
00628
00635 Array3D<Type>&
00636 operator/=(const Type arg);
00637
00638 private:
00639
00640 void allocate();
00641
00642
00643
00644 inline void
00645 checkBounds(size_t index) const;
00646
00647
00648
00649 inline void
00650 checkBounds(size_t index0, size_t index1, size_t index2) const;
00651
00652 void deAllocate();
00653
00654
00655
00656
00657
00662 static const std::string& ioIntro();
00663
00668 static const std::string& ioOutro();
00669
00674 static const char ioOpening = '[';
00675
00680 static const char ioClosing = ']';
00681
00686 static const char ioSeparator = ',';
00687
00688
00689 size_t m_shape0;
00690 size_t m_shape1;
00691 size_t m_shape2;
00692 size_t m_shape1Times2;
00693 size_t m_size;
00694 Type* m_dataPtr;
00695 size_t* m_refCountPtr;
00696 bool m_isAllocated;
00697
00698 };
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00759 template <class Type>
00760 Array3D<Type>
00761 operator+(const Array3D<Type>& array0, const Array3D<Type>& array1);
00762
00763
00777 template <class Type>
00778 Array3D<Type>
00779 operator-(const Array3D<Type>& array0, const Array3D<Type>& array1);
00780
00781
00795 template <class Type>
00796 Array3D<Type>
00797 operator*(const Array3D<Type>& array0, const Array3D<Type>& array1);
00798
00799
00813 template <class Type>
00814 Array3D<Type>
00815 operator/(const Array3D<Type>& array0, const Array3D<Type>& array1);
00816
00817
00829 template <class Type>
00830 Array3D<Type>
00831 operator+(const Array3D<Type>& array0, Type scalar);
00832
00833
00845 template <class Type>
00846 Array3D<Type>
00847 operator-(const Array3D<Type>& array0, Type scalar);
00848
00849
00861 template <class Type>
00862 Array3D<Type>
00863 operator*(const Array3D<Type>& array0, Type scalar);
00864
00865
00877 template <class Type>
00878 Array3D<Type>
00879 operator/(const Array3D<Type>& array0, Type scalar);
00880
00881
00893 template <class Type>
00894 inline Array3D<Type>
00895 operator+(Type scalar, const Array3D<Type>& array0);
00896
00897
00909 template <class Type>
00910 inline Array3D<Type>
00911 operator*(Type scalar, const Array3D<Type>& array0);
00912
00913
00925 template <class Type>
00926 Array3D<bool>
00927 operator==(const Array3D<Type>& array0, const Type arg);
00928
00929
00942 template <class Type>
00943 Array3D<bool>
00944 operator==(const Array3D<Type>& array0, const Array3D<Type>& array1);
00945
00946
00957 template <class Type>
00958 Array3D<bool>
00959 operator<(const Array3D<Type>& array0, Type arg);
00960
00961
00972 template <class Type>
00973 Array3D<bool>
00974 operator<=(const Array3D<Type>& array0, Type arg);
00975
00976
00987 template <class Type>
00988 Array3D<bool>
00989 operator>(const Array3D<Type>& array0, Type arg);
00990
00991
01002 template <class Type>
01003 Array3D<bool>
01004 operator>=(const Array3D<Type>& array0, Type arg);
01005
01006
01027 template <class Type>
01028 std::ostream& operator<<(std::ostream& stream, const Array3D<Type>& array0);
01029
01030
01042 template <class Type>
01043 std::istream&
01044 operator>>(std::istream& stream, Array3D<Type>& array0);
01045
01046 }
01047
01048 }
01049
01050
01051
01052
01053 namespace dlr {
01054
01055 using numeric::Array3D;
01056
01057 }
01058
01059
01060
01061
01062
01063
01064
01065 #include <algorithm>
01066 #include <sstream>
01067 #include <numeric>
01068 #include <functional>
01069 #include <dlrNumeric/numericTraits.h>
01070
01071 namespace dlr {
01072
01073 namespace numeric {
01074
01075
01076
01077 template <class Type>
01078 const std::string&
01079 Array3D<Type>::
01080 ioIntro()
01081 {
01082 static const std::string intro = "Array3D(";
01083 return intro;
01084 }
01085
01086
01087
01088
01089 template <class Type>
01090 const std::string&
01091 Array3D<Type>::
01092 ioOutro()
01093 {
01094 static const std::string outro = ")";
01095 return outro;
01096 }
01097
01098
01099
01100 template <class Type>
01101 Array3D<Type>::
01102 Array3D()
01103 : m_shape0(0),
01104 m_shape1(0),
01105 m_shape2(0),
01106 m_shape1Times2(0),
01107 m_size(0),
01108 m_dataPtr(0),
01109 m_refCountPtr(0),
01110 m_isAllocated(false)
01111 {
01112
01113 }
01114
01115
01116 template <class Type>
01117 Array3D<Type>::
01118 Array3D(size_t shape0, size_t shape1, size_t shape2)
01119 : m_shape0(shape0),
01120 m_shape1(shape1),
01121 m_shape2(shape2),
01122 m_shape1Times2(0),
01123 m_size(0),
01124 m_dataPtr(0),
01125 m_refCountPtr(0),
01126 m_isAllocated(false)
01127 {
01128 this->allocate();
01129 }
01130
01131
01132
01133 template <class Type>
01134 Array3D<Type>::
01135 Array3D(const std::string& inputString)
01136 : m_shape0(0),
01137 m_shape1(0),
01138 m_shape2(0),
01139 m_shape1Times2(0),
01140 m_size(0),
01141 m_dataPtr(0),
01142 m_refCountPtr(0),
01143 m_isAllocated(false)
01144 {
01145
01146 std::istringstream inputStream(inputString);
01147
01148
01149 Array3D<Type> inputArray;
01150 inputStream >> inputArray;
01151 if(!inputStream) {
01152 std::ostringstream message;
01153 message << "Couldn't parse input string: \"" << inputString << "\".";
01154 DLR_THROW3(ValueException, "Array3D::Array3D(const std::string&)",
01155 message.str().c_str());
01156 }
01157
01158
01159 *this = inputArray;
01160 }
01161
01162
01163
01164
01165
01166
01167 template <class Type>
01168 Array3D<Type>::
01169 Array3D(const Array3D<Type>& source)
01170 : m_shape0(source.m_shape0),
01171 m_shape1(source.m_shape1),
01172 m_shape2(source.m_shape2),
01173 m_shape1Times2(source.m_shape1 * source.m_shape2),
01174 m_size(source.m_size),
01175 m_dataPtr(source.m_dataPtr),
01176 m_refCountPtr(source.m_refCountPtr),
01177 m_isAllocated(source.m_isAllocated)
01178 {
01179 if(m_isAllocated) {
01180 ++(*m_refCountPtr);
01181 }
01182 }
01183
01184
01185
01186
01187 template <class Type>
01188 Array3D<Type>::
01189 Array3D(size_t shape0, size_t shape1, size_t shape2, Type* const dataPtr)
01190 : m_shape0(shape0),
01191 m_shape1(shape1),
01192 m_shape2(shape2),
01193 m_shape1Times2(shape1 * shape2),
01194 m_size(shape0 * shape1 * shape2),
01195 m_dataPtr(dataPtr),
01196 m_refCountPtr(0),
01197 m_isAllocated(false)
01198 {
01199
01200 }
01201
01202
01203 template <class Type>
01204 Array3D<Type>::
01205 ~Array3D()
01206 {
01207 deAllocate();
01208 }
01209
01210
01211 template <class Type>
01212 inline void Array3D<Type>::
01213 checkDimension(size_t shape0, size_t shape1, size_t shape2) const
01214 {
01215 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01216 if(shape0 != this->shape0()
01217 || shape1 != this->shape1()
01218 || shape2 != this->shape2()){
01219 std::ostringstream message;
01220 message << "Size mismatch: required dimension is ("
01221 << shape0 << ", " << shape1 << ", " << shape2 << ") "
01222 << " while *this has dimension "
01223 << this->shape0() << ", " << this->shape1() << ", "
01224 << this->shape2() << ") ";
01225 DLR_THROW(IndexException, "Array3D::checkDimension()",
01226 message.str().c_str());
01227 }
01228 #endif
01229 }
01230
01231
01232 template <class Type>
01233 Array3D<Type> Array3D<Type>::
01234 copy() const
01235 {
01236 Array3D<Type> newArray(m_shape0, m_shape1, m_shape2);
01237 newArray.copy(*this);
01238 return newArray;
01239 }
01240
01241
01242 template <class Type> template <class Type2>
01243 void Array3D<Type>::
01244 copy(const Array3D<Type2>& source)
01245 {
01246 if(source.size() != m_size) {
01247 std::ostringstream message;
01248 message << "Mismatched array sizes. Source array has "
01249 << source.size() << " elements, while destination array has "
01250 << m_size << " elements.";
01251 DLR_THROW3(ValueException, "Array3D::copy(const Array3D&)",
01252 message.str().c_str());
01253 }
01254 if(m_size != 0) {
01255 this->copy(source.data());
01256 }
01257 }
01258
01259
01260 template <class Type> template <class Type2>
01261 void Array3D<Type>::
01262 copy(const Type2* dataPtr)
01263 {
01264 if (dataPtr == 0) {
01265 DLR_THROW(ValueException, "Array3D::copy(const Type2*)",
01266 "Argument is a NULL pointer.");
01267 }
01268 std::copy(dataPtr, dataPtr + m_size, m_dataPtr);
01269 }
01270
01271
01272
01273
01274 template <class Type>
01275 std::istream&
01276 Array3D<Type>::
01277 readFromStream(std::istream& inputStream)
01278 {
01279
01280 typedef typename NumericTraits<Type>::TextOutputType InputType;
01281
01282
01283 if (!inputStream){
01284 return inputStream;
01285 }
01286
01287
01288
01289
01290 std::ios_base::iostate oldExceptionState = inputStream.exceptions();
01291 inputStream.exceptions(
01292 std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit);
01293
01294
01295 try{
01296
01297
01298 InputStream stream(inputStream);
01299
01300
01301
01302 bool foundIntro = false;
01303 if(stream.peek() == ioIntro()[0]) {
01304 foundIntro = true;
01305 stream.expect(ioIntro());
01306 }
01307
01308
01309
01310
01311 stream.expect(ioOpening);
01312
01313
01314
01315 Array2D<Type> inputValue;
01316 std::vector< Array2D<Type> > inputBuffer;
01317 while(1) {
01318
01319 stream >> inputValue;
01320 inputBuffer.push_back(inputValue);
01321
01322
01323 char inChar = 0;
01324 stream >> inChar;
01325 if(inChar == ioClosing) {
01326
01327 break;
01328 }
01329 if(inChar != ioSeparator) {
01330
01331 stream.clear(std::ios_base::failbit);
01332 }
01333 }
01334
01335
01336 if(foundIntro) {
01337 stream.expect(ioOutro());
01338 }
01339
01340
01341
01342 size_t shape0 = inputBuffer.size();
01343 size_t shape1 = ((shape0 != 0) ? inputBuffer[0].rows() : 0);
01344 size_t shape2 = ((shape0 != 0) ? inputBuffer[0].columns() : 0);
01345 for(size_t index = 1; index < shape0; ++index) {
01346 if((inputBuffer[index].rows() != shape1)
01347 || (inputBuffer[index].columns() != shape2)) {
01348
01349 stream.clear(std::ios_base::failbit);
01350 }
01351 }
01352
01353
01354 size_t sliceSize = shape1 * shape2;
01355 this->reinit(shape0, shape1, shape2);
01356 for(size_t index = 0; index < shape0; ++index) {
01357 std::copy(inputBuffer[index].begin(), inputBuffer[index].end(),
01358 this->begin() + (index * sliceSize));
01359 }
01360 } catch(std::ios_base::failure) {
01361
01362 }
01363 inputStream.exceptions(oldExceptionState);
01364 return inputStream;
01365 }
01366
01367
01368 template <class Type>
01369 void Array3D<Type>::
01370 reinit(size_t shape0, size_t shape1, size_t shape2)
01371 {
01372 this->deAllocate();
01373 this->m_shape0 = shape0;
01374 this->m_shape1 = shape1;
01375 this->m_shape2 = shape2;
01376 this->allocate();
01377 }
01378
01379
01380 template <class Type>
01381 void Array3D<Type>::
01382 reshape(int shape0, int shape1, int shape2)
01383 {
01384 if ((shape0 * shape1 * shape2 != 0)){
01385
01386
01387 if((shape0 == -1) && (shape1 != -1) && (shape2 != -1)) {
01388 shape0 = static_cast<int>(this->size()) / (shape1 * shape2);
01389 } else if((shape1 == -1) && (shape0 != -1) && (shape2 != -1)) {
01390 shape1 = static_cast<int>(this->size()) / (shape0 * shape2);
01391 } else if((shape2 == -1) && (shape1 != -1) && (shape0 != -1)) {
01392 shape2 = static_cast<int>(this->size()) / (shape1 * shape0);
01393 }
01394 }
01395 if((shape0 * shape1 * shape2) != static_cast<int>(this->size())) {
01396 std::ostringstream message;
01397 message << "Can't reshape a(n) " << this->size()
01398 << " element array to be " << shape0 << " x " << shape1
01399 << " x " << shape2 << ".";
01400 DLR_THROW(ValueException, "Array3D::reshape()", message.str().c_str());
01401 }
01402
01403 m_shape0 = static_cast<size_t>(shape0);
01404 m_shape1 = static_cast<size_t>(shape1);
01405 m_shape2 = static_cast<size_t>(shape2);
01406 m_shape1Times2 = shape1 * shape2;
01407 }
01408
01409
01410 template <class Type>
01411 Array1D<size_t> Array3D<Type>::
01412 shape() const
01413 {
01414 Array1D<size_t> rc(3);
01415 rc(0) = this->shape0();
01416 rc(1) = this->shape1();
01417 rc(2) = this->shape2();
01418 return rc;
01419 }
01420
01421
01422 template <class Type>
01423 size_t Array3D<Type>::
01424 shape(size_t axis) const
01425 {
01426 switch(axis) {
01427 case 0:
01428 return this->shape0();
01429 break;
01430 case 1:
01431 return this->shape1();
01432 break;
01433 case 2:
01434 return this->shape2();
01435 break;
01436 default:
01437 std::ostringstream message;
01438 message << "Invalid Axis: "<< axis << ".";
01439 DLR_THROW(ValueException, "Array3D::shape(size_t)",
01440 message.str().c_str());
01441 break;
01442 }
01443 return 0;
01444 }
01445
01446
01447 template <class Type>
01448 Array2D<Type>
01449 Array3D<Type>::
01450 slice(size_t index0)
01451 {
01452 this->checkBounds(index0, 0, 0);
01453 return Array2D<Type>(
01454 m_shape1, m_shape2, m_dataPtr + (index0 * m_shape1Times2));
01455 }
01456
01457
01458 template <class Type>
01459 const Array2D<Type>
01460 Array3D<Type>::
01461 slice(size_t index0) const
01462 {
01463 this->checkBounds(index0, 0, 0);
01464 return Array2D<Type>(
01465 m_shape1, m_shape2, m_dataPtr + (index0 * m_shape1Times2));
01466 }
01467
01468
01469 template <class Type>
01470 Array3D<Type>& Array3D<Type>::
01471 operator=(const Array3D<Type>& source)
01472 {
01473
01474 if(&source != this) {
01475 this->deAllocate();
01476 m_shape0 = source.m_shape0;
01477 m_shape1 = source.m_shape1;
01478 m_shape2 = source.m_shape2;
01479 m_shape1Times2 = source.m_shape1Times2;
01480 m_size = source.m_size;
01481 m_dataPtr = source.m_dataPtr;
01482 m_refCountPtr = source.m_refCountPtr;
01483 m_isAllocated = source.m_isAllocated;
01484 if(m_isAllocated) {
01485 ++(*m_refCountPtr);
01486 }
01487 }
01488 return *this;
01489 }
01490
01491
01492 template <class Type>
01493 Array3D<Type>& Array3D<Type>::
01494 operator=(Type value)
01495 {
01496 std::fill(m_dataPtr, m_dataPtr + m_size, value);
01497 return *this;
01498 }
01499
01500
01501 template <class Type> template <class Type2>
01502 Array3D<Type>& Array3D<Type>::
01503 operator*=(const Array3D<Type2>& arg)
01504 {
01505 if(m_size != arg.size()) {
01506 std::ostringstream message;
01507 message << "Mismatched array sizes. Argument array has "
01508 << arg.size() << " elements, while destination array has "
01509 << m_size << " elements.";
01510 DLR_THROW(ValueException, "Array3D::operator*=()",
01511 message.str().c_str());
01512 }
01513 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01514 std::multiplies<Type>());
01515 return *this;
01516 }
01517
01518
01519 template <class Type> template <class Type2>
01520 Array3D<Type>& Array3D<Type>::
01521 operator/=(const Array3D<Type2>& arg)
01522 {
01523 if(m_size != arg.size()) {
01524 std::ostringstream message;
01525 message << "Mismatched array sizes. Argument array has "
01526 << arg.size() << " elements, while destination array has "
01527 << m_size << " elements.";
01528 DLR_THROW(ValueException, "Array3D::operator/=()",
01529 message.str().c_str());
01530 }
01531 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01532 std::divides<Type>());
01533 return *this;
01534 }
01535
01536
01537 template <class Type> template <class Type2>
01538 Array3D<Type>& Array3D<Type>::
01539 operator+=(const Array3D<Type2>& arg)
01540 {
01541 if(m_size != arg.size()) {
01542 std::ostringstream message;
01543 message << "Mismatched array sizes. Argument array has "
01544 << arg.size() << " elements, while destination array has "
01545 << m_size << " elements.";
01546 DLR_THROW(ValueException, "Array3D::operator+=()",
01547 message.str().c_str());
01548 }
01549 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01550 std::plus<Type>());
01551 return *this;
01552 }
01553
01554
01555 template <class Type> template <class Type2>
01556 Array3D<Type>& Array3D<Type>::
01557 operator-=(const Array3D<Type2>& arg)
01558 {
01559 if(m_size != arg.size()) {
01560 std::ostringstream message;
01561 message << "Mismatched array sizes. Argument array has "
01562 << arg.size() << " elements, while destination array has "
01563 << m_size << " elements.";
01564 DLR_THROW(ValueException, "Array3D::operator-=()",
01565 message.str().c_str());
01566 }
01567 std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01568 std::minus<Type>());
01569 return *this;
01570 }
01571
01572
01573 template <class Type>
01574 Array3D<Type>& Array3D<Type>::
01575 operator+=(const Type arg)
01576 {
01577 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01578 std::bind2nd(std::plus<Type>(), arg));
01579 return *this;
01580 }
01581
01582
01583 template <class Type>
01584 Array3D<Type>& Array3D<Type>::
01585 operator-=(const Type arg)
01586 {
01587 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01588 std::bind2nd(std::minus<Type>(), arg));
01589 return *this;
01590 }
01591
01592
01593 template <class Type>
01594 Array3D<Type>& Array3D<Type>::
01595 operator*=(const Type arg)
01596 {
01597 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01598 std::bind2nd(std::multiplies<Type>(), arg));
01599 return *this;
01600 }
01601
01602
01603 template <class Type>
01604 Array3D<Type>& Array3D<Type>::
01605 operator/=(const Type arg)
01606 {
01607 std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01608 std::bind2nd(std::divides<Type>(), arg));
01609 return *this;
01610 }
01611
01612
01613 template <class Type>
01614 void Array3D<Type>::
01615 allocate()
01616 {
01617 m_shape1Times2 = m_shape1 * m_shape2;
01618 m_size = m_shape0 * m_shape1 * m_shape2;
01619 if(m_shape0 > 0 && m_shape1 > 0 && m_shape2 > 0) {
01620 m_dataPtr = new(Type[m_size]);
01621 m_refCountPtr = new size_t;
01622 *m_refCountPtr = 1;
01623 m_isAllocated = true;
01624 return;
01625 }
01626 m_dataPtr = 0;
01627 m_refCountPtr = 0;
01628 m_isAllocated = false;
01629 return;
01630 }
01631
01632
01633 template <class Type>
01634 inline void Array3D<Type>::
01635 checkBounds(size_t index) const
01636 {
01637 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01638 if(index >= m_size) {
01639 std::ostringstream message;
01640 message << "Index " << index << " is invalid for a(n) " << m_size
01641 << " element array.";
01642 DLR_THROW(IndexException, "Array3D::checkBounds(size_t)",
01643 message.str().c_str());
01644 }
01645 #endif
01646 }
01647
01648
01649 template <class Type>
01650 inline void Array3D<Type>::
01651 checkBounds(size_t index0, size_t index1, size_t index2) const
01652 {
01653 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01654 if(index0 >= m_shape0) {
01655 std::ostringstream message;
01656 message << "index0 should be less than " << m_shape0
01657 << ", but is actually " << index0 << ".";
01658 DLR_THROW3(IndexException, "Array3D::checkBounds()",
01659 message.str().c_str());
01660 }
01661 if(index1 >= m_shape1) {
01662 std::ostringstream message;
01663 message << "index1 should be less than " << m_shape1
01664 << ", but is actually " << index1 << ".";
01665 DLR_THROW3(IndexException, "Array3D::checkBounds()",
01666 message.str().c_str());
01667 }
01668 if(index2 >= m_shape2) {
01669 std::ostringstream message;
01670 message << "index2 should be less than " << m_shape2
01671 << ", but is actually " << index2 << ".";
01672 DLR_THROW3(IndexException, "Array3D::checkBounds()",
01673 message.str().c_str());
01674 }
01675 #endif
01676 }
01677
01678
01679 template <class Type>
01680 void Array3D<Type>::
01681 deAllocate()
01682 {
01683 if(m_isAllocated == true) {
01684 if(--(*m_refCountPtr) == 0) {
01685 delete[] m_dataPtr;
01686 delete m_refCountPtr;
01687 m_isAllocated = false;
01688 m_dataPtr = 0;
01689 m_refCountPtr = 0;
01690 }
01691 } else {
01692 m_dataPtr = 0;
01693 m_refCountPtr = 0;
01694 }
01695 }
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718 template <class Type>
01719 Array3D<Type> operator+(const Array3D<Type>& array0,
01720 const Array3D<Type>& array1)
01721 {
01722 if((array0.shape0() != array1.shape0())
01723 || (array0.shape1() != array1.shape1())
01724 || (array0.shape2() != array1.shape2())) {
01725 std::ostringstream message;
01726 message << "Array sizes do not match. Array0 is "
01727 << array0.shape0() << " x " << array0.shape1()
01728 << " x " << array0.shape2()
01729 << ", while array1 is "
01730 << array1.shape0() << " x " << array1.shape1()
01731 << " x " << array1.shape2() << ".";
01732 DLR_THROW(ValueException, "Array3D::operator+()", message.str().c_str());
01733 }
01734 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01735 std::transform(array0.begin(), array0.end(), array1.begin(),
01736 result.begin(), std::plus<Type>());
01737 return result;
01738 }
01739
01740
01741 template <class Type>
01742 Array3D<Type> operator-(const Array3D<Type>& array0,
01743 const Array3D<Type>& array1)
01744 {
01745 if((array0.shape0() != array1.shape0())
01746 || (array0.shape1() != array1.shape1())
01747 || (array0.shape2() != array1.shape2())) {
01748 std::ostringstream message;
01749 message << "Array sizes do not match. Array0 is "
01750 << array0.shape0() << " x " << array0.shape1()
01751 << " x " << array0.shape2()
01752 << ", while array1 is "
01753 << array1.shape0() << " x " << array1.shape1()
01754 << " x " << array1.shape2() << ".";
01755 DLR_THROW(ValueException, "Array3D::operator-()", message.str().c_str());
01756 }
01757 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01758 std::transform(array0.begin(), array0.end(), array1.begin(),
01759 result.begin(), std::minus<Type>());
01760 return result;
01761 }
01762
01763
01764 template <class Type>
01765 Array3D<Type> operator*(const Array3D<Type>& array0,
01766 const Array3D<Type>& array1)
01767 {
01768 if((array0.shape0() != array1.shape0())
01769 || (array0.shape1() != array1.shape1())
01770 || (array0.shape2() != array1.shape2())) {
01771 std::ostringstream message;
01772 message << "Array sizes do not match. Array0 is "
01773 << array0.shape0() << " x " << array0.shape1()
01774 << " x " << array0.shape2()
01775 << ", while array1 is "
01776 << array1.shape0() << " x " << array1.shape1()
01777 << " x " << array1.shape2() << ".";
01778 DLR_THROW(ValueException, "Array3D::operator*()", message.str().c_str());
01779 }
01780 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01781 std::transform(array0.begin(), array0.end(), array1.begin(),
01782 result.begin(), std::multiplies<Type>());
01783 return result;
01784 }
01785
01786
01787 template <class Type>
01788 Array3D<Type> operator/(const Array3D<Type>& array0,
01789 const Array3D<Type>& array1)
01790 {
01791 if((array0.shape0() != array1.shape0())
01792 || (array0.shape1() != array1.shape1())
01793 || (array0.shape2() != array1.shape2())) {
01794 std::ostringstream message;
01795 message << "Array sizes do not match. Array0 is "
01796 << array0.shape0() << " x " << array0.shape1()
01797 << " x " << array0.shape2()
01798 << ", while array1 is "
01799 << array1.shape0() << " x " << array1.shape1()
01800 << " x " << array1.shape2() << ".";
01801 DLR_THROW(ValueException, "Array3D::operator/()", message.str().c_str());
01802 }
01803 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01804 std::transform(array0.begin(), array0.end(), array1.begin(), result.begin(),
01805 std::divides<Type>());
01806 return result;
01807 }
01808
01809
01810 template <class Type>
01811 Array3D<Type> operator+(const Array3D<Type>& array0, Type scalar)
01812 {
01813 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01814 std::transform(array0.begin(), array0.end(), result.begin(),
01815 std::bind2nd(std::plus<Type>(), scalar));
01816 return result;
01817 }
01818
01819
01820 template <class Type>
01821 Array3D<Type> operator-(const Array3D<Type>& array0, Type scalar)
01822 {
01823 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01824 std::transform(array0.begin(), array0.end(), result.begin(),
01825 std::bind2nd(std::minus<Type>(), scalar));
01826 return result;
01827 }
01828
01829
01830 template <class Type>
01831 Array3D<Type> operator*(const Array3D<Type>& array0, Type scalar)
01832 {
01833 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01834 std::transform(array0.begin(), array0.end(), result.begin(),
01835 std::bind2nd(std::multiplies<Type>(), scalar));
01836 return result;
01837 }
01838
01839
01840 template <class Type>
01841 Array3D<Type> operator/(const Array3D<Type>& array0, Type scalar)
01842 {
01843 Array3D<Type> result(array0.shape0(), array0.shape1(), array0.shape2());
01844 std::transform(array0.begin(), array0.end(), result.begin(),
01845 std::bind2nd(std::divides<Type>(), scalar));
01846 return result;
01847 }
01848
01849
01850 template <class Type>
01851 inline Array3D<Type> operator+(Type scalar, const Array3D<Type>& array0)
01852 {
01853 return array0 + scalar;
01854 }
01855
01856
01857 template <class Type>
01858 inline Array3D<Type> operator*(Type scalar, const Array3D<Type>& array0)
01859 {
01860 return array0 * scalar;
01861 }
01862
01863
01864
01865 template <class Type>
01866 Array3D<bool>
01867 operator==(const Array3D<Type>& array0, const Type arg)
01868 {
01869 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
01870 std::transform(array0.begin(), array0.end(), result.data(),
01871 std::bind2nd(std::equal_to<Type>(), arg));
01872 return result;
01873 }
01874
01875
01876
01877 template <class Type>
01878 Array3D<bool>
01879 operator==(const Array3D<Type>& array0, const Array3D<Type>& array1)
01880 {
01881 array0.checkDimension(array1.shape0(), array1.shape1(), array1.shape2());
01882 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
01883 std::transform(array0.begin(), array0.end(), array1.begin(),
01884 result.begin(), std::equal_to<Type>());
01885 return result;
01886 }
01887
01888
01889 template <class Type>
01890 Array3D<bool> operator>(const Array3D<Type>& array0, Type arg)
01891 {
01892 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
01893 std::transform(array0.begin(), array0.end(), result.begin(),
01894 std::bind2nd(std::greater<Type>(), arg));
01895 return result;
01896 }
01897
01898
01899 template <class Type>
01900 Array3D<bool> operator<(const Array3D<Type>& array0, Type arg)
01901 {
01902 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
01903 std::transform(array0.begin(), array0.end(), result.begin(),
01904 std::bind2nd(std::less<Type>(), arg));
01905 return result;
01906 }
01907
01908
01909 template <class Type>
01910 Array3D<bool> operator>=(const Array3D<Type>& array0, Type arg)
01911 {
01912 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
01913 std::transform(array0.begin(), array0.end(), result.begin(),
01914 std::bind2nd(std::greater_equal<Type>(), arg));
01915 return result;
01916 }
01917
01918
01919 template <class Type>
01920 Array3D<bool> operator<=(const Array3D<Type>& array0, Type arg)
01921 {
01922 Array3D<bool> result(array0.shape0(), array0.shape1(), array0.shape2());
01923 std::transform(array0.begin(), array0.end(), result.begin(),
01924 std::bind2nd(std::less_equal<Type>(), arg));
01925 return result;
01926 }
01927
01928
01929
01930
01931 template <class Type>
01932 std::ostream& operator<<(std::ostream& stream, const Array3D<Type>& array0)
01933 {
01934
01935 typedef typename NumericTraits<Type>::TextOutputType OutputType;
01936
01937 size_t index0, index1, index2;
01938 stream << "Array3D([";
01939 for(index0 = 0; index0 < array0.shape0(); ++index0) {
01940 if(index0 != 0) {
01941 stream << " ";
01942 }
01943 stream << "[";
01944 for(index1 = 0; index1 < array0.shape1(); ++index1) {
01945 if(index1 != 0) {
01946 stream << " ";
01947 }
01948 stream << "[";
01949 for(index2 = 0; index2 < array0.shape2(); ++index2) {
01950 stream << static_cast<OutputType>(array0(index0, index1, index2));
01951 if(index2 != array0.shape2() - 1) {
01952 stream << ", ";
01953 }
01954 }
01955 stream << "]";
01956 if(index1 != array0.shape1() - 1) {
01957 stream << ",\n";
01958 }
01959 }
01960 stream << "]";
01961 if(index0 != array0.shape0() - 1) {
01962 stream << ",\n";
01963 }
01964 }
01965 stream << "])\n";
01966 stream.flush();
01967 return stream;
01968 }
01969
01970
01971 template <class Type>
01972 std::istream&
01973 operator>>(std::istream& inputStream, Array3D<Type>& array0)
01974 {
01975 return array0.readFromStream(inputStream);
01976 }
01977
01978 }
01979
01980 }
01981
01982 #endif // #ifdef _DLR_ARRAY3D_H_