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_EQUALITY_CONST(av2.getRawPtr(),av2.data());
147  TEST_ITER_EQUALITY(av2.begin(),av2.end());
148 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
152  TEST_THROW(av2.assign(av2), Teuchos::NullReferenceError);
155 #endif
156  ArrayView<const T> cav2(av2); // Tests copy constructor and implicit conversion operator!
157  TEST_EQUALITY_CONST(cav2.size(),0);
158  TEST_EQUALITY_CONST(cav2.getRawPtr(),0);
159  TEST_EQUALITY_CONST(cav2.getRawPtr(),cav2.data());
160  TEST_ITER_EQUALITY(cav2.begin(),av2.end());
161 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
163  TEST_THROW(*cav2.begin(), Teuchos::NullReferenceError);
166 #endif
167 #ifdef SHOW_INVALID_CONST_ASSIGN
168  TEST_NOTHROW(cav2.assign(av2)); // Should not compile!
169 #endif
170  }
171 
172  std::vector<T> v(n);
173 
174  const ArrayView<T> av = arrayViewFromVector(v);
175  TEST_EQUALITY_CONST(is_null(av), false);
176  TEST_EQUALITY( as<int>(av.size()), n );
177 
178  const ArrayView<const T> cav = av;
179 
180  {
181  out << "\nInitializing data for std::vector v through view av ...\n";
182  for( int i = 0; i < n; ++i )
183  av[i] = i; // tests non-const operator[](i)
184  }
185 
186  {
187  out << "\nTest that v[i] == i through ArrayView<const T> ...\n";
188  const ArrayView<const T> cav2 = cav;
189  bool local_success = true;
190  for( int i = 0; i < n; ++i ) {
191  TEST_ARRAY_ELE_EQUALITY( cav2, i, as<T>(i) );
192  }
193  if (local_success) out << "passed\n";
194  else success = false;
195  }
196 
197  {
198  out << "\nTest explicit copy to std::vector from non-const array view ...\n";
199  std::vector<T> v2 = Teuchos::createVector(av);
200  TEST_COMPARE_ARRAYS( v2, v );
201  }
202 
203  {
204  out << "\nTest explicit copy to std::vector from const array view ...\n";
205  std::vector<T> v2 = Teuchos::createVector(cav);
206  TEST_COMPARE_ARRAYS( v2, v );
207  }
208 
209  {
210  out << "\nTest shallow implicit conversion from ArrayView<T> to ArrayView<T> ...\n";
211  ArrayView<T> av2(av);
212  TEST_COMPARE_ARRAYS( av2, av );
213  }
214 
215  {
216  out << "\nTest shallow implicit conversion from ArrayView<const T> to ArrayView<const T> ...\n";
217  ArrayView<const T> cav2(cav);
218  TEST_COMPARE_ARRAYS( cav2, cav );
219  }
220 
221  {
222  out << "\nTest shallow implicit conversion from ArrayView<const T> to ArrayView<T> ...\n";
223  ArrayView<const T> cav2(av);
224  TEST_COMPARE_ARRAYS( cav2, av );
225  }
226 
227  {
228  out << "\nTest shallow implicit conversion from std::vector<T> to ArrayView<T> ...\n";
229  std::vector<T> v2 = Teuchos::createVector(cav);
230  ArrayView<T> cav2(v2);
231  TEST_COMPARE_ARRAYS( cav2, av );
232  }
233 
234  {
235  out << "\nTest shallow implicit conversion from const std::vector<T> to ArrayView<const T> ...\n";
236  const std::vector<T> v2 = Teuchos::createVector(cav);
237  ArrayView<const T> cav2(v2);
238  TEST_COMPARE_ARRAYS( cav2, av );
239  }
240 
241  {
242  // Try to copy construct from ArrayView<const T> to ArrayView<T> ..
243 #ifdef SHOW_INVALID_COPY_CONSTRUCTION
244  ArrayView<T> cav2(cav); // should not compile!
245 #endif
246  }
247 
248  {
249  out << "\ntest assign(...) ...\n";
250  std::vector<T> v2(n);
251  ArrayView<T> av2(v2);
252  av2.assign(av);
253  TEST_COMPARE_ARRAYS( v2, v );
254  }
255 
256  //
257  out << "\nB) Test element access ...\n";
258  //
259 
260 
261  TEST_EQUALITY_CONST( av.front(), as<T>(0) );
262  TEST_EQUALITY( av.back(), as<T>(n-1) );
263  TEST_EQUALITY_CONST( cav.front(), as<T>(0) );
264  TEST_EQUALITY( cav.back(), as<T>(n-1) );
265 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
266  TEST_THROW( av[-1], Teuchos::RangeError );
268  TEST_THROW( cav[-1], Teuchos::RangeError );
270 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
271 
272  //
273  out << "\nC) Test iterator access ...\n";
274  //
275 
276 
277  {
278  out << "\nTest non-const forward iterator access ...\n";
279  std::vector<T> v2(n);
280  ArrayView<T> av2(v2);
281  typedef typename ArrayView<T>::iterator iter_t;
282  iter_t iter = av2.begin();
283  for ( int i = 0; iter != av2.end(); ++i )
284  *iter++ = i;
285  TEST_COMPARE_ARRAYS( v2, v );
286  }
287 
288  {
289  out << "\nTest const forward iterator access ... ";
290  bool local_success = true;
291  typedef typename ArrayView<const T>::iterator iter_t;
292  const ArrayView<const T> cav2 = av.getConst();
293  iter_t iter = cav2.begin();
294  for ( int i = 0; i < n; ++i, ++iter ) {
295  TEST_ARRAY_ELE_EQUALITY( av, i, *iter );
296 
297 #ifdef SHOW_INVALID_CONST_ITER_MODIFICATION
298  *iter = as<T>(i); // Should not compile!
299 #endif
300  }
301  iter = NullIteratorTraits<iter_t>::getNull();
302  if (local_success) out << "passed\n";
303  else success = false;
304  }
305 
306  //
307  out << "\nD) Test sub-views ...\n";
308  //
309 
310  {
311  out << "\nTest full non-const subview ...\n";
312  const ArrayView<T> av2 = av(0,n);
313  TEST_COMPARE_ARRAYS( av2, av );
314  }
315 
316  {
317  out << "\nTest full shorthand non-const subview ...\n";
318  const ArrayView<T> av2 = av();
319  TEST_COMPARE_ARRAYS( av2, av );
320  }
321 
322  {
323  out << "\nTest full const subview ...\n";
324  const ArrayView<const T> cav2 = cav(0,n);
325  TEST_COMPARE_ARRAYS( cav2, cav );
326  }
327 
328  {
329  out << "\nTest full non-const to const subview ...\n";
330  const ArrayView<const T> cav2 = av(0,n);
331  TEST_COMPARE_ARRAYS( cav2, cav );
332  }
333 
334  {
335  out << "\nTest full short-hand const subview ...\n";
336  const ArrayView<const T> cav2 = cav();
337  TEST_COMPARE_ARRAYS( cav2, cav );
338  }
339 
340  {
341  out << "\nTest non-const initial range view ...\n";
342  std::vector<T> v2(n,as<T>(-1));
343  const ArrayView<T> av2(v2);
344  const ArrayView<T> av2_init = av2(0,n-1);
345  TEST_EQUALITY( av2_init.size(), n-1 );
346  av2_init.assign( av(0,n-1) );
347  av2.back() = as<T>(n-1);
348  TEST_COMPARE_ARRAYS( v2, v );
349  }
350 
351  {
352  out << "\nTest non-const final range view ...\n";
353  std::vector<T> v2(n,as<T>(-1));
354  const ArrayView<T> av2(v2);
355  const ArrayView<T> av2_init = av2(1,n-1);
356  TEST_EQUALITY( av2_init.size(), n-1 );
357  av2_init.assign( av(1,n-1) );
358  av2.front() = as<T>(0);
359  TEST_COMPARE_ARRAYS( v2, v );
360  }
361 
362  {
363  out << "\nTest non-const middle range view ...\n";
364  std::vector<T> v2(n,as<T>(-1));
365  const ArrayView<T> av2(v2);
366  const ArrayView<T> av2_init = av2(1,n-2);
367  TEST_EQUALITY( av2_init.size(), n-2 );
368  av2_init.assign( av(1,n-2) );
369  av2.front() = as<T>(0);
370  av2.back() = as<T>(n-1);
371  TEST_COMPARE_ARRAYS( v2, v );
372  }
373 
374  // ToDo: Test requesting views outside of valid range!
375 
376  return success;
377 
378 }
379 
380 
381 //
382 // Main testing program
383 //
384 
385 int main( int argc, char* argv[] )
386 {
387 
388  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
389 
391 
392  bool success = true;
393  bool result;
394 
397 
398  try {
399 
400  //
401  // Read options from the commandline
402  //
403 
404  CommandLineProcessor clp(false); // Don't throw exceptions
405 
406  int n = 4;
407  clp.setOption( "n", &n, "Number of elements in the array" );
408 
409  CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
410 
411  if ( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) {
412  *out << "\nEnd Result: TEST FAILED" << std::endl;
413  return parse_return;
414  }
415 
416  *out << std::endl << Teuchos::Teuchos_Version() << std::endl;
417 
418  result = testArrayView<int>(n,*out);
419  if (!result) success = false;
420 
421  result = testArrayView<float>(n,*out);
422  if (!result) success = false;
423 
424  result = testArrayView<double>(n,*out);
425  if (!result) success = false;
426 
427  result = testArrayView<std::complex<double> >(n,*out);
428  if (!result) success = false;
429 
430  }
431  TEUCHOS_STANDARD_CATCH_STATEMENTS(true,std::cerr,success);
432 
433  if (success)
434  *out << "\nEnd Result: TEST PASSED" << std::endl;
435  else
436  *out << "\nEnd Result: TEST FAILED" << std::endl;
437 
438  return ( success ? 0 : 1 );
439 
440 }
int main(int argc, char *argv[])
#define TEST_EQUALITY_CONST(v1, v2)
#define TEST_EQUALITY(v1, v2)
bool testArrayView(const int n, Teuchos::FancyOStream &out)
#define TEST_NOTHROW(code)
#define TEST_ARRAY_ELE_EQUALITY(a, i, val)
#define TEST_THROW(code, ExceptType)
#define TEST_COMPARE_ARRAYS(a1, a2)
#define TEST_ITER_EQUALITY(iter1, iter2)
Basic command line parser for input from (argc,argv[])
A MPI utilities class, providing methods for initializing, finalizing, and querying the global MPI se...
#define TEUCHOS_STANDARD_CATCH_STATEMENTS(VERBOSE, ERR_STREAM, SUCCESS_FLAG)
Simple macro that catches and reports standard exceptions and other exceptions.
Utilities to make writing tests easier.
Definition of Teuchos::as, for conversions between types.
bool is_null(const ArrayRCP< T > &p)
Returns true if p.get()==NULL.
Nonowning array view.
ArrayView< T > arrayViewFromVector(std::vector< T > &vec)
Construct a non-const view of an std::vector.
Class that helps parse command line input arguments from (argc,argv[]) and set options.
Initialize, finalize, and query the global MPI session.
Base traits class for getting a properly initialized null pointer.
Null reference error exception class.
Smart reference counting pointer class for automatic garbage collection.
Range error exception class.
Default traits class that just returns typeid(T).name().
static RCP< FancyOStream > getDefaultOStream()
Get the default output stream object.
std::ostream subclass that performs the magic of indenting data sent to an std::ostream object among ...
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...
Tabbing class for helping to create formated, indented output for a basic_FancyOStream object.
TypeTo as(const TypeFrom &t)
Convert from one value type to another.
std::string Teuchos_Version()
const T & getConst(T &t)
Return a constant reference to an object given a non-const reference.