Teuchos - Trilinos Tools Package Version of the Day
Teuchos_ArrayView.hpp
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_ARRAY_VIEW_HPP
00043 #define TEUCHOS_ARRAY_VIEW_HPP
00044 
00045 
00046 #include "Teuchos_ArrayViewDecl.hpp"
00047 #include "Teuchos_ArrayRCP.hpp"
00048 #include "Teuchos_as.hpp"
00049 
00050 
00051 namespace Teuchos {
00052 
00053 
00054 // Constructors/Destructors
00055 
00056 
00057 template<class T> inline
00058 ArrayView<T>::ArrayView( ENull )
00059   :ptr_(0), size_(0)
00060 {
00061   setUpIterators();
00062 }
00063 
00064 
00065 template<class T> inline
00066 ArrayView<T>::ArrayView( T* p, size_type size_in, const ERCPNodeLookup rcpNodeLookup )
00067   :ptr_(p), size_(size_in)
00068 {
00069 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00070   TEUCHOS_TEST_FOR_EXCEPT( p != 0 && size_in <= 0 );
00071   TEUCHOS_TEST_FOR_EXCEPT( p == 0 && size_in != 0 );
00072   setUpIterators(rcpNodeLookup);
00073 #endif
00074 }
00075 
00076 
00077 template<class T> inline
00078 ArrayView<T>::ArrayView(const ArrayView<T>& array)
00079   :ptr_(array.ptr_), size_(array.size_)
00080 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00081   ,arcp_(array.arcp_)
00082 #endif
00083 {}
00084 
00085 
00086 template<class T> inline
00087 ArrayView<T>::ArrayView(
00088   std::vector<typename ConstTypeTraits<T>::NonConstType>& vec
00089   )
00090   : ptr_( vec.empty() ? 0 : &vec[0] ), size_(vec.size())
00091 {
00092   setUpIterators();
00093 }
00094 
00095 
00096 template<class T> inline
00097 ArrayView<T>::ArrayView(
00098   const std::vector<typename ConstTypeTraits<T>::NonConstType>& vec
00099   )
00100   : ptr_( vec.empty() ? 0 : &vec[0] ), size_(vec.size())
00101 {
00102   setUpIterators();
00103 }
00104 
00105 
00106 template<class T> inline
00107 ArrayView<T>& ArrayView<T>::operator=(const ArrayView<T>& array)
00108 {
00109   ptr_ = array.ptr_;
00110   size_ = array.size_;
00111 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00112   arcp_ = array.arcp_;
00113 #endif
00114   return *this;
00115 }
00116 
00117 
00118 template<class T> inline
00119 ArrayView<T>::~ArrayView()
00120 {}
00121 
00122 
00123 // General query functions
00124 
00125 
00126 template<class T>
00127 inline
00128 bool ArrayView<T>::is_null() const
00129 {
00130   return ptr_ == 0;
00131 }
00132 
00133 
00134 template<class T> inline
00135 typename ArrayView<T>::size_type ArrayView<T>::size() const
00136 {
00137   debug_assert_valid_ptr();
00138   return size_;
00139 }
00140 
00141 
00142 template<typename T>
00143 std::string ArrayView<T>::toString() const
00144 {
00145 
00146   using Teuchos::as;
00147   std::ostringstream ss;
00148 
00149   debug_assert_valid_ptr();
00150 
00151   ss << "{";
00152   for (size_type i = 0; i < size (); ++i) {
00153     // NOTE: This depends on std::ostream::operator<<(const T&).
00154     ss << operator[] (i);
00155     if (i + 1 < size ()) {
00156       ss << ", ";
00157     }
00158   }
00159   ss << "}";
00160   return ss.str ();
00161 }
00162 
00163 
00164 // Specialization for float.  We use sufficient precision that no
00165 // digits are lost after writing to string and reading back in again.
00166 template<>
00167 TEUCHOSCORE_LIB_DLL_EXPORT std::string
00168 ArrayView<float>::toString() const;
00169 
00170 // Specialization for (const) float.  We use sufficient precision that no
00171 // digits are lost after writing to string and reading back in again.
00172 template<>
00173 TEUCHOSCORE_LIB_DLL_EXPORT std::string
00174 ArrayView<const float>::toString() const;
00175 
00176 // Specialization for double.  We use sufficient precision that no
00177 // digits are lost after writing to string and reading back in again.
00178 template<>
00179 TEUCHOSCORE_LIB_DLL_EXPORT std::string
00180 ArrayView<double>::toString() const;
00181 
00182 // Specialization for (const) double.  We use sufficient precision that no
00183 // digits are lost after writing to string and reading back in again.
00184 template<>
00185 TEUCHOSCORE_LIB_DLL_EXPORT std::string
00186 ArrayView<const double>::toString() const;
00187 
00188 
00189 // Element Access Functions
00190 
00191 
00192 template<class T> inline
00193 T* ArrayView<T>::getRawPtr() const
00194 {
00195   debug_assert_valid_ptr();
00196   return ptr_;
00197 }
00198 
00199 
00200 template<class T> inline
00201 T& ArrayView<T>::operator[](size_type i) const
00202 {
00203   debug_assert_valid_ptr();
00204   debug_assert_in_range(i,1);
00205   return ptr_[i];
00206 }
00207 
00208 
00209 template<class T> inline
00210 T& ArrayView<T>::front() const
00211 {
00212   debug_assert_not_null();
00213   debug_assert_valid_ptr();
00214   return *ptr_;
00215 }
00216 
00217 
00218 template<class T> inline
00219 T& ArrayView<T>::back() const
00220 {
00221   debug_assert_not_null();
00222   debug_assert_valid_ptr();
00223   return *(ptr_+size_-1);
00224 }
00225 
00226 
00227 // Views
00228 
00229 
00230 template<class T> inline
00231 ArrayView<T> ArrayView<T>::view(size_type offset, size_type size_in) const
00232 {
00233   if (size_in == 0) {
00234     return null;
00235   }
00236   debug_assert_valid_ptr();
00237   debug_assert_in_range(offset, size_in);
00238 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00239   return arcp_(offset, size_in);
00240 #endif
00241   return ArrayView<T>(ptr_+offset, size_in);
00242   // WARNING: The above code had better be correct since we are using raw
00243   // pointer arithmetic!
00244 }
00245 
00246 
00247 template<class T> inline
00248 ArrayView<T> ArrayView<T>::operator()(size_type offset, size_type size_in) const
00249 {
00250   return view(offset, size_in);
00251 }
00252 
00253 
00254 template<class T> inline
00255 const ArrayView<T>& ArrayView<T>::operator()() const
00256 {
00257   debug_assert_valid_ptr();
00258   return *this;
00259 }
00260 
00261 
00262 template<class T> inline
00263 ArrayView<const T> ArrayView<T>::getConst() const
00264 {
00265   debug_assert_valid_ptr();
00266 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00267   return arcp_.getConst()();
00268 #endif
00269   return ArrayView<const T>(ptr_, size_);
00270 }
00271 
00272 
00273 template<class T> inline
00274 ArrayView<T>::operator ArrayView<const T>() const
00275 {
00276   return getConst();
00277 }
00278 
00279 
00280 // Assignment
00281 
00282 
00283 template<class T>
00284 void ArrayView<T>::assign(const ArrayView<const T>& array) const
00285 {
00286   debug_assert_valid_ptr();
00287   debug_assert_not_null();
00288   if (this->getRawPtr()==array.getRawPtr() && this->size()==array.size())
00289     return; // Assignment to self
00290   debug_assert_in_range(0,array.size());
00291   std::copy( array.begin(), array.end(), this->begin() );
00292   // Note: Above, in debug mode, the iterators are range checked!  In
00293   // optimized mode, these are raw pointers which should run very fast!
00294 }
00295 
00296 
00297 // Standard Container-Like Functions
00298 
00299 
00300 template<class T>
00301 typename ArrayView<T>::iterator ArrayView<T>::begin() const
00302 {
00303   debug_assert_valid_ptr();
00304 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00305   return arcp_.create_weak();
00306 #else
00307   return ptr_;
00308 #endif
00309 }
00310 
00311 
00312 template<class T>
00313 typename ArrayView<T>::iterator ArrayView<T>::end() const
00314 {
00315   debug_assert_valid_ptr();
00316 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00317   return arcp_.create_weak() + size_;
00318 #else
00319   return ptr_ + size_;
00320 #endif
00321 }
00322 
00323 
00324 // Assertion Functions.
00325 
00326 
00327 template<class T>
00328 const ArrayView<T>& ArrayView<T>::assert_not_null() const
00329 {
00330   if(!ptr_)
00331     throw_null_ptr_error(typeName(*this));
00332   return *this;
00333 }
00334 
00335 
00336 template<class T>
00337 const ArrayView<T>&
00338 ArrayView<T>::assert_in_range(size_type offset, size_type size_in) const
00339 {
00340   assert_not_null();
00341   TEUCHOS_TEST_FOR_EXCEPTION( size_in == as<size_type>(0), RangeError,
00342     "Error, size=0 is not allowed!" );
00343   TEUCHOS_TEST_FOR_EXCEPTION(
00344     !(
00345       ( 0 <= offset && offset+size_in <= this->size() )
00346       &&
00347       size_in >= 0
00348       ),
00349     RangeError,
00350     typeName(*this)<<"::assert_in_range():"
00351     " Error, [offset,offset+size) = ["<<offset<<","<<(offset+size_in)<<")"
00352     " does not lie in the range [0,"<<this->size()<<")!"
00353     );
00354   return*this;
00355 }
00356 
00357 
00358 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00359 
00360 template<class T>
00361 ArrayView<T>::ArrayView( const ArrayRCP<T> &arcp )
00362   : ptr_(arcp.getRawPtr()), size_(arcp.size()), arcp_(arcp)
00363 {}
00364 
00365 
00366 template<class T>
00367 ArrayView<T>::ArrayView(T* p, size_type size_in, const ArrayRCP<T> &arcp)
00368   : ptr_(p), size_(size_in), arcp_(arcp)
00369 {}
00370 
00371 
00372 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00373 
00374 
00375 // private
00376 
00377 
00378 template<class T>
00379 void ArrayView<T>::setUpIterators(const ERCPNodeLookup rcpNodeLookup)
00380 {
00381 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00382   if (ptr_ && arcp_.is_null()) {
00383     arcp_ = ArrayRCP<T>(ptr_, 0, size_, false, rcpNodeLookup);
00384   }
00385 #endif
00386 }
00387 
00388 
00389 } // namespace Teuchos
00390 
00391 
00392 //
00393 // Nonmember helper functions
00394 //
00395 
00396 
00397 template<class T> inline
00398 Teuchos::ArrayView<T>
00399 Teuchos::arrayView( T* p, typename ArrayView<T>::size_type size )
00400 {
00401   if (size == 0)
00402     return null;
00403   return ArrayView<T>(p, size);
00404 }
00405 
00406 
00407 template<class T> inline
00408 Teuchos::ArrayView<T> Teuchos::arrayViewFromVector( std::vector<T>& vec )
00409 {
00410   if (vec.size() == 0)
00411     return null;
00412   return ArrayView<T>(vec);
00413 }
00414 
00415 
00416 template<class T> inline
00417 Teuchos::ArrayView<const T> Teuchos::arrayViewFromVector( const std::vector<T>& vec )
00418 {
00419   if (vec.size() == 0)
00420     return null;
00421   return ArrayView<const T>(vec);
00422 }
00423 
00424 
00425 #ifndef __sun
00426 
00427 template<class T> inline
00428 std::vector<T> Teuchos::createVector( const ArrayView<T> &av )
00429 {
00430   std::vector<T> v(av.begin(), av.end());
00431   return v;
00432 }
00433 
00434 #endif // __sun
00435 
00436 
00437 template<class T> inline
00438 std::vector<T> Teuchos::createVector( const ArrayView<const T> &av )
00439 {
00440   std::vector<T> v(av.begin(), av.end());
00441   return v;
00442 }
00443 
00444 
00445 template<class T> inline
00446 bool Teuchos::is_null( const ArrayView<T> &av )
00447 {
00448   return av.is_null();
00449 }
00450 
00451 
00452 template<class T> inline
00453 bool Teuchos::nonnull( const ArrayView<T> &av )
00454 {
00455   return !av.is_null();
00456 }
00457 
00458 
00459 template<class T>
00460 std::ostream& Teuchos::operator<<( std::ostream& out, const ArrayView<T>& p )
00461 {
00462   return out << p.toString();
00463 }
00464 
00465 
00466 template<class T2, class T1>
00467 REFCOUNTPTR_INLINE
00468 Teuchos::ArrayView<T2>
00469 Teuchos::av_const_cast(const ArrayView<T1>& p1)
00470 {
00471   T2 *ptr2 = const_cast<T2*>(p1.getRawPtr());
00472   return ArrayView<T2>(ptr2, p1.size());
00473   // Note: Above is just fine even if p1.get()==NULL!
00474 }
00475 
00476 
00477 template<class T2, class T1>
00478 REFCOUNTPTR_INLINE
00479 Teuchos::ArrayView<T2>
00480 Teuchos::av_reinterpret_cast(const ArrayView<T1>& p1)
00481 {
00482   typedef typename ArrayView<T1>::size_type size_type;
00483   const int sizeOfT1 = sizeof(T1);
00484   const int sizeOfT2 = sizeof(T2);
00485   size_type size2 = (p1.size()*sizeOfT1) / sizeOfT2;
00486   T2 *ptr2 = reinterpret_cast<T2*>(p1.getRawPtr());
00487   return ArrayView<T2>(
00488     ptr2, size2
00489 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00490     ,arcp_reinterpret_cast<T2>(p1.access_private_arcp())
00491 #endif
00492     );
00493   // Note: Above is just fine even if p1.get()==NULL!
00494 }
00495 
00496 
00497 #endif  // TEUCHOS_ARRAY_VIEW_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines