Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
ArrayView_test.cpp
Go to the documentation of this file.
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 #include "Teuchos_ArrayView.hpp"
47 #include "Teuchos_Version.hpp"
48 #include "Teuchos_getConst.hpp"
49 #include "Teuchos_as.hpp"
51 
52 
53 // Uncomment to show compile errors from invalid usage
54 //#define SHOW_INVALID_COPY_CONSTRUCTION
55 //#define SHOW_INVALID_CONST_ASSIGN
56 //#define SHOW_INVALID_CONST_ITER_MODIFICATION
57 
58 //
59 // Define local macros to make defining tests easier for this particular test
60 // code.
61 //
62 // Note, macros with these types of names should only exist in a *.cpp file
63 // after all #includes are done!
64 //
65 
66 
67 #define TEST_EQUALITY_CONST( v1, v2 ) \
68  TEUCHOS_TEST_EQUALITY_CONST( v1, v2, out, success )
69 
70 #define TEST_EQUALITY( v1, v2 ) \
71  TEUCHOS_TEST_EQUALITY( v1, v2, out, success )
72 
73 #define TEST_ITER_EQUALITY( iter1, iter2 ) \
74  TEUCHOS_TEST_ITER_EQUALITY( iter1, iter2, out, success )
75 
76 #define TEST_ARRAY_ELE_EQUALITY( a, i, val ) \
77  TEUCHOS_TEST_ARRAY_ELE_EQUALITY( a, i, val, false, out, local_success )
78 
79 #define TEST_COMPARE( v1, comp, v2 ) \
80  TEUCHOS_TEST_COMPARE( v1, comp, v2, out, success )
81 
82 #define TEST_COMPARE_ARRAYS( a1, a2 ) \
83  { \
84  const bool result = compareArrays(a1,#a1,a2,#a2,out); \
85  if (!result) success = false; \
86  }
87 
88 #define TEST_THROW( code, ExceptType ) \
89  TEUCHOS_TEST_THROW( code, ExceptType, out, success )
90 
91 #define TEST_NOTHROW( code ) \
92  TEUCHOS_TEST_NOTHROW( code, out, success )
93 
94 
95 //
96 // Main templated array test function
97 //
98 
99 
100 template<class T>
101 bool testArrayView( const int n, Teuchos::FancyOStream &out )
102 {
103 
104  using Teuchos::ArrayView;
105  using Teuchos::arrayView;
106  using Teuchos::arrayViewFromVector;
107  using Teuchos::outArg;
110  using Teuchos::getConst;
111  using Teuchos::as;
112  typedef typename ArrayView<T>::size_type size_type;
113  // mfh 03 Apr 2014: The point of the above line of code is to ensure
114  // that ArrayView<T> has a public size_type typedef. However, the
115  // above line of code in isolation causes some compilers to warn
116  // about a declared but unused typedef. We deal with this by
117  // declaring a variable (actually, the oxymoron "const variable") of
118  // type size_type, then using the "cast to void" trick to forestall
119  // compiler warnings for the declared but unused variable. (Fun
120  // fact: "oxymoron" means "sharp dull" and is itself an oxymoron.)
121  // The "cast to void" trick doesn't always work, but if it doesn't,
122  // it's easy to make it go away by printing it to the output stream
123  // 'out'.
124  const size_type arbitrarySizeTypeValue = 0;
125  (void) arbitrarySizeTypeValue;
126 
127  bool success = true;
128 
129  out
130  << "\n***"
131  << "\n*** Testing "<<TypeNameTraits<ArrayView<T> >::name()<<" of size = "<<n
132  << "\n***\n";
133 
134  Teuchos::OSTab tab(out);
135 
136  //
137  out << "\nA) Initial setup testing ...\n\n";
138  //
139 
140  {
141  out << "\nTesting basic null construction!\n\n";
142  ArrayView<T> av2 = Teuchos::null;
143  TEST_EQUALITY_CONST(is_null(av2),true);
144  TEST_EQUALITY_CONST(av2.size(),0);
145  TEST_EQUALITY_CONST(av2.getRawPtr(),0);
146  TEST_ITER_EQUALITY(av2.begin(),av2.end());
147 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
151  TEST_THROW(av2.assign(av2), Teuchos::NullReferenceError);
154 #endif
155  ArrayView<const T> cav2(av2); // Tests copy constructor and implicit conversion operator!
156  TEST_EQUALITY_CONST(cav2.size(),0);
157  TEST_EQUALITY_CONST(cav2.getRawPtr(),0);
158  TEST_ITER_EQUALITY(cav2.begin(),av2.end());
159 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
161  TEST_THROW(*cav2.begin(), Teuchos::NullReferenceError);
164 #endif
165 #ifdef SHOW_INVALID_CONST_ASSIGN
166  TEST_NOTHROW(cav2.assign(av2)); // Should not compile!
167 #endif
168  }
169 
170  std::vector<T> v(n);
171 
172  const ArrayView<T> av = arrayViewFromVector(v);
173  TEST_EQUALITY_CONST(is_null(av), false);
174  TEST_EQUALITY( as<int>(av.size()), n );
175 
176  const ArrayView<const T> cav = av;
177 
178  {
179  out << "\nInitializing data for std::vector v through view av ...\n";
180  for( int i = 0; i < n; ++i )
181  av[i] = i; // tests non-const operator[](i)
182  }
183 
184  {
185  out << "\nTest that v[i] == i through ArrayView<const T> ...\n";
186  const ArrayView<const T> cav2 = cav;
187  bool local_success = true;
188  for( int i = 0; i < n; ++i ) {
189  TEST_ARRAY_ELE_EQUALITY( cav2, i, as<T>(i) );
190  }
191  if (local_success) out << "passed\n";
192  else success = false;
193  }
194 
195  {
196  out << "\nTest explicit copy to std::vector from non-const array view ...\n";
197  std::vector<T> v2 = Teuchos::createVector(av);
198  TEST_COMPARE_ARRAYS( v2, v );
199  }
200 
201  {
202  out << "\nTest explicit copy to std::vector from const array view ...\n";
203  std::vector<T> v2 = Teuchos::createVector(cav);
204  TEST_COMPARE_ARRAYS( v2, v );
205  }
206 
207  {
208  out << "\nTest shallow implicit conversion from ArrayView<T> to ArrayView<T> ...\n";
209  ArrayView<T> av2(av);
210  TEST_COMPARE_ARRAYS( av2, av );
211  }
212 
213  {
214  out << "\nTest shallow implicit conversion from ArrayView<const T> to ArrayView<const T> ...\n";
215  ArrayView<const T> cav2(cav);
216  TEST_COMPARE_ARRAYS( cav2, cav );
217  }
218 
219  {
220  out << "\nTest shallow implicit conversion from ArrayView<const T> to ArrayView<T> ...\n";
221  ArrayView<const T> cav2(av);
222  TEST_COMPARE_ARRAYS( cav2, av );
223  }
224 
225  {
226  out << "\nTest shallow implicit conversion from std::vector<T> to ArrayView<T> ...\n";
227  std::vector<T> v2 = Teuchos::createVector(cav);
228  ArrayView<T> cav2(v2);
229  TEST_COMPARE_ARRAYS( cav2, av );
230  }
231 
232  {
233  out << "\nTest shallow implicit conversion from const std::vector<T> to ArrayView<const T> ...\n";
234  const std::vector<T> v2 = Teuchos::createVector(cav);
235  ArrayView<const T> cav2(v2);
236  TEST_COMPARE_ARRAYS( cav2, av );
237  }
238 
239  {
240  // Try to copy construct from ArrayView<const T> to ArrayView<T> ..
241 #ifdef SHOW_INVALID_COPY_CONSTRUCTION
242  ArrayView<T> cav2(cav); // should not compile!
243 #endif
244  }
245 
246  {
247  out << "\ntest assign(...) ...\n";
248  std::vector<T> v2(n);
249  ArrayView<T> av2(v2);
250  av2.assign(av);
251  TEST_COMPARE_ARRAYS( v2, v );
252  }
253 
254  //
255  out << "\nB) Test element access ...\n";
256  //
257 
258 
259  TEST_EQUALITY_CONST( av.front(), as<T>(0) );
260  TEST_EQUALITY( av.back(), as<T>(n-1) );
261  TEST_EQUALITY_CONST( cav.front(), as<T>(0) );
262  TEST_EQUALITY( cav.back(), as<T>(n-1) );
263 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
264  TEST_THROW( av[-1], Teuchos::RangeError );
266  TEST_THROW( cav[-1], Teuchos::RangeError );
268 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
269 
270  //
271  out << "\nC) Test iterator access ...\n";
272  //
273 
274 
275  {
276  out << "\nTest non-const forward iterator access ...\n";
277  std::vector<T> v2(n);
278  ArrayView<T> av2(v2);
279  typedef typename ArrayView<T>::iterator iter_t;
280  iter_t iter = av2.begin();
281  for ( int i = 0; iter != av2.end(); ++i )
282  *iter++ = i;
283  TEST_COMPARE_ARRAYS( v2, v );
284  }
285 
286  {
287  out << "\nTest const forward iterator access ... ";
288  bool local_success = true;
289  typedef typename ArrayView<const T>::iterator iter_t;
290  const ArrayView<const T> cav2 = av.getConst();
291  iter_t iter = cav2.begin();
292  for ( int i = 0; i < n; ++i, ++iter ) {
293  TEST_ARRAY_ELE_EQUALITY( av, i, *iter );
294 
295 #ifdef SHOW_INVALID_CONST_ITER_MODIFICATION
296  *iter = as<T>(i); // Should not compile!
297 #endif
298  }
299  iter = NullIteratorTraits<iter_t>::getNull();
300  if (local_success) out << "passed\n";
301  else success = false;
302  }
303 
304  //
305  out << "\nD) Test sub-views ...\n";
306  //
307 
308  {
309  out << "\nTest full non-const subview ...\n";
310  const ArrayView<T> av2 = av(0,n);
311  TEST_COMPARE_ARRAYS( av2, av );
312  }
313 
314  {
315  out << "\nTest full shorthand non-const subview ...\n";
316  const ArrayView<T> av2 = av();
317  TEST_COMPARE_ARRAYS( av2, av );
318  }
319 
320  {
321  out << "\nTest full const subview ...\n";
322  const ArrayView<const T> cav2 = cav(0,n);
323  TEST_COMPARE_ARRAYS( cav2, cav );
324  }
325 
326  {
327  out << "\nTest full non-const to const subview ...\n";
328  const ArrayView<const T> cav2 = av(0,n);
329  TEST_COMPARE_ARRAYS( cav2, cav );
330  }
331 
332  {
333  out << "\nTest full short-hand const subview ...\n";
334  const ArrayView<const T> cav2 = cav();
335  TEST_COMPARE_ARRAYS( cav2, cav );
336  }
337 
338  {
339  out << "\nTest non-const initial range view ...\n";
340  std::vector<T> v2(n,as<T>(-1));
341  const ArrayView<T> av2(v2);
342  const ArrayView<T> av2_init = av2(0,n-1);
343  TEST_EQUALITY( av2_init.size(), n-1 );
344  av2_init.assign( av(0,n-1) );
345  av2.back() = as<T>(n-1);
346  TEST_COMPARE_ARRAYS( v2, v );
347  }
348 
349  {
350  out << "\nTest non-const final range view ...\n";
351  std::vector<T> v2(n,as<T>(-1));
352  const ArrayView<T> av2(v2);
353  const ArrayView<T> av2_init = av2(1,n-1);
354  TEST_EQUALITY( av2_init.size(), n-1 );
355  av2_init.assign( av(1,n-1) );
356  av2.front() = as<T>(0);
357  TEST_COMPARE_ARRAYS( v2, v );
358  }
359 
360  {
361  out << "\nTest non-const middle range view ...\n";
362  std::vector<T> v2(n,as<T>(-1));
363  const ArrayView<T> av2(v2);
364  const ArrayView<T> av2_init = av2(1,n-2);
365  TEST_EQUALITY( av2_init.size(), n-2 );
366  av2_init.assign( av(1,n-2) );
367  av2.front() = as<T>(0);
368  av2.back() = as<T>(n-1);
369  TEST_COMPARE_ARRAYS( v2, v );
370  }
371 
372  // ToDo: Test requesting views outside of valid range!
373 
374  return success;
375 
376 }
377 
378 
379 //
380 // Main testing program
381 //
382 
383 int main( int argc, char* argv[] )
384 {
385 
386  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
387 
389 
390  bool success = true;
391  bool result;
392 
395 
396  try {
397 
398  //
399  // Read options from the commandline
400  //
401 
402  CommandLineProcessor clp(false); // Don't throw exceptions
403 
404  int n = 4;
405  clp.setOption( "n", &n, "Number of elements in the array" );
406 
407  CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
408 
409  if ( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) {
410  *out << "\nEnd Result: TEST FAILED" << std::endl;
411  return parse_return;
412  }
413 
414  *out << std::endl << Teuchos::Teuchos_Version() << std::endl;
415 
416  result = testArrayView<int>(n,*out);
417  if (!result) success = false;
418 
419  result = testArrayView<float>(n,*out);
420  if (!result) success = false;
421 
422  result = testArrayView<double>(n,*out);
423  if (!result) success = false;
424 
425  result = testArrayView<std::complex<double> >(n,*out);
426  if (!result) success = false;
427 
428  }
429  TEUCHOS_STANDARD_CATCH_STATEMENTS(true,std::cerr,success);
430 
431  if (success)
432  *out << "\nEnd Result: TEST PASSED" << std::endl;
433  else
434  *out << "\nEnd Result: TEST FAILED" << std::endl;
435 
436  return ( success ? 0 : 1 );
437 
438 }
#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.
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[])
int main(int argc, char *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.