Teuchos - Trilinos Tools Package  Version of the Day
Teuchos_ArrayView.hpp
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Teuchos: Common Tools Package
5 // Copyright (2004) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #ifndef TEUCHOS_ARRAY_VIEW_HPP
43 #define TEUCHOS_ARRAY_VIEW_HPP
44 
45 
46 #include "Teuchos_ArrayViewDecl.hpp"
47 #include "Teuchos_ArrayRCP.hpp"
48 #include "Teuchos_as.hpp"
49 
50 
51 namespace Teuchos {
52 
53 
54 // Constructors/Destructors
55 
56 
57 template<class T> inline
59  : ptr_(0), size_(0)
60 {
61  setUpIterators();
62 }
63 
64 template<class T> inline
66  : ptr_(0), size_(0)
67 {
68  setUpIterators();
69 }
70 
71 
72 
73 template<class T> inline
74 ArrayView<T>::ArrayView( T* p, size_type size_in, const ERCPNodeLookup rcpNodeLookup )
75  :ptr_(p), size_(size_in)
76 {
77 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
78  TEUCHOS_TEST_FOR_EXCEPT( p != 0 && size_in <= 0 );
79  TEUCHOS_TEST_FOR_EXCEPT( p == 0 && size_in != 0 );
80  // This only does something if HAVE_TEUCHOS_ARRAY_BOUNDSCHECK is defined.
81  setUpIterators(rcpNodeLookup);
82 #else
83  (void) rcpNodeLookup; // Silence "unused variable" compiler warning.
84 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
85 }
86 
87 template<class T> inline
88 ArrayView<const T>::ArrayView(const T* p, size_type size_in, const ERCPNodeLookup rcpNodeLookup )
89  : ptr_(p), size_(size_in)
90 {
91 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
92  TEUCHOS_TEST_FOR_EXCEPT( p != 0 && size_in <= 0 );
93  TEUCHOS_TEST_FOR_EXCEPT( p == 0 && size_in != 0 );
94  // This only does something if HAVE_TEUCHOS_ARRAY_BOUNDSCHECK is defined.
95  setUpIterators(rcpNodeLookup);
96 #else
97  (void) rcpNodeLookup; // Silence "unused variable" compiler warning.
98 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
99 }
100 
101 
102 template<class T> inline
104  :ptr_(array.ptr_), size_(array.size_)
105 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
106  ,arcp_(array.arcp_)
107 #endif
108 {}
109 
110 template<class T> inline
112  :ptr_(array.ptr_), size_(array.size_)
113 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
114  ,arcp_(array.arcp_)
115 #endif
116 {}
117 
118 
119 template<class T> inline
121  std::vector<typename ConstTypeTraits<T>::NonConstType>& vec
122  )
123  : ptr_( vec.empty() ? 0 : &vec[0] ), size_(vec.size())
124 {
125  setUpIterators();
126 }
127 
128 template<class T> inline
130  std::vector<typename ConstTypeTraits<T>::NonConstType>& vec
131  )
132  : ptr_( vec.empty() ? 0 : &vec[0] ), size_(vec.size())
133 {
134  setUpIterators();
135 }
136 
137 
138 template<class T> inline
140  const std::vector<typename ConstTypeTraits<T>::NonConstType>& vec
141  )
142  : ptr_( vec.empty() ? 0 : &vec[0] ), size_(vec.size())
143 {
144  setUpIterators();
145 }
146 
147 template<class T> inline
149  const std::vector<typename ConstTypeTraits<T>::NonConstType>& vec
150  )
151  : ptr_( vec.empty() ? 0 : &vec[0] ), size_(vec.size())
152 {
153  setUpIterators();
154 }
155 
156 
157 template<class T> inline
159 {
160  ptr_ = array.ptr_;
161  size_ = array.size_;
162 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
163  arcp_ = array.arcp_;
164 #endif
165  return *this;
166 }
167 
168 template<class T> inline
170 {
171  ptr_ = array.ptr_;
172  size_ = array.size_;
173 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
174  arcp_ = array.arcp_;
175 #endif
176  return *this;
177 }
178 
179 
180 template<class T> inline
182 {}
183 
184 template<class T> inline
186 {}
187 
188 
189 // General query functions
190 
191 
192 template<class T>
193 inline
195 {
196  return ptr_ == 0;
197 }
198 
199 template<class T>
200 inline
201 bool ArrayView<const T>::is_null() const
202 {
203  return ptr_ == 0;
204 }
205 
206 
207 template<class T> inline
209 {
210  debug_assert_valid_ptr();
211  return size_;
212 }
213 
214 template<class T> inline
216 {
217  debug_assert_valid_ptr();
218  return size_;
219 }
220 
221 
222 template<typename T>
223 std::string ArrayView<T>::toString() const
224 {
225  using Teuchos::as;
226  std::ostringstream ss;
227 
228  debug_assert_valid_ptr();
229 
230  ss << "{";
231  for (size_type i = 0; i < size (); ++i) {
232  // NOTE: This depends on std::ostream::operator<<(const T&).
233  ss << operator[] (i);
234  if (i + 1 < size ()) {
235  ss << ", ";
236  }
237  }
238  ss << "}";
239  return ss.str ();
240 }
241 
242 template<typename T>
243 std::string ArrayView<const T>::toString() const
244 {
245  using Teuchos::as;
246  std::ostringstream ss;
247 
248  debug_assert_valid_ptr();
249 
250  ss << "{";
251  for (size_type i = 0; i < size (); ++i) {
252  // NOTE: This depends on std::ostream::operator<<(const T&).
253  ss << operator[] (i);
254  if (i + 1 < size ()) {
255  ss << ", ";
256  }
257  }
258  ss << "}";
259  return ss.str ();
260 }
261 
262 
263 // Specialization for float. We use sufficient precision that no
264 // digits are lost after writing to string and reading back in again.
265 template<>
266 TEUCHOSCORE_LIB_DLL_EXPORT std::string
268 
269 // Specialization for (const) float. We use sufficient precision that no
270 // digits are lost after writing to string and reading back in again.
271 template<>
272 TEUCHOSCORE_LIB_DLL_EXPORT std::string
274 
275 // Specialization for double. We use sufficient precision that no
276 // digits are lost after writing to string and reading back in again.
277 template<>
278 TEUCHOSCORE_LIB_DLL_EXPORT std::string
280 
281 // Specialization for (const) double. We use sufficient precision that no
282 // digits are lost after writing to string and reading back in again.
283 template<>
284 TEUCHOSCORE_LIB_DLL_EXPORT std::string
286 
287 
288 // Element Access Functions
289 
290 
291 template<class T> inline
293 {
294  debug_assert_valid_ptr();
295  return ptr_;
296 }
297 
298 template<class T> inline
299 const T* ArrayView<const T>::getRawPtr() const
300 {
301  debug_assert_valid_ptr();
302  return ptr_;
303 }
304 
305 
306 template<class T> inline
308 {
309  debug_assert_valid_ptr();
310  debug_assert_in_range(i,1);
311  return ptr_[i];
312 }
313 
314 template<class T> inline
316 {
317  debug_assert_valid_ptr();
318  debug_assert_in_range(i,1);
319  return ptr_[i];
320 }
321 
322 
323 template<class T> inline
325 {
326  debug_assert_not_null();
327  debug_assert_valid_ptr();
328  return *ptr_;
329 }
330 
331 template<class T> inline
332 const T& ArrayView<const T>::front() const
333 {
334  debug_assert_not_null();
335  debug_assert_valid_ptr();
336  return *ptr_;
337 }
338 
339 template<class T> inline
341 {
342  debug_assert_not_null();
343  debug_assert_valid_ptr();
344  return *(ptr_+size_-1);
345 }
346 
347 template<class T> inline
348 const T& ArrayView<const T>::back() const
349 {
350  debug_assert_not_null();
351  debug_assert_valid_ptr();
352  return *(ptr_+size_-1);
353 }
354 
355 
356 // Views
357 
358 
359 template<class T> inline
361 {
362  if (size_in == 0) { return null; }
363  debug_assert_valid_ptr();
364  debug_assert_in_range(offset, size_in);
365  return ArrayView<T>(
366  ptr_+offset, size_in
367 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
368  ,arcp_.persistingView(offset, size_in)
369 #endif
370  );
371  // WARNING: The above code had better be correct since we are using raw
372  // pointer arithmetic!
373 }
374 
375 template<class T> inline
377 {
378  if (size_in == 0) { return null; }
379  debug_assert_valid_ptr();
380  debug_assert_in_range(offset, size_in);
381  return ArrayView<const T>(
382  ptr_+offset, size_in
383 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
384  ,arcp_.persistingView(offset, size_in)
385 #endif
386  );
387  // WARNING: The above code had better be correct since we are using raw
388  // pointer arithmetic!
389 }
390 
391 
392 template<class T> inline
394 {
395  return view(offset, size_in);
396 }
397 
398 template<class T> inline
400 {
401  return view(offset, size_in);
402 }
403 
404 
405 template<class T> inline
407 {
408  debug_assert_valid_ptr();
409  return *this;
410 }
411 
412 template<class T> inline
414 {
415  debug_assert_valid_ptr();
416  return *this;
417 }
418 
419 
420 template<class T> inline
422 {
423  debug_assert_valid_ptr();
424 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
425  return ArrayView<const T>(arcp_.getConst());
426 #else
427  return ArrayView<const T>(ptr_, size_);
428 #endif
429 }
430 
431 template<class T> inline
433  return *this;
434 }
435 
436 
437 template<class T> inline
439 {
440  return getConst();
441 }
442 
443 
444 // Assignment
445 
446 
447 template<class T>
448 void ArrayView<T>::assign(const ArrayView<const T>& array) const
449 {
450  debug_assert_valid_ptr();
451  debug_assert_not_null();
452  if (this->getRawPtr()==array.getRawPtr() && this->size()==array.size())
453  return; // Assignment to self
454  debug_assert_in_range(0,array.size());
455  std::copy( array.begin(), array.end(), this->begin() );
456  // Note: Above, in debug mode, the iterators are range checked! In
457  // optimized mode, these are raw pointers which should run very fast!
458 }
459 
460 
461 // Standard Container-Like Functions
462 
463 
464 template<class T>
466 {
467  debug_assert_valid_ptr();
468 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
469  return arcp_.create_weak();
470 #else
471  return ptr_;
472 #endif
473 }
474 
475 template<class T>
477 {
478  debug_assert_valid_ptr();
479 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
480  return arcp_.create_weak();
481 #else
482  return ptr_;
483 #endif
484 }
485 
486 
487 template<class T>
489 {
490  debug_assert_valid_ptr();
491 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
492  return arcp_.create_weak() + size_;
493 #else
494  return ptr_ + size_;
495 #endif
496 }
497 
498 template<class T>
500 {
501  debug_assert_valid_ptr();
502 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
503  return arcp_.create_weak() + size_;
504 #else
505  return ptr_ + size_;
506 #endif
507 }
508 
509 
510 // Assertion Functions.
511 
512 
513 template<class T>
515 {
516  if(!ptr_)
517  throw_null_ptr_error(typeName(*this));
518  return *this;
519 }
520 
521 template<class T>
523 {
524  if(!ptr_)
525  throw_null_ptr_error(typeName(*this));
526  return *this;
527 }
528 
529 
530 template<class T>
531 const ArrayView<T>&
533 {
534  assert_not_null();
535  TEUCHOS_TEST_FOR_EXCEPTION( size_in == as<size_type>(0), RangeError,
536  "Error, size=0 is not allowed!" );
538  !(
539  ( 0 <= offset && offset+size_in <= this->size() )
540  &&
541  size_in >= 0
542  ),
543  RangeError,
544  typeName(*this)<<"::assert_in_range():"
545  " Error, [offset,offset+size) = ["<<offset<<","<<(offset+size_in)<<")"
546  " does not lie in the range [0,"<<this->size()<<")!"
547  );
548  return*this;
549 }
550 
551 template<class T>
552 const ArrayView<const T>&
554 {
555  assert_not_null();
556  TEUCHOS_TEST_FOR_EXCEPTION( size_in == as<size_type>(0), RangeError,
557  "Error, size=0 is not allowed!" );
559  !(
560  ( 0 <= offset && offset+size_in <= this->size() )
561  &&
562  size_in >= 0
563  ),
564  RangeError,
565  typeName(*this)<<"::assert_in_range():"
566  " Error, [offset,offset+size) = ["<<offset<<","<<(offset+size_in)<<")"
567  " does not lie in the range [0,"<<this->size()<<")!"
568  );
569  return*this;
570 }
571 
572 
573 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
574 
575 template<class T>
577  : ptr_(arcp.getRawPtr()), size_(arcp.size()), arcp_(arcp)
578 {}
579 
580 template<class T>
582  : ptr_(arcp.getRawPtr()), size_(arcp.size()), arcp_(arcp)
583 {}
584 
585 
586 template<class T>
587 ArrayView<T>::ArrayView(T* p, size_type size_in, const ArrayRCP<T> &arcp)
588  : ptr_(p), size_(size_in), arcp_(arcp)
589 {}
590 
591 template<class T>
592 ArrayView<const T>::ArrayView(const T* p, size_type size_in, const ArrayRCP<const T> &arcp)
593  : ptr_(p), size_(size_in), arcp_(arcp)
594 {}
595 
596 
597 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
598 
599 
600 // private
601 
602 
603 template<class T>
604 void ArrayView<T>::setUpIterators(const ERCPNodeLookup rcpNodeLookup)
605 {
606 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
607  if (ptr_ && arcp_.is_null()) {
608  arcp_ = ArrayRCP<T>(ptr_, 0, size_, false, rcpNodeLookup);
609  }
610 #else
611  (void) rcpNodeLookup; // Silence "unused variable" compiler warning.
612 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
613 }
614 
615 template<class T>
616 void ArrayView<const T>::setUpIterators(const ERCPNodeLookup rcpNodeLookup)
617 {
618 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
619  if (ptr_ && arcp_.is_null()) {
620  arcp_ = ArrayRCP<const T>(ptr_, 0, size_, false, rcpNodeLookup);
621  }
622 #else
623  (void) rcpNodeLookup; // Silence "unused variable" compiler warning.
624 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
625 }
626 
627 
628 } // namespace Teuchos
629 
630 
631 //
632 // Nonmember helper functions
633 //
634 
635 
636 template<class T> inline
638 Teuchos::arrayView( T* p, typename ArrayView<T>::size_type size )
639 {
640  if (size == 0)
641  return null;
642  return ArrayView<T>(p, size);
643 }
644 
645 
646 template<class T> inline
647 Teuchos::ArrayView<T> Teuchos::arrayViewFromVector( std::vector<T>& vec )
648 {
649  if (vec.size() == 0)
650  return null;
651  return ArrayView<T>(vec);
652 }
653 
654 
655 template<class T> inline
656 Teuchos::ArrayView<const T> Teuchos::arrayViewFromVector( const std::vector<T>& vec )
657 {
658  if (vec.size() == 0)
659  return null;
660  return ArrayView<const T>(vec);
661 }
662 
663 
664 #ifndef __sun
665 
666 template<class T> inline
667 std::vector<T> Teuchos::createVector( const ArrayView<T> &av )
668 {
669  std::vector<T> v(av.begin(), av.end());
670  return v;
671 }
672 
673 #endif // __sun
674 
675 
676 template<class T> inline
677 std::vector<T> Teuchos::createVector( const ArrayView<const T> &av )
678 {
679  std::vector<T> v(av.begin(), av.end());
680  return v;
681 }
682 
683 
684 template<class T> inline
685 bool Teuchos::is_null( const ArrayView<T> &av )
686 {
687  return av.is_null();
688 }
689 
690 
691 template<class T> inline
692 bool Teuchos::nonnull( const ArrayView<T> &av )
693 {
694  return !av.is_null();
695 }
696 
697 
698 template<class T>
699 std::ostream& Teuchos::operator<<( std::ostream& out, const ArrayView<T>& p )
700 {
701  return out << p.toString();
702 }
703 
704 
705 template<class T2, class T1>
706 REFCOUNTPTR_INLINE
708 Teuchos::av_const_cast(const ArrayView<T1>& p1)
709 {
710  T2 *ptr2 = const_cast<T2*>(p1.getRawPtr());
711  return ArrayView<T2>(ptr2, p1.size());
712  // Note: Above is just fine even if p1.get()==NULL!
713 }
714 
715 
716 template<class T2, class T1>
717 REFCOUNTPTR_INLINE
719 Teuchos::av_reinterpret_cast(const ArrayView<T1>& p1)
720 {
721  typedef typename ArrayView<T1>::size_type size_type;
722  const int sizeOfT1 = sizeof(T1);
723  const int sizeOfT2 = sizeof(T2);
724  size_type size2 = (p1.size()*sizeOfT1) / sizeOfT2;
725  T2 *ptr2 = reinterpret_cast<T2*>(p1.getRawPtr());
726  return ArrayView<T2>(
727  ptr2, size2
728 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
729  ,arcp_reinterpret_cast<T2>(p1.access_private_arcp())
730 #endif
731  );
732  // Note: Above is just fine even if p1.get()==NULL!
733 }
734 
735 
736 #endif // TEUCHOS_ARRAY_VIEW_HPP
bool is_null(const boost::shared_ptr< T > &p)
Returns true if p.get()==NULL.
pointer iterator
Type of a nonconst iterator.
Partial specialization of ArrayRCP for const T.
size_type size() const
The total number of entries in the array.
bool nonnull(const std::shared_ptr< T > &p)
Returns true if p.get()!=NULL.
bool is_null(const std::shared_ptr< T > &p)
Returns true if p.get()==NULL.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
Ordinal size_type
Type representing the number of elements in an ArrayRCP or view thereof.
size_type size() const
The total number of items in the managed array.
iterator begin() const
Return an iterator to beginning of the array of data.
bool is_null() const
Returns true if the underlying pointer is null.
Nonowning array view.
T * getRawPtr() const
Return a raw pointer to beginning of array or NULL if unsized.
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos, as well as a number of utility routines.
ERCPNodeLookup
Used to determine if RCPNode lookup is performed or not.
ArrayView(ENull null_arg=null)
Constructor that initializes to NULL (implicitly or explicitly).
TypeTo as(const TypeFrom &t)
Convert from one value type to another.
T * getRawPtr() const
Get the raw C++ pointer to the underlying object.
Partial specialization of ArrayView for const T.
Range error exception class.
iterator end() const
Return an iterator to past the end of the array of data.
const T & getConst(T &t)
Return a constant reference to an object given a non-const reference.
Definition of Teuchos::as, for conversions between types.
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
This macro is designed to be a short version of TEUCHOS_TEST_FOR_EXCEPTION() that is easier to call...
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in object.
Reference-counted smart pointer for managing arrays.