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     
00355 
00362       void
00363       reinit(size_t arraySize);
00364     
00365 
00373       inline void
00374       reinitIfNecessary(size_t arraySize);
00375     
00376 
00390       Type&
00391       setElement(size_t index0, const Type& value) {
00392         return this->operator()(index0) = value;
00393       }
00394 
00395 
00402       size_t
00403       size() const {return m_size;}
00404   
00413       Array1D<Type>&
00414       operator=(const Array1D<Type>& source);
00415 
00423       Array1D<Type>&
00424       operator=(Type value);
00425 
00433       Type&
00434       operator()(size_t index) {
00435         this->checkBounds(index);
00436         return m_dataPtr[index];
00437       }
00438   
00446       Type operator()(size_t index) const {
00447         this->checkBounds(index);
00448         return m_dataPtr[index];
00449       }
00450 
00459       Type& operator[](size_t index) {return this->operator()(index);}
00460 
00469       Type operator[](size_t index) const {return this->operator()(index);}
00470 
00482       template <class Type2>
00483       Array1D<Type>&
00484       operator+=(const Array1D<Type2>& arg);
00485     
00493       Array1D<Type>&
00494       operator+=(const Type arg);
00495 
00507       template <class Type2>
00508       Array1D<Type>&
00509       operator-=(const Array1D<Type2>& arg);
00510 
00518       Array1D<Type>&
00519       operator-=(const Type arg);
00520 
00532       template <class Type2>
00533       Array1D<Type>&
00534       operator*=(const Array1D<Type2>& arg);
00535 
00543       Array1D<Type>&
00544       operator*=(const Type arg);
00545 
00557       template <class Type2>
00558       Array1D<Type>&
00559       operator/=(const Array1D<Type2>& arg);
00560 
00568       Array1D<Type>&
00569       operator/=(const Type arg);
00570 
00571     private:
00572       /* ======== Private member functions ======== */
00573 
00577       void
00578       allocate();
00579 
00586       inline void
00587       checkBounds(size_t index) const;
00588 
00589 
00595       void
00596       deAllocate();
00597 
00598       // Constants to help with formatting.  We use the initialization
00599       // on first use paradigm for the string constants to avoid
00600       // headaches.
00601 
00606       static const std::string& ioIntro(); 
00607 
00612       static const std::string& ioOutro();
00613 
00618       static const char ioOpening = '[';
00619 
00624       static const char ioClosing = ']';
00625 
00630       static const char ioSeparator = ',';
00631     
00632       /* ======== Private data members ======== */
00633       size_t m_size;
00634       Type* m_dataPtr;
00635       size_t* m_refCountPtr;
00636       bool m_isAllocated;
00637 
00638     };
00639 
00640     /* Non-member functions which should maybe wind up in a different file */
00641 
00655     template <class Type>
00656     Array1D<Type>
00657     operator+(const Array1D<Type>& array0, const Array1D<Type>& array1);
00658   
00672     template <class Type>
00673     Array1D<Type>
00674     operator-(const Array1D<Type>& array0, const Array1D<Type>& array1);
00675 
00689     template <class Type>
00690     Array1D<Type>
00691     operator*(const Array1D<Type>& array0, const Array1D<Type>& array1);
00692   
00706     template <class Type>
00707     Array1D<Type>
00708     operator/(const Array1D<Type>& array0, const Array1D<Type>& array1);
00709 
00721     template <class Type>
00722     Array1D<Type> operator+(const Array1D<Type>& array, Type scalar);
00723 
00735     template <class Type>
00736     Array1D<Type> operator-(const Array1D<Type>& array0, Type scalar);
00737 
00749     template <class Type>
00750     Array1D<Type> operator*(const Array1D<Type>& array0, Type scalar);
00751 
00763     template <class Type>
00764     Array1D<Type> operator/(const Array1D<Type>& array0, Type scalar);
00765 
00777     template <class Type>
00778     inline Array1D<Type> operator+(Type scalar, const Array1D<Type>& array0);
00779 
00780 
00792     template <class Type>
00793     inline Array1D<Type> operator-(Type scalar, const Array1D<Type>& array0);
00794 
00806     template <class Type>
00807     inline Array1D<Type> operator*(Type scalar, const Array1D<Type>& array0);
00808 
00820     template <class Type>
00821     inline Array1D<Type> operator/(Type scalar, const Array1D<Type>& array0);
00822 
00823 
00835     template <class Type>
00836     Array1D<bool>
00837     operator==(const Array1D<Type>& array0, const Type arg);
00838 
00839     
00852     template <class Type>
00853     Array1D<bool>
00854     operator==(const Array1D<Type>& array0, const Array1D<Type>& array1);
00855     
00856 
00867     template <class Type>
00868     Array1D<bool>
00869     operator>(const Array1D<Type>& array0, const Type arg);
00870 
00871   
00883     template <class Type>
00884     Array1D<bool>
00885     operator>=(const Array1D<Type>& array0, const Type arg);
00886 
00887 
00898     template <class Type>
00899     Array1D<bool>
00900     operator<(const Array1D<Type>& array0, const Type arg);
00901 
00902 
00914     template <class Type>
00915     Array1D<bool>
00916     operator<=(const Array1D<Type>& array0, const Type arg);
00917 
00918   
00938     template <class Type>
00939     std::ostream& operator<<(std::ostream& stream, const Array1D<Type>& array0);
00940 
00952     template <class Type>
00953     std::istream&
00954     operator>>(std::istream& stream, Array1D<Type>& array0);
00955 
00956   } // namespace numeric
00957 
00958 } // namespace dlr
00959 
00960 
00961 /* ======= Declarations to maintain compatibility with legacy code. ======= */
00962 
00963 namespace dlr {
00964 
00965   using numeric::Array1D;
00966 
00967 } // namespace dlr
00968 
00969 
00970 /* *****************************************************************
00971  * Member function definitions follow.  This would be a .C file
00972  * if it weren't templated.
00973  * ***************************************************************** */
00974 
00975 #include <algorithm>
00976 #include <sstream>
00977 #include <vector>
00978 #include <dlrCommon/inputStream.h>
00979 #include <dlrNumeric/numericTraits.h>
00980 
00981 namespace dlr {
00982 
00983   namespace numeric {
00984     
00985     // Static constant describing how the string representation of an
00986     // Array1D should start.
00987     template <class Type>
00988     const std::string&
00989     Array1D<Type>::
00990     ioIntro()
00991     {
00992       static const std::string intro = "Array1D(";
00993       return intro;
00994     }
00995 
00996 
00997     // Static constant describing how the string representation of an
00998     // Array1D should end.
00999     template <class Type>
01000     const std::string&
01001     Array1D<Type>::
01002     ioOutro()
01003     {
01004       static const std::string outro = ")";
01005       return outro;
01006     }
01007 
01008     // Non-static member functions below.
01009 
01010     template <class Type>
01011     Array1D<Type>::
01012     Array1D()
01013       : m_size(0),
01014         m_dataPtr(0),
01015         m_refCountPtr(0),
01016         m_isAllocated(false)
01017     {
01018       // Empty.
01019     }
01020 
01021   
01022     template <class Type>
01023     Array1D<Type>::
01024     Array1D(size_t arraySize)
01025       : m_size(arraySize),
01026         m_dataPtr(0),           // This will be set in the call to allocate().
01027         m_refCountPtr(0), // This will be set in the call to allocate().
01028         m_isAllocated(false)
01029     {
01030       this->allocate();
01031     }
01032 
01033 
01034     // Construct from an initialization string.
01035     template <class Type>
01036     Array1D<Type>::
01037     Array1D(const std::string& inputString)
01038       : m_size(0),
01039         m_dataPtr(0),
01040         m_refCountPtr(0),
01041         m_isAllocated(false)
01042     {
01043       // We'll use the stream input operator to parse the string.
01044       std::istringstream inputStream(inputString);
01045 
01046       // Now read the string into an array.
01047       Array1D<Type> inputArray;
01048       inputStream >> inputArray;
01049       if(!inputStream) {
01050         std::ostringstream message;
01051         message << "Couldn't parse input string: \"" << inputString << "\".";
01052         DLR_THROW3(ValueException, "Array1D::Array1D(const std::string&)",
01053                    message.str().c_str());                 
01054       }
01055 
01056       // If all went well, copy into *this.
01057       *this = inputArray;
01058     }
01059 
01060   
01061     /* When copying from a Array1D do a shallow copy */
01062     /* Update reference count if the array we're copying has */
01063     /* valid data. */
01064     template <class Type>
01065     Array1D<Type>::
01066     Array1D(const Array1D<Type>& source)
01067       : m_size(source.m_size),
01068         m_dataPtr(source.m_dataPtr),
01069         m_refCountPtr(source.m_refCountPtr),
01070         m_isAllocated(source.m_isAllocated)
01071     {
01072       if(m_isAllocated) {
01073         ++(*m_refCountPtr);
01074       }
01075     }
01076 
01077 
01078     template <class Type>
01079     Array1D<Type>::
01080     Array1D(size_t arraySize, Type* const dataPtr)
01081       : m_size(arraySize),
01082         m_dataPtr(dataPtr),
01083         m_refCountPtr(NULL),
01084         m_isAllocated(false)
01085     {
01086       // empty
01087     }
01088 
01089 
01090     template <class Type>
01091     Array1D<Type>::
01092     Array1D(size_t arraySize, Type* const dataPtr,
01093             size_t* const referenceCountPtr)
01094       : m_size(arraySize),
01095         m_dataPtr(dataPtr),
01096         m_refCountPtr(referenceCountPtr),
01097         m_isAllocated(true)
01098     {
01099       ++(*m_refCountPtr);
01100     }
01101 
01102 
01103     template <class Type>
01104     Array1D<Type>::~Array1D()
01105     {
01106       deAllocate();
01107     }
01108 
01109 
01110     template <class Type>
01111     inline void Array1D<Type>::
01112     checkDimension(size_t arraySize) const
01113     {
01114 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01115       if(arraySize != this->size()) {
01116         std::ostringstream message;
01117         message << "Size mismatch: required size is " << arraySize
01118                 << " while *this has dimension " << this->size() << ".";
01119         DLR_THROW(IndexException, "Array1D::checkDimension()",
01120                   message.str().c_str());
01121       }
01122 #endif
01123     }
01124 
01125 
01126     template <class Type>
01127     Array1D<Type> Array1D<Type>::
01128     copy() const
01129     {
01130       Array1D<Type> newArray(m_size);
01131       newArray.copy(*this);
01132       return newArray;
01133     }
01134 
01135   
01136     template <class Type> template <class Type2>
01137     void Array1D<Type>::
01138     copy(const Array1D<Type2>& source)
01139     {
01140       if(source.size() != m_size) {
01141         std::ostringstream message;
01142         message << "Mismatched array sizes. Source array has "
01143                 << source.size() << " elements, while destination array has "
01144                 << m_size << " elements.";
01145         DLR_THROW3(ValueException, "Array1D::copy(const Array1D&)",
01146                    message.str().c_str());
01147       }
01148       if(m_size != 0) {
01149         this->copy(source.data());
01150       }
01151     }
01152 
01153   
01154     template <class Type> template <class Type2>
01155     void
01156     Array1D<Type>::
01157     copy(const Type2* dataPtr)
01158     {
01159       std::copy(dataPtr, dataPtr + m_size, m_dataPtr);
01160     }
01161 
01162 
01163     template <class Type>
01164     Array1D<Type>& Array1D<Type>::
01165     operator=(Type val)
01166     {
01167       std::fill(m_dataPtr, m_dataPtr + m_size, val);
01168       return *this;
01169     }
01170 
01171 
01172     // This member function sets the value of the array from an input
01173     // stream.
01174     template <class Type>
01175     std::istream&
01176     Array1D<Type>::
01177     readFromStream(std::istream& inputStream)
01178     {
01179       // Most of the time, InputType will be the same as Type.
01180       typedef typename NumericTraits<Type>::TextOutputType InputType;
01181 
01182       // If stream is in a bad state, we can't read from it.
01183       if (!inputStream){
01184         return inputStream;
01185       }
01186     
01187       // It's a lot easier to use a try block than to be constantly
01188       // testing whether the IO has succeeded, so we tell inputStream to
01189       // complain if anything goes wrong.
01190       std::ios_base::iostate oldExceptionState = inputStream.exceptions();
01191       inputStream.exceptions(
01192         std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit);
01193 
01194       // Now on with the show.
01195       try{
01196         // Construct an InputStream instance so we can use our
01197         // convenience functions.
01198         InputStream stream(inputStream);
01199 
01200         stream.skipWhiteSpace();
01201       
01202         // We won't require the input format to start with "Array1D(", but
01203         // if it does we read it here.
01204         bool foundIntro = false;
01205         if(stream.peek() == ioIntro()[0]) {
01206           foundIntro = true;
01207           stream.expect(ioIntro());
01208         }
01209 
01210         // OK.  We've dispensed with the intro.  What's left should be of
01211         // the format "[#, #, #, ...]".  We require the square brackets to
01212         // be there.
01213         stream.expect(ioOpening);
01214 
01215         // Read the data.
01216         InputType inputValue;
01217         std::vector<Type> inputBuffer;
01218         while(1) {
01219           // Read the next value.
01220           stream >> inputValue;
01221           inputBuffer.push_back(static_cast<Type>(inputValue));
01222 
01223           // Read the separator, or else the closing character.
01224           char inChar = 0;
01225           stream >> inChar;
01226           if(inChar == ioClosing) {
01227             // Found a closing.  Stop here.
01228             break;
01229           }
01230           if(inChar != ioSeparator) {
01231             // Missing separator.  Fail here.
01232             stream.clear(std::ios_base::failbit);
01233           }
01234         }
01235 
01236         // If we found an intro, we expect the corresponding outro.
01237         if(foundIntro) {
01238           stream.expect(ioOutro());
01239         }
01240 
01241         // Now we're done with all of the parsing.  Copy the data to *this.
01242         this->reinit(inputBuffer.size());
01243         std::copy(inputBuffer.begin(), inputBuffer.end(), this->begin());
01244 
01245       } catch(std::ios_base::failure) {
01246         // Empty
01247       }
01248       inputStream.exceptions(oldExceptionState);
01249       return inputStream;
01250     }
01251   
01252 
01253     template <class Type>
01254     void Array1D<Type>::
01255     reinit(size_t arraySize)
01256     {
01257       this->deAllocate();
01258       this->m_size = arraySize;
01259       this->allocate();
01260     }
01261   
01262 
01263     template <class Type>
01264     void Array1D<Type>::
01265     reinitIfNecessary(size_t arraySize)
01266     {
01267       if(this->size() != arraySize) {
01268         this->reinit(arraySize);
01269       }
01270     }
01271   
01272 
01273     template <class Type>
01274     Array1D<Type>& Array1D<Type>::
01275     operator=(const Array1D<Type>& source)
01276     {
01277       // Check for self-assignment
01278       if(&source != this) {
01279         this->deAllocate();
01280         m_size = source.m_size;
01281         m_dataPtr = source.m_dataPtr;
01282         m_refCountPtr = source.m_refCountPtr;
01283         m_isAllocated = source.m_isAllocated;
01284         // Update reference count, if appropriate.
01285         if(m_isAllocated) {
01286           ++(*m_refCountPtr);
01287         }
01288       }
01289       return *this;
01290     }
01291 
01292 
01293     template <class Type> template <class Type2>
01294     Array1D<Type>&
01295     Array1D<Type>::
01296     operator+=(const Array1D<Type2>& arg)
01297     {
01298       if(m_size != arg.size()) {
01299         std::ostringstream message;
01300         message << "Mismatched array sizes. Argument array has "
01301                 << arg.size() << " elements, while destination array has "
01302                 << m_size << " elements.";
01303         DLR_THROW3(ValueException, "Array1D::operator+=(const Array1D&)",
01304                    message.str().c_str());
01305       }
01306       std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01307                      std::plus<Type>());
01308       return *this;
01309     }
01310 
01311 
01312     template <class Type>
01313     Array1D<Type>&
01314     Array1D<Type>::
01315     operator+=(const Type arg)
01316     {
01317       std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01318                      std::bind2nd(std::plus<Type>(), arg));
01319       return *this;
01320     }
01321 
01322 
01323     template <class Type> template <class Type2>
01324     Array1D<Type>&
01325     Array1D<Type>::
01326     operator-=(const Array1D<Type2>& arg)
01327     {
01328       if(m_size != arg.size()) {
01329         std::ostringstream message;
01330         message << "Mismatched array sizes. Argument array has "
01331                 << arg.size() << " elements, while destination array has "
01332                 << m_size << " elements.";
01333         DLR_THROW3(ValueException, "Array1D::operator-=(const Array1D&)",
01334                    message.str().c_str());
01335       }
01336       std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01337                      std::minus<Type>());
01338       return *this;
01339     }
01340 
01341 
01342     template <class Type>
01343     Array1D<Type>&
01344     Array1D<Type>::
01345     operator-=(const Type arg)
01346     {
01347       std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01348                      std::bind2nd(std::minus<Type>(), arg));
01349       return *this;
01350     }
01351 
01352 
01353     template <class Type> template <class Type2>
01354     Array1D<Type>&
01355     Array1D<Type>::
01356     operator*=(const Array1D<Type2>& arg)
01357     {
01358       if(m_size != arg.size()) {
01359         std::ostringstream message;
01360         message << "Mismatched array sizes. Argument array has "
01361                 << arg.size() << " elements, while destination array has "
01362                 << m_size << " elements.";
01363         DLR_THROW3(ValueException, "Array1D::operator*=(const Array1D&)",
01364                    message.str().c_str());
01365       }
01366       std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01367                      std::multiplies<Type>());
01368       return *this;
01369     }
01370 
01371 
01372     template <class Type>
01373     Array1D<Type>&
01374     Array1D<Type>::
01375     operator*=(const Type arg)
01376     {
01377       std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01378                      std::bind2nd(std::multiplies<Type>(), arg));
01379       return *this;
01380     }
01381 
01382 
01383     template <class Type> template <class Type2>
01384     Array1D<Type>&
01385     Array1D<Type>::
01386     operator/=(const Array1D<Type2>& arg)
01387     {
01388       if(m_size != arg.size()) {
01389         std::ostringstream message;
01390         message << "Mismatched array sizes. Argument array has "
01391                 << arg.size() << " elements, while destination array has "
01392                 << m_size << " elements.";
01393         DLR_THROW3(ValueException, "Array1D::operator/=(const Array1D&)",
01394                    message.str().c_str());
01395       }
01396       std::transform(m_dataPtr, m_dataPtr + m_size, arg.data(), m_dataPtr,
01397                      std::divides<Type>());
01398       return *this;
01399     }
01400 
01401 
01402     template <class Type>
01403     Array1D<Type>&
01404     Array1D<Type>::
01405     operator/=(const Type arg)
01406     {
01407       std::transform(m_dataPtr, m_dataPtr + m_size, m_dataPtr,
01408                      std::bind2nd(std::divides<Type>(), arg));
01409       return *this;
01410     }
01411 
01412 
01413     template <class Type>
01414     void Array1D<Type>::
01415     allocate()
01416     {
01417       // First check array size.  It doesn't make sense to allocate memory
01418       // for a zero size array.
01419       if(m_size > 0) {
01420         // Allocate data storage, and a new reference count.  new() should
01421         // throw an exception if we run out of memory.
01422         m_dataPtr = new(Type[m_size]);
01423         m_refCountPtr = new size_t;
01424         // Set reference count to show that exactly one Array is pointing
01425         // to this data.
01426         *m_refCountPtr = 1;
01427         m_isAllocated = true;
01428       } else {
01429         // Array size is zero, so no need to allocate memory.
01430         m_dataPtr = 0;
01431         m_refCountPtr = 0;
01432         m_isAllocated = false;
01433       }
01434       return;
01435     }
01436 
01437 
01438     template <class Type>
01439     inline void Array1D<Type>::
01440     checkBounds(size_t index) const
01441     {
01442 #ifdef _DLRNUMERIC_CHECKBOUNDS_
01443       if(index >= m_size) {
01444         std::ostringstream message;
01445         message << "Index " << index << " is invalid for a(n) " << m_size
01446                 << " element array.";
01447         DLR_THROW(IndexException, "Array1D::checkBounds()",
01448                   message.str().c_str());
01449       }
01450 #endif
01451     }
01452 
01453 
01454     template <class Type>
01455     void Array1D<Type>::
01456     deAllocate()
01457     {
01458       // Are we responsible for deallocating the contents of this array?
01459       if(m_isAllocated == true) {
01460         // If yes, are we currently the only array pointing to this data?
01461         if(--(*m_refCountPtr) == 0) {
01462           // If yes, then delete both data and reference count, and change
01463           // m_isAllocated to reflect this.
01464           delete[] m_dataPtr;
01465           delete m_refCountPtr;
01466           m_isAllocated = false;
01467         }
01468       }
01469       // Abandon our pointers to data and reference count.
01470       m_dataPtr = 0;
01471       m_refCountPtr = 0;
01472     }
01473 
01474     /* Non-member functions which should maybe wind up in a different file? */
01475   
01476     template <class Type>
01477     Array1D<Type> operator+(const Array1D<Type>& array0,
01478                             const Array1D<Type>& array1)
01479     {
01480       if(array0.size() != array1.size()) {
01481         std::ostringstream message;
01482         message << "Array sizes do not match.  Array0 has " << array0.size()
01483                 << " elements, while array1 has " << array1.size()
01484                 << " elements.";
01485         DLR_THROW(ValueException, "Array1D::operator+()", message.str().c_str());
01486       }
01487       Array1D<Type> result(array0.size());
01488       std::transform(array0.begin(), array0.end(), array1.begin(),
01489                      result.begin(), std::plus<Type>());
01490       return result;
01491     }
01492 
01493 
01494     template <class Type>
01495     Array1D<Type> operator-(const Array1D<Type>& array0,
01496                             const Array1D<Type>& array1)
01497     {
01498       if(array0.size() != array1.size()) {
01499         std::ostringstream message;
01500         message << "Array sizes do not match.  Array0 has " << array0.size()
01501                 << " elements, while array1 has " << array1.size()
01502                 << " elements.";
01503         DLR_THROW(ValueException, "Array1D::operator-()", message.str().c_str());
01504       }
01505       Array1D<Type> result(array0.size());
01506       std::transform(array0.begin(), array0.end(), array1.begin(),
01507                      result.begin(), std::minus<Type>());
01508       return result;
01509     }
01510 
01511 
01512     template <class Type>
01513     Array1D<Type> operator*(const Array1D<Type>& array0,
01514                             const Array1D<Type>& array1)
01515     {
01516       if(array0.size() != array1.size()) {
01517         std::ostringstream message;
01518         message << "Array sizes do not match.  Array0 has " << array0.size()
01519                 << " elements, while array1 has " << array1.size()
01520                 << " elements.";
01521         DLR_THROW(ValueException, "Array1D::operator*()", message.str().c_str());
01522       }
01523       Array1D<Type> result(array0.size());
01524       std::transform(array0.begin(), array0.end(), array1.begin(),
01525                      result.begin(), std::multiplies<Type>());
01526       return result;
01527     }
01528 
01529 
01530     template <class Type>
01531     Array1D<Type> operator/(const Array1D<Type>& array0,
01532                             const Array1D<Type>& array1)
01533     {
01534       if(array0.size() != array1.size()) {
01535         std::ostringstream message;
01536         message << "Array sizes do not match.  Array0 has " << array0.size()
01537                 << " elements, while array1 has " << array1.size()
01538                 << " elements.";
01539         DLR_THROW(ValueException, "Array1D::operator/()", message.str().c_str());
01540       }
01541       Array1D<Type> result(array0.size());
01542       std::transform(array0.begin(), array0.end(), array1.begin(),
01543                      result.begin(), std::divides<Type>());
01544       return result;
01545     }
01546 
01547 
01548     template <class Type>
01549     Array1D<Type> operator+(const Array1D<Type>& array0, Type scalar)
01550     {
01551       Array1D<Type> result(array0.size());
01552       std::transform(array0.begin(), array0.end(), result.begin(),
01553                      std::bind2nd(std::plus<Type>(), scalar));
01554       return result;
01555     }
01556 
01557 
01558     template <class Type>
01559     Array1D<Type> operator-(const Array1D<Type>& array0, Type scalar)
01560     {
01561       Array1D<Type> result(array0.size());
01562       std::transform(array0.begin(), array0.end(), result.begin(),
01563                      std::bind2nd(std::minus<Type>(), scalar));
01564       return result;
01565     }
01566 
01567 
01568     template <class Type>
01569     Array1D<Type> operator*(const Array1D<Type>& array0, Type scalar)
01570     {
01571       Array1D<Type> result(array0.size());
01572       std::transform(array0.begin(), array0.end(), result.begin(),
01573                      std::bind2nd(std::multiplies<Type>(), scalar));
01574       return result;
01575     }
01576 
01577 
01578     template <class Type>
01579     Array1D<Type> operator/(const Array1D<Type>& array0, Type scalar)
01580     {
01581       Array1D<Type> result(array0.size());
01582       std::transform(array0.begin(), array0.end(), result.begin(),
01583                      std::bind2nd(std::divides<Type>(), scalar));
01584       return result;
01585     }
01586 
01587 
01588     template <class Type>
01589     inline Array1D<Type> operator+(Type scalar, const Array1D<Type>& array0)
01590     {
01591       return array0 + scalar;
01592     }
01593 
01594 
01595     template <class Type>
01596     Array1D<Type> operator-(Type scalar, const Array1D<Type>& array0)
01597     {
01598       Array1D<Type> result(array0.size());
01599       std::transform(array0.begin(), array0.end(), result.begin(),
01600                      std::bind1st(std::minus<Type>(), scalar));
01601       return result;
01602     }
01603 
01604   
01605     template <class Type>
01606     inline Array1D<Type> operator*(Type scalar, const Array1D<Type>& array0)
01607     {
01608       return array0 * scalar;
01609     }
01610 
01611   
01612     template <class Type>
01613     Array1D<Type> operator/(Type scalar, const Array1D<Type>& array0)
01614     {
01615       Array1D<Type> result(array0.size());
01616       std::transform(array0.begin(), array0.end(), result.begin(),
01617                      std::bind1st(std::divides<Type>(), scalar));
01618       return result;
01619     }
01620   
01621 
01622     // Elementwise comparison of an Array1D with a constant.
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.data(),
01629                      std::bind2nd(std::equal_to<Type>(), arg));
01630       return result;
01631     }
01632 
01633     
01634     // Elementwise comparison of an Array1D with another array.
01635     template <class Type>
01636     Array1D<bool>
01637     operator==(const Array1D<Type>& array0, const Array1D<Type>& array1)
01638     {
01639       array0.checkDimension(array1.size());
01640       Array1D<bool> result(array0.size());
01641       std::transform(array0.begin(), array0.end(), array1.begin(),
01642                      result.begin(), std::equal_to<Type>());
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::greater<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::greater_equal<Type>(), arg));
01665       return result;
01666     }
01667 
01668 
01669     template <class Type>
01670     Array1D<bool>
01671     operator<(const Array1D<Type>& array0, const Type arg)
01672     {
01673       Array1D<bool> result(array0.size());
01674       std::transform(array0.begin(), array0.end(), result.begin(),
01675                      std::bind2nd(std::less<Type>(), arg));
01676       return result;
01677     }
01678 
01679 
01680     template <class Type>
01681     Array1D<bool>
01682     operator<=(const Array1D<Type>& array0, const Type arg)
01683     {
01684       Array1D<bool> result(array0.size());
01685       std::transform(array0.begin(), array0.end(), result.begin(),
01686                      std::bind2nd(std::less_equal<Type>(), arg));
01687       return result;
01688     }
01689 
01690 
01691     template <class Type>
01692     std::ostream& operator<<(std::ostream& stream, const Array1D<Type>& array0)
01693     {
01694       // Most of the time, OutputType will be the same as Type.
01695       typedef typename NumericTraits<Type>::TextOutputType OutputType;
01696     
01697       if (!stream){
01698         DLR_THROW(IOException, "operator<<(std::ostream&, const Array1D&)",
01699                   "Invalid stream\n");
01700       }
01701 
01702       size_t index;
01703       stream << "Array1D([";
01704       if (array0.size() > 0){
01705         for(index = 0; index < array0.size() - 1; ++index) {
01706           stream << static_cast<OutputType>(array0(index)) << ", ";
01707         }
01708         stream << static_cast<OutputType>(array0(index));
01709       }
01710       stream << "])";
01711       return stream;
01712     }
01713 
01714     // Sets the value of an Array1D instance from a std::istream.
01715     template <class Type>
01716     std::istream& operator>>(std::istream& inputStream, Array1D<Type>& array0)
01717     {
01718       return array0.readFromStream(inputStream);
01719     }
01720 
01721   } // namespace numeric
01722 
01723 } // namespace dlr
01724 
01725 #endif /* #ifdef _DLR_ARRAY1D_H_ */

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