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

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