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 
00303       bool
00304       isAllocated() const {return m_isAllocated;}
00305 
00312       size_t
00313       length() const {return this->size();}
00314 
00327       std::istream&
00328       readFromStream(std::istream& inputStream);
00329 
00337       size_t*
00338       refCountPtr() const {return m_refCountPtr;}
00339     
00346       void
00347       reinit(size_t size);
00348     
00355       size_t
00356       size() const {return m_size;}
00357   
00366       Array1D<Type>&
00367       operator=(const Array1D<Type>& source);
00368 
00376       Array1D<Type>&
00377       operator=(Type value);
00378 
00386       Type&
00387       operator()(size_t index) {
00388         this->checkBounds(index);
00389         return m_dataPtr[index];
00390       }
00391   
00399       Type operator()(size_t index) const {
00400         this->checkBounds(index);
00401         return m_dataPtr[index];
00402       }
00403 
00412       Type& operator[](size_t index) {return this->operator()(index);}
00413 
00422       Type operator[](size_t index) const {return this->operator()(index);}
00423 
00435       template <class Type2>
00436       Array1D<Type>&
00437       operator+=(const Array1D<Type2>& arg);
00438     
00446       Array1D<Type>&
00447       operator+=(const Type arg);
00448 
00460       template <class Type2>
00461       Array1D<Type>&
00462       operator-=(const Array1D<Type2>& arg);
00463 
00471       Array1D<Type>&
00472       operator-=(const Type arg);
00473 
00485       template <class Type2>
00486       Array1D<Type>&
00487       operator*=(const Array1D<Type2>& arg);
00488 
00496       Array1D<Type>&
00497       operator*=(const Type arg);
00498 
00510       template <class Type2>
00511       Array1D<Type>&
00512       operator/=(const Array1D<Type2>& arg);
00513 
00521       Array1D<Type>&
00522       operator/=(const Type arg);
00523 
00524     private:
00525       /* ======== Private member functions ======== */
00526 
00530       void
00531       allocate();
00532 
00539       inline void
00540       checkBounds(size_t index) const;
00541 
00542 
00548       void
00549       deAllocate();
00550 
00551       // Constants to help with formatting.  We use the initialization
00552       // on first use paradigm for the string constants to avoid
00553       // headaches.
00554 
00559       static const std::string& ioIntro(); 
00560 
00565       static const std::string& ioOutro();
00566 
00571       static const char ioOpening = '[';
00572 
00577       static const char ioClosing = ']';
00578 
00583       static const char ioSeparator = ',';
00584     
00585       /* ======== Private data members ======== */
00586       size_t m_size;
00587       Type* m_dataPtr;
00588       size_t* m_refCountPtr;
00589       bool m_isAllocated;
00590 
00591     };
00592 
00593     /* Non-member functions which should maybe wind up in a different file */
00594 
00608     template <class Type>
00609     Array1D<Type>
00610     operator+(const Array1D<Type>& array0, const Array1D<Type>& array1);
00611   
00625     template <class Type>
00626     Array1D<Type>
00627     operator-(const Array1D<Type>& array0, const Array1D<Type>& array1);
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 
00674     template <class Type>
00675     Array1D<Type> operator+(const Array1D<Type>& array, Type scalar);
00676 
00688     template <class Type>
00689     Array1D<Type> operator-(const Array1D<Type>& array0, Type scalar);
00690 
00702     template <class Type>
00703     Array1D<Type> operator*(const Array1D<Type>& array0, Type scalar);
00704 
00716     template <class Type>
00717     Array1D<Type> operator/(const Array1D<Type>& array0, Type scalar);
00718 
00730     template <class Type>
00731     inline Array1D<Type> operator+(Type scalar, const Array1D<Type>& array0);
00732 
00733 
00745     template <class Type>
00746     inline Array1D<Type> operator-(Type scalar, const Array1D<Type>& array0);
00747 
00759     template <class Type>
00760     inline Array1D<Type> operator*(Type scalar, const Array1D<Type>& array0);
00761 
00773     template <class Type>
00774     inline Array1D<Type> operator/(Type scalar, const Array1D<Type>& array0);
00775 
00776 
00788     template <class Type>
00789     Array1D<bool>
00790     operator==(const Array1D<Type>& array0, const Type arg);
00791 
00792     
00805     template <class Type>
00806     Array1D<bool>
00807     operator==(const Array1D<Type>& array0, const Array1D<Type>& array1);
00808     
00809 
00820     template <class Type>
00821     Array1D<bool>
00822     operator>(const Array1D<Type>& array0, const Type arg);
00823 
00824   
00836     template <class Type>
00837     Array1D<bool>
00838     operator>=(const Array1D<Type>& array0, const Type arg);
00839 
00840 
00851     template <class Type>
00852     Array1D<bool>
00853     operator<(const Array1D<Type>& array0, const Type arg);
00854 
00855 
00867     template <class Type>
00868     Array1D<bool>
00869     operator<=(const Array1D<Type>& array0, const Type arg);
00870 
00871   
00891     template <class Type>
00892     std::ostream& operator<<(std::ostream& stream, const Array1D<Type>& array0);
00893 
00905     template <class Type>
00906     std::istream&
00907     operator>>(std::istream& stream, Array1D<Type>& array0);
00908 
00909   } // namespace numeric
00910 
00911 } // namespace dlr
00912 
00913 
00914 /* ======= Declarations to maintain compatibility with legacy code. ======= */
00915 
00916 namespace dlr {
00917 
00918   using numeric::Array1D;
00919 
00920 } // namespace dlr
00921 
00922 
00923 /* *****************************************************************
00924  * Member function definitions follow.  This would be a .C file
00925  * if it weren't templated.
00926  * ***************************************************************** */
00927 
00928 #include <algorithm>
00929 #include <sstream>
00930 #include <vector>
00931 #include <dlrCommon/inputStream.h>
00932 #include <dlrNumeric/numericTraits.h>
00933 
00934 namespace dlr {
00935 
00936   namespace numeric {
00937     
00938     // Static constant describing how the string representation of an
00939     // Array1D should start.
00940     template <class Type>
00941     const std::string&
00942     Array1D<Type>::
00943     ioIntro()
00944     {
00945       static const std::string intro = "Array1D(";
00946       return intro;
00947     }
00948 
00949 
00950     // Static constant describing how the string representation of an
00951     // Array1D should end.
00952     template <class Type>
00953     const std::string&
00954     Array1D<Type>::
00955     ioOutro()
00956     {
00957       static const std::string outro = ")";
00958       return outro;
00959     }
00960 
00961     // Non-static member functions below.
00962 
00963     template <class Type>
00964     Array1D<Type>::
00965     Array1D()
00966       : m_size(0),
00967         m_dataPtr(0),
00968         m_refCountPtr(0),
00969         m_isAllocated(false)
00970     {
00971       // Empty.
00972     }
00973 
00974   
00975     template <class Type>
00976     Array1D<Type>::
00977     Array1D(size_t size)
00978       : m_size(size),
00979         m_dataPtr(0),           // This will be set in the call to allocate().
00980         m_refCountPtr(0), // This will be set in the call to allocate().
00981         m_isAllocated(false)
00982     {
00983       this->allocate();
00984     }
00985 
00986 
00987     // Construct from an initialization string.
00988     template <class Type>
00989     Array1D<Type>::
00990     Array1D(const std::string& inputString)
00991       : m_size(0),
00992         m_dataPtr(0),
00993         m_refCountPtr(0),
00994         m_isAllocated(false)
00995     {
00996       // We'll use the stream input operator to parse the string.
00997       std::istringstream inputStream(inputString);
00998 
00999       // Now read the string into an array.
01000       Array1D<Type> inputArray;
01001       inputStream >> inputArray;
01002       if(!inputStream) {
01003         std::ostringstream message;
01004         message << "Couldn't parse input string: \"" << inputString << "\".";
01005         DLR_THROW3(ValueException, "Array1D::Array1D(const std::string&)",
01006                    message.str().c_str());                 
01007       }
01008 
01009       // If all went well, copy into *this.
01010       *this = inputArray;
01011     }
01012 
01013   
01014     /* When copying from a Array1D do a shallow copy */
01015     /* Update reference count if the array we're copying has */
01016     /* valid data. */
01017     template <class Type>
01018     Array1D<Type>::
01019     Array1D(const Array1D<Type>& source)
01020       : m_size(source.m_size),
01021         m_dataPtr(source.m_dataPtr),
01022         m_refCountPtr(source.m_refCountPtr),
01023         m_isAllocated(source.m_isAllocated)
01024     {
01025       if(m_isAllocated) {
01026         ++(*m_refCountPtr);
01027       }
01028     }
01029 
01030 
01031     template <class Type>
01032     Array1D<Type>::
01033     Array1D(size_t size, Type* const dataPtr)
01034       : m_size(size),
01035         m_dataPtr(dataPtr),
01036         m_refCountPtr(NULL),
01037         m_isAllocated(false)
01038     {
01039       // empty
01040     }
01041 
01042 
01043     template <class Type>
01044     Array1D<Type>::
01045     Array1D(size_t size, Type* const dataPtr, size_t* const refCountPtr)
01046       : m_size(size),
01047         m_dataPtr(dataPtr),
01048         m_refCountPtr(refCountPtr),
01049         m_isAllocated(true)
01050     {
01051       ++(*m_refCountPtr);
01052     }
01053 
01054 
01055     template <class Type>
01056     Array1D<Type>::~Array1D()
01057     {
01058       deAllocate();
01059     }
01060 
01061 
01062     template <class Type>
01063     inline void Array1D<Type>::
01064     checkDimension(size_t size) const
01065     {
01066 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01067       if(size != this->size()) {
01068         std::ostringstream message;
01069         message << "Size mismatch: required size is " << size
01070                 << " while *this has dimension " << this->size() << ".";
01071         DLR_THROW(IndexException, "Array1D::checkDimension()",
01072                   message.str().c_str());
01073       }
01074 #endif
01075     }
01076 
01077 
01078     template <class Type>
01079     Array1D<Type> Array1D<Type>::
01080     copy() const
01081     {
01082       Array1D<Type> newArray(m_size);
01083       newArray.copy(*this);
01084       return newArray;
01085     }
01086 
01087   
01088     template <class Type> template <class Type2>
01089     void Array1D<Type>::
01090     copy(const Array1D<Type2>& source)
01091     {
01092       if(source.size() != m_size) {
01093         std::ostringstream message;
01094         message << "Mismatched array sizes. Source array has "
01095                 << source.size() << " elements, while destination array has "
01096                 << m_size << " elements.";
01097         DLR_THROW3(ValueException, "Array1D::copy(const Array1D&)",
01098                    message.str().c_str());
01099       }
01100       if(m_size != 0) {
01101         this->copy(source.data());
01102       }
01103     }
01104 
01105   
01106     template <class Type> template <class Type2>
01107     void
01108     Array1D<Type>::
01109     copy(const Type2* dataPtr)
01110     {
01111       std::copy(dataPtr, dataPtr + m_size, m_dataPtr);
01112     }
01113 
01114 
01115     template <class Type>
01116     Array1D<Type>& Array1D<Type>::
01117     operator=(Type val)
01118     {
01119       std::fill(m_dataPtr, m_dataPtr + m_size, val);
01120       return *this;
01121     }
01122 
01123 
01124     // This member function sets the value of the array from an input
01125     // stream.
01126     template <class Type>
01127     std::istream&
01128     Array1D<Type>::
01129     readFromStream(std::istream& inputStream)
01130     {
01131       // Most of the time, InputType will be the same as Type.
01132       typedef typename NumericTraits<Type>::TextOutputType InputType;
01133 
01134       // If stream is in a bad state, we can't read from it.
01135       if (!inputStream){
01136         return inputStream;
01137       }
01138     
01139       // It's a lot easier to use a try block than to be constantly
01140       // testing whether the IO has succeeded, so we tell inputStream to
01141       // complain if anything goes wrong.
01142       std::ios_base::iostate oldExceptionState = inputStream.exceptions();
01143       inputStream.exceptions(
01144         std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit);
01145 
01146       // Now on with the show.
01147       try{
01148         // Construct an InputStream instance so we can use our
01149         // convenience functions.
01150         InputStream stream(inputStream);
01151 
01152         stream.skipWhiteSpace();
01153       
01154         // We won't require the input format to start with "Array1D(", but
01155         // if it does we read it here.
01156         bool foundIntro = false;
01157         if(stream.peek() == ioIntro()[0]) {
01158           foundIntro = true;
01159           stream.expect(ioIntro());
01160         }
01161 
01162         // OK.  We've dispensed with the intro.  What's left should be of
01163         // the format "[#, #, #, ...]".  We require the square brackets to
01164         // be there.
01165         stream.expect(ioOpening);
01166 
01167         // Read the data.
01168         InputType inputValue;
01169         std::vector<Type> inputBuffer;
01170         while(1) {
01171           // Read the next value.
01172           stream >> inputValue;
01173           inputBuffer.push_back(static_cast<Type>(inputValue));
01174 
01175           // Read the separator, or else the closing character.
01176           char inChar = 0;
01177           stream >> inChar;
01178           if(inChar == ioClosing) {
01179             // Found a closing.  Stop here.
01180             break;
01181           }
01182           if(inChar != ioSeparator) {
01183             // Missing separator.  Fail here.
01184             stream.clear(std::ios_base::failbit);
01185           }
01186         }
01187 
01188         // If we found an intro, we expect the corresponding outro.
01189         if(foundIntro) {
01190           stream.expect(ioOutro());
01191         }
01192 
01193         // Now we're done with all of the parsing.  Copy the data to *this.
01194         this->reinit(inputBuffer.size());
01195         std::copy(inputBuffer.begin(), inputBuffer.end(), this->begin());
01196 
01197       } catch(std::ios_base::failure) {
01198         // Empty
01199       }
01200       inputStream.exceptions(oldExceptionState);
01201       return inputStream;
01202     }
01203   
01204 
01205     template <class Type>
01206     void Array1D<Type>::
01207     reinit(size_t size)
01208     {
01209       this->deAllocate();
01210       this->m_size = size;
01211       this->allocate();
01212     }
01213   
01214 
01215     template <class Type>
01216     Array1D<Type>& Array1D<Type>::
01217     operator=(const Array1D<Type>& source)
01218     {
01219       // Check for self-assignment
01220       if(&source != this) {
01221         this->deAllocate();
01222         m_size = source.m_size;
01223         m_dataPtr = source.m_dataPtr;
01224         m_refCountPtr = source.m_refCountPtr;
01225         m_isAllocated = source.m_isAllocated;
01226         // Update reference count, if appropriate.
01227         if(m_isAllocated) {
01228           ++(*m_refCountPtr);
01229         }
01230       }
01231       return *this;
01232     }
01233 
01234 
01235     template <class Type> template <class Type2>
01236     Array1D<Type>&
01237     Array1D<Type>::
01238     operator+=(const Array1D<Type2>& arg)
01239     {
01240       if(m_size != arg.size()) {
01241         std::ostringstream message;
01242         message << "Mismatched array sizes. Argument array has "
01243                 << arg.size() << " elements, while destination array has "
01244                 << m_size << " elements.";
01245         DLR_THROW3(ValueException, "Array1D::operator+=(const Array1D&)",
01246                    message.str().c_str());
01247       }
01248       std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01249                      std::plus<Type>());
01250       return *this;
01251     }
01252 
01253 
01254     template <class Type>
01255     Array1D<Type>&
01256     Array1D<Type>::
01257     operator+=(const Type arg)
01258     {
01259       std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01260                      std::bind2nd(std::plus<Type>(), arg));
01261       return *this;
01262     }
01263 
01264 
01265     template <class Type> template <class Type2>
01266     Array1D<Type>&
01267     Array1D<Type>::
01268     operator-=(const Array1D<Type2>& arg)
01269     {
01270       if(m_size != arg.size()) {
01271         std::ostringstream message;
01272         message << "Mismatched array sizes. Argument array has "
01273                 << arg.size() << " elements, while destination array has "
01274                 << m_size << " elements.";
01275         DLR_THROW3(ValueException, "Array1D::operator-=(const Array1D&)",
01276                    message.str().c_str());
01277       }
01278       std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01279                      std::minus<Type>());
01280       return *this;
01281     }
01282 
01283 
01284     template <class Type>
01285     Array1D<Type>&
01286     Array1D<Type>::
01287     operator-=(const Type arg)
01288     {
01289       std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01290                      std::bind2nd(std::minus<Type>(), arg));
01291       return *this;
01292     }
01293 
01294 
01295     template <class Type> template <class Type2>
01296     Array1D<Type>&
01297     Array1D<Type>::
01298     operator*=(const Array1D<Type2>& arg)
01299     {
01300       if(m_size != arg.size()) {
01301         std::ostringstream message;
01302         message << "Mismatched array sizes. Argument array has "
01303                 << arg.size() << " elements, while destination array has "
01304                 << m_size << " elements.";
01305         DLR_THROW3(ValueException, "Array1D::operator*=(const Array1D&)",
01306                    message.str().c_str());
01307       }
01308       std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01309                      std::multiplies<Type>());
01310       return *this;
01311     }
01312 
01313 
01314     template <class Type>
01315     Array1D<Type>&
01316     Array1D<Type>::
01317     operator*=(const Type arg)
01318     {
01319       std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01320                      std::bind2nd(std::multiplies<Type>(), arg));
01321       return *this;
01322     }
01323 
01324 
01325     template <class Type> template <class Type2>
01326     Array1D<Type>&
01327     Array1D<Type>::
01328     operator/=(const Array1D<Type2>& arg)
01329     {
01330       if(m_size != arg.size()) {
01331         std::ostringstream message;
01332         message << "Mismatched array sizes. Argument array has "
01333                 << arg.size() << " elements, while destination array has "
01334                 << m_size << " elements.";
01335         DLR_THROW3(ValueException, "Array1D::operator/=(const Array1D&)",
01336                    message.str().c_str());
01337       }
01338       std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01339                      std::divides<Type>());
01340       return *this;
01341     }
01342 
01343 
01344     template <class Type>
01345     Array1D<Type>&
01346     Array1D<Type>::
01347     operator/=(const Type arg)
01348     {
01349       std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01350                      std::bind2nd(std::divides<Type>(), arg));
01351       return *this;
01352     }
01353 
01354 
01355     template <class Type>
01356     void Array1D<Type>::
01357     allocate()
01358     {
01359       // First check array size.  It doesn't make sense to allocate memory
01360       // for a zero size array.
01361       if(m_size > 0) {
01362         // Allocate data storage, and a new reference count.  new() should
01363         // throw an exception if we run out of memory.
01364         m_dataPtr = new(Type[m_size]);
01365         m_refCountPtr = new size_t;
01366         // Set reference count to show that exactly one Array is pointing
01367         // to this data.
01368         *m_refCountPtr = 1;
01369         m_isAllocated = true;
01370       } else {
01371         // Array size is zero, so no need to allocate memory.
01372         m_dataPtr = 0;
01373         m_refCountPtr = 0;
01374         m_isAllocated = false;
01375       }
01376       return;
01377     }
01378 
01379 
01380     template <class Type>
01381     inline void Array1D<Type>::
01382     checkBounds(size_t index) const
01383     {
01384 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01385       if(index < 0 || index >= m_size) {
01386         std::ostringstream message;
01387         message << "Index " << index << " is invalid for a(n) " << m_size
01388                 << " element array.";
01389         DLR_THROW(IndexException, "Array1D::checkBounds()",
01390                   message.str().c_str());
01391       }
01392 #endif
01393     }
01394 
01395 
01396     template <class Type>
01397     void Array1D<Type>::
01398     deAllocate()
01399     {
01400       // Are we responsible for deallocating the contents of this array?
01401       if(m_isAllocated == true) {
01402         // If yes, are we currently the only array pointing to this data?
01403         if(--(*m_refCountPtr) == 0) {
01404           // If yes, then delete both data and reference count, and change
01405           // m_isAllocated to reflect this.
01406           delete[] m_dataPtr;
01407           delete m_refCountPtr;
01408           m_isAllocated = false;
01409         }
01410       }
01411       // Abandon our pointers to data and reference count.
01412       m_dataPtr = 0;
01413       m_refCountPtr = 0;
01414     }
01415 
01416     /* Non-member functions which should maybe wind up in a different file? */
01417   
01418     template <class Type>
01419     Array1D<Type> operator+(const Array1D<Type>& array0,
01420                             const Array1D<Type>& array1)
01421     {
01422       if(array0.size() != array1.size()) {
01423         std::ostringstream message;
01424         message << "Array sizes do not match.  Array0 has " << array0.size()
01425                 << " elements, while array1 has " << array1.size()
01426                 << " elements.";
01427         DLR_THROW(ValueException, "Array1D::operator+()", message.str().c_str());
01428       }
01429       Array1D<Type> result(array0.size());
01430       std::transform(array0.begin(), array0.end(), array1.begin(),
01431                      result.begin(), std::plus<Type>());
01432       return result;
01433     }
01434 
01435 
01436     template <class Type>
01437     Array1D<Type> operator-(const Array1D<Type>& array0,
01438                             const Array1D<Type>& array1)
01439     {
01440       if(array0.size() != array1.size()) {
01441         std::ostringstream message;
01442         message << "Array sizes do not match.  Array0 has " << array0.size()
01443                 << " elements, while array1 has " << array1.size()
01444                 << " elements.";
01445         DLR_THROW(ValueException, "Array1D::operator-()", message.str().c_str());
01446       }
01447       Array1D<Type> result(array0.size());
01448       std::transform(array0.begin(), array0.end(), array1.begin(),
01449                      result.begin(), std::minus<Type>());
01450       return result;
01451     }
01452 
01453 
01454     template <class Type>
01455     Array1D<Type> operator*(const Array1D<Type>& array0,
01456                             const Array1D<Type>& array1)
01457     {
01458       if(array0.size() != array1.size()) {
01459         std::ostringstream message;
01460         message << "Array sizes do not match.  Array0 has " << array0.size()
01461                 << " elements, while array1 has " << array1.size()
01462                 << " elements.";
01463         DLR_THROW(ValueException, "Array1D::operator*()", message.str().c_str());
01464       }
01465       Array1D<Type> result(array0.size());
01466       std::transform(array0.begin(), array0.end(), array1.begin(),
01467                      result.begin(), std::multiplies<Type>());
01468       return result;
01469     }
01470 
01471 
01472     template <class Type>
01473     Array1D<Type> operator/(const Array1D<Type>& array0,
01474                             const Array1D<Type>& array1)
01475     {
01476       if(array0.size() != array1.size()) {
01477         std::ostringstream message;
01478         message << "Array sizes do not match.  Array0 has " << array0.size()
01479                 << " elements, while array1 has " << array1.size()
01480                 << " elements.";
01481         DLR_THROW(ValueException, "Array1D::operator/()", message.str().c_str());
01482       }
01483       Array1D<Type> result(array0.size());
01484       std::transform(array0.begin(), array0.end(), array1.begin(),
01485                      result.begin(), std::divides<Type>());
01486       return result;
01487     }
01488 
01489 
01490     template <class Type>
01491     Array1D<Type> operator+(const Array1D<Type>& array0, Type scalar)
01492     {
01493       Array1D<Type> result(array0.size());
01494       std::transform(array0.begin(), array0.end(), result.begin(),
01495                      std::bind2nd(std::plus<Type>(), scalar));
01496       return result;
01497     }
01498 
01499 
01500     template <class Type>
01501     Array1D<Type> operator-(const Array1D<Type>& array0, Type scalar)
01502     {
01503       Array1D<Type> result(array0.size());
01504       std::transform(array0.begin(), array0.end(), result.begin(),
01505                      std::bind2nd(std::minus<Type>(), scalar));
01506       return result;
01507     }
01508 
01509 
01510     template <class Type>
01511     Array1D<Type> operator*(const Array1D<Type>& array0, Type scalar)
01512     {
01513       Array1D<Type> result(array0.size());
01514       std::transform(array0.begin(), array0.end(), result.begin(),
01515                      std::bind2nd(std::multiplies<Type>(), scalar));
01516       return result;
01517     }
01518 
01519 
01520     template <class Type>
01521     Array1D<Type> operator/(const Array1D<Type>& array0, Type scalar)
01522     {
01523       Array1D<Type> result(array0.size());
01524       std::transform(array0.begin(), array0.end(), result.begin(),
01525                      std::bind2nd(std::divides<Type>(), scalar));
01526       return result;
01527     }
01528 
01529 
01530     template <class Type>
01531     inline Array1D<Type> operator+(Type scalar, const Array1D<Type>& array0)
01532     {
01533       return array0 + scalar;
01534     }
01535 
01536 
01537     template <class Type>
01538     Array1D<Type> operator-(Type scalar, const Array1D<Type>& array0)
01539     {
01540       Array1D<Type> result(array0.size());
01541       std::transform(array0.begin(), array0.end(), result.begin(),
01542                      std::bind1st(std::minus<Type>(), scalar));
01543       return result;
01544     }
01545 
01546   
01547     template <class Type>
01548     inline Array1D<Type> operator*(Type scalar, const Array1D<Type>& array0)
01549     {
01550       return array0 * scalar;
01551     }
01552 
01553   
01554     template <class Type>
01555     Array1D<Type> operator/(Type scalar, const Array1D<Type>& array0)
01556     {
01557       Array1D<Type> result(array0.size());
01558       std::transform(array0.begin(), array0.end(), result.begin(),
01559                      std::bind1st(std::divides<Type>(), scalar));
01560       return result;
01561     }
01562   
01563 
01564     // Elementwise comparison of an Array1D with a constant.
01565     template <class Type>
01566     Array1D<bool>
01567     operator==(const Array1D<Type>& array0, const Type arg)
01568     {
01569       Array1D<bool> result(array0.size());
01570       std::transform(array0.begin(), array0.end(), result.data(),
01571                      std::bind2nd(std::equal_to<Type>(), arg));
01572       return result;
01573     }
01574 
01575     
01576     // Elementwise comparison of an Array1D with another array.
01577     template <class Type>
01578     Array1D<bool>
01579     operator==(const Array1D<Type>& array0, const Array1D<Type>& array1)
01580     {
01581       array0.checkDimension(array1.size());
01582       Array1D<bool> result(array0.size());
01583       std::transform(array0.begin(), array0.end(), array1.begin(),
01584                      result.begin(), std::equal_to<Type>());
01585       return result;
01586     }
01587 
01588   
01589     template <class Type>
01590     Array1D<bool>
01591     operator>(const Array1D<Type>& array0, const Type arg)
01592     {
01593       Array1D<bool> result(array0.size());
01594       std::transform(array0.begin(), array0.end(), result.begin(),
01595                      std::bind2nd(std::greater<Type>(), arg));
01596       return result;
01597     }
01598 
01599   
01600     template <class Type>
01601     Array1D<bool>
01602     operator>=(const Array1D<Type>& array0, const Type arg)
01603     {
01604       Array1D<bool> result(array0.size());
01605       std::transform(array0.begin(), array0.end(), result.begin(),
01606                      std::bind2nd(std::greater_equal<Type>(), arg));
01607       return result;
01608     }
01609 
01610 
01611     template <class Type>
01612     Array1D<bool>
01613     operator<(const Array1D<Type>& array0, const Type arg)
01614     {
01615       Array1D<bool> result(array0.size());
01616       std::transform(array0.begin(), array0.end(), result.begin(),
01617                      std::bind2nd(std::less<Type>(), arg));
01618       return result;
01619     }
01620 
01621 
01622     template <class Type>
01623     Array1D<bool>
01624     operator<=(const Array1D<Type>& array0, const Type arg)
01625     {
01626       Array1D<bool> result(array0.size());
01627       std::transform(array0.begin(), array0.end(), result.begin(),
01628                      std::bind2nd(std::less_equal<Type>(), arg));
01629       return result;
01630     }
01631 
01632 
01633     template <class Type>
01634     std::ostream& operator<<(std::ostream& stream, const Array1D<Type>& array0)
01635     {
01636       // Most of the time, OutputType will be the same as Type.
01637       typedef typename NumericTraits<Type>::TextOutputType OutputType;
01638     
01639       if (!stream){
01640         DLR_THROW(IOException, "operator<<(std::ostream&, const Array1D&)",
01641                   "Invalid stream\n");
01642       }
01643 
01644       size_t index;
01645       stream << "Array1D([";
01646       if (array0.size() > 0){
01647         for(index = 0; index < array0.size() - 1; ++index) {
01648           stream << static_cast<OutputType>(array0(index)) << ", ";
01649         }
01650         stream << static_cast<OutputType>(array0(index));
01651       }
01652       stream << "])";
01653       return stream;
01654     }
01655 
01656     // Sets the value of an Array1D instance from a std::istream.
01657     template <class Type>
01658     std::istream& operator>>(std::istream& inputStream, Array1D<Type>& array0)
01659     {
01660       return array0.readFromStream(inputStream);
01661     }
01662 
01663   } // namespace numeric
01664 
01665 } // namespace dlr
01666 
01667 #endif // #ifdef _DLR_ARRAY1D_H_
01668 

Generated on Mon Jul 9 20:34:02 2007 for dlrLibs Utility Libraries by  doxygen 1.5.2