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 
00153   for (int i=0; i < as<int>(size()); ++i)
00154   {
00155     ss << operator[](i);
00156     if (i < size()-1) ss << ", ";
00157   }
00158   ss << "}";
00159 
00160   return ss.str();
00161 
00162 }
00163 
00164 
00165 // Element Access Functions
00166 
00167 
00168 template<class T> inline
00169 T* ArrayView<T>::getRawPtr() const
00170 {
00171   debug_assert_valid_ptr();
00172   return ptr_;
00173 }
00174 
00175 
00176 template<class T> inline
00177 T& ArrayView<T>::operator[](size_type i) const
00178 {
00179   debug_assert_valid_ptr();
00180   debug_assert_in_range(i,1);
00181   return ptr_[i];
00182 }
00183 
00184 
00185 template<class T> inline
00186 T& ArrayView<T>::front() const
00187 {
00188   debug_assert_not_null();
00189   debug_assert_valid_ptr();
00190   return *ptr_;
00191 }
00192 
00193 
00194 template<class T> inline
00195 T& ArrayView<T>::back() const
00196 {
00197   debug_assert_not_null();
00198   debug_assert_valid_ptr();
00199   return *(ptr_+size_-1);
00200 }
00201 
00202 
00203 // Views 
00204 
00205 
00206 template<class T> inline
00207 ArrayView<T> ArrayView<T>::view(size_type offset, size_type size_in) const
00208 {
00209   if (size_in == 0) {
00210     return null;
00211   }
00212   debug_assert_valid_ptr();
00213   debug_assert_in_range(offset, size_in);
00214 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00215   return arcp_(offset, size_in);
00216 #endif
00217   return ArrayView<T>(ptr_+offset, size_in);
00218   // WARNING: The above code had better be correct since we are using raw
00219   // pointer arithmetic!
00220 }
00221 
00222 
00223 template<class T> inline
00224 ArrayView<T> ArrayView<T>::operator()(size_type offset, size_type size_in) const
00225 {
00226   return view(offset, size_in);
00227 }
00228 
00229 
00230 template<class T> inline
00231 const ArrayView<T>& ArrayView<T>::operator()() const
00232 {
00233   debug_assert_valid_ptr();
00234   return *this;
00235 }
00236 
00237 
00238 template<class T> inline
00239 ArrayView<const T> ArrayView<T>::getConst() const
00240 {
00241   debug_assert_valid_ptr();
00242 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00243   return arcp_.getConst()();
00244 #endif
00245   return ArrayView<const T>(ptr_, size_);
00246 }
00247 
00248 
00249 template<class T> inline
00250 ArrayView<T>::operator ArrayView<const T>() const
00251 {
00252   return getConst();
00253 }
00254 
00255 
00256 // Assignment
00257 
00258 
00259 template<class T>
00260 void ArrayView<T>::assign(const ArrayView<const T>& array) const
00261 {
00262   debug_assert_valid_ptr();
00263   debug_assert_not_null();
00264   if (this->getRawPtr()==array.getRawPtr() && this->size()==array.size())
00265     return; // Assignment to self
00266   debug_assert_in_range(0,array.size());
00267   std::copy( array.begin(), array.end(), this->begin() );
00268   // Note: Above, in debug mode, the iterators are range checked!  In
00269   // optimized mode, these are raw pointers which should run very fast!
00270 }
00271 
00272 
00273 // Standard Container-Like Functions 
00274 
00275 
00276 template<class T>
00277 typename ArrayView<T>::iterator ArrayView<T>::begin() const
00278 {
00279   debug_assert_valid_ptr();
00280 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00281   return arcp_.create_weak();
00282 #else
00283   return ptr_;
00284 #endif
00285 }
00286 
00287 
00288 template<class T>
00289 typename ArrayView<T>::iterator ArrayView<T>::end() const
00290 {
00291   debug_assert_valid_ptr();
00292 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00293   return arcp_.create_weak() + size_;
00294 #else
00295   return ptr_ + size_;
00296 #endif
00297 }
00298 
00299 
00300 // Assertion Functions. 
00301 
00302 
00303 template<class T>
00304 const ArrayView<T>& ArrayView<T>::assert_not_null() const
00305 {
00306   if(!ptr_)
00307     throw_null_ptr_error(typeName(*this));
00308   return *this;
00309 }
00310 
00311 
00312 template<class T>
00313 const ArrayView<T>&
00314 ArrayView<T>::assert_in_range(size_type offset, size_type size_in) const
00315 {
00316   assert_not_null();
00317   TEUCHOS_TEST_FOR_EXCEPTION( size_in == as<size_type>(0), RangeError,
00318     "Error, size=0 is not allowed!" );
00319   TEUCHOS_TEST_FOR_EXCEPTION(
00320     !(
00321       ( 0 <= offset && offset+size_in <= this->size() )
00322       &&
00323       size_in >= 0
00324       ),
00325     RangeError,
00326     typeName(*this)<<"::assert_in_range():"
00327     " Error, [offset,offset+size) = ["<<offset<<","<<(offset+size_in)<<")"
00328     " does not lie in the range [0,"<<this->size()<<")!"
00329     );
00330   return*this;
00331 }
00332 
00333 
00334 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00335 
00336 template<class T>
00337 ArrayView<T>::ArrayView( const ArrayRCP<T> &arcp )
00338   : ptr_(arcp.getRawPtr()), size_(arcp.size()), arcp_(arcp)
00339 {}
00340 
00341 
00342 template<class T>
00343 ArrayView<T>::ArrayView(T* p, size_type size_in, const ArrayRCP<T> &arcp)
00344   : ptr_(p), size_(size_in), arcp_(arcp)
00345 {}
00346 
00347 
00348 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00349 
00350 
00351 // private
00352 
00353 
00354 template<class T>
00355 void ArrayView<T>::setUpIterators(const ERCPNodeLookup rcpNodeLookup)
00356 {
00357 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00358   if (ptr_ && arcp_.is_null()) {
00359     arcp_ = ArrayRCP<T>(ptr_, 0, size_, false, rcpNodeLookup);
00360   }
00361 #endif
00362 }
00363 
00364 
00365 } // namespace Teuchos
00366 
00367 
00368 //
00369 // Nonmember helper functions
00370 //
00371 
00372 
00373 template<class T> inline
00374 Teuchos::ArrayView<T>
00375 Teuchos::arrayView( T* p, typename ArrayView<T>::size_type size )
00376 {
00377   if (size == 0)
00378     return null;
00379   return ArrayView<T>(p, size);
00380 }
00381 
00382 
00383 template<class T> inline
00384 Teuchos::ArrayView<T> Teuchos::arrayViewFromVector( std::vector<T>& vec )
00385 {
00386   if (vec.size() == 0)
00387     return null;
00388   return ArrayView<T>(vec);
00389 }
00390 
00391 
00392 template<class T> inline
00393 Teuchos::ArrayView<const T> Teuchos::arrayViewFromVector( const std::vector<T>& vec )
00394 {
00395   if (vec.size() == 0)
00396     return null;
00397   return ArrayView<const T>(vec);
00398 }
00399 
00400 
00401 #ifndef __sun
00402 
00403 template<class T> inline
00404 std::vector<T> Teuchos::createVector( const ArrayView<T> &av )
00405 {
00406   std::vector<T> v(av.begin(), av.end());
00407   return v;
00408 }
00409 
00410 #endif // __sun
00411 
00412 
00413 template<class T> inline
00414 std::vector<T> Teuchos::createVector( const ArrayView<const T> &av )
00415 {
00416   std::vector<T> v(av.begin(), av.end());
00417   return v;
00418 }
00419 
00420 
00421 template<class T> inline
00422 bool Teuchos::is_null( const ArrayView<T> &av )
00423 {
00424   return av.is_null();
00425 }
00426 
00427 
00428 template<class T> inline
00429 bool Teuchos::nonnull( const ArrayView<T> &av )
00430 {
00431   return !av.is_null();
00432 }
00433 
00434 
00435 template<class T>
00436 std::ostream& Teuchos::operator<<( std::ostream& out, const ArrayView<T>& p )
00437 {
00438   return out << p.toString();
00439 }
00440 
00441 
00442 template<class T2, class T1>
00443 REFCOUNTPTR_INLINE
00444 Teuchos::ArrayView<T2>
00445 Teuchos::av_const_cast(const ArrayView<T1>& p1)
00446 {
00447   T2 *ptr2 = const_cast<T2*>(p1.getRawPtr());
00448   return ArrayView<T2>(ptr2, p1.size());
00449   // Note: Above is just fine even if p1.get()==NULL!
00450 }
00451 
00452 
00453 template<class T2, class T1>
00454 REFCOUNTPTR_INLINE
00455 Teuchos::ArrayView<T2>
00456 Teuchos::av_reinterpret_cast(const ArrayView<T1>& p1)
00457 {
00458   typedef typename ArrayView<T1>::size_type size_type;
00459   const int sizeOfT1 = sizeof(T1);
00460   const int sizeOfT2 = sizeof(T2);
00461   size_type size2 = (p1.size()*sizeOfT1) / sizeOfT2;
00462   T2 *ptr2 = reinterpret_cast<T2*>(p1.getRawPtr());
00463   return ArrayView<T2>(
00464     ptr2, size2
00465 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00466     ,arcp_reinterpret_cast<T2>(p1.access_private_arcp())
00467 #endif
00468     );
00469   // Note: Above is just fine even if p1.get()==NULL!
00470 }
00471 
00472 
00473 #endif  // TEUCHOS_ARRAY_VIEW_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines