arrayND.h

Go to the documentation of this file.
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       /* ======== Public typedefs ======== */
00076 
00080       typedef Type value_type;
00081 
00085       typedef Type* iterator;
00086     
00091       typedef const Type* const_iterator;
00092 
00093 
00094       /* ======== Public member functions ======== */
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       /* ======== Private member functions ======== */
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       /* ======== Private data members ======== */
00701       Array1D<size_t> m_shape;
00702       Array1D<Type> m_storage;
00703       Array1D<size_t> m_strideArray;
00704     };
00705 
00706 
00707     /* Non-member functions which should maybe wind up in a different file */
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   } // namespace numeric
01019 
01020 } // namespace dlr
01021 
01022 
01023 
01024 /* ============ Inline and template definitions follow. ============ */
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       // Empty.
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     // Construct from an initialization string.
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       // Empty.
01068     }
01069 
01070   
01071     /* When copying from a ArrayND do a shallow copy */
01072     /* Update reference count if the array we're copying has */
01073     /* valid data. */
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()),            // Deep copy.
01078         m_storage(source.m_storage),               // Shallow copy.
01079         m_strideArray(source.m_strideArray.copy()) // Deep copy.
01080     {
01081       // Empty.
01082     }
01083 
01084 
01085     // Construct from an initialization string.
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       // Empty.
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       // Hmm.  Seems like this should happen even if we're optimizing.
01112 // #ifdef _DLRNUMERIC_CHECKBOUNDS_
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 // #endif
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       // Check for self-assignment
01201       if(&source != this) {
01202         m_shape = source.m_shape.copy();             // Deep copy.
01203         m_storage = source.m_storage;                // Shallow copy.
01204         m_strideArray = source.m_strideArray.copy(); // Deep 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       // Let m_storage worry about array size errors.
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       // Let m_storage worry about array size errors.
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       // Let m_storage worry about array size errors.
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       // Let m_storage worry about array size errors.
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     /* ========== Non-member functions ========== */
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     // Elementwise comparison of an ArrayND with a constant.
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     // Elementwise comparison of an ArrayND with another array.
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     // Sets the value of an ArrayND instance from a std::istream.
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       // Construct an InputStream instance so we can use our
01560       // convenience functions.
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   } // namespace numeric
01582 
01583 } // namespace dlr
01584 
01585 #endif /* #ifdef DLRNUMERIC_ARRAYND_H */

Generated on Wed Nov 25 00:42:41 2009 for dlrUtilities Utility Library by  doxygen 1.5.8