1 /* =========================================================================
2    Copyright (c) 2010-2016, Institute for Microelectronics,
3                             Institute for Analysis and Scientific Computing,
4                             TU Wien.
5    Portions of this software are copyright by UChicago Argonne, LLC.
6 
7                             -----------------
8                   ViennaCL - The Vienna Computing Library
9                             -----------------
10 
11    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
12 
13    (A list of authors and contributors can be found in the PDF manual)
14 
15    License:         MIT (X11), see file LICENSE in the base directory
16 ============================================================================= */
17 
18 
19 /** \file tests/src/matrix_convert.cpp  Tests conversion between matrices with different numeric type
20 *   \test  Tests conversion between matrices with different numeric type
21 **/
22 
23 //
24 // *** System
25 //
26 #include <iostream>
27 #include <iomanip>
28 #include <vector>
29 
30 
31 //
32 // *** ViennaCL
33 //
34 //#define VIENNACL_DEBUG_ALL
35 #include "viennacl/backend/memory.hpp"
36 #include "viennacl/matrix.hpp"
37 #include "viennacl/matrix_proxy.hpp"
38 
39 
40 template<typename NumericT, typename MatrixT>
check(std::vector<NumericT> const & std_dest,std::size_t start1,std::size_t inc1,std::size_t size1,std::size_t start2,std::size_t inc2,std::size_t size2,std::size_t internal_size2,MatrixT const & vcl_dest)41 int check(std::vector<NumericT> const & std_dest,
42           std::size_t start1, std::size_t inc1, std::size_t size1,
43           std::size_t start2, std::size_t inc2, std::size_t size2, std::size_t internal_size2,
44           MatrixT const & vcl_dest)
45 {
46   viennacl::backend::typesafe_host_array<NumericT> tempmat(vcl_dest.handle(), vcl_dest.internal_size());
47   viennacl::backend::memory_read(vcl_dest.handle(), 0, tempmat.raw_size(), reinterpret_cast<NumericT*>(tempmat.get()));
48 
49   for (std::size_t i=0; i < size1; ++i)
50   {
51     for (std::size_t j=0; j < size2; ++j)
52     {
53       NumericT value_std  = std_dest[(i*inc1 + start1) * internal_size2 + (j*inc2 + start2)];
54       NumericT value_dest = vcl_dest.row_major() ? tempmat[(i * vcl_dest.stride1() + vcl_dest.start1()) * vcl_dest.internal_size2() + (j * vcl_dest.stride2() + vcl_dest.start2())]
55                                                  : tempmat[(i * vcl_dest.stride1() + vcl_dest.start1())                             + (j * vcl_dest.stride2() + vcl_dest.start2()) * vcl_dest.internal_size1()];
56 
57       if (value_std < value_dest || value_std > value_dest)
58       {
59         std::cerr << "Failure at row " << i << ", col " << j << ": STL value " << value_std << ", ViennaCL value " << value_dest << std::endl;
60         return EXIT_FAILURE;
61       }
62     }
63   }
64 
65   return EXIT_SUCCESS;
66 }
67 
68 
69 //
70 // -------------------------------------------------------------
71 //
72 template<typename STLVectorT1, typename STLVectorT2, typename ViennaCLVectorT1, typename ViennaCLVectorT2 >
test(STLVectorT1 & std_src,std::size_t start1_src,std::size_t inc1_src,std::size_t size1_src,std::size_t start2_src,std::size_t inc2_src,std::size_t size2_src,std::size_t internal_size2_src,STLVectorT2 & std_dest,std::size_t start1_dest,std::size_t inc1_dest,std::size_t size1_dest,std::size_t start2_dest,std::size_t inc2_dest,std::size_t size2_dest,std::size_t internal_size2_dest,ViennaCLVectorT1 const & vcl_src,ViennaCLVectorT2 & vcl_dest)73 int test(STLVectorT1 & std_src,  std::size_t start1_src,  std::size_t inc1_src,  std::size_t size1_src,  std::size_t start2_src,  std::size_t inc2_src,  std::size_t size2_src,  std::size_t internal_size2_src,
74          STLVectorT2 & std_dest, std::size_t start1_dest, std::size_t inc1_dest, std::size_t size1_dest, std::size_t start2_dest, std::size_t inc2_dest, std::size_t size2_dest, std::size_t internal_size2_dest,
75          ViennaCLVectorT1 const & vcl_src, ViennaCLVectorT2 & vcl_dest)
76 {
77   assert(size1_src       == size1_dest       && bool("Size1 mismatch for STL matrices"));
78   assert(size2_src       == size2_dest       && bool("Size2 mismatch for STL matrices"));
79   assert(vcl_src.size1() == vcl_dest.size1() && bool("Size1 mismatch for ViennaCL matrices"));
80   assert(vcl_src.size2() == vcl_dest.size2() && bool("Size2 mismatch for ViennaCL matrices"));
81   assert(size1_src       == vcl_src.size1()  && bool("Size1 mismatch for STL and ViennaCL matrices"));
82   assert(size2_src       == vcl_src.size2()  && bool("Size2 mismatch for STL and ViennaCL matrices"));
83 
84   typedef typename STLVectorT2::value_type  DestNumericT;
85 
86   for (std::size_t i=0; i<size1_src; ++i)
87     for (std::size_t j=0; j<size2_src; ++j)
88       std_dest[(start1_dest + i * inc1_dest) * internal_size2_dest + (start2_dest + j * inc2_dest)] = static_cast<DestNumericT>(std_src[(start1_src + i * inc1_src) * internal_size2_src + (start2_src + j * inc2_src)]);
89 
90   vcl_dest = vcl_src; // here is the conversion taking place
91 
92   if (check(std_dest, start1_dest, inc1_dest, size1_dest, start2_dest, inc2_dest, size2_dest, internal_size2_dest, vcl_dest) != EXIT_SUCCESS)
93     return EXIT_FAILURE;
94 
95   if (vcl_src.row_major())
96   {
97     viennacl::matrix<DestNumericT> A(vcl_src);
98     if (check(std_dest, start1_dest, inc1_dest, size1_dest, start2_dest, inc2_dest, size2_dest, internal_size2_dest, A) != EXIT_SUCCESS)
99       return EXIT_FAILURE;
100   }
101   else
102   {
103     viennacl::matrix<DestNumericT, viennacl::column_major> A(vcl_src);
104     if (check(std_dest, start1_dest, inc1_dest, size1_dest, start2_dest, inc2_dest, size2_dest, internal_size2_dest, A) != EXIT_SUCCESS)
105       return EXIT_FAILURE;
106   }
107 
108   // --------------------------------------------------------------------------
109   return EXIT_SUCCESS;
110 }
111 
type_string(unsigned int)112 inline std::string type_string(unsigned int)    { return "unsigned int"; }
type_string(int)113 inline std::string type_string(int)             { return "int"; }
type_string(unsigned long)114 inline std::string type_string(unsigned long)   { return "unsigned long"; }
type_string(long)115 inline std::string type_string(long)            { return "long"; }
type_string(float)116 inline std::string type_string(float)           { return "float"; }
type_string(double)117 inline std::string type_string(double)          { return "double"; }
118 
119 template<typename LayoutT, typename FromNumericT, typename ToNumericT>
test()120 int test()
121 {
122   int retval = EXIT_SUCCESS;
123 
124   std::cout << std::endl;
125   std::cout << "-----------------------------------------------" << std::endl;
126   std::cout << std::endl;
127   std::cout << "Conversion test from " << type_string(FromNumericT()) << " to " << type_string(ToNumericT()) << std::endl;
128   std::cout << std::endl;
129 
130   std::size_t full_size1  = 578;
131   std::size_t small_size1 = full_size1 / 4;
132 
133   std::size_t full_size2  = 687;
134   std::size_t small_size2 = full_size2 / 4;
135 
136   //
137   // Set up STL objects
138   //
139   std::vector<FromNumericT>               std_src(full_size1 * full_size2);
140   std::vector<std::vector<FromNumericT> > std_src2(full_size1, std::vector<FromNumericT>(full_size2));
141   std::vector<std::vector<FromNumericT> > std_src_small(small_size1, std::vector<FromNumericT>(small_size2));
142   std::vector<ToNumericT> std_dest(std_src.size());
143 
144   for (std::size_t i=0; i<full_size1; ++i)
145     for (std::size_t j=0; j<full_size2; ++j)
146     {
147       std_src[i * full_size2 + j]  = FromNumericT(1.0) + FromNumericT(i) + FromNumericT(j);
148       std_src2[i][j]  = FromNumericT(1.0) + FromNumericT(i) + FromNumericT(j);
149       if (i < small_size1 && j < small_size2)
150         std_src_small[i][j]  = FromNumericT(1.0) + FromNumericT(i) + FromNumericT(j);
151     }
152 
153   //
154   // Set up ViennaCL objects
155   //
156   viennacl::matrix<FromNumericT, LayoutT> vcl_src(full_size1, full_size2);
157   viennacl::matrix<ToNumericT,   LayoutT> vcl_dest(full_size1, full_size2);
158 
159   viennacl::copy(std_src2, vcl_src);
160 
161   viennacl::matrix<FromNumericT, LayoutT> vcl_src_small(small_size1, small_size2);
162   viennacl::copy(std_src_small, vcl_src_small);
163   viennacl::matrix<ToNumericT, LayoutT> vcl_dest_small(small_size1, small_size2);
164 
165   std::size_t r11_start = 1 + full_size1 / 4;
166   std::size_t r11_stop  = r11_start + small_size1;
167   viennacl::range vcl_r11(r11_start, r11_stop);
168 
169   std::size_t r12_start = 2 * full_size1 / 4;
170   std::size_t r12_stop  = r12_start + small_size1;
171   viennacl::range vcl_r12(r12_start, r12_stop);
172 
173   std::size_t r21_start = 2 * full_size2 / 4;
174   std::size_t r21_stop  = r21_start + small_size2;
175   viennacl::range vcl_r21(r21_start, r21_stop);
176 
177   std::size_t r22_start = 1 + full_size2 / 4;
178   std::size_t r22_stop  = r22_start + small_size2;
179   viennacl::range vcl_r22(r22_start, r22_stop);
180 
181   viennacl::matrix_range< viennacl::matrix<FromNumericT, LayoutT> > vcl_range_src(vcl_src, vcl_r11, vcl_r21);
182   viennacl::matrix_range< viennacl::matrix<ToNumericT, LayoutT> >   vcl_range_dest(vcl_dest, vcl_r12, vcl_r22);
183 
184 
185 
186   std::size_t s11_start = 1 + full_size1 / 5;
187   std::size_t s11_inc   = 3;
188   std::size_t s11_size  = small_size1;
189   viennacl::slice vcl_s11(s11_start, s11_inc, s11_size);
190 
191   std::size_t s12_start = 2 * full_size1 / 5;
192   std::size_t s12_inc   = 2;
193   std::size_t s12_size  = small_size1;
194   viennacl::slice vcl_s12(s12_start, s12_inc, s12_size);
195 
196   std::size_t s21_start = 1 + full_size2 / 5;
197   std::size_t s21_inc   = 3;
198   std::size_t s21_size  = small_size2;
199   viennacl::slice vcl_s21(s21_start, s21_inc, s21_size);
200 
201   std::size_t s22_start = 2 * full_size2 / 5;
202   std::size_t s22_inc   = 2;
203   std::size_t s22_size  = small_size2;
204   viennacl::slice vcl_s22(s22_start, s22_inc, s22_size);
205 
206   viennacl::matrix_slice< viennacl::matrix<FromNumericT, LayoutT> > vcl_slice_src(vcl_src, vcl_s11, vcl_s21);
207   viennacl::matrix_slice< viennacl::matrix<ToNumericT, LayoutT> >   vcl_slice_dest(vcl_dest, vcl_s12, vcl_s22);
208 
209   //
210   // Now start running tests for vectors, ranges and slices:
211   //
212 
213   std::cout << " ** vcl_src = matrix, vcl_dest = matrix **" << std::endl;
214   retval = test(std_src,  0, 1, full_size1, 0, 1, full_size2, full_size2,
215                 std_dest, 0, 1, full_size1, 0, 1, full_size2, full_size2,
216                 vcl_src, vcl_dest);
217   if (retval != EXIT_SUCCESS)
218     return EXIT_FAILURE;
219 
220   std::cout << " ** vcl_src = matrix, vcl_dest = range **" << std::endl;
221   retval = test(std_src,          0, 1, small_size1,                  0, 1,          small_size2, full_size2,
222                 std_dest, r12_start, 1, r12_stop - r12_start, r22_start, 1, r22_stop - r22_start, full_size2,
223                 vcl_src_small, vcl_range_dest);
224   if (retval != EXIT_SUCCESS)
225     return EXIT_FAILURE;
226 
227   std::cout << " ** vcl_src = matrix, vcl_dest = slice **" << std::endl;
228   retval = test(std_src,          0,       1, small_size1,         0,       1, small_size2, full_size2,
229                 std_dest, s12_start, s12_inc,    s12_size, s22_start, s22_inc,    s22_size, full_size2,
230                 vcl_src_small, vcl_slice_dest);
231   if (retval != EXIT_SUCCESS)
232     return EXIT_FAILURE;
233 
234   ///////
235 
236   std::cout << " ** vcl_src = range, vcl_dest = matrix **" << std::endl;
237   retval = test(std_src,  r11_start, 1, r11_stop - r11_start, r21_start, 1, r21_stop - r21_start, full_size2,
238                 std_dest,         0, 1,          small_size1,         0, 1,          small_size2, full_size2,
239                 vcl_range_src, vcl_dest_small);
240   if (retval != EXIT_SUCCESS)
241     return EXIT_FAILURE;
242 
243   std::cout << " ** vcl_src = range, vcl_dest = range **" << std::endl;
244   retval = test(std_src,  r11_start, 1, r11_stop - r11_start, r21_start, 1, r21_stop - r21_start, full_size2,
245                 std_dest, r12_start, 1, r12_stop - r12_start, r22_start, 1, r22_stop - r22_start, full_size2,
246                 vcl_range_src, vcl_range_dest);
247   if (retval != EXIT_SUCCESS)
248     return EXIT_FAILURE;
249 
250   std::cout << " ** vcl_src = range, vcl_dest = slice **" << std::endl;
251   retval = test(std_src,  r11_start,       1, r11_stop - r11_start, r21_start,       1, r21_stop - r21_start, full_size2,
252                 std_dest, s12_start, s12_inc,             s12_size, s22_start, s22_inc,             s22_size, full_size2,
253                 vcl_range_src, vcl_slice_dest);
254   if (retval != EXIT_SUCCESS)
255     return EXIT_FAILURE;
256 
257   ///////
258 
259   std::cout << " ** vcl_src = slice, vcl_dest = matrix **" << std::endl;
260   retval = test(std_src,  s11_start, s11_inc,    s11_size, s21_start, s21_inc,    s21_size, full_size2,
261                 std_dest,         0,       1, small_size1,         0,       1, small_size2, full_size2,
262                 vcl_slice_src, vcl_dest_small);
263   if (retval != EXIT_SUCCESS)
264     return EXIT_FAILURE;
265 
266   std::cout << " ** vcl_src = slice, vcl_dest = range **" << std::endl;
267   retval = test(std_src,  s11_start, s11_inc,             s11_size, s21_start, s21_inc,             s21_size, full_size2,
268                 std_dest, r12_start,       1, r12_stop - r12_start, r22_start,       1, r22_stop - r22_start, full_size2,
269                 vcl_slice_src, vcl_range_dest);
270   if (retval != EXIT_SUCCESS)
271     return EXIT_FAILURE;
272 
273   std::cout << " ** vcl_src = slice, vcl_dest = slice **" << std::endl;
274   retval = test(std_src,  s11_start, s11_inc, s11_size, s21_start, s21_inc, s21_size, full_size2,
275                 std_dest, s12_start, s12_inc, s12_size, s22_start, s22_inc, s22_size, full_size2,
276                 vcl_slice_src, vcl_slice_dest);
277   if (retval != EXIT_SUCCESS)
278     return EXIT_FAILURE;
279 
280   return EXIT_SUCCESS;
281 }
282 
283 
284 template<typename FromNumericT, typename ToNumericT>
test()285 int test()
286 {
287   int retval = test<viennacl::row_major, FromNumericT, ToNumericT>();
288   if (retval == EXIT_SUCCESS)
289   {
290     retval = test<viennacl::column_major, FromNumericT, ToNumericT>();
291     if (retval != EXIT_SUCCESS)
292       std::cerr << "Test failed for column-major!" << std::endl;
293   }
294   else
295     std::cerr << "Test failed for row-major!" << std::endl;
296 
297   return retval;
298 }
299 
300 //
301 // -------------------------------------------------------------
302 //
main()303 int main()
304 {
305   std::cout << std::endl;
306   std::cout << "----------------------------------------------" << std::endl;
307   std::cout << "----------------------------------------------" << std::endl;
308   std::cout << "## Test :: Type conversion test for matrices  " << std::endl;
309   std::cout << "----------------------------------------------" << std::endl;
310   std::cout << "----------------------------------------------" << std::endl;
311   std::cout << std::endl;
312 
313   int retval = EXIT_SUCCESS;
314 
315   //
316   // from int
317   //
318   retval = test<int, int>();
319   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
320   else return retval;
321 
322   retval = test<int, unsigned int>();
323   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
324   else return retval;
325 
326   retval = test<int, long>();
327   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
328   else return retval;
329 
330   retval = test<int, unsigned long>();
331   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
332   else return retval;
333 
334   retval = test<int, float>();
335   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
336   else return retval;
337 
338   retval = test<int, unsigned long>();
339   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
340   else return retval;
341 
342 #ifdef VIENNACL_WITH_OPENCL
343   if ( viennacl::ocl::current_device().double_support() )
344 #endif
345   {
346     retval = test<int, double>();
347     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
348     else return retval;
349   }
350 
351 
352   //
353   // from unsigned int
354   //
355   retval = test<unsigned int, int>();
356   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
357   else return retval;
358 
359   retval = test<unsigned int, unsigned int>();
360   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
361   else return retval;
362 
363   retval = test<unsigned int, long>();
364   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
365   else return retval;
366 
367   retval = test<unsigned int, unsigned long>();
368   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
369   else return retval;
370 
371   retval = test<unsigned int, float>();
372   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
373   else return retval;
374 
375   retval = test<unsigned int, unsigned long>();
376   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
377   else return retval;
378 
379 #ifdef VIENNACL_WITH_OPENCL
380   if ( viennacl::ocl::current_device().double_support() )
381 #endif
382   {
383     retval = test<unsigned int, double>();
384     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
385     else return retval;
386   }
387 
388 
389   //
390   // from long
391   //
392   retval = test<long, int>();
393   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
394   else return retval;
395 
396   retval = test<long, unsigned int>();
397   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
398   else return retval;
399 
400   retval = test<long, long>();
401   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
402   else return retval;
403 
404   retval = test<long, unsigned long>();
405   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
406   else return retval;
407 
408   retval = test<long, float>();
409   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
410   else return retval;
411 
412   retval = test<long, unsigned long>();
413   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
414   else return retval;
415 
416 #ifdef VIENNACL_WITH_OPENCL
417   if ( viennacl::ocl::current_device().double_support() )
418 #endif
419   {
420     retval = test<long, double>();
421     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
422     else return retval;
423   }
424 
425 
426   //
427   // from unsigned long
428   //
429   retval = test<unsigned long, int>();
430   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
431   else return retval;
432 
433   retval = test<unsigned long, unsigned int>();
434   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
435   else return retval;
436 
437   retval = test<unsigned long, long>();
438   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
439   else return retval;
440 
441   retval = test<unsigned long, unsigned long>();
442   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
443   else return retval;
444 
445   retval = test<unsigned long, float>();
446   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
447   else return retval;
448 
449   retval = test<unsigned long, unsigned long>();
450   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
451   else return retval;
452 
453 #ifdef VIENNACL_WITH_OPENCL
454   if ( viennacl::ocl::current_device().double_support() )
455 #endif
456   {
457     retval = test<unsigned long, double>();
458     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
459     else return retval;
460   }
461 
462   //
463   // from float
464   //
465   retval = test<float, int>();
466   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
467   else return retval;
468 
469   retval = test<float, unsigned int>();
470   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
471   else return retval;
472 
473   retval = test<float, long>();
474   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
475   else return retval;
476 
477   retval = test<float, unsigned long>();
478   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
479   else return retval;
480 
481   retval = test<float, float>();
482   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
483   else return retval;
484 
485   retval = test<float, unsigned long>();
486   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
487   else return retval;
488 
489 #ifdef VIENNACL_WITH_OPENCL
490   if ( viennacl::ocl::current_device().double_support() )
491 #endif
492   {
493     retval = test<float, double>();
494     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
495     else return retval;
496   }
497 
498   //
499   // from double
500   //
501 #ifdef VIENNACL_WITH_OPENCL
502   if ( viennacl::ocl::current_device().double_support() )
503 #endif
504   {
505     retval = test<double, int>();
506     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
507     else return retval;
508 
509     retval = test<double, unsigned int>();
510     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
511     else return retval;
512 
513     retval = test<double, long>();
514     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
515     else return retval;
516 
517     retval = test<double, unsigned long>();
518     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
519     else return retval;
520 
521     retval = test<double, float>();
522     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
523     else return retval;
524 
525     retval = test<double, unsigned long>();
526     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
527     else return retval;
528 
529     retval = test<double, double>();
530     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
531     else return retval;
532   }
533 
534 
535   std::cout << std::endl;
536   std::cout << "------- Test completed --------" << std::endl;
537   std::cout << std::endl;
538 
539   return retval;
540 }
541