array1D.h

Go to the documentation of this file.
00001 
00015 #ifndef _DLR_ARRAY1D_H_
00016 #define _DLR_ARRAY1D_H_
00017 
00018 #include <iostream>
00019 #include <string>
00020 #include <dlrCommon/exception.h>
00021 
00022 namespace dlr {
00023 
00024 
00030   namespace numeric {
00031     
00054     template <class Type>
00055     class Array1D {
00056     public:
00057       /* ======== Public typedefs ======== */
00058 
00062       typedef Type value_type;
00063 
00067       typedef Type* iterator;
00068     
00073       typedef const Type* const_iterator;
00074 
00075       /* ======== Public member functions ======== */
00076 
00080       Array1D();
00081     
00088       explicit
00089       Array1D(size_t size);
00090 
00102       explicit
00103       Array1D(const std::string& inputString);
00104     
00111       Array1D(const Array1D<Type> &source);
00112     
00123       Array1D(size_t size, Type* const dataPtr);
00124     
00142       Array1D(size_t size, Type* const dataPtr, size_t* const refCountPtr);
00143     
00148       ~Array1D();
00149 
00155       iterator
00156       begin() {return m_dataPtr;}
00157 
00164       const_iterator
00165       begin() const {return m_dataPtr;}
00166 
00167 
00174       inline void
00175       checkDimension(size_t size) const;
00176 
00177     
00182       void
00183       clear() {this->reinit(0);}
00184     
00190       Array1D<Type>
00191       copy() const;
00192 
00203       template <class Type2> void
00204       copy(const Array1D<Type2>& source);
00205 
00212       template <class Type2> void
00213       copy(const Type2* dataPtr);
00214 
00222       Type*
00223       data() {return m_dataPtr;}
00224 
00231       const Type*
00232       data() const {return m_dataPtr;}
00233 
00244       Type*
00245       data(size_t index) {
00246         this->checkBounds(index);
00247         return m_dataPtr + index;
00248       }
00249     
00259       const Type*
00260       data(size_t index) const {
00261         this->checkBounds(index);
00262         return m_dataPtr + index;
00263       }
00264 
00265 
00273       bool
00274       empty() const {return this->size() == 0;}
00275 
00276     
00283       iterator
00284       end() {return m_dataPtr + m_size;}
00285 
00292       const_iterator
00293       end() const {return m_dataPtr + m_size;}
00294 
00295       
00305       inline Type
00306       getElement(size_t index0) const {return this->operator()(index0);}
00307 
00308 
00317       bool
00318       isAllocated() const {return m_isAllocated;}
00319 
00326       size_t
00327       length() const {return this->size();}
00328 
00341       std::istream&
00342       readFromStream(std::istream& inputStream);
00343 
00351       size_t*
00352       refCountPtr() const {return m_refCountPtr;}
00353     
00360       void
00361       reinit(size_t size);
00362     
00363 
00377       Type&
00378       setElement(size_t index0, const Type& value) {
00379         return this->operator()(index0) = value;
00380       }
00381 
00382 
00389       size_t
00390       size() const {return m_size;}
00391   
00400       Array1D<Type>&
00401       operator=(const Array1D<Type>& source);
00402 
00410       Array1D<Type>&
00411       operator=(Type value);
00412 
00420       Type&
00421       operator()(size_t index) {
00422         this->checkBounds(index);
00423         return m_dataPtr[index];
00424       }
00425   
00433       Type operator()(size_t index) const {
00434         this->checkBounds(index);
00435         return m_dataPtr[index];
00436       }
00437 
00446       Type& operator[](size_t index) {return this->operator()(index);}
00447 
00456       Type operator[](size_t index) const {return this->operator()(index);}
00457 
00469       template <class Type2>
00470       Array1D<Type>&
00471       operator+=(const Array1D<Type2>& arg);
00472     
00480       Array1D<Type>&
00481       operator+=(const Type arg);
00482 
00494       template <class Type2>
00495       Array1D<Type>&
00496       operator-=(const Array1D<Type2>& arg);
00497 
00505       Array1D<Type>&
00506       operator-=(const Type arg);
00507 
00519       template <class Type2>
00520       Array1D<Type>&
00521       operator*=(const Array1D<Type2>& arg);
00522 
00530       Array1D<Type>&
00531       operator*=(const Type arg);
00532 
00544       template <class Type2>
00545       Array1D<Type>&
00546       operator/=(const Array1D<Type2>& arg);
00547 
00555       Array1D<Type>&
00556       operator/=(const Type arg);
00557 
00558     private:
00559       /* ======== Private member functions ======== */
00560 
00564       void
00565       allocate();
00566 
00573       inline void
00574       checkBounds(size_t index) const;
00575 
00576 
00582       void
00583       deAllocate();
00584 
00585       // Constants to help with formatting.  We use the initialization
00586       // on first use paradigm for the string constants to avoid
00587       // headaches.
00588 
00593       static const std::string& ioIntro(); 
00594 
00599       static const std::string& ioOutro();
00600 
00605       static const char ioOpening = '[';
00606 
00611       static const char ioClosing = ']';
00612 
00617       static const char ioSeparator = ',';
00618     
00619       /* ======== Private data members ======== */
00620       size_t m_size;
00621       Type* m_dataPtr;
00622       size_t* m_refCountPtr;
00623       bool m_isAllocated;
00624 
00625     };
00626 
00627     /* Non-member functions which should maybe wind up in a different file */
00628 
00642     template <class Type>
00643     Array1D<Type>
00644     operator+(const Array1D<Type>& array0, const Array1D<Type>& array1);
00645   
00659     template <class Type>
00660     Array1D<Type>
00661     operator-(const Array1D<Type>& array0, const Array1D<Type>& array1);
00662 
00676     template <class Type>
00677     Array1D<Type>
00678     operator*(const Array1D<Type>& array0, const Array1D<Type>& array1);
00679   
00693     template <class Type>
00694     Array1D<Type>
00695     operator/(const Array1D<Type>& array0, const Array1D<Type>& array1);
00696 
00708     template <class Type>
00709     Array1D<Type> operator+(const Array1D<Type>& array, Type scalar);
00710 
00722     template <class Type>
00723     Array1D<Type> operator-(const Array1D<Type>& array0, Type scalar);
00724 
00736     template <class Type>
00737     Array1D<Type> operator*(const Array1D<Type>& array0, Type scalar);
00738 
00750     template <class Type>
00751     Array1D<Type> operator/(const Array1D<Type>& array0, Type scalar);
00752 
00764     template <class Type>
00765     inline Array1D<Type> operator+(Type scalar, const Array1D<Type>& array0);
00766 
00767 
00779     template <class Type>
00780     inline Array1D<Type> operator-(Type scalar, const Array1D<Type>& array0);
00781 
00793     template <class Type>
00794     inline Array1D<Type> operator*(Type scalar, const Array1D<Type>& array0);
00795 
00807     template <class Type>
00808     inline Array1D<Type> operator/(Type scalar, const Array1D<Type>& array0);
00809 
00810 
00822     template <class Type>
00823     Array1D<bool>
00824     operator==(const Array1D<Type>& array0, const Type arg);
00825 
00826     
00839     template <class Type>
00840     Array1D<bool>
00841     operator==(const Array1D<Type>& array0, const Array1D<Type>& array1);
00842     
00843 
00854     template <class Type>
00855     Array1D<bool>
00856     operator>(const Array1D<Type>& array0, const Type arg);
00857 
00858   
00870     template <class Type>
00871     Array1D<bool>
00872     operator>=(const Array1D<Type>& array0, const Type arg);
00873 
00874 
00885     template <class Type>
00886     Array1D<bool>
00887     operator<(const Array1D<Type>& array0, const Type arg);
00888 
00889 
00901     template <class Type>
00902     Array1D<bool>
00903     operator<=(const Array1D<Type>& array0, const Type arg);
00904 
00905   
00925     template <class Type>
00926     std::ostream& operator<<(std::ostream& stream, const Array1D<Type>& array0);
00927 
00939     template <class Type>
00940     std::istream&
00941     operator>>(std::istream& stream, Array1D<Type>& array0);
00942 
00943   } // namespace numeric
00944 
00945 } // namespace dlr
00946 
00947 
00948 /* ======= Declarations to maintain compatibility with legacy code. ======= */
00949 
00950 namespace dlr {
00951 
00952   using numeric::Array1D;
00953 
00954 } // namespace dlr
00955 
00956 
00957 /* *****************************************************************
00958  * Member function definitions follow.  This would be a .C file
00959  * if it weren't templated.
00960  * ***************************************************************** */
00961 
00962 #include <algorithm>
00963 #include <sstream>
00964 #include <vector>
00965 #include <dlrCommon/inputStream.h>
00966 #include <dlrNumeric/numericTraits.h>
00967 
00968 namespace dlr {
00969 
00970   namespace numeric {
00971     
00972     // Static constant describing how the string representation of an
00973     // Array1D should start.
00974     template <class Type>
00975     const std::string&
00976     Array1D<Type>::
00977     ioIntro()
00978     {
00979       static const std::string intro = "Array1D(";
00980       return intro;
00981     }
00982 
00983 
00984     // Static constant describing how the string representation of an
00985     // Array1D should end.
00986     template <class Type>
00987     const std::string&
00988     Array1D<Type>::
00989     ioOutro()
00990     {
00991       static const std::string outro = ")";
00992       return outro;
00993     }
00994 
00995     // Non-static member functions below.
00996 
00997     template <class Type>
00998     Array1D<Type>::
00999     Array1D()
01000       : m_size(0),
01001         m_dataPtr(0),
01002         m_refCountPtr(0),
01003         m_isAllocated(false)
01004     {
01005       // Empty.
01006     }
01007 
01008   
01009     template <class Type>
01010     Array1D<Type>::
01011     Array1D(size_t size)
01012       : m_size(size),
01013         m_dataPtr(0),           // This will be set in the call to allocate().
01014         m_refCountPtr(0), // This will be set in the call to allocate().
01015         m_isAllocated(false)
01016     {
01017       this->allocate();
01018     }
01019 
01020 
01021     // Construct from an initialization string.
01022     template <class Type>
01023     Array1D<Type>::
01024     Array1D(const std::string& inputString)
01025       : m_size(0),
01026         m_dataPtr(0),
01027         m_refCountPtr(0),
01028         m_isAllocated(false)
01029     {
01030       // We'll use the stream input operator to parse the string.
01031       std::istringstream inputStream(inputString);
01032 
01033       // Now read the string into an array.
01034       Array1D<Type> inputArray;
01035       inputStream >> inputArray;
01036       if(!inputStream) {
01037         std::ostringstream message;
01038         message << "Couldn't parse input string: \"" << inputString << "\".";
01039         DLR_THROW3(ValueException, "Array1D::Array1D(const std::string&)",
01040                    message.str().c_str());                 
01041       }
01042 
01043       // If all went well, copy into *this.
01044       *this = inputArray;
01045     }
01046 
01047   
01048     /* When copying from a Array1D do a shallow copy */
01049     /* Update reference count if the array we're copying has */
01050     /* valid data. */
01051     template <class Type>
01052     Array1D<Type>::
01053     Array1D(const Array1D<Type>& source)
01054       : m_size(source.m_size),
01055         m_dataPtr(source.m_dataPtr),
01056         m_refCountPtr(source.m_refCountPtr),
01057         m_isAllocated(source.m_isAllocated)
01058     {
01059       if(m_isAllocated) {
01060         ++(*m_refCountPtr);
01061       }
01062     }
01063 
01064 
01065     template <class Type>
01066     Array1D<Type>::
01067     Array1D(size_t size, Type* const dataPtr)
01068       : m_size(size),
01069         m_dataPtr(dataPtr),
01070         m_refCountPtr(NULL),
01071         m_isAllocated(false)
01072     {
01073       // empty
01074     }
01075 
01076 
01077     template <class Type>
01078     Array1D<Type>::
01079     Array1D(size_t size, Type* const dataPtr, size_t* const refCountPtr)
01080       : m_size(size),
01081         m_dataPtr(dataPtr),
01082         m_refCountPtr(refCountPtr),
01083         m_isAllocated(true)
01084     {
01085       ++(*m_refCountPtr);
01086     }
01087 
01088 
01089     template <class Type>
01090     Array1D<Type>::~Array1D()
01091     {
01092       deAllocate();
01093     }
01094 
01095 
01096     template <class Type>
01097     inline void Array1D<Type>::
01098     checkDimension(size_t size) const
01099     {
01100 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01101       if(size != this->size()) {
01102         std::ostringstream message;
01103         message << "Size mismatch: required size is " << size
01104                 << " while *this has dimension " << this->size() << ".";
01105         DLR_THROW(IndexException, "Array1D::checkDimension()",
01106                   message.str().c_str());
01107       }
01108 #endif
01109     }
01110 
01111 
01112     template <class Type>
01113     Array1D<Type> Array1D<Type>::
01114     copy() const
01115     {
01116       Array1D<Type> newArray(m_size);
01117       newArray.copy(*this);
01118       return newArray;
01119     }
01120 
01121   
01122     template <class Type> template <class Type2>
01123     void Array1D<Type>::
01124     copy(const Array1D<Type2>& source)
01125     {
01126       if(source.size() != m_size) {
01127         std::ostringstream message;
01128         message << "Mismatched array sizes. Source array has "
01129                 << source.size() << " elements, while destination array has "
01130                 << m_size << " elements.";
01131         DLR_THROW3(ValueException, "Array1D::copy(const Array1D&)",
01132                    message.str().c_str());
01133       }
01134       if(m_size != 0) {
01135         this->copy(source.data());
01136       }
01137     }
01138 
01139   
01140     template <class Type> template <class Type2>
01141     void
01142     Array1D<Type>::
01143     copy(const Type2* dataPtr)
01144     {
01145       std::copy(dataPtr, dataPtr + m_size, m_dataPtr);
01146     }
01147 
01148 
01149     template <class Type>
01150     Array1D<Type>& Array1D<Type>::
01151     operator=(Type val)
01152     {
01153       std::fill(m_dataPtr, m_dataPtr + m_size, val);
01154       return *this;
01155     }
01156 
01157 
01158     // This member function sets the value of the array from an input
01159     // stream.
01160     template <class Type>
01161     std::istream&
01162     Array1D<Type>::
01163     readFromStream(std::istream& inputStream)
01164     {
01165       // Most of the time, InputType will be the same as Type.
01166       typedef typename NumericTraits<Type>::TextOutputType InputType;
01167 
01168       // If stream is in a bad state, we can't read from it.
01169       if (!inputStream){
01170         return inputStream;
01171       }
01172     
01173       // It's a lot easier to use a try block than to be constantly
01174       // testing whether the IO has succeeded, so we tell inputStream to
01175       // complain if anything goes wrong.
01176       std::ios_base::iostate oldExceptionState = inputStream.exceptions();
01177       inputStream.exceptions(
01178         std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit);
01179 
01180       // Now on with the show.
01181       try{
01182         // Construct an InputStream instance so we can use our
01183         // convenience functions.
01184         InputStream stream(inputStream);
01185 
01186         stream.skipWhiteSpace();
01187       
01188         // We won't require the input format to start with "Array1D(", but
01189         // if it does we read it here.
01190         bool foundIntro = false;
01191         if(stream.peek() == ioIntro()[0]) {
01192           foundIntro = true;
01193           stream.expect(ioIntro());
01194         }
01195 
01196         // OK.  We've dispensed with the intro.  What's left should be of
01197         // the format "[#, #, #, ...]".  We require the square brackets to
01198         // be there.
01199         stream.expect(ioOpening);
01200 
01201         // Read the data.
01202         InputType inputValue;
01203         std::vector<Type> inputBuffer;
01204         while(1) {
01205           // Read the next value.
01206           stream >> inputValue;
01207           inputBuffer.push_back(static_cast<Type>(inputValue));
01208 
01209           // Read the separator, or else the closing character.
01210           char inChar = 0;
01211           stream >> inChar;
01212           if(inChar == ioClosing) {
01213             // Found a closing.  Stop here.
01214             break;
01215           }
01216           if(inChar != ioSeparator) {
01217             // Missing separator.  Fail here.
01218             stream.clear(std::ios_base::failbit);
01219           }
01220         }
01221 
01222         // If we found an intro, we expect the corresponding outro.
01223         if(foundIntro) {
01224           stream.expect(ioOutro());
01225         }
01226 
01227         // Now we're done with all of the parsing.  Copy the data to *this.
01228         this->reinit(inputBuffer.size());
01229         std::copy(inputBuffer.begin(), inputBuffer.end(), this->begin());
01230 
01231       } catch(std::ios_base::failure) {
01232         // Empty
01233       }
01234       inputStream.exceptions(oldExceptionState);
01235       return inputStream;
01236     }
01237   
01238 
01239     template <class Type>
01240     void Array1D<Type>::
01241     reinit(size_t size)
01242     {
01243       this->deAllocate();
01244       this->m_size = size;
01245       this->allocate();
01246     }
01247   
01248 
01249     template <class Type>
01250     Array1D<Type>& Array1D<Type>::
01251     operator=(const Array1D<Type>& source)
01252     {
01253       // Check for self-assignment
01254       if(&source != this) {
01255         this->deAllocate();
01256         m_size = source.m_size;
01257         m_dataPtr = source.m_dataPtr;
01258         m_refCountPtr = source.m_refCountPtr;
01259         m_isAllocated = source.m_isAllocated;
01260         // Update reference count, if appropriate.
01261         if(m_isAllocated) {
01262           ++(*m_refCountPtr);
01263         }
01264       }
01265       return *this;
01266     }
01267 
01268 
01269     template <class Type> template <class Type2>
01270     Array1D<Type>&
01271     Array1D<Type>::
01272     operator+=(const Array1D<Type2>& arg)
01273     {
01274       if(m_size != arg.size()) {
01275         std::ostringstream message;
01276         message << "Mismatched array sizes. Argument array has "
01277                 << arg.size() << " elements, while destination array has "
01278                 << m_size << " elements.";
01279         DLR_THROW3(ValueException, "Array1D::operator+=(const Array1D&)",
01280                    message.str().c_str());
01281       }
01282       std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01283                      std::plus<Type>());
01284       return *this;
01285     }
01286 
01287 
01288     template <class Type>
01289     Array1D<Type>&
01290     Array1D<Type>::
01291     operator+=(const Type arg)
01292     {
01293       std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01294                      std::bind2nd(std::plus<Type>(), arg));
01295       return *this;
01296     }
01297 
01298 
01299     template <class Type> template <class Type2>
01300     Array1D<Type>&
01301     Array1D<Type>::
01302     operator-=(const Array1D<Type2>& arg)
01303     {
01304       if(m_size != arg.size()) {
01305         std::ostringstream message;
01306         message << "Mismatched array sizes. Argument array has "
01307                 << arg.size() << " elements, while destination array has "
01308                 << m_size << " elements.";
01309         DLR_THROW3(ValueException, "Array1D::operator-=(const Array1D&)",
01310                    message.str().c_str());
01311       }
01312       std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01313                      std::minus<Type>());
01314       return *this;
01315     }
01316 
01317 
01318     template <class Type>
01319     Array1D<Type>&
01320     Array1D<Type>::
01321     operator-=(const Type arg)
01322     {
01323       std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01324                      std::bind2nd(std::minus<Type>(), arg));
01325       return *this;
01326     }
01327 
01328 
01329     template <class Type> template <class Type2>
01330     Array1D<Type>&
01331     Array1D<Type>::
01332     operator*=(const Array1D<Type2>& arg)
01333     {
01334       if(m_size != arg.size()) {
01335         std::ostringstream message;
01336         message << "Mismatched array sizes. Argument array has "
01337                 << arg.size() << " elements, while destination array has "
01338                 << m_size << " elements.";
01339         DLR_THROW3(ValueException, "Array1D::operator*=(const Array1D&)",
01340                    message.str().c_str());
01341       }
01342       std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01343                      std::multiplies<Type>());
01344       return *this;
01345     }
01346 
01347 
01348     template <class Type>
01349     Array1D<Type>&
01350     Array1D<Type>::
01351     operator*=(const Type arg)
01352     {
01353       std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01354                      std::bind2nd(std::multiplies<Type>(), arg));
01355       return *this;
01356     }
01357 
01358 
01359     template <class Type> template <class Type2>
01360     Array1D<Type>&
01361     Array1D<Type>::
01362     operator/=(const Array1D<Type2>& arg)
01363     {
01364       if(m_size != arg.size()) {
01365         std::ostringstream message;
01366         message << "Mismatched array sizes. Argument array has "
01367                 << arg.size() << " elements, while destination array has "
01368                 << m_size << " elements.";
01369         DLR_THROW3(ValueException, "Array1D::operator/=(const Array1D&)",
01370                    message.str().c_str());
01371       }
01372       std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01373                      std::divides<Type>());
01374       return *this;
01375     }
01376 
01377 
01378     template <class Type>
01379     Array1D<Type>&
01380     Array1D<Type>::
01381     operator/=(const Type arg)
01382     {
01383       std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01384                      std::bind2nd(std::divides<Type>(), arg));
01385       return *this;
01386     }
01387 
01388 
01389     template <class Type>
01390     void Array1D<Type>::
01391     allocate()
01392     {
01393       // First check array size.  It doesn't make sense to allocate memory
01394       // for a zero size array.
01395       if(m_size > 0) {
01396         // Allocate data storage, and a new reference count.  new() should
01397         // throw an exception if we run out of memory.
01398         m_dataPtr = new(Type[m_size]);
01399         m_refCountPtr = new size_t;
01400         // Set reference count to show that exactly one Array is pointing
01401         // to this data.
01402         *m_refCountPtr = 1;
01403         m_isAllocated = true;
01404       } else {
01405         // Array size is zero, so no need to allocate memory.
01406         m_dataPtr = 0;
01407         m_refCountPtr = 0;
01408         m_isAllocated = false;
01409       }
01410       return;
01411     }
01412 
01413 
01414     template <class Type>
01415     inline void Array1D<Type>::
01416     checkBounds(size_t index) const
01417     {
01418 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01419       if(index < 0 || index >= m_size) {
01420         std::ostringstream message;
01421         message << "Index " << index << " is invalid for a(n) " << m_size
01422                 << " element array.";
01423         DLR_THROW(IndexException, "Array1D::checkBounds()",
01424                   message.str().c_str());
01425       }
01426 #endif
01427     }
01428 
01429 
01430     template <class Type>
01431     void Array1D<Type>::
01432     deAllocate()
01433     {
01434       // Are we responsible for deallocating the contents of this array?
01435       if(m_isAllocated == true) {
01436         // If yes, are we currently the only array pointing to this data?
01437         if(--(*m_refCountPtr) == 0) {
01438           // If yes, then delete both data and reference count, and change
01439           // m_isAllocated to reflect this.
01440           delete[] m_dataPtr;
01441           delete m_refCountPtr;
01442           m_isAllocated = false;
01443         }
01444       }
01445       // Abandon our pointers to data and reference count.
01446       m_dataPtr = 0;
01447       m_refCountPtr = 0;
01448     }
01449 
01450     /* Non-member functions which should maybe wind up in a different file? */
01451   
01452     template <class Type>
01453     Array1D<Type> operator+(const Array1D<Type>& array0,
01454                             const Array1D<Type>& array1)
01455     {
01456       if(array0.size() != array1.size()) {
01457         std::ostringstream message;
01458         message << "Array sizes do not match.  Array0 has " << array0.size()
01459                 << " elements, while array1 has " << array1.size()
01460                 << " elements.";
01461         DLR_THROW(ValueException, "Array1D::operator+()", message.str().c_str());
01462       }
01463       Array1D<Type> result(array0.size());
01464       std::transform(array0.begin(), array0.end(), array1.begin(),
01465                      result.begin(), std::plus<Type>());
01466       return result;
01467     }
01468 
01469 
01470     template <class Type>
01471     Array1D<Type> operator-(const Array1D<Type>& array0,
01472                             const Array1D<Type>& array1)
01473     {
01474       if(array0.size() != array1.size()) {
01475         std::ostringstream message;
01476         message << "Array sizes do not match.  Array0 has " << array0.size()
01477                 << " elements, while array1 has " << array1.size()
01478                 << " elements.";
01479         DLR_THROW(ValueException, "Array1D::operator-()", message.str().c_str());
01480       }
01481       Array1D<Type> result(array0.size());
01482       std::transform(array0.begin(), array0.end(), array1.begin(),
01483                      result.begin(), std::minus<Type>());
01484       return result;
01485     }
01486 
01487 
01488     template <class Type>
01489     Array1D<Type> operator*(const Array1D<Type>& array0,
01490                             const Array1D<Type>& array1)
01491     {
01492       if(array0.size() != array1.size()) {
01493         std::ostringstream message;
01494         message << "Array sizes do not match.  Array0 has " << array0.size()
01495                 << " elements, while array1 has " << array1.size()
01496                 << " elements.";
01497         DLR_THROW(ValueException, "Array1D::operator*()", message.str().c_str());
01498       }
01499       Array1D<Type> result(array0.size());
01500       std::transform(array0.begin(), array0.end(), array1.begin(),
01501                      result.begin(), std::multiplies<Type>());
01502       return result;
01503     }
01504 
01505 
01506     template <class Type>
01507     Array1D<Type> operator/(const Array1D<Type>& array0,
01508                             const Array1D<Type>& array1)
01509     {
01510       if(array0.size() != array1.size()) {
01511         std::ostringstream message;
01512         message << "Array sizes do not match.  Array0 has " << array0.size()
01513                 << " elements, while array1 has " << array1.size()
01514                 << " elements.";
01515         DLR_THROW(ValueException, "Array1D::operator/()", message.str().c_str());
01516       }
01517       Array1D<Type> result(array0.size());
01518       std::transform(array0.begin(), array0.end(), array1.begin(),
01519                      result.begin(), std::divides<Type>());
01520       return result;
01521     }
01522 
01523 
01524     template <class Type>
01525     Array1D<Type> operator+(const Array1D<Type>& array0, Type scalar)
01526     {
01527       Array1D<Type> result(array0.size());
01528       std::transform(array0.begin(), array0.end(), result.begin(),
01529                      std::bind2nd(std::plus<Type>(), scalar));
01530       return result;
01531     }
01532 
01533 
01534     template <class Type>
01535     Array1D<Type> operator-(const Array1D<Type>& array0, Type scalar)
01536     {
01537       Array1D<Type> result(array0.size());
01538       std::transform(array0.begin(), array0.end(), result.begin(),
01539                      std::bind2nd(std::minus<Type>(), scalar));
01540       return result;
01541     }
01542 
01543 
01544     template <class Type>
01545     Array1D<Type> operator*(const Array1D<Type>& array0, Type scalar)
01546     {
01547       Array1D<Type> result(array0.size());
01548       std::transform(array0.begin(), array0.end(), result.begin(),
01549                      std::bind2nd(std::multiplies<Type>(), scalar));
01550       return result;
01551     }
01552 
01553 
01554     template <class Type>
01555     Array1D<Type> operator/(const Array1D<Type>& array0, Type scalar)
01556     {
01557       Array1D<Type> result(array0.size());
01558       std::transform(array0.begin(), array0.end(), result.begin(),
01559                      std::bind2nd(std::divides<Type>(), scalar));
01560       return result;
01561     }
01562 
01563 
01564     template <class Type>
01565     inline Array1D<Type> operator+(Type scalar, const Array1D<Type>& array0)
01566     {
01567       return array0 + scalar;
01568     }
01569 
01570 
01571     template <class Type>
01572     Array1D<Type> operator-(Type scalar, const Array1D<Type>& array0)
01573     {
01574       Array1D<Type> result(array0.size());
01575       std::transform(array0.begin(), array0.end(), result.begin(),
01576                      std::bind1st(std::minus<Type>(), scalar));
01577       return result;
01578     }
01579 
01580   
01581     template <class Type>
01582     inline Array1D<Type> operator*(Type scalar, const Array1D<Type>& array0)
01583     {
01584       return array0 * scalar;
01585     }
01586 
01587   
01588     template <class Type>
01589     Array1D<Type> operator/(Type scalar, const Array1D<Type>& array0)
01590     {
01591       Array1D<Type> result(array0.size());
01592       std::transform(array0.begin(), array0.end(), result.begin(),
01593                      std::bind1st(std::divides<Type>(), scalar));
01594       return result;
01595     }
01596   
01597 
01598     // Elementwise comparison of an Array1D with a constant.
01599     template <class Type>
01600     Array1D<bool>
01601     operator==(const Array1D<Type>& array0, const Type arg)
01602     {
01603       Array1D<bool> result(array0.size());
01604       std::transform(array0.begin(), array0.end(), result.data(),
01605                      std::bind2nd(std::equal_to<Type>(), arg));
01606       return result;
01607     }
01608 
01609     
01610     // Elementwise comparison of an Array1D with another array.
01611     template <class Type>
01612     Array1D<bool>
01613     operator==(const Array1D<Type>& array0, const Array1D<Type>& array1)
01614     {
01615       array0.checkDimension(array1.size());
01616       Array1D<bool> result(array0.size());
01617       std::transform(array0.begin(), array0.end(), array1.begin(),
01618                      result.begin(), std::equal_to<Type>());
01619       return result;
01620     }
01621 
01622   
01623     template <class Type>
01624     Array1D<bool>
01625     operator>(const Array1D<Type>& array0, const Type arg)
01626     {
01627       Array1D<bool> result(array0.size());
01628       std::transform(array0.begin(), array0.end(), result.begin(),
01629                      std::bind2nd(std::greater<Type>(), arg));
01630       return result;
01631     }
01632 
01633   
01634     template <class Type>
01635     Array1D<bool>
01636     operator>=(const Array1D<Type>& array0, const Type arg)
01637     {
01638       Array1D<bool> result(array0.size());
01639       std::transform(array0.begin(), array0.end(), result.begin(),
01640                      std::bind2nd(std::greater_equal<Type>(), arg));
01641       return result;
01642     }
01643 
01644 
01645     template <class Type>
01646     Array1D<bool>
01647     operator<(const Array1D<Type>& array0, const Type arg)
01648     {
01649       Array1D<bool> result(array0.size());
01650       std::transform(array0.begin(), array0.end(), result.begin(),
01651                      std::bind2nd(std::less<Type>(), arg));
01652       return result;
01653     }
01654 
01655 
01656     template <class Type>
01657     Array1D<bool>
01658     operator<=(const Array1D<Type>& array0, const Type arg)
01659     {
01660       Array1D<bool> result(array0.size());
01661       std::transform(array0.begin(), array0.end(), result.begin(),
01662                      std::bind2nd(std::less_equal<Type>(), arg));
01663       return result;
01664     }
01665 
01666 
01667     template <class Type>
01668     std::ostream& operator<<(std::ostream& stream, const Array1D<Type>& array0)
01669     {
01670       // Most of the time, OutputType will be the same as Type.
01671       typedef typename NumericTraits<Type>::TextOutputType OutputType;
01672     
01673       if (!stream){
01674         DLR_THROW(IOException, "operator<<(std::ostream&, const Array1D&)",
01675                   "Invalid stream\n");
01676       }
01677 
01678       size_t index;
01679       stream << "Array1D([";
01680       if (array0.size() > 0){
01681         for(index = 0; index < array0.size() - 1; ++index) {
01682           stream << static_cast<OutputType>(array0(index)) << ", ";
01683         }
01684         stream << static_cast<OutputType>(array0(index));
01685       }
01686       stream << "])";
01687       return stream;
01688     }
01689 
01690     // Sets the value of an Array1D instance from a std::istream.
01691     template <class Type>
01692     std::istream& operator>>(std::istream& inputStream, Array1D<Type>& array0)
01693     {
01694       return array0.readFromStream(inputStream);
01695     }
01696 
01697   } // namespace numeric
01698 
01699 } // namespace dlr
01700 
01701 #endif /* #ifdef _DLR_ARRAY1D_H_ */

Generated on Tue Jun 24 16:48:37 2008 for dlrUtilities Utility Library by  doxygen 1.5.5