Teuchos - Trilinos Tools Package Version of the Day
Teuchos_TwoDArray.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #ifndef TEUCHOS_TWODARRAY_HPP
00043 #define TEUCHOS_TWODARRAY_HPP
00044 
00045 
00051 #include "Teuchos_Array.hpp"
00052 
00053 
00054 namespace Teuchos{
00055 
00067 template<class T> 
00068 class TwoDArray{
00069 public:
00073   typedef Ordinal size_type;
00074 
00077 
00086   TwoDArray(size_type numRows, size_type numCols, T value=T()):
00087     _numRows(numRows),
00088     _numCols(numCols),
00089     _data(Array<T>(numCols*numRows, value)),
00090     _symmetrical(false)
00091     {}
00095   TwoDArray():
00096     _numRows(0),_numCols(0),_data(Array<T>()),_symmetrical(false){}
00097 
00099   virtual ~TwoDArray(){}
00100 
00102   
00105   
00107   inline ArrayView<T> operator[](size_type i);
00108   
00110   inline const ArrayView<T> operator[](size_type i) const;
00111 
00113   inline size_type getNumRows() const{
00114     return _numRows;
00115   }
00116 
00118   inline size_type getNumCols() const{
00119     return _numCols;
00120   }
00121 
00123   inline const Array<T>& getDataArray() const{
00124     return _data;
00125   }
00126 
00128   inline T& operator()(size_type i, size_type j){
00129     return _data[(i*_numCols)+j];
00130   }
00131 
00133   inline const T& operator()(size_type i, size_type j) const{
00134     return _data[(i*_numCols)+j];
00135   }
00136 
00138   inline void clear(){
00139     _data.clear();
00140     _numRows =0;
00141     _numCols =0;
00142   }
00143 
00144   inline bool isEmpty(){
00145     return _numRows == 0 &&
00146       _numCols == 0 &&
00147       _data.size() == 0;
00148   }
00149 
00163   inline bool isSymmetrical() const{
00164     return _symmetrical;
00165   }
00166 
00182   inline void setSymmetrical(bool symmetrical){
00183     _symmetrical = symmetrical;
00184   }
00185 
00187 
00190 
00202   void resizeRows(size_type numberOfRows);
00203 
00218   void resizeCols(size_type numberOfCols);
00219 
00221 
00222   
00225 
00229   static const std::string& getMetaSeperator(){
00230     static const std::string metaSeperator = ":";
00231     return metaSeperator;
00232   }
00233 
00237   static const std::string& getDimensionsDelimiter(){
00238     static const std::string dimensionsDelimiter = "x";
00239     return dimensionsDelimiter;
00240   }
00241 
00243   static std::string toString(const TwoDArray<T> array);
00244 
00246   static TwoDArray<T> fromString(const std::string& string);
00247 
00249   
00250 private:
00251   size_type _numRows,_numCols;
00252   Array<T> _data;
00253   TwoDArray(size_type numRows, size_type numCols, Array<T> data):
00254     _numRows(numRows),_numCols(numCols),_data(data){}
00255   bool _symmetrical;
00256 };
00257 
00258 template<class T> inline
00259 ArrayView<T> TwoDArray<T>::operator[](size_type i){
00260   return _data.view(_numCols*i, _numCols);  
00261 }
00262 
00263 template<class T> inline
00264 const ArrayView<T> TwoDArray<T>::operator[](size_type i) const{
00265   return _data.view(_numCols*i, _numCols);  
00266 }
00267 
00268 template<class T>
00269 void TwoDArray<T>::resizeRows(size_type numberOfRows){
00270   _data.resize(_numCols*numberOfRows);
00271   _numRows = numberOfRows;
00272 }
00273 
00274 
00275 template<class T>
00276 void TwoDArray<T>::resizeCols(size_type numberOfCols){
00277   Array<T> newData(numberOfCols*_numRows);
00278   size_type colLimit = (numberOfCols < _numCols ? numberOfCols : _numCols);
00279   for(size_type i = 0; i<_numRows; i++){
00280     for(size_type j = 0; j<colLimit; j++){
00281       newData[i*numberOfCols+j] = _data[i*_numCols+j];
00282     }
00283   }
00284   _data = newData;
00285   _numCols=numberOfCols;
00286 }
00287 
00288 
00289 template<class T>
00290 std::string TwoDArray<T>::toString(const TwoDArray<T> array){
00291   std::stringstream numColsStream;
00292   std::stringstream numRowsStream;
00293   numColsStream << array.getNumCols();
00294   numRowsStream << array.getNumRows();
00295   std::string metaSeperator = TwoDArray<T>::getMetaSeperator();
00296   return 
00297     numRowsStream.str() +
00298     TwoDArray<T>::getDimensionsDelimiter() +
00299     numColsStream.str() +
00300     metaSeperator +
00301     (array.isSymmetrical() ? "sym"+metaSeperator : "") +
00302     array.getDataArray().toString();
00303 }
00304 
00305 template<class T>
00306 TwoDArray<T> TwoDArray<T>::fromString(const std::string& string){
00307   std::string curString = string;
00308   std::string metaSeperator = TwoDArray<T>::getMetaSeperator();
00309   size_t curPos = curString.find(metaSeperator);
00310   std::string dimString = curString.substr(0, curPos);
00311   curString = curString.substr(curPos+1);
00312 
00313   //process dimensions
00314   size_t dimCharPos = 
00315     dimString.find(TwoDArray<T>::getDimensionsDelimiter());
00316   std::istringstream numRowsStream(dimString.substr(0,dimCharPos));
00317   std::istringstream numColsStream(dimString.substr(dimCharPos+1));
00318   size_t numRows, numCols;
00319   numRowsStream >> numRows;
00320   numColsStream >> numCols;
00321 
00322   //determine symetry state
00323   bool symmetrical = false;
00324   curPos = curString.find(metaSeperator);
00325   if(curPos != std::string::npos){
00326     symmetrical = true;
00327     curString = curString.substr(curPos+1);
00328   }
00329 
00330   //Get actual data
00331   Array<T> array = fromStringToArray<T>(curString);
00332 
00333   TEST_FOR_EXCEPTION(array.size() != (typename Array<T>::size_type)(numRows*numCols),
00334     InvalidArrayStringRepresentation,
00335     "Error: You've specified an TwoDArray as having the dimensions of "
00336     << numRows << "x" << numCols << ". This means you should have " <<
00337     (numRows*numCols) << " entries specified in your array. However you "
00338     "only specified " << array.size() << " entries."
00339   )
00340 
00341   //Construct object to return
00342   TwoDArray<T> toReturn(numRows, numCols, array);
00343   toReturn.setSymmetrical(symmetrical);
00344   return toReturn;
00345 }
00346 
00347 /* \brief .
00348  * \relates TwoDArray
00349  */
00350 template<class T>
00351 std::istringstream& operator>> (std::istringstream& in, TwoDArray<T>& array){
00352   array = TwoDArray<T>::fromString(in.str());
00353   return in;
00354 }
00355 
00356 /* \brief .
00357  * \relates TwoDArray
00358  */
00359 template<class T> inline
00360 std::ostream& operator<<(std::ostream& os, const TwoDArray<T>& array){
00361   return os << TwoDArray<T>::toString(array);
00362 }
00363 
00364 
00365 namespace TwoDDetails {
00366 
00375 template<typename T>
00376 bool symmetricCompare(const TwoDArray<T> &a1, const TwoDArray<T> &a2 ){
00377   if(a1.getNumRows() != a2.getNumRows() || 
00378     a1.getNumRows() != a2.getNumRows())
00379   {
00380     return false;
00381   }
00382   else{
00383     typedef typename TwoDArray<T>::size_type ST;
00384     for(ST i=0;i<a1.getNumRows(); ++i){
00385       for(ST j=0;j<a1.getNumCols()-a1.getNumRows()+i; ++j){
00386         if(a1(i,j) != a2(i,j)){
00387           return false;
00388         }
00389       }
00390     }
00391     return true;
00392   }
00393 }
00394 
00395 
00396 }
00397 
00398 /* \brief Returns true of the two TwoDArrays have the same contents and
00399  * their dimensions are the same.
00400  *
00401  * \note If the arrays are symmetrical, only the values in the upper half
00402  * of the array are compared. For example: in a 4x4 array, only the values 
00403  * indicated with x's in the figure below would be compared.
00404  *
00405  *   o o o o
00406  *   x o o o 
00407  *   x x o o  
00408  *   x x x o
00409  *
00410  * \relates TwoDArray
00411  */
00412 template<typename T> 
00413 bool operator==( const TwoDArray<T> &a1, const TwoDArray<T> &a2 ){
00414   if(a1.isSymmetrical() != a2.isSymmetrical()){
00415     return false;
00416   }
00417   if(a1.isSymmetrical()){
00418     return TwoDDetails::symmetricCompare(a1,a2);
00419   }
00420   else{
00421     return a1.getDataArray() == a2.getDataArray() && 
00422     a1.getNumRows() == a2.getNumRows() &&
00423     a1.getNumCols() == a2.getNumCols();
00424   }
00425 }
00426 
00436 inline
00437 std::string getTwoDArrayTypeNameTraitsFormat(){
00438   return "TwoDArray(*)";
00439 }
00440 
00442 template<typename T>
00443 class TEUCHOS_LIB_DLL_EXPORT TypeNameTraits<TwoDArray<T> > {
00444 public:
00445   static std::string name(){ 
00446     std::string formatString = getTwoDArrayTypeNameTraitsFormat();
00447     size_t starPos = formatString.find("*");
00448     std::string prefix = formatString.substr(0,starPos);
00449     std::string postFix = formatString.substr(starPos+1);
00450     return prefix+TypeNameTraits<T>::name()+postFix;
00451   }
00452   static std::string concreteName(const TwoDArray<T>&)
00453     { return name(); }
00454 };
00455 
00456 } //namespace Teuchos
00457 
00458 
00459 #endif // TEUCHOS_TWODARRAY_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines