Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ArrayView_test.cpp
Go to the documentation of this file.
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 #include "Teuchos_ArrayView.hpp"
15 #include "Teuchos_Version.hpp"
16 #include "Teuchos_getConst.hpp"
17 #include "Teuchos_as.hpp"
19 
20 
21 // Uncomment to show compile errors from invalid usage
22 //#define SHOW_INVALID_COPY_CONSTRUCTION
23 //#define SHOW_INVALID_CONST_ASSIGN
24 //#define SHOW_INVALID_CONST_ITER_MODIFICATION
25 
26 //
27 // Define local macros to make defining tests easier for this particular test
28 // code.
29 //
30 // Note, macros with these types of names should only exist in a *.cpp file
31 // after all #includes are done!
32 //
33 
34 
35 #define TEST_EQUALITY_CONST( v1, v2 ) \
36  TEUCHOS_TEST_EQUALITY_CONST( v1, v2, out, success )
37 
38 #define TEST_EQUALITY( v1, v2 ) \
39  TEUCHOS_TEST_EQUALITY( v1, v2, out, success )
40 
41 #define TEST_ITER_EQUALITY( iter1, iter2 ) \
42  TEUCHOS_TEST_ITER_EQUALITY( iter1, iter2, out, success )
43 
44 #define TEST_ARRAY_ELE_EQUALITY( a, i, val ) \
45  TEUCHOS_TEST_ARRAY_ELE_EQUALITY( a, i, val, false, out, local_success )
46 
47 #define TEST_COMPARE( v1, comp, v2 ) \
48  TEUCHOS_TEST_COMPARE( v1, comp, v2, out, success )
49 
50 #define TEST_COMPARE_ARRAYS( a1, a2 ) \
51  { \
52  const bool result = compareArrays(a1,#a1,a2,#a2,out); \
53  if (!result) success = false; \
54  }
55 
56 #define TEST_THROW( code, ExceptType ) \
57  TEUCHOS_TEST_THROW( code, ExceptType, out, success )
58 
59 #define TEST_NOTHROW( code ) \
60  TEUCHOS_TEST_NOTHROW( code, out, success )
61 
62 
63 //
64 // Main templated array test function
65 //
66 
67 
68 template<class T>
69 bool testArrayView( const int n, Teuchos::FancyOStream &out )
70 {
71 
72  using Teuchos::ArrayView;
73  using Teuchos::arrayView;
74  using Teuchos::arrayViewFromVector;
75  using Teuchos::outArg;
78  using Teuchos::getConst;
79  using Teuchos::as;
80  typedef typename ArrayView<T>::size_type size_type;
81  // mfh 03 Apr 2014: The point of the above line of code is to ensure
82  // that ArrayView<T> has a public size_type typedef. However, the
83  // above line of code in isolation causes some compilers to warn
84  // about a declared but unused typedef. We deal with this by
85  // declaring a variable (actually, the oxymoron "const variable") of
86  // type size_type, then using the "cast to void" trick to forestall
87  // compiler warnings for the declared but unused variable. (Fun
88  // fact: "oxymoron" means "sharp dull" and is itself an oxymoron.)
89  // The "cast to void" trick doesn't always work, but if it doesn't,
90  // it's easy to make it go away by printing it to the output stream
91  // 'out'.
92  const size_type arbitrarySizeTypeValue = 0;
93  (void) arbitrarySizeTypeValue;
94 
95  bool success = true;
96 
97  out
98  << "\n***"
99  << "\n*** Testing "<<TypeNameTraits<ArrayView<T> >::name()<<" of size = "<<n
100  << "\n***\n";
101 
102  Teuchos::OSTab tab(out);
103 
104  //
105  out << "\nA) Initial setup testing ...\n\n";
106  //
107 
108  {
109  out << "\nTesting basic null construction!\n\n";
110  ArrayView<T> av2 = Teuchos::null;
111  TEST_EQUALITY_CONST(is_null(av2),true);
112  TEST_EQUALITY_CONST(av2.size(),0);
113  TEST_EQUALITY_CONST(av2.getRawPtr(),0);
114  TEST_EQUALITY_CONST(av2.getRawPtr(),av2.data());
115  TEST_ITER_EQUALITY(av2.begin(),av2.end());
116 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
120  TEST_THROW(av2.assign(av2), Teuchos::NullReferenceError);
123 #endif
124  ArrayView<const T> cav2(av2); // Tests copy constructor and implicit conversion operator!
125  TEST_EQUALITY_CONST(cav2.size(),0);
126  TEST_EQUALITY_CONST(cav2.getRawPtr(),0);
127  TEST_EQUALITY_CONST(cav2.getRawPtr(),cav2.data());
128  TEST_ITER_EQUALITY(cav2.begin(),av2.end());
129 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
131  TEST_THROW(*cav2.begin(), Teuchos::NullReferenceError);
134 #endif
135 #ifdef SHOW_INVALID_CONST_ASSIGN
136  TEST_NOTHROW(cav2.assign(av2)); // Should not compile!
137 #endif
138  }
139 
140  std::vector<T> v(n);
141 
142  const ArrayView<T> av = arrayViewFromVector(v);
143  TEST_EQUALITY_CONST(is_null(av), false);
144  TEST_EQUALITY( as<int>(av.size()), n );
145 
146  const ArrayView<const T> cav = av;
147 
148  {
149  out << "\nInitializing data for std::vector v through view av ...\n";
150  for( int i = 0; i < n; ++i )
151  av[i] = i; // tests non-const operator[](i)
152  }
153 
154  {
155  out << "\nTest that v[i] == i through ArrayView<const T> ...\n";
156  const ArrayView<const T> cav2 = cav;
157  bool local_success = true;
158  for( int i = 0; i < n; ++i ) {
159  TEST_ARRAY_ELE_EQUALITY( cav2, i, as<T>(i) );
160  }
161  if (local_success) out << "passed\n";
162  else success = false;
163  }
164 
165  {
166  out << "\nTest explicit copy to std::vector from non-const array view ...\n";
167  std::vector<T> v2 = Teuchos::createVector(av);
168  TEST_COMPARE_ARRAYS( v2, v );
169  }
170 
171  {
172  out << "\nTest explicit copy to std::vector from const array view ...\n";
173  std::vector<T> v2 = Teuchos::createVector(cav);
174  TEST_COMPARE_ARRAYS( v2, v );
175  }
176 
177  {
178  out << "\nTest shallow implicit conversion from ArrayView<T> to ArrayView<T> ...\n";
179  ArrayView<T> av2(av);
180  TEST_COMPARE_ARRAYS( av2, av );
181  }
182 
183  {
184  out << "\nTest shallow implicit conversion from ArrayView<const T> to ArrayView<const T> ...\n";
185  ArrayView<const T> cav2(cav);
186  TEST_COMPARE_ARRAYS( cav2, cav );
187  }
188 
189  {
190  out << "\nTest shallow implicit conversion from ArrayView<const T> to ArrayView<T> ...\n";
191  ArrayView<const T> cav2(av);
192  TEST_COMPARE_ARRAYS( cav2, av );
193  }
194 
195  {
196  out << "\nTest shallow implicit conversion from std::vector<T> to ArrayView<T> ...\n";
197  std::vector<T> v2 = Teuchos::createVector(cav);
198  ArrayView<T> cav2(v2);
199  TEST_COMPARE_ARRAYS( cav2, av );
200  }
201 
202  {
203  out << "\nTest shallow implicit conversion from const std::vector<T> to ArrayView<const T> ...\n";
204  const std::vector<T> v2 = Teuchos::createVector(cav);
205  ArrayView<const T> cav2(v2);
206  TEST_COMPARE_ARRAYS( cav2, av );
207  }
208 
209  {
210  // Try to copy construct from ArrayView<const T> to ArrayView<T> ..
211 #ifdef SHOW_INVALID_COPY_CONSTRUCTION
212  ArrayView<T> cav2(cav); // should not compile!
213 #endif
214  }
215 
216  {
217  out << "\ntest assign(...) ...\n";
218  std::vector<T> v2(n);
219  ArrayView<T> av2(v2);
220  av2.assign(av);
221  TEST_COMPARE_ARRAYS( v2, v );
222  }
223 
224  //
225  out << "\nB) Test element access ...\n";
226  //
227 
228 
229  TEST_EQUALITY_CONST( av.front(), as<T>(0) );
230  TEST_EQUALITY( av.back(), as<T>(n-1) );
231  TEST_EQUALITY_CONST( cav.front(), as<T>(0) );
232  TEST_EQUALITY( cav.back(), as<T>(n-1) );
233 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
234  TEST_THROW( av[-1], Teuchos::RangeError );
236  TEST_THROW( cav[-1], Teuchos::RangeError );
237  TEST_THROW( cav[n], Teuchos::RangeError );
238 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
239 
240  //
241  out << "\nC) Test iterator access ...\n";
242  //
243 
244 
245  {
246  out << "\nTest non-const forward iterator access ...\n";
247  std::vector<T> v2(n);
248  ArrayView<T> av2(v2);
249  typedef typename ArrayView<T>::iterator iter_t;
250  iter_t iter = av2.begin();
251  for ( int i = 0; iter != av2.end(); ++i )
252  *iter++ = i;
253  TEST_COMPARE_ARRAYS( v2, v );
254  }
255 
256  {
257  out << "\nTest const forward iterator access ... ";
258  bool local_success = true;
259  typedef typename ArrayView<const T>::iterator iter_t;
260  const ArrayView<const T> cav2 = av.getConst();
261  iter_t iter = cav2.begin();
262  for ( int i = 0; i < n; ++i, ++iter ) {
263  TEST_ARRAY_ELE_EQUALITY( av, i, *iter );
264 
265 #ifdef SHOW_INVALID_CONST_ITER_MODIFICATION
266  *iter = as<T>(i); // Should not compile!
267 #endif
268  }
269  iter = NullIteratorTraits<iter_t>::getNull();
270  if (local_success) out << "passed\n";
271  else success = false;
272  }
273 
274  //
275  out << "\nD) Test sub-views ...\n";
276  //
277 
278  {
279  out << "\nTest full non-const subview ...\n";
280  const ArrayView<T> av2 = av(0,n);
281  TEST_COMPARE_ARRAYS( av2, av );
282  }
283 
284  {
285  out << "\nTest full shorthand non-const subview ...\n";
286  const ArrayView<T> av2 = av();
287  TEST_COMPARE_ARRAYS( av2, av );
288  }
289 
290  {
291  out << "\nTest full const subview ...\n";
292  const ArrayView<const T> cav2 = cav(0,n);
293  TEST_COMPARE_ARRAYS( cav2, cav );
294  }
295 
296  {
297  out << "\nTest full non-const to const subview ...\n";
298  const ArrayView<const T> cav2 = av(0,n);
299  TEST_COMPARE_ARRAYS( cav2, cav );
300  }
301 
302  {
303  out << "\nTest full short-hand const subview ...\n";
304  const ArrayView<const T> cav2 = cav();
305  TEST_COMPARE_ARRAYS( cav2, cav );
306  }
307 
308  {
309  out << "\nTest non-const initial range view ...\n";
310  std::vector<T> v2(n,as<T>(-1));
311  const ArrayView<T> av2(v2);
312  const ArrayView<T> av2_init = av2(0,n-1);
313  TEST_EQUALITY( av2_init.size(), n-1 );
314  av2_init.assign( av(0,n-1) );
315  av2.back() = as<T>(n-1);
316  TEST_COMPARE_ARRAYS( v2, v );
317  }
318 
319  {
320  out << "\nTest non-const final range view ...\n";
321  std::vector<T> v2(n,as<T>(-1));
322  const ArrayView<T> av2(v2);
323  const ArrayView<T> av2_init = av2(1,n-1);
324  TEST_EQUALITY( av2_init.size(), n-1 );
325  av2_init.assign( av(1,n-1) );
326  av2.front() = as<T>(0);
327  TEST_COMPARE_ARRAYS( v2, v );
328  }
329 
330  {
331  out << "\nTest non-const middle range view ...\n";
332  std::vector<T> v2(n,as<T>(-1));
333  const ArrayView<T> av2(v2);
334  const ArrayView<T> av2_init = av2(1,n-2);
335  TEST_EQUALITY( av2_init.size(), n-2 );
336  av2_init.assign( av(1,n-2) );
337  av2.front() = as<T>(0);
338  av2.back() = as<T>(n-1);
339  TEST_COMPARE_ARRAYS( v2, v );
340  }
341 
342  // ToDo: Test requesting views outside of valid range!
343 
344  return success;
345 
346 }
347 
348 
349 //
350 // Main testing program
351 //
352 
353 int main( int argc, char* argv[] )
354 {
355 
356  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
357 
359 
360  bool success = true;
361  bool result;
362 
365 
366  try {
367 
368  //
369  // Read options from the commandline
370  //
371 
372  CommandLineProcessor clp(false); // Don't throw exceptions
373 
374  int n = 4;
375  clp.setOption( "n", &n, "Number of elements in the array" );
376 
377  CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
378 
379  if ( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) {
380  *out << "\nEnd Result: TEST FAILED" << std::endl;
381  return parse_return;
382  }
383 
384  *out << std::endl << Teuchos::Teuchos_Version() << std::endl;
385 
386  result = testArrayView<int>(n,*out);
387  if (!result) success = false;
388 
389  result = testArrayView<float>(n,*out);
390  if (!result) success = false;
391 
392  result = testArrayView<double>(n,*out);
393  if (!result) success = false;
394 
395  result = testArrayView<std::complex<double> >(n,*out);
396  if (!result) success = false;
397 
398  }
399  TEUCHOS_STANDARD_CATCH_STATEMENTS(true,std::cerr,success);
400 
401  if (success)
402  *out << "\nEnd Result: TEST PASSED" << std::endl;
403  else
404  *out << "\nEnd Result: TEST FAILED" << std::endl;
405 
406  return ( success ? 0 : 1 );
407 
408 }
#define TEST_NOTHROW(code)
Null reference error exception class.
#define TEST_EQUALITY_CONST(v1, v2)
const T & getConst(T &t)
Return a constant reference to an object given a non-const reference.
ArrayView< T > arrayViewFromVector(std::vector< T > &vec)
Construct a non-const view of an std::vector.
#define TEST_ITER_EQUALITY(iter1, iter2)
Tabbing class for helping to create formated, indented output for a basic_FancyOStream object...
Initialize, finalize, and query the global MPI session.
bool is_null(const ArrayRCP< T > &p)
Returns true if p.get()==NULL.
#define TEST_COMPARE_ARRAYS(a1, a2)
std::ostream subclass that performs the magic of indenting data sent to an std::ostream object among ...
#define TEUCHOS_STANDARD_CATCH_STATEMENTS(VERBOSE, ERR_STREAM, SUCCESS_FLAG)
Simple macro that catches and reports standard exceptions and other exceptions.
static RCP< FancyOStream > getDefaultOStream()
Get the default output stream object.
std::string Teuchos_Version()
Base traits class for getting a properly initialized null pointer.
TypeTo as(const TypeFrom &t)
Convert from one value type to another.
int main(int argc, char *argv[])
bool testArrayView(const int n, Teuchos::FancyOStream &out)
Utilities to make writing tests easier.
Nonowning array view.
Default traits class that just returns typeid(T).name().
A MPI utilities class, providing methods for initializing, finalizing, and querying the global MPI se...
Basic command line parser for input from (argc,argv[])
#define TEST_THROW(code, ExceptType)
Smart reference counting pointer class for automatic garbage collection.
#define TEST_ARRAY_ELE_EQUALITY(a, i, val)
#define TEST_EQUALITY(v1, v2)
Range error exception class.
RCP< basic_FancyOStream< CharT, Traits > > tab(const RCP< basic_FancyOStream< CharT, Traits > > &out, const int tabs=1, const std::basic_string< CharT, Traits > linePrefix="")
Create a tab for an RCP-wrapped basic_FancyOStream object to cause the indentation of all output auto...
Definition of Teuchos::as, for conversions between types.
Class that helps parse command line input arguments from (argc,argv[]) and set options.