Teuchos - Trilinos Tools Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Teuchos_ArrayView.hpp
1 // @HEADER
2 // *****************************************************************************
3 // Teuchos: Common Tools Package
4 //
5 // Copyright 2004 NTESS and the Teuchos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef TEUCHOS_ARRAY_VIEW_HPP
11 #define TEUCHOS_ARRAY_VIEW_HPP
12 
13 
14 #include "Teuchos_ArrayViewDecl.hpp"
15 #include "Teuchos_ArrayRCP.hpp"
16 #include "Teuchos_as.hpp"
17 
18 
19 namespace Teuchos {
20 
21 
22 // Constructors/Destructors
23 
24 
25 template<class T> inline
27  : ptr_(0), size_(0)
28 {
29  setUpIterators();
30 }
31 
32 template<class T> inline
34  : ptr_(0), size_(0)
35 {
36  setUpIterators();
37 }
38 
39 
40 
41 template<class T> inline
42 ArrayView<T>::ArrayView( T* p, size_type size_in, const ERCPNodeLookup rcpNodeLookup )
43  :ptr_(size_in == 0 ? nullptr : p), size_(size_in)
44 {
45 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
46  // We comment out the one check below, as part of the fix for #4234:
47  //
48  // https://github.com/trilinos/Trilinos/issues/4234
49  //
50  // This permits conversion from std::vector or Kokkos::View, using
51  // ArrayView(x.data(), x.size(), RCP_DISABLE_NODE_LOOKUP). The
52  // other part of the fix is that we make sure ptr_ is null if
53  // size_in is zero.
54  //
55  //TEUCHOS_TEST_FOR_EXCEPT( p != 0 && size_in <= 0 );
56 
57  TEUCHOS_TEST_FOR_EXCEPT( p == 0 && size_in != 0 );
58  // This only does something if HAVE_TEUCHOS_ARRAY_BOUNDSCHECK is defined.
59  setUpIterators(rcpNodeLookup);
60 #else
61  (void) rcpNodeLookup; // Silence "unused variable" compiler warning.
62 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
63 }
64 
65 template<class T> inline
66 ArrayView<const T>::ArrayView(const T* p, size_type size_in, const ERCPNodeLookup rcpNodeLookup )
67  : ptr_(size_in == 0 ? nullptr : p), size_(size_in)
68 {
69 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
70  // We comment out the one check below, as part of the fix for #4234:
71  //
72  // https://github.com/trilinos/Trilinos/issues/4234
73  //
74  // This permits conversion from std::vector or Kokkos::View, using
75  // ArrayView(x.data(), x.size(), RCP_DISABLE_NODE_LOOKUP). The
76  // other part of the fix is that we make sure ptr_ is null if
77  // size_in is zero.
78  //
79  //TEUCHOS_TEST_FOR_EXCEPT( p != 0 && size_in <= 0 );
80 
81  TEUCHOS_TEST_FOR_EXCEPT( p == 0 && size_in != 0 );
82  // This only does something if HAVE_TEUCHOS_ARRAY_BOUNDSCHECK is defined.
83  setUpIterators(rcpNodeLookup);
84 #else
85  (void) rcpNodeLookup; // Silence "unused variable" compiler warning.
86 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
87 }
88 
89 
90 template<class T> inline
92  :ptr_(array.ptr_), size_(array.size_)
93 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
94  ,arcp_(array.arcp_)
95 #endif
96 {}
97 
98 template<class T> inline
100  :ptr_(array.ptr_), size_(array.size_)
101 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
102  ,arcp_(array.arcp_)
103 #endif
104 {}
105 
106 
107 template<class T> inline
109  std::vector<typename std::remove_const_t<T>>& vec
110  )
111  : ptr_( vec.empty() ? 0 : vec.data() ), size_(vec.size())
112 {
113  setUpIterators();
114 }
115 
116 template<class T> inline
118  std::vector<typename std::remove_const_t<T>>& vec
119  )
120  : ptr_( vec.empty() ? 0 : vec.data() ), size_(vec.size())
121 {
122  setUpIterators();
123 }
124 
125 
126 template<class T> inline
128  const std::vector<typename std::remove_const_t<T>>& vec
129  )
130  : ptr_( vec.empty() ? 0 : vec.data() ), size_(vec.size())
131 {
132  setUpIterators();
133 }
134 
135 template<class T> inline
137  const std::vector<typename std::remove_const_t<T>>& vec
138  )
139  : ptr_( vec.empty() ? 0 : vec.data() ), size_(vec.size())
140 {
141  setUpIterators();
142 }
143 
144 
145 template<class T> inline
147 {
148  ptr_ = array.ptr_;
149  size_ = array.size_;
150 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
151  arcp_ = array.arcp_;
152 #endif
153  return *this;
154 }
155 
156 template<class T> inline
158 {
159  ptr_ = array.ptr_;
160  size_ = array.size_;
161 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
162  arcp_ = array.arcp_;
163 #endif
164  return *this;
165 }
166 
167 
168 template<class T> inline
170 {}
171 
172 template<class T> inline
174 {}
175 
176 
177 // General query functions
178 
179 
180 template<class T>
181 inline
183 {
184  return ptr_ == 0;
185 }
186 
187 template<class T>
188 inline
189 bool ArrayView<const T>::is_null() const
190 {
191  return ptr_ == 0;
192 }
193 
194 
195 template<class T> inline
197 {
198  debug_assert_valid_ptr();
199  return size_;
200 }
201 
202 template<class T> inline
204 {
205  debug_assert_valid_ptr();
206  return size_;
207 }
208 
209 
210 template<typename T>
211 std::string ArrayView<T>::toString() const
212 {
213  using Teuchos::as;
214  std::ostringstream ss;
215 
216  debug_assert_valid_ptr();
217 
218  ss << "{";
219  for (size_type i = 0; i < size (); ++i) {
220  // NOTE: This depends on std::ostream::operator<<(const T&).
221  ss << operator[] (i);
222  if (i + 1 < size ()) {
223  ss << ", ";
224  }
225  }
226  ss << "}";
227  return ss.str ();
228 }
229 
230 template<typename T>
231 std::string ArrayView<const T>::toString() const
232 {
233  using Teuchos::as;
234  std::ostringstream ss;
235 
236  debug_assert_valid_ptr();
237 
238  ss << "{";
239  for (size_type i = 0; i < size (); ++i) {
240  // NOTE: This depends on std::ostream::operator<<(const T&).
241  ss << operator[] (i);
242  if (i + 1 < size ()) {
243  ss << ", ";
244  }
245  }
246  ss << "}";
247  return ss.str ();
248 }
249 
250 
251 // Specialization for float. We use sufficient precision that no
252 // digits are lost after writing to string and reading back in again.
253 template<>
254 TEUCHOSCORE_LIB_DLL_EXPORT std::string
256 
257 // Specialization for (const) float. We use sufficient precision that no
258 // digits are lost after writing to string and reading back in again.
259 template<>
260 TEUCHOSCORE_LIB_DLL_EXPORT std::string
262 
263 // Specialization for double. 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) double. 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 
276 // Element Access Functions
277 
278 
279 template<class T> inline
281 {
282  debug_assert_valid_ptr();
283  return ptr_;
284 }
285 
286 template<class T> inline
288 {
289  debug_assert_valid_ptr();
290  return ptr_;
291 }
292 
293 template<class T> inline
294 const T* ArrayView<const T>::getRawPtr() const
295 {
296  debug_assert_valid_ptr();
297  return ptr_;
298 }
299 
300 template<class T> inline
301 const T* ArrayView<const T>::data() const
302 {
303  debug_assert_valid_ptr();
304  return ptr_;
305 }
306 
307 template<class T> inline
309 {
310  debug_assert_valid_ptr();
311  debug_assert_in_range(i,1);
312  return ptr_[i];
313 }
314 
315 template<class T> inline
316 const T& ArrayView<const T>::operator[](size_type i) const
317 {
318  debug_assert_valid_ptr();
319  debug_assert_in_range(i,1);
320  return ptr_[i];
321 }
322 
323 
324 template<class T> inline
326 {
327  debug_assert_not_null();
328  debug_assert_valid_ptr();
329  return *ptr_;
330 }
331 
332 template<class T> inline
333 const T& ArrayView<const T>::front() const
334 {
335  debug_assert_not_null();
336  debug_assert_valid_ptr();
337  return *ptr_;
338 }
339 
340 template<class T> inline
342 {
343  debug_assert_not_null();
344  debug_assert_valid_ptr();
345  return *(ptr_+size_-1);
346 }
347 
348 template<class T> inline
349 const T& ArrayView<const T>::back() const
350 {
351  debug_assert_not_null();
352  debug_assert_valid_ptr();
353  return *(ptr_+size_-1);
354 }
355 
356 
357 // Views
358 
359 
360 template<class T> inline
362 {
363  if (size_in == 0) { return null; }
364  debug_assert_valid_ptr();
365  debug_assert_in_range(offset, size_in);
366  return ArrayView<T>(
367  ptr_+offset, size_in
368 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
369  ,arcp_.persistingView(offset, size_in)
370 #endif
371  );
372  // WARNING: The above code had better be correct since we are using raw
373  // pointer arithmetic!
374 }
375 
376 template<class T> inline
377 ArrayView<const T> ArrayView<const T>::view(size_type offset, size_type size_in) const
378 {
379  if (size_in == 0) { return null; }
380  debug_assert_valid_ptr();
381  debug_assert_in_range(offset, size_in);
382  return ArrayView<const T>(
383  ptr_+offset, size_in
384 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
385  ,arcp_.persistingView(offset, size_in)
386 #endif
387  );
388  // WARNING: The above code had better be correct since we are using raw
389  // pointer arithmetic!
390 }
391 
392 
393 template<class T> inline
395 {
396  return view(offset, size_in);
397 }
398 
399 template<class T> inline
400 ArrayView<const T> ArrayView<const T>::operator()(size_type offset, size_type size_in) const
401 {
402  return view(offset, size_in);
403 }
404 
405 
406 template<class T> inline
408 {
409  debug_assert_valid_ptr();
410  return *this;
411 }
412 
413 template<class T> inline
415 {
416  debug_assert_valid_ptr();
417  return *this;
418 }
419 
420 
421 template<class T> inline
423 {
424  debug_assert_valid_ptr();
425 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
426  return ArrayView<const T>(arcp_.getConst());
427 #else
428  return ArrayView<const T>(ptr_, size_);
429 #endif
430 }
431 
432 template<class T> inline
434  return *this;
435 }
436 
437 
438 template<class T> inline
440 {
441  return getConst();
442 }
443 
444 
445 // Assignment
446 
447 
448 template<class T>
449 void ArrayView<T>::assign(const ArrayView<const T>& array) const
450 {
451  debug_assert_valid_ptr();
452  debug_assert_not_null();
453  if (this->getRawPtr()==array.getRawPtr() && this->size()==array.size())
454  return; // Assignment to self
455  debug_assert_in_range(0,array.size());
456  std::copy( array.begin(), array.end(), this->begin() );
457  // Note: Above, in debug mode, the iterators are range checked! In
458  // optimized mode, these are raw pointers which should run very fast!
459 }
460 
461 
462 // Standard Container-Like Functions
463 
464 
465 template<class T>
467 {
468  debug_assert_valid_ptr();
469 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
470  return arcp_.create_weak();
471 #else
472  return ptr_;
473 #endif
474 }
475 
476 template<class T>
478 {
479  debug_assert_valid_ptr();
480 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
481  return arcp_.create_weak();
482 #else
483  return ptr_;
484 #endif
485 }
486 
487 
488 template<class T>
490 {
491  debug_assert_valid_ptr();
492 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
493  return arcp_.create_weak() + size_;
494 #else
495  return ptr_ + size_;
496 #endif
497 }
498 
499 template<class T>
501 {
502  debug_assert_valid_ptr();
503 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
504  return arcp_.create_weak() + size_;
505 #else
506  return ptr_ + size_;
507 #endif
508 }
509 
510 
511 // Assertion Functions.
512 
513 
514 template<class T>
516 {
517  if(!ptr_)
518  throw_null_ptr_error(typeName(*this));
519  return *this;
520 }
521 
522 template<class T>
524 {
525  if(!ptr_)
526  throw_null_ptr_error(typeName(*this));
527  return *this;
528 }
529 
530 
531 template<class T>
532 const ArrayView<T>&
534 {
535  assert_not_null();
536  TEUCHOS_TEST_FOR_EXCEPTION( size_in == as<size_type>(0), RangeError,
537  "Error, size=0 is not allowed!" );
539  !(
540  ( 0 <= offset && offset+size_in <= this->size() )
541  &&
542  size_in >= 0
543  ),
544  RangeError,
545  typeName(*this)<<"::assert_in_range():"
546  " Error, [offset,offset+size) = ["<<offset<<","<<(offset+size_in)<<")"
547  " does not lie in the range [0,"<<this->size()<<")!"
548  );
549  return*this;
550 }
551 
552 template<class T>
553 const ArrayView<const T>&
554 ArrayView<const T>::assert_in_range(size_type offset, size_type size_in) const
555 {
556  assert_not_null();
557  TEUCHOS_TEST_FOR_EXCEPTION( size_in == as<size_type>(0), RangeError,
558  "Error, size=0 is not allowed!" );
560  !(
561  ( 0 <= offset && offset+size_in <= this->size() )
562  &&
563  size_in >= 0
564  ),
565  RangeError,
566  typeName(*this)<<"::assert_in_range():"
567  " Error, [offset,offset+size) = ["<<offset<<","<<(offset+size_in)<<")"
568  " does not lie in the range [0,"<<this->size()<<")!"
569  );
570  return*this;
571 }
572 
573 
574 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
575 
576 template<class T>
577 ArrayView<T>::ArrayView( const ArrayRCP<T> &arcp )
578  : ptr_(arcp.getRawPtr()), size_(arcp.size()), arcp_(arcp)
579 {}
580 
581 template<class T>
582 ArrayView<const T>::ArrayView( const ArrayRCP<const T> &arcp )
583  : ptr_(arcp.getRawPtr()), size_(arcp.size()), arcp_(arcp)
584 {}
585 
586 
587 template<class T>
588 ArrayView<T>::ArrayView(T* p, size_type size_in, const ArrayRCP<T> &arcp)
589  : ptr_(p), size_(size_in), arcp_(arcp)
590 {}
591 
592 template<class T>
593 ArrayView<const T>::ArrayView(const T* p, size_type size_in, const ArrayRCP<const T> &arcp)
594  : ptr_(p), size_(size_in), arcp_(arcp)
595 {}
596 
597 
598 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
599 
600 
601 // private
602 
603 
604 template<class T>
605 void ArrayView<T>::setUpIterators(const ERCPNodeLookup rcpNodeLookup)
606 {
607 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
608  if (ptr_ && arcp_.is_null()) {
609  arcp_ = ArrayRCP<T>(ptr_, 0, size_, false, rcpNodeLookup);
610  }
611 #else
612  (void) rcpNodeLookup; // Silence "unused variable" compiler warning.
613 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
614 }
615 
616 template<class T>
617 void ArrayView<const T>::setUpIterators(const ERCPNodeLookup rcpNodeLookup)
618 {
619 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
620  if (ptr_ && arcp_.is_null()) {
621  arcp_ = ArrayRCP<const T>(ptr_, 0, size_, false, rcpNodeLookup);
622  }
623 #else
624  (void) rcpNodeLookup; // Silence "unused variable" compiler warning.
625 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
626 }
627 
628 
629 } // namespace Teuchos
630 
631 
632 //
633 // Nonmember helper functions
634 //
635 
636 
637 template<class T> inline
639 Teuchos::arrayView( T* p, typename ArrayView<T>::size_type size )
640 {
641  if (size == 0)
642  return null;
643  return ArrayView<T>(p, size);
644 }
645 
646 
647 template<class T> inline
648 Teuchos::ArrayView<T> Teuchos::arrayViewFromVector( std::vector<T>& vec )
649 {
650  if (vec.size() == 0)
651  return null;
652  return ArrayView<T>(vec);
653 }
654 
655 
656 template<class T> inline
657 Teuchos::ArrayView<const T> Teuchos::arrayViewFromVector( const std::vector<T>& vec )
658 {
659  if (vec.size() == 0)
660  return null;
661  return ArrayView<const T>(vec);
662 }
663 
664 
665 #ifndef __sun
666 
667 template<class T> inline
668 std::vector<T> Teuchos::createVector( const ArrayView<T> &av )
669 {
670  std::vector<T> v(av.begin(), av.end());
671  return v;
672 }
673 
674 #endif // __sun
675 
676 
677 template<class T> inline
678 std::vector<T> Teuchos::createVector( const ArrayView<const T> &av )
679 {
680  std::vector<T> v(av.begin(), av.end());
681  return v;
682 }
683 
684 
685 template<class T> inline
686 bool Teuchos::is_null( const ArrayView<T> &av )
687 {
688  return av.is_null();
689 }
690 
691 
692 template<class T> inline
693 bool Teuchos::nonnull( const ArrayView<T> &av )
694 {
695  return !av.is_null();
696 }
697 
698 
699 template<class T>
700 std::ostream& Teuchos::operator<<( std::ostream& out, const ArrayView<T>& p )
701 {
702  return out << p.toString();
703 }
704 
705 
706 template<class T2, class T1>
707 REFCOUNTPTR_INLINE
709 Teuchos::av_const_cast(const ArrayView<T1>& p1)
710 {
711  T2 *ptr2 = const_cast<T2*>(p1.getRawPtr());
712  return ArrayView<T2>(ptr2, p1.size());
713  // Note: Above is just fine even if p1.get()==NULL!
714 }
715 
716 
717 template<class T2, class T1>
718 REFCOUNTPTR_INLINE
720 Teuchos::av_reinterpret_cast(const ArrayView<T1>& p1)
721 {
722  typedef typename ArrayView<T1>::size_type size_type;
723  const int sizeOfT1 = sizeof(T1);
724  const int sizeOfT2 = sizeof(T2);
725  size_type size2 = (p1.size()*sizeOfT1) / sizeOfT2;
726  T2 *ptr2 = reinterpret_cast<T2*>(p1.getRawPtr());
727  return ArrayView<T2>(
728  ptr2, size2
729 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
730  ,arcp_reinterpret_cast<T2>(p1.access_private_arcp())
731 #endif
732  );
733  // Note: Above is just fine even if p1.get()==NULL!
734 }
735 
736 
737 #endif // TEUCHOS_ARRAY_VIEW_HPP
std::string toString() const
Convert an ArrayView&lt;T&gt; to an std::string
T & front() const
Get the first element.
pointer iterator
Type of a nonconst iterator.
bool is_null() const
Returns true if the underlying pointer is null.
const ArrayView< T > & assert_in_range(size_type offset, size_type size) const
Throws NullReferenceError if this-&gt;get()==NULL orthis-&gt;get()!=NULL, throws RangeError if (offset &lt; 0 ...
iterator begin() const
Return an iterator to beginning of the array of data.
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.
ENull
Used to initialize a RCP object to NULL using an implicit conversion!
T * data() const
Return a raw pointer to beginning of array.
ArrayRCP< T2 > arcp_reinterpret_cast(const ArrayRCP< T1 > &p1)
Reinterpret cast of underlying ArrayRCP type from T1* to T2*.
void assign(const ArrayView< const T > &array) const
Copy the data from one array view object to this array view object.
int size(const Comm< Ordinal > &comm)
Get the number of processes in the communicator.
T * getRawPtr() const
Return a raw pointer to beginning of array or NULL if unsized.
const ArrayView< T > & assert_not_null() const
Throws NullReferenceError if this-&gt;get()==NULL, otherwise returns reference to *this.
const ArrayView< T > & operator()() const
Return *this (just for compatibility with Array and ArrayPtr).
Nonowning array view.
ERCPNodeLookup
Used to determine if RCPNode lookup is performed or not.
ArrayView(ENull null_arg=null)
Constructor that initializes to NULL (implicitly or explicitly).
iterator end() const
Return an iterator to past the end of the array of data.
TypeTo as(const TypeFrom &t)
Convert from one value type to another.
ArrayView< T > view(size_type offset, size_type size) const
Return a view of a contiguous range of elements.
Partial specialization of ArrayView for const T.
Range error exception class.
T & operator[](size_type i) const
Random object access.
const T & getConst(T &t)
Return a constant reference to an object given a non-const reference.
ArrayView< T > & operator=(const ArrayView< T > &array)
Shallow copy assignment operator.
Definition of Teuchos::as, for conversions between types.
ArrayView< const T > getConst() const
Return a const view of a possibly nonconst view.
T & back() const
Get the last element.
#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.