00001
00012 #ifndef DLRNUMERIC_ARRAYND_H
00013 #define DLRNUMERIC_ARRAYND_H
00014
00015 #include <iostream>
00016 #include <string>
00017 #include <dlrCommon/exception.h>
00018 #include <dlrNumeric/array1D.h>
00019
00020 namespace dlr {
00021
00022
00023 namespace numeric {
00024
00072 template <size_t Dimension, class Type>
00073 class ArrayND {
00074 public:
00075
00076
00080 typedef Type value_type;
00081
00085 typedef Type* iterator;
00086
00091 typedef const Type* const_iterator;
00092
00093
00094
00095
00099 ArrayND();
00100
00101
00128 explicit
00129 ArrayND(size_t dimension, size_t const shape[]);
00130
00131
00151 explicit
00152 ArrayND(const Array1D<size_t>& shape);
00153
00154
00161 ArrayND(const ArrayND<Dimension, Type> &source);
00162
00163
00173 explicit
00174 ArrayND(const std::string& inputString);
00175
00176
00181 ~ArrayND();
00182
00183
00189 iterator
00190 begin() {return m_storage.begin();}
00191
00192
00199 const_iterator
00200 begin() const {return m_storage.begin();}
00201
00202
00209 inline void
00210 checkDimension(Array1D<size_t> const& shape) const;
00211
00212
00217 void
00218 clear() {m_shape.reinit(0); m_storage.reinit(0);}
00219
00220
00226 ArrayND<Dimension, Type>
00227 copy() const;
00228
00229
00240 template <class Type2> void
00241 copy(const ArrayND<Dimension, Type2>& source);
00242
00243
00250 template <class Type2> void
00251 copy(const Type2* dataPtr);
00252
00253
00265 Type*
00266 data() {return m_storage.data();}
00267
00268
00277 const Type*
00278 data() const {return m_storage.data();}
00279
00280
00288 bool
00289 empty() const {return m_storage.empty();}
00290
00291
00298 iterator
00299 end() {return m_storage.end();}
00300
00301
00308 const_iterator
00309 end() const {return m_storage.end();}
00310
00311
00322 size_t
00323 flattenIndex(const Array1D<size_t>& indexArray) const;
00324
00325
00335 inline Type
00336 getElement(size_t index0) const {return this->operator()(index0);}
00337
00338
00348 inline Type
00349 getElement(Array1D<size_t> const& index0) const {
00350 return this->operator()(index0);
00351 }
00352
00353
00365 inline const Array1D<size_t>&
00366 getShape() const {return m_shape;}
00367
00368
00383 size_t
00384 getStride(size_t axis) const {return m_strideArray[axis];}
00385
00386
00400 Array1D<size_t> const&
00401 getStrideArray() const {return m_strideArray;}
00402
00403
00412 bool
00413 isAllocated() const {return true;}
00414
00415
00423 Array1D<Type>
00424 ravel() {return m_storage;}
00425
00426
00434 Array1D<Type> const
00435 ravel() const {return m_storage;}
00436
00437
00444 void
00445 reinit(Array1D<size_t> const& shape);
00446
00447
00461 Type&
00462 setElement(size_t index0, const Type& value) {
00463 return this->operator()(index0) = value;
00464 }
00465
00466
00480 Type&
00481 setElement(Array1D<size_t> const& index0, const Type& value) {
00482 return this->operator()(this->flattenIndex(index0)) = value;
00483 }
00484
00485
00491 size_t
00492 size() const {return m_storage.size();}
00493
00494
00503 ArrayND<Dimension, Type>&
00504 operator=(const ArrayND<Dimension, Type>& source);
00505
00506
00514 inline ArrayND<Dimension, Type>&
00515 operator=(Type value);
00516
00517
00525 Type&
00526 operator()(size_t index0) {return m_storage(index0);}
00527
00528
00536 Type operator()(size_t index0) const {return m_storage(index0);}
00537
00538
00546 Type&
00547 operator()(Array1D<size_t> const& index0) {
00548 return m_storage[this->flattenIndex(index0)];
00549 }
00550
00551
00559 Type operator()(Array1D<size_t> const& index0) const {
00560 return m_storage[this->flattenIndex(index0)];
00561 }
00562
00563
00572 Type& operator[](size_t index) {return this->operator()(index);}
00573
00574
00583 Type operator[](size_t index) const {return this->operator()(index);}
00584
00585
00597 template <class Type2>
00598 ArrayND<Dimension, Type>&
00599 operator+=(const ArrayND<Dimension, Type2>& arg);
00600
00601
00609 ArrayND<Dimension, Type>&
00610 operator+=(const Type arg);
00611
00612
00624 template <class Type2>
00625 ArrayND<Dimension, Type>&
00626 operator-=(const ArrayND<Dimension, Type2>& arg);
00627
00628
00636 ArrayND<Dimension, Type>&
00637 operator-=(const Type arg);
00638
00639
00651 template <class Type2>
00652 ArrayND<Dimension, Type>&
00653 operator*=(const ArrayND<Dimension, Type2>& arg);
00654
00655
00663 ArrayND<Dimension, Type>&
00664 operator*=(const Type arg);
00665
00666
00678 template <class Type2>
00679 ArrayND<Dimension, Type>&
00680 operator/=(const ArrayND<Dimension, Type2>& arg);
00681
00682
00690 ArrayND<Dimension, Type>&
00691 operator/=(const Type arg);
00692
00693 private:
00694
00695
00696 size_t computeSize(Array1D<size_t> const& shape) const;
00697 Array1D<size_t> computeStride(Array1D<size_t> const& shape) const;
00698
00699
00700
00701 Array1D<size_t> m_shape;
00702 Array1D<Type> m_storage;
00703 Array1D<size_t> m_strideArray;
00704 };
00705
00706
00707
00708
00722 template <size_t Dimension, class Type>
00723 ArrayND<Dimension, Type>
00724 operator+(const ArrayND<Dimension, Type>& array0,
00725 const ArrayND<Dimension, Type>& arrayN);
00726
00727
00741 template <size_t Dimension, class Type>
00742 ArrayND<Dimension, Type>
00743 operator-(const ArrayND<Dimension, Type>& array0,
00744 const ArrayND<Dimension, Type>& arrayN);
00745
00746
00760 template <size_t Dimension, class Type>
00761 ArrayND<Dimension, Type>
00762 operator*(const ArrayND<Dimension, Type>& array0,
00763 const ArrayND<Dimension, Type>& arrayN);
00764
00765
00779 template <size_t Dimension, class Type>
00780 ArrayND<Dimension, Type>
00781 operator/(const ArrayND<Dimension, Type>& array0,
00782 const ArrayND<Dimension, Type>& arrayN);
00783
00784
00796 template <size_t Dimension, class Type>
00797 ArrayND<Dimension, Type>
00798 operator+(const ArrayND<Dimension, Type>& array, Type scalar);
00799
00800
00812 template <size_t Dimension, class Type>
00813 ArrayND<Dimension, Type>
00814 operator-(const ArrayND<Dimension, Type>& array0, Type scalar);
00815
00816
00828 template <size_t Dimension, class Type>
00829 ArrayND<Dimension, Type>
00830 operator*(const ArrayND<Dimension, Type>& array0, Type scalar);
00831
00832
00844 template <size_t Dimension, class Type>
00845 ArrayND<Dimension, Type>
00846 operator/(const ArrayND<Dimension, Type>& array0, Type scalar);
00847
00848
00860 template <size_t Dimension, class Type>
00861 inline ArrayND<Dimension, Type>
00862 operator+(Type scalar, const ArrayND<Dimension, Type>& array0);
00863
00864
00876 template <size_t Dimension, class Type>
00877 inline ArrayND<Dimension, Type>
00878 operator-(Type scalar, const ArrayND<Dimension, Type>& array0);
00879
00880
00892 template <size_t Dimension, class Type>
00893 inline ArrayND<Dimension, Type>
00894 operator*(Type scalar, const ArrayND<Dimension, Type>& array0);
00895
00896
00908 template <size_t Dimension, class Type>
00909 inline ArrayND<Dimension, Type>
00910 operator/(Type scalar, const ArrayND<Dimension, Type>& array0);
00911
00912
00924 template <size_t Dimension, class Type>
00925 ArrayND<Dimension, bool>
00926 operator==(const ArrayND<Dimension, Type>& array0, const Type arg);
00927
00928
00941 template <size_t Dimension, class Type>
00942 ArrayND<Dimension, bool>
00943 operator==(const ArrayND<Dimension, Type>& array0,
00944 const ArrayND<Dimension, Type>& arrayN);
00945
00946
00957 template <size_t Dimension, class Type>
00958 ArrayND<Dimension, bool>
00959 operator>(const ArrayND<Dimension, Type>& array0, const Type arg);
00960
00961
00973 template <size_t Dimension, class Type>
00974 ArrayND<Dimension, bool>
00975 operator>=(const ArrayND<Dimension, Type>& array0, const Type arg);
00976
00977
00988 template <size_t Dimension, class Type>
00989 ArrayND<Dimension, bool>
00990 operator<(const ArrayND<Dimension, Type>& array0, const Type arg);
00991
00992
01004 template <size_t Dimension, class Type>
01005 ArrayND<Dimension, bool>
01006 operator<=(const ArrayND<Dimension, Type>& array0, const Type arg);
01007
01008
01009 template <size_t Dimension, class Type>
01010 std::ostream& operator<<(std::ostream& stream,
01011 const ArrayND<Dimension, Type>& array0);
01012
01013
01014 template <size_t Dimension, class Type>
01015 std::istream& operator>>(std::istream& stream,
01016 ArrayND<Dimension, Type> & array0);
01017
01018 }
01019
01020 }
01021
01022
01023
01024
01025
01026 #include <algorithm>
01027 #include <numeric>
01028 #include <sstream>
01029 #include <vector>
01030 #include <dlrNumeric/numericTraits.h>
01031
01032 namespace dlr {
01033
01034 namespace numeric {
01035
01036 template <size_t Dimension, class Type>
01037 ArrayND<Dimension, Type>::
01038 ArrayND()
01039 : m_shape(),
01040 m_storage(),
01041 m_strideArray()
01042 {
01043
01044 }
01045
01046
01047 template <size_t Dimension, class Type>
01048 ArrayND<Dimension, Type>::
01049 ArrayND(size_t dimension, size_t const shape[])
01050 : m_shape(dimension),
01051 m_storage(),
01052 m_strideArray()
01053 {
01054 m_shape.copy(shape);
01055 m_storage.reinit(this->computeSize(m_shape));
01056 }
01057
01058
01059
01060 template <size_t Dimension, class Type>
01061 ArrayND<Dimension, Type>::
01062 ArrayND(const Array1D<size_t>& shape)
01063 : m_shape(shape.copy()),
01064 m_storage(this->computeSize(m_shape)),
01065 m_strideArray(this->computeStride(m_shape))
01066 {
01067
01068 }
01069
01070
01071
01072
01073
01074 template <size_t Dimension, class Type>
01075 ArrayND<Dimension, Type>::
01076 ArrayND(const ArrayND<Dimension, Type>& source)
01077 : m_shape(source.m_shape.copy()),
01078 m_storage(source.m_storage),
01079 m_strideArray(source.m_strideArray.copy())
01080 {
01081
01082 }
01083
01084
01085
01086 template <size_t Dimension, class Type>
01087 ArrayND<Dimension, Type>::
01088 ArrayND(const std::string& inputString)
01089 {
01090 std::istringstream stream(inputString);
01091 stream >> *this;
01092 if(!stream) {
01093 DLR_THROW(ValueException, "ArrayND::ArrayND(std::string const&)",
01094 "Malformed input string.");
01095 }
01096 }
01097
01098
01099 template <size_t Dimension, class Type>
01100 ArrayND<Dimension, Type>::
01101 ~ArrayND()
01102 {
01103
01104 }
01105
01106
01107 template <size_t Dimension, class Type>
01108 inline void ArrayND<Dimension, Type>::
01109 checkDimension(Array1D<size_t> const& shape) const
01110 {
01111
01112
01113 if(shape.size() != m_shape.size()) {
01114 std::ostringstream message;
01115 message << "Dimensionality mismatch: required dimensionality is "
01116 << shape.size()
01117 << " while *this has dimension " << m_shape.size() << ".";
01118 DLR_THROW(IndexException, "ArrayND::checkDimension()",
01119 message.str().c_str());
01120 }
01121 for(size_t dimension = 0; dimension < m_shape.size(); ++dimension) {
01122 if(m_shape[dimension] != shape[dimension]) {
01123 std::ostringstream message;
01124 message << "Shape mismatch: required shape is " << shape
01125 << " while *this has shape " << m_shape << ".";
01126 DLR_THROW(IndexException, "ArrayND::checkDimension()",
01127 message.str().c_str());
01128 }
01129 }
01130
01131 }
01132
01133
01134 template <size_t Dimension, class Type>
01135 ArrayND<Dimension, Type> ArrayND<Dimension, Type>::
01136 copy() const
01137 {
01138 ArrayND<Dimension, Type> newArray(m_shape);
01139 newArray.copy(*this);
01140 return newArray;
01141 }
01142
01143
01144 template <size_t Dimension, class Type> template <class Type2>
01145 void ArrayND<Dimension, Type>::
01146 copy(const ArrayND<Dimension, Type2>& source)
01147 {
01148 this->checkDimension(source.getShape());
01149 if(m_storage.size() != 0) {
01150 this->copy(source.data());
01151 }
01152 }
01153
01154
01155 template <size_t Dimension, class Type> template <class Type2>
01156 void
01157 ArrayND<Dimension, Type>::
01158 copy(const Type2* dataPtr)
01159 {
01160 m_storage.copy(dataPtr);
01161 }
01162
01163
01164 template <size_t Dimension, class Type>
01165 ArrayND<Dimension, Type>&
01166 ArrayND<Dimension, Type>::
01167 operator=(Type val)
01168 {
01169 m_storage = val;
01170 return *this;
01171 }
01172
01173
01174 template <size_t Dimension, class Type>
01175 size_t
01176 ArrayND<Dimension, Type>::
01177 flattenIndex(const Array1D<size_t>& indexArray) const
01178 {
01179 dlr::numeric::Array1D<size_t>::const_iterator endMinus = indexArray.end();
01180 --endMinus;
01181 return std::inner_product(indexArray.begin(), endMinus,
01182 m_strideArray.begin(), *endMinus);
01183 }
01184
01185
01186 template <size_t Dimension, class Type>
01187 void ArrayND<Dimension, Type>::
01188 reinit(Array1D<size_t> const& shape)
01189 {
01190 m_shape = shape.copy();
01191 m_storage.reinit(this->computeSize(m_shape));
01192 m_strideArray = this->computeStride(m_shape);
01193 }
01194
01195
01196 template <size_t Dimension, class Type>
01197 ArrayND<Dimension, Type>& ArrayND<Dimension, Type>::
01198 operator=(const ArrayND<Dimension, Type>& source)
01199 {
01200
01201 if(&source != this) {
01202 m_shape = source.m_shape.copy();
01203 m_storage = source.m_storage;
01204 m_strideArray = source.m_strideArray.copy();
01205 }
01206 return *this;
01207 }
01208
01209
01210 template <size_t Dimension, class Type> template <class Type2>
01211 ArrayND<Dimension, Type>&
01212 ArrayND<Dimension, Type>::
01213 operator+=(const ArrayND<Dimension, Type2>& arg)
01214 {
01215
01216 m_storage += arg.m_storage;
01217 return *this;
01218 }
01219
01220
01221 template <size_t Dimension, class Type>
01222 ArrayND<Dimension, Type>&
01223 ArrayND<Dimension, Type>::
01224 operator+=(const Type arg)
01225 {
01226 m_storage += arg;
01227 return *this;
01228 }
01229
01230
01231 template <size_t Dimension, class Type> template <class Type2>
01232 ArrayND<Dimension, Type>&
01233 ArrayND<Dimension, Type>::
01234 operator-=(const ArrayND<Dimension, Type2>& arg)
01235 {
01236
01237 m_storage -= arg.m_storage;
01238 return *this;
01239 }
01240
01241
01242 template <size_t Dimension, class Type>
01243 ArrayND<Dimension, Type>&
01244 ArrayND<Dimension, Type>::
01245 operator-=(const Type arg)
01246 {
01247 m_storage -= arg;
01248 return *this;
01249 }
01250
01251
01252 template <size_t Dimension, class Type> template <class Type2>
01253 ArrayND<Dimension, Type>&
01254 ArrayND<Dimension, Type>::
01255 operator*=(const ArrayND<Dimension, Type2>& arg)
01256 {
01257
01258 m_storage *= arg.m_storage;
01259 return *this;
01260 }
01261
01262
01263 template <size_t Dimension, class Type>
01264 ArrayND<Dimension, Type>&
01265 ArrayND<Dimension, Type>::
01266 operator*=(const Type arg)
01267 {
01268 m_storage *= arg;
01269 return *this;
01270 }
01271
01272
01273 template <size_t Dimension, class Type> template <class Type2>
01274 ArrayND<Dimension, Type>&
01275 ArrayND<Dimension, Type>::
01276 operator/=(const ArrayND<Dimension, Type2>& arg)
01277 {
01278
01279 m_storage /= arg.m_storage;
01280 return *this;
01281 }
01282
01283
01284 template <size_t Dimension, class Type>
01285 ArrayND<Dimension, Type>&
01286 ArrayND<Dimension, Type>::
01287 operator/=(const Type arg)
01288 {
01289 m_storage /= arg;
01290 return *this;
01291 }
01292
01293
01294 template <size_t Dimension, class Type>
01295 size_t
01296 ArrayND<Dimension, Type>::
01297 computeSize(Array1D<size_t> const& shape) const
01298 {
01299 return std::accumulate(shape.begin(), shape.end(), size_t(1),
01300 std::multiplies<size_t>());
01301 }
01302
01303
01304 template <size_t Dimension, class Type>
01305 Array1D<size_t>
01306 ArrayND<Dimension, Type>::
01307 computeStride(Array1D<size_t> const& shape) const
01308 {
01309 Array1D<size_t> strideArray(shape.size());
01310 strideArray[shape.size() - 1] = 1;
01311 for(size_t ii = shape.size() - 1; ii != 0; --ii) {
01312 strideArray[ii - 1] = shape[ii] * strideArray[ii];
01313 }
01314 return strideArray;
01315 }
01316
01317
01318
01319
01320 template <size_t Dimension, class Type>
01321 ArrayND<Dimension, Type> operator+(const ArrayND<Dimension, Type>& array0,
01322 const ArrayND<Dimension, Type>& arrayN)
01323 {
01324 if(array0.size() != arrayN.size()) {
01325 std::ostringstream message;
01326 message << "Array sizes do not match. Array0 has " << array0.size()
01327 << " elements, while arrayN has " << arrayN.size()
01328 << " elements.";
01329 DLR_THROW(ValueException, "ArrayND::operator+()", message.str().c_str());
01330 }
01331 ArrayND<Dimension, Type> result(array0.getShape());
01332 std::transform(array0.begin(), array0.end(), arrayN.begin(),
01333 result.begin(), std::plus<Type>());
01334 return result;
01335 }
01336
01337
01338 template <size_t Dimension, class Type>
01339 ArrayND<Dimension, Type> operator-(const ArrayND<Dimension, Type>& array0,
01340 const ArrayND<Dimension, Type>& arrayN)
01341 {
01342 if(array0.size() != arrayN.size()) {
01343 std::ostringstream message;
01344 message << "Array sizes do not match. Array0 has " << array0.size()
01345 << " elements, while arrayN has " << arrayN.size()
01346 << " elements.";
01347 DLR_THROW(ValueException, "ArrayND::operator-()", message.str().c_str());
01348 }
01349 ArrayND<Dimension, Type> result(array0.getShape());
01350 std::transform(array0.begin(), array0.end(), arrayN.begin(),
01351 result.begin(), std::minus<Type>());
01352 return result;
01353 }
01354
01355
01356 template <size_t Dimension, class Type>
01357 ArrayND<Dimension, Type> operator*(const ArrayND<Dimension, Type>& array0,
01358 const ArrayND<Dimension, Type>& arrayN)
01359 {
01360 if(array0.size() != arrayN.size()) {
01361 std::ostringstream message;
01362 message << "Array sizes do not match. Array0 has " << array0.size()
01363 << " elements, while arrayN has " << arrayN.size()
01364 << " elements.";
01365 DLR_THROW(ValueException, "ArrayND::operator*()", message.str().c_str());
01366 }
01367 ArrayND<Dimension, Type> result(array0.getShape());
01368 std::transform(array0.begin(), array0.end(), arrayN.begin(),
01369 result.begin(), std::multiplies<Type>());
01370 return result;
01371 }
01372
01373
01374 template <size_t Dimension, class Type>
01375 ArrayND<Dimension, Type> operator/(const ArrayND<Dimension, Type>& array0,
01376 const ArrayND<Dimension, Type>& arrayN)
01377 {
01378 if(array0.size() != arrayN.size()) {
01379 std::ostringstream message;
01380 message << "Array sizes do not match. Array0 has " << array0.size()
01381 << " elements, while arrayN has " << arrayN.size()
01382 << " elements.";
01383 DLR_THROW(ValueException, "ArrayND::operator/()", message.str().c_str());
01384 }
01385 ArrayND<Dimension, Type> result(array0.getShape());
01386 std::transform(array0.begin(), array0.end(), arrayN.begin(),
01387 result.begin(), std::divides<Type>());
01388 return result;
01389 }
01390
01391
01392 template <size_t Dimension, class Type>
01393 ArrayND<Dimension, Type> operator+(const ArrayND<Dimension, Type>& array0, Type scalar)
01394 {
01395 ArrayND<Dimension, Type> result(array0.getShape());
01396 std::transform(array0.begin(), array0.end(), result.begin(),
01397 std::bind2nd(std::plus<Type>(), scalar));
01398 return result;
01399 }
01400
01401
01402 template <size_t Dimension, class Type>
01403 ArrayND<Dimension, Type> operator-(const ArrayND<Dimension, Type>& array0, Type scalar)
01404 {
01405 ArrayND<Dimension, Type> result(array0.getShape());
01406 std::transform(array0.begin(), array0.end(), result.begin(),
01407 std::bind2nd(std::minus<Type>(), scalar));
01408 return result;
01409 }
01410
01411
01412 template <size_t Dimension, class Type>
01413 ArrayND<Dimension, Type> operator*(const ArrayND<Dimension, Type>& array0, Type scalar)
01414 {
01415 ArrayND<Dimension, Type> result(array0.getShape());
01416 std::transform(array0.begin(), array0.end(), result.begin(),
01417 std::bind2nd(std::multiplies<Type>(), scalar));
01418 return result;
01419 }
01420
01421
01422 template <size_t Dimension, class Type>
01423 ArrayND<Dimension, Type> operator/(const ArrayND<Dimension, Type>& array0, Type scalar)
01424 {
01425 ArrayND<Dimension, Type> result(array0.getShape());
01426 std::transform(array0.begin(), array0.end(), result.begin(),
01427 std::bind2nd(std::divides<Type>(), scalar));
01428 return result;
01429 }
01430
01431
01432 template <size_t Dimension, class Type>
01433 inline ArrayND<Dimension, Type> operator+(Type scalar, const ArrayND<Dimension, Type>& array0)
01434 {
01435 return array0 + scalar;
01436 }
01437
01438
01439 template <size_t Dimension, class Type>
01440 ArrayND<Dimension, Type> operator-(Type scalar, const ArrayND<Dimension, Type>& array0)
01441 {
01442 ArrayND<Dimension, Type> result(array0.getShape());
01443 std::transform(array0.begin(), array0.end(), result.begin(),
01444 std::bind1st(std::minus<Type>(), scalar));
01445 return result;
01446 }
01447
01448
01449 template <size_t Dimension, class Type>
01450 inline ArrayND<Dimension, Type> operator*(Type scalar, const ArrayND<Dimension, Type>& array0)
01451 {
01452 return array0 * scalar;
01453 }
01454
01455
01456 template <size_t Dimension, class Type>
01457 ArrayND<Dimension, Type> operator/(Type scalar, const ArrayND<Dimension, Type>& array0)
01458 {
01459 ArrayND<Dimension, Type> result(array0.getShape());
01460 std::transform(array0.begin(), array0.end(), result.begin(),
01461 std::bind1st(std::divides<Type>(), scalar));
01462 return result;
01463 }
01464
01465
01466
01467 template <size_t Dimension, class Type>
01468 ArrayND<Dimension, bool>
01469 operator==(const ArrayND<Dimension, Type>& array0, const Type arg)
01470 {
01471 ArrayND<Dimension, bool> result(array0.getShape());
01472 std::transform(array0.begin(), array0.end(), result.data(),
01473 std::bind2nd(std::equal_to<Type>(), arg));
01474 return result;
01475 }
01476
01477
01478
01479 template <size_t Dimension, class Type>
01480 ArrayND<Dimension, bool>
01481 operator==(const ArrayND<Dimension, Type>& array0,
01482 const ArrayND<Dimension, Type>& arrayN)
01483 {
01484 array0.checkDimension(arrayN.getShape());
01485 ArrayND<Dimension, bool> result(array0.getShape());
01486 std::transform(array0.begin(), array0.end(), arrayN.begin(),
01487 result.begin(), std::equal_to<Type>());
01488 return result;
01489 }
01490
01491
01492 template <size_t Dimension, class Type>
01493 ArrayND<Dimension, bool>
01494 operator>(const ArrayND<Dimension, Type>& array0, const Type arg)
01495 {
01496 ArrayND<Dimension, bool> result(array0.getShape());
01497 std::transform(array0.begin(), array0.end(), result.begin(),
01498 std::bind2nd(std::greater<Type>(), arg));
01499 return result;
01500 }
01501
01502
01503 template <size_t Dimension, class Type>
01504 ArrayND<Dimension, bool>
01505 operator>=(const ArrayND<Dimension, Type>& array0, const Type arg)
01506 {
01507 ArrayND<Dimension, bool> result(array0.getShape());
01508 std::transform(array0.begin(), array0.end(), result.begin(),
01509 std::bind2nd(std::greater_equal<Type>(), arg));
01510 return result;
01511 }
01512
01513
01514 template <size_t Dimension, class Type>
01515 ArrayND<Dimension, bool>
01516 operator<(const ArrayND<Dimension, Type>& array0, const Type arg)
01517 {
01518 ArrayND<Dimension, bool> result(array0.getShape());
01519 std::transform(array0.begin(), array0.end(), result.begin(),
01520 std::bind2nd(std::less<Type>(), arg));
01521 return result;
01522 }
01523
01524
01525 template <size_t Dimension, class Type>
01526 ArrayND<Dimension, bool>
01527 operator<=(const ArrayND<Dimension, Type>& array0, const Type arg)
01528 {
01529 ArrayND<Dimension, bool> result(array0.getShape());
01530 std::transform(array0.begin(), array0.end(), result.begin(),
01531 std::bind2nd(std::less_equal<Type>(), arg));
01532 return result;
01533 }
01534
01535
01536 template <size_t Dimension, class Type>
01537 std::ostream& operator<<(std::ostream& stream,
01538 const ArrayND<Dimension, Type>& array0)
01539 {
01540 if (!stream){
01541 return stream;
01542 }
01543 stream << "ArrayND {\n"
01544 << " shape: " << array0.getShape() << "\n"
01545 << " data: " << array0.ravel() << "\n"
01546 << "}";
01547 return stream;
01548 }
01549
01550
01551
01552 template <size_t Dimension, class Type>
01553 std::istream& operator>>(std::istream& stream,
01554 ArrayND<Dimension, Type> & array0)
01555 {
01556 if (!stream){
01557 return stream;
01558 }
01559
01560
01561 InputStream inputStream(stream, InputStream::SKIP_WHITESPACE);
01562 inputStream.expect("ArrayND");
01563 inputStream.expect("{");
01564
01565 Array1D<size_t> shape;
01566 inputStream.expect("shape:");
01567 inputStream >> shape;
01568
01569 Array1D<Type> data;
01570 inputStream.expect("data:");
01571 inputStream >> data;
01572
01573 if(!inputStream) {
01574 return stream;
01575 }
01576 array0.reinit(shape);
01577 array0.copy(data.data());
01578 return stream;
01579 }
01580
01581 }
01582
01583 }
01584
01585 #endif