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       
00395       bool
00396       isAllocated() const {return true;}
00397 
00398 
00406       Array1D<Type>
00407       ravel() {return m_storage;}
00408 
00409       
00417       Array1D<Type> const
00418       ravel() const {return m_storage;}
00419 
00420       
00427       void
00428       reinit(Array1D<size_t> const& shape);
00429     
00430 
00444       Type&
00445       setElement(size_t index0, const Type& value) {
00446         return this->operator()(index0) = value;
00447       }
00448 
00449 
00463       Type&
00464       setElement(Array1D<size_t> const& index0, const Type& value) {
00465         return this->operator()(this->flattenIndex(index0)) = value;
00466       }
00467 
00468 
00474       size_t
00475       size() const {return m_storage.size();}
00476 
00477       
00486       ArrayND<Dimension, Type>&
00487       operator=(const ArrayND<Dimension, Type>& source);
00488 
00489       
00497       inline ArrayND<Dimension, Type>&
00498       operator=(Type value);
00499 
00500 
00508       Type&
00509       operator()(size_t index0) {return m_storage(index0);}
00510   
00511 
00519       Type operator()(size_t index0) const {return m_storage(index0);}
00520 
00521       
00529       Type&
00530       operator()(Array1D<size_t> const& index0) {
00531         return m_storage[this->flattenIndex(index0)];
00532       }
00533   
00534 
00542       Type operator()(Array1D<size_t> const& index0) const {
00543         return m_storage[this->flattenIndex(index0)];
00544       }
00545 
00546 
00555       Type& operator[](size_t index) {return this->operator()(index);}
00556 
00557       
00566       Type operator[](size_t index) const {return this->operator()(index);}
00567 
00568 
00580       template <class Type2>
00581       ArrayND<Dimension, Type>&
00582       operator+=(const ArrayND<Dimension, Type2>& arg);
00583 
00584       
00592       ArrayND<Dimension, Type>&
00593       operator+=(const Type arg);
00594 
00595 
00607       template <class Type2>
00608       ArrayND<Dimension, Type>&
00609       operator-=(const ArrayND<Dimension, Type2>& arg);
00610 
00611       
00619       ArrayND<Dimension, Type>&
00620       operator-=(const Type arg);
00621 
00622       
00634       template <class Type2>
00635       ArrayND<Dimension, Type>&
00636       operator*=(const ArrayND<Dimension, Type2>& arg);
00637 
00638       
00646       ArrayND<Dimension, Type>&
00647       operator*=(const Type arg);
00648 
00649 
00661       template <class Type2>
00662       ArrayND<Dimension, Type>&
00663       operator/=(const ArrayND<Dimension, Type2>& arg);
00664 
00665       
00673       ArrayND<Dimension, Type>&
00674       operator/=(const Type arg);
00675 
00676     private:
00677       /* ======== Private member functions ======== */
00678 
00679       size_t computeSize(Array1D<size_t> const& shape) const;
00680       Array1D<size_t> computeStride(Array1D<size_t> const& shape) const;
00681 
00682       
00683       /* ======== Private data members ======== */
00684       Array1D<size_t> m_shape;
00685       Array1D<Type> m_storage;
00686       Array1D<size_t> m_strideArray;
00687     };
00688 
00689 
00690     /* Non-member functions which should maybe wind up in a different file */
00691 
00705     template <size_t Dimension, class Type>
00706     ArrayND<Dimension, Type>
00707     operator+(const ArrayND<Dimension, Type>& array0,
00708               const ArrayND<Dimension, Type>& arrayN);
00709   
00710 
00724     template <size_t Dimension, class Type>
00725     ArrayND<Dimension, Type>
00726     operator-(const ArrayND<Dimension, Type>& array0,
00727               const ArrayND<Dimension, Type>& arrayN);
00728 
00729 
00743     template <size_t Dimension, class Type>
00744     ArrayND<Dimension, Type>
00745     operator*(const ArrayND<Dimension, Type>& array0,
00746               const ArrayND<Dimension, Type>& arrayN);
00747   
00748 
00762     template <size_t Dimension, class Type>
00763     ArrayND<Dimension, Type>
00764     operator/(const ArrayND<Dimension, Type>& array0,
00765               const ArrayND<Dimension, Type>& arrayN);
00766 
00767 
00779     template <size_t Dimension, class Type>
00780     ArrayND<Dimension, Type>
00781     operator+(const ArrayND<Dimension, Type>& array, Type scalar);
00782 
00783 
00795     template <size_t Dimension, class Type>
00796     ArrayND<Dimension, Type>
00797     operator-(const ArrayND<Dimension, Type>& array0, Type scalar);
00798 
00799 
00811     template <size_t Dimension, class Type>
00812     ArrayND<Dimension, Type>
00813     operator*(const ArrayND<Dimension, Type>& array0, Type scalar);
00814 
00815 
00827     template <size_t Dimension, class Type>
00828     ArrayND<Dimension, Type>
00829     operator/(const ArrayND<Dimension, Type>& array0, Type scalar);
00830 
00831 
00843     template <size_t Dimension, class Type>
00844     inline ArrayND<Dimension, Type>
00845     operator+(Type scalar, const ArrayND<Dimension, Type>& array0);
00846 
00847 
00859     template <size_t Dimension, class Type>
00860     inline ArrayND<Dimension, Type>
00861     operator-(Type scalar, const ArrayND<Dimension, Type>& array0);
00862 
00863 
00875     template <size_t Dimension, class Type>
00876     inline ArrayND<Dimension, Type>
00877     operator*(Type scalar, const ArrayND<Dimension, Type>& array0);
00878 
00879 
00891     template <size_t Dimension, class Type>
00892     inline ArrayND<Dimension, Type>
00893     operator/(Type scalar, const ArrayND<Dimension, Type>& array0);
00894 
00895 
00907     template <size_t Dimension, class Type>
00908     ArrayND<Dimension, bool>
00909     operator==(const ArrayND<Dimension, Type>& array0, const Type arg);
00910 
00911     
00924     template <size_t Dimension, class Type>
00925     ArrayND<Dimension, bool>
00926     operator==(const ArrayND<Dimension, Type>& array0,
00927                const ArrayND<Dimension, Type>& arrayN);
00928     
00929 
00940     template <size_t Dimension, class Type>
00941     ArrayND<Dimension, bool>
00942     operator>(const ArrayND<Dimension, Type>& array0, const Type arg);
00943 
00944   
00956     template <size_t Dimension, class Type>
00957     ArrayND<Dimension, bool>
00958     operator>=(const ArrayND<Dimension, Type>& array0, const Type arg);
00959 
00960 
00971     template <size_t Dimension, class Type>
00972     ArrayND<Dimension, bool>
00973     operator<(const ArrayND<Dimension, Type>& array0, const Type arg);
00974 
00975 
00987     template <size_t Dimension, class Type>
00988     ArrayND<Dimension, bool>
00989     operator<=(const ArrayND<Dimension, Type>& array0, const Type arg);
00990 
00991 
00992     template <size_t Dimension, class Type>
00993     std::ostream& operator<<(std::ostream& stream,
00994                              const ArrayND<Dimension, Type>& array0);
00995 
00996     
00997     template <size_t Dimension, class Type>
00998     std::istream& operator>>(std::istream& stream,
00999                              ArrayND<Dimension, Type> & array0);
01000     
01001   } // namespace numeric
01002 
01003 } // namespace dlr
01004 
01005 
01006 
01007 /* ============ Inline and template definitions follow. ============ */
01008 
01009 #include <algorithm>
01010 #include <numeric>
01011 #include <sstream>
01012 #include <vector>
01013 #include <dlrNumeric/numericTraits.h>
01014 
01015 namespace dlr {
01016 
01017   namespace numeric {
01018     
01019     template <size_t Dimension, class Type>
01020     ArrayND<Dimension, Type>::
01021     ArrayND()
01022       : m_shape(),
01023         m_storage(),
01024         m_strideArray()
01025     {
01026       // Empty.
01027     }
01028 
01029 
01030     template <size_t Dimension, class Type>
01031     ArrayND<Dimension, Type>::
01032     ArrayND(size_t dimension, size_t const shape[])
01033       : m_shape(dimension),
01034         m_storage(),
01035         m_strideArray()
01036     {
01037       m_shape.copy(shape);
01038       m_storage.reinit(this->computeSize(m_shape));
01039     }
01040 
01041 
01042     // Construct from an initialization string.
01043     template <size_t Dimension, class Type>
01044     ArrayND<Dimension, Type>::
01045     ArrayND(const Array1D<size_t>& shape)
01046       : m_shape(shape.copy()),
01047         m_storage(this->computeSize(m_shape)),
01048         m_strideArray(this->computeStride(m_shape))
01049     {
01050       // Empty.
01051     }
01052 
01053   
01054     /* When copying from a ArrayND do a shallow copy */
01055     /* Update reference count if the array we're copying has */
01056     /* valid data. */
01057     template <size_t Dimension, class Type>
01058     ArrayND<Dimension, Type>::
01059     ArrayND(const ArrayND<Dimension, Type>& source)
01060       : m_shape(source.m_shape.copy()),            // Deep copy.
01061         m_storage(source.m_storage),               // Shallow copy.
01062         m_strideArray(source.m_strideArray.copy()) // Deep copy.
01063     {
01064       // Empty.
01065     }
01066 
01067 
01068     // Construct from an initialization string.
01069     template <size_t Dimension, class Type>
01070     ArrayND<Dimension, Type>::
01071     ArrayND(const std::string& inputString)
01072     {
01073       std::istringstream stream(inputString);
01074       stream >> *this;
01075       if(!stream) {
01076         DLR_THROW(ValueException, "ArrayND::ArrayND(std::string const&)",
01077                   "Malformed input string.");
01078       }
01079     }
01080 
01081 
01082     template <size_t Dimension, class Type>
01083     ArrayND<Dimension, Type>::
01084     ~ArrayND()
01085     {
01086       // Empty.
01087     }
01088 
01089 
01090     template <size_t Dimension, class Type>
01091     inline void ArrayND<Dimension, Type>::
01092     checkDimension(Array1D<size_t> const& shape) const
01093     {
01094       // Hmm.  Seems like this should happen even if we're optimizing.
01095 // #ifdef _DLRNUMERIC_CHECKBOUNDS_
01096       if(shape.size() != m_shape.size()) {
01097         std::ostringstream message;
01098         message << "Dimensionality mismatch: required dimensionality is "
01099                 << shape.size()
01100                 << " while *this has dimension " << m_shape.size() << ".";
01101         DLR_THROW(IndexException, "ArrayND::checkDimension()",
01102                   message.str().c_str());
01103       }
01104       for(size_t dimension = 0; dimension < m_shape.size(); ++dimension) {
01105         if(m_shape[dimension] != shape[dimension]) {
01106           std::ostringstream message;
01107           message << "Shape mismatch: required shape is " << shape
01108                 << " while *this has shape " << m_shape << ".";
01109           DLR_THROW(IndexException, "ArrayND::checkDimension()",
01110                     message.str().c_str());
01111         }
01112       }
01113 // #endif
01114     }
01115 
01116 
01117     template <size_t Dimension, class Type>
01118     ArrayND<Dimension, Type> ArrayND<Dimension, Type>::
01119     copy() const
01120     {
01121       ArrayND<Dimension, Type> newArray(m_shape);
01122       newArray.copy(*this);
01123       return newArray;
01124     }
01125 
01126   
01127     template <size_t Dimension, class Type> template <class Type2>
01128     void ArrayND<Dimension, Type>::
01129     copy(const ArrayND<Dimension, Type2>& source)
01130     {
01131       this->checkDimension(source.m_shape);
01132       if(m_storage.size() != 0) {
01133         this->copy(source.data());
01134       }
01135     }
01136 
01137   
01138     template <size_t Dimension, class Type> template <class Type2>
01139     void
01140     ArrayND<Dimension, Type>::
01141     copy(const Type2* dataPtr)
01142     {
01143       m_storage.copy(dataPtr);
01144     }
01145 
01146 
01147     template <size_t Dimension, class Type>
01148     ArrayND<Dimension, Type>&
01149     ArrayND<Dimension, Type>::
01150     operator=(Type val)
01151     {
01152       m_storage = val;
01153       return *this;
01154     }
01155 
01156 
01157     template <size_t Dimension, class Type>
01158     size_t
01159     ArrayND<Dimension, Type>::
01160     flattenIndex(const Array1D<size_t>& indexArray) const
01161     {
01162       dlr::numeric::Array1D<size_t>::const_iterator endMinus = indexArray.end();
01163       --endMinus;
01164       return std::inner_product(indexArray.begin(), endMinus,
01165                                 m_strideArray.begin(), *endMinus);
01166     }
01167 
01168     
01169     template <size_t Dimension, class Type>
01170     void ArrayND<Dimension, Type>::
01171     reinit(Array1D<size_t> const& shape)
01172     {
01173       m_shape = shape.copy();
01174       m_storage.reinit(this->computeSize(m_shape));
01175       m_strideArray = this->computeStride(m_shape);
01176     }
01177   
01178 
01179     template <size_t Dimension, class Type>
01180     ArrayND<Dimension, Type>& ArrayND<Dimension, Type>::
01181     operator=(const ArrayND<Dimension, Type>& source)
01182     {
01183       // Check for self-assignment
01184       if(&source != this) {
01185         m_shape = source.m_shape.copy();             // Deep copy.
01186         m_storage = source.m_storage;                // Shallow copy.
01187         m_strideArray = source.m_strideArray.copy(); // Deep copy.
01188       }
01189       return *this;
01190     }
01191 
01192 
01193     template <size_t Dimension, class Type> template <class Type2>
01194     ArrayND<Dimension, Type>&
01195     ArrayND<Dimension, Type>::
01196     operator+=(const ArrayND<Dimension, Type2>& arg)
01197     {
01198       // Let m_storage worry about array size errors.
01199       m_storage += arg.m_storage;
01200       return *this;
01201     }
01202 
01203 
01204     template <size_t Dimension, class Type>
01205     ArrayND<Dimension, Type>&
01206     ArrayND<Dimension, Type>::
01207     operator+=(const Type arg)
01208     {
01209       m_storage += arg;
01210       return *this;
01211     }
01212 
01213 
01214     template <size_t Dimension, class Type> template <class Type2>
01215     ArrayND<Dimension, Type>&
01216     ArrayND<Dimension, Type>::
01217     operator-=(const ArrayND<Dimension, Type2>& arg)
01218     {
01219       // Let m_storage worry about array size errors.
01220       m_storage -= arg.m_storage;
01221       return *this;
01222     }
01223 
01224 
01225     template <size_t Dimension, class Type>
01226     ArrayND<Dimension, Type>&
01227     ArrayND<Dimension, Type>::
01228     operator-=(const Type arg)
01229     {
01230       m_storage -= arg;
01231       return *this;
01232     }
01233 
01234 
01235     template <size_t Dimension, class Type> template <class Type2>
01236     ArrayND<Dimension, Type>&
01237     ArrayND<Dimension, Type>::
01238     operator*=(const ArrayND<Dimension, Type2>& arg)
01239     {
01240       // Let m_storage worry about array size errors.
01241       m_storage *= arg.m_storage;
01242       return *this;
01243     }
01244 
01245 
01246     template <size_t Dimension, class Type>
01247     ArrayND<Dimension, Type>&
01248     ArrayND<Dimension, Type>::
01249     operator*=(const Type arg)
01250     {
01251       m_storage *= arg;
01252       return *this;
01253     }
01254 
01255 
01256     template <size_t Dimension, class Type> template <class Type2>
01257     ArrayND<Dimension, Type>&
01258     ArrayND<Dimension, Type>::
01259     operator/=(const ArrayND<Dimension, Type2>& arg)
01260     {
01261       // Let m_storage worry about array size errors.
01262       m_storage /= arg.m_storage;
01263       return *this;
01264     }
01265 
01266 
01267     template <size_t Dimension, class Type>
01268     ArrayND<Dimension, Type>&
01269     ArrayND<Dimension, Type>::
01270     operator/=(const Type arg)
01271     {
01272       m_storage /= arg;
01273       return *this;
01274     }
01275 
01276 
01277     template <size_t Dimension, class Type>
01278     size_t
01279     ArrayND<Dimension, Type>::
01280     computeSize(Array1D<size_t> const& shape) const
01281     {
01282       return std::accumulate(shape.begin(), shape.end(), size_t(1),
01283                              std::multiplies<size_t>());
01284     }
01285     
01286 
01287     template <size_t Dimension, class Type>
01288     Array1D<size_t>
01289     ArrayND<Dimension, Type>::
01290     computeStride(Array1D<size_t> const& shape) const
01291     {
01292       Array1D<size_t> strideArray(shape.size());
01293       strideArray[shape.size() - 1] = 1;
01294       for(size_t ii = shape.size() - 1; ii != 0; --ii) {
01295         strideArray[ii - 1] = shape[ii] * strideArray[ii];
01296       }
01297       return strideArray;
01298     }
01299     
01300 
01301     /* ========== Non-member functions ========== */
01302   
01303     template <size_t Dimension, class Type>
01304     ArrayND<Dimension, Type> operator+(const ArrayND<Dimension, Type>& array0,
01305                                        const ArrayND<Dimension, Type>& arrayN)
01306     {
01307       if(array0.size() != arrayN.size()) {
01308         std::ostringstream message;
01309         message << "Array sizes do not match.  Array0 has " << array0.size()
01310                 << " elements, while arrayN has " << arrayN.size()
01311                 << " elements.";
01312         DLR_THROW(ValueException, "ArrayND::operator+()", message.str().c_str());
01313       }
01314       ArrayND<Dimension, Type> result(array0.getShape());
01315       std::transform(array0.begin(), array0.end(), arrayN.begin(),
01316                      result.begin(), std::plus<Type>());
01317       return result;
01318     }
01319 
01320 
01321     template <size_t Dimension, class Type>
01322     ArrayND<Dimension, Type> operator-(const ArrayND<Dimension, Type>& array0,
01323                             const ArrayND<Dimension, Type>& arrayN)
01324     {
01325       if(array0.size() != arrayN.size()) {
01326         std::ostringstream message;
01327         message << "Array sizes do not match.  Array0 has " << array0.size()
01328                 << " elements, while arrayN has " << arrayN.size()
01329                 << " elements.";
01330         DLR_THROW(ValueException, "ArrayND::operator-()", message.str().c_str());
01331       }
01332       ArrayND<Dimension, Type> result(array0.getShape());
01333       std::transform(array0.begin(), array0.end(), arrayN.begin(),
01334                      result.begin(), std::minus<Type>());
01335       return result;
01336     }
01337 
01338 
01339     template <size_t Dimension, class Type>
01340     ArrayND<Dimension, Type> operator*(const ArrayND<Dimension, Type>& array0,
01341                             const ArrayND<Dimension, Type>& arrayN)
01342     {
01343       if(array0.size() != arrayN.size()) {
01344         std::ostringstream message;
01345         message << "Array sizes do not match.  Array0 has " << array0.size()
01346                 << " elements, while arrayN has " << arrayN.size()
01347                 << " elements.";
01348         DLR_THROW(ValueException, "ArrayND::operator*()", message.str().c_str());
01349       }
01350       ArrayND<Dimension, Type> result(array0.getShape());
01351       std::transform(array0.begin(), array0.end(), arrayN.begin(),
01352                      result.begin(), std::multiplies<Type>());
01353       return result;
01354     }
01355 
01356 
01357     template <size_t Dimension, class Type>
01358     ArrayND<Dimension, Type> operator/(const ArrayND<Dimension, Type>& array0,
01359                             const ArrayND<Dimension, Type>& arrayN)
01360     {
01361       if(array0.size() != arrayN.size()) {
01362         std::ostringstream message;
01363         message << "Array sizes do not match.  Array0 has " << array0.size()
01364                 << " elements, while arrayN has " << arrayN.size()
01365                 << " elements.";
01366         DLR_THROW(ValueException, "ArrayND::operator/()", message.str().c_str());
01367       }
01368       ArrayND<Dimension, Type> result(array0.getShape());
01369       std::transform(array0.begin(), array0.end(), arrayN.begin(),
01370                      result.begin(), std::divides<Type>());
01371       return result;
01372     }
01373 
01374 
01375     template <size_t Dimension, class Type>
01376     ArrayND<Dimension, Type> operator+(const ArrayND<Dimension, Type>& array0, Type scalar)
01377     {
01378       ArrayND<Dimension, Type> result(array0.getShape());
01379       std::transform(array0.begin(), array0.end(), result.begin(),
01380                      std::bind2nd(std::plus<Type>(), scalar));
01381       return result;
01382     }
01383 
01384 
01385     template <size_t Dimension, class Type>
01386     ArrayND<Dimension, Type> operator-(const ArrayND<Dimension, Type>& array0, Type scalar)
01387     {
01388       ArrayND<Dimension, Type> result(array0.getShape());
01389       std::transform(array0.begin(), array0.end(), result.begin(),
01390                      std::bind2nd(std::minus<Type>(), scalar));
01391       return result;
01392     }
01393 
01394 
01395     template <size_t Dimension, class Type>
01396     ArrayND<Dimension, Type> operator*(const ArrayND<Dimension, Type>& array0, Type scalar)
01397     {
01398       ArrayND<Dimension, Type> result(array0.getShape());
01399       std::transform(array0.begin(), array0.end(), result.begin(),
01400                      std::bind2nd(std::multiplies<Type>(), scalar));
01401       return result;
01402     }
01403 
01404 
01405     template <size_t Dimension, class Type>
01406     ArrayND<Dimension, Type> operator/(const ArrayND<Dimension, Type>& array0, Type scalar)
01407     {
01408       ArrayND<Dimension, Type> result(array0.getShape());
01409       std::transform(array0.begin(), array0.end(), result.begin(),
01410                      std::bind2nd(std::divides<Type>(), scalar));
01411       return result;
01412     }
01413 
01414 
01415     template <size_t Dimension, class Type>
01416     inline ArrayND<Dimension, Type> operator+(Type scalar, const ArrayND<Dimension, Type>& array0)
01417     {
01418       return array0 + scalar;
01419     }
01420 
01421 
01422     template <size_t Dimension, class Type>
01423     ArrayND<Dimension, Type> operator-(Type scalar, const ArrayND<Dimension, Type>& array0)
01424     {
01425       ArrayND<Dimension, Type> result(array0.getShape());
01426       std::transform(array0.begin(), array0.end(), result.begin(),
01427                      std::bind1st(std::minus<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::divides<Type>(), scalar));
01445       return result;
01446     }
01447   
01448 
01449     // Elementwise comparison of an ArrayND with a constant.
01450     template <size_t Dimension, class Type>
01451     ArrayND<Dimension, bool>
01452     operator==(const ArrayND<Dimension, Type>& array0, const Type arg)
01453     {
01454       ArrayND<Dimension, bool> result(array0.getShape());
01455       std::transform(array0.begin(), array0.end(), result.data(),
01456                      std::bind2nd(std::equal_to<Type>(), arg));
01457       return result;
01458     }
01459 
01460     
01461     // Elementwise comparison of an ArrayND with another array.
01462     template <size_t Dimension, class Type>
01463     ArrayND<Dimension, bool>
01464     operator==(const ArrayND<Dimension, Type>& array0,
01465                const ArrayND<Dimension, Type>& arrayN)
01466     {
01467       array0.checkDimension(arrayN.getShape());
01468       ArrayND<Dimension, bool> result(array0.getShape());
01469       std::transform(array0.begin(), array0.end(), arrayN.begin(),
01470                      result.begin(), std::equal_to<Type>());
01471       return result;
01472     }
01473 
01474   
01475     template <size_t Dimension, class Type>
01476     ArrayND<Dimension, bool>
01477     operator>(const ArrayND<Dimension, Type>& array0, const Type arg)
01478     {
01479       ArrayND<Dimension, bool> result(array0.getShape());
01480       std::transform(array0.begin(), array0.end(), result.begin(),
01481                      std::bind2nd(std::greater<Type>(), arg));
01482       return result;
01483     }
01484 
01485   
01486     template <size_t Dimension, class Type>
01487     ArrayND<Dimension, bool>
01488     operator>=(const ArrayND<Dimension, Type>& array0, const Type arg)
01489     {
01490       ArrayND<Dimension, bool> result(array0.getShape());
01491       std::transform(array0.begin(), array0.end(), result.begin(),
01492                      std::bind2nd(std::greater_equal<Type>(), arg));
01493       return result;
01494     }
01495 
01496 
01497     template <size_t Dimension, class Type>
01498     ArrayND<Dimension, bool>
01499     operator<(const ArrayND<Dimension, Type>& array0, const Type arg)
01500     {
01501       ArrayND<Dimension, bool> result(array0.getShape());
01502       std::transform(array0.begin(), array0.end(), result.begin(),
01503                      std::bind2nd(std::less<Type>(), arg));
01504       return result;
01505     }
01506 
01507 
01508     template <size_t Dimension, class Type>
01509     ArrayND<Dimension, bool>
01510     operator<=(const ArrayND<Dimension, Type>& array0, const Type arg)
01511     {
01512       ArrayND<Dimension, bool> result(array0.getShape());
01513       std::transform(array0.begin(), array0.end(), result.begin(),
01514                      std::bind2nd(std::less_equal<Type>(), arg));
01515       return result;
01516     }
01517 
01518 
01519     template <size_t Dimension, class Type>
01520     std::ostream& operator<<(std::ostream& stream,
01521                              const ArrayND<Dimension, Type>& array0)
01522     {
01523       if (!stream){
01524         return stream;
01525       }
01526       stream << "ArrayND {\n"
01527              << "  shape: " << array0.getShape() << "\n"
01528              << "  data: " << array0.ravel() << "\n"
01529              << "}";
01530       return stream;
01531     }
01532 
01533     
01534     // Sets the value of an ArrayND instance from a std::istream.
01535     template <size_t Dimension, class Type>
01536     std::istream& operator>>(std::istream& stream,
01537                              ArrayND<Dimension, Type> & array0)
01538     {
01539       if (!stream){
01540         return stream;
01541       }
01542       // Construct an InputStream instance so we can use our
01543       // convenience functions.
01544       InputStream inputStream(stream, InputStream::SKIP_WHITESPACE);
01545       inputStream.expect("ArrayND");
01546       inputStream.expect("{");
01547 
01548       Array1D<size_t> shape;
01549       inputStream.expect("shape:");
01550       inputStream >> shape;
01551 
01552       Array1D<Type> data;
01553       inputStream.expect("data:");
01554       inputStream >> data;
01555       
01556       if(!inputStream) {
01557         return stream;
01558       }
01559       array0.reinit(shape);
01560       array0.copy(data.data());
01561       return stream;
01562     }
01563 
01564   } // namespace numeric
01565 
01566 } // namespace dlr
01567 
01568 #endif /* #ifdef DLRNUMERIC_ARRAYND_H */

Generated on Tue Jan 6 17:52:06 2009 for dlrUtilities Utility Library by  doxygen 1.5.6