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/vector_convert.cpp  Tests conversion between vectors with different numeric type
20 *   \test  Tests conversion between vectors 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/vector.hpp"
36 #include "viennacl/vector_proxy.hpp"
37 
38 
39 template<typename NumericT, typename VectorT>
check(std::vector<NumericT> const & std_dest,std::size_t start_dest,std::size_t inc_dest,std::size_t size_dest,VectorT const & vcl_dest)40 int check(std::vector<NumericT> const & std_dest, std::size_t start_dest, std::size_t inc_dest, std::size_t size_dest,
41           VectorT const & vcl_dest)
42 {
43   std::vector<NumericT> tempvec(vcl_dest.size());
44   viennacl::copy(vcl_dest, tempvec);
45 
46   for (std::size_t i=0; i < size_dest; ++i)
47   {
48     if (   std_dest[start_dest + i * inc_dest] < tempvec[i]
49         || std_dest[start_dest + i * inc_dest] > tempvec[i])
50     {
51       std::cerr << "Failure at index " << i << ": STL value " << std_dest[start_dest + i * inc_dest] << ", ViennaCL value " << tempvec[i] << std::endl;
52       return EXIT_FAILURE;
53     }
54   }
55 
56   return EXIT_SUCCESS;
57 }
58 
59 
60 //
61 // -------------------------------------------------------------
62 //
63 template<typename STLVectorT1, typename STLVectorT2, typename ViennaCLVectorT1, typename ViennaCLVectorT2 >
test(STLVectorT1 & std_src,std::size_t start_src,std::size_t inc_src,std::size_t size_src,STLVectorT2 & std_dest,std::size_t start_dest,std::size_t inc_dest,std::size_t size_dest,ViennaCLVectorT1 const & vcl_src,ViennaCLVectorT2 & vcl_dest)64 int test(STLVectorT1 & std_src,  std::size_t start_src,  std::size_t inc_src,  std::size_t size_src,
65          STLVectorT2 & std_dest, std::size_t start_dest, std::size_t inc_dest, std::size_t size_dest,
66          ViennaCLVectorT1 const & vcl_src, ViennaCLVectorT2 & vcl_dest)
67 {
68   assert(size_src       == size_dest       && bool("Size mismatch for STL vectors"));
69   assert(vcl_src.size() == vcl_dest.size() && bool("Size mismatch for ViennaCL vectors"));
70   assert(size_src       == vcl_src.size()  && bool("Size mismatch for STL and ViennaCL vectors"));
71 
72   typedef typename STLVectorT2::value_type  DestNumericT;
73 
74   for (std::size_t i=0; i<size_src; ++i)
75     std_dest[start_dest + i * inc_dest] = static_cast<DestNumericT>(std_src[start_src + i * inc_src]);
76 
77   vcl_dest = vcl_src; // here is the conversion taking place
78 
79   if (check(std_dest, start_dest, inc_dest, size_dest, vcl_dest) != EXIT_SUCCESS)
80     return EXIT_FAILURE;
81 
82   viennacl::vector<DestNumericT> x(vcl_src);
83   if (check(std_dest, start_dest, inc_dest, size_dest, x) != EXIT_SUCCESS)
84     return EXIT_FAILURE;
85 
86   // --------------------------------------------------------------------------
87   return EXIT_SUCCESS;
88 }
89 
type_string(unsigned int)90 inline std::string type_string(unsigned int)    { return "unsigned int"; }
type_string(int)91 inline std::string type_string(int)             { return "int"; }
type_string(unsigned long)92 inline std::string type_string(unsigned long)   { return "unsigned long"; }
type_string(long)93 inline std::string type_string(long)            { return "long"; }
type_string(float)94 inline std::string type_string(float)           { return "float"; }
type_string(double)95 inline std::string type_string(double)          { return "double"; }
96 
97 template<typename FromNumericT, typename ToNumericT>
test()98 int test()
99 {
100   int retval = EXIT_SUCCESS;
101 
102   std::cout << std::endl;
103   std::cout << "-----------------------------------------------" << std::endl;
104   std::cout << std::endl;
105   std::cout << "Conversion test from " << type_string(FromNumericT()) << " to " << type_string(ToNumericT()) << std::endl;
106   std::cout << std::endl;
107 
108   std::size_t full_size  = 12345;
109   std::size_t small_size = full_size / 4;
110   //
111   // Set up STL objects
112   //
113   std::vector<FromNumericT> std_src(full_size);
114   std::vector<ToNumericT>   std_dest(std_src.size());
115 
116   for (std::size_t i=0; i<std_src.size(); ++i)
117     std_src[i]  = FromNumericT(1.0) + FromNumericT(i);
118 
119   //
120   // Set up ViennaCL objects
121   //
122   viennacl::vector<FromNumericT> vcl_src(std_src.size());
123   viennacl::vector<ToNumericT>   vcl_dest(std_src.size());
124 
125   viennacl::copy(std_src, vcl_src);
126 
127   viennacl::vector<FromNumericT> vcl_src_small(small_size);
128   viennacl::copy(std_src.begin(), std_src.begin() + typename std::vector<FromNumericT>::difference_type(small_size), vcl_src_small.begin());
129   viennacl::vector<ToNumericT> vcl_dest_small(small_size);
130 
131   std::size_t r1_start = 1 +     vcl_src.size() / 4;
132   std::size_t r1_stop  = 1 + 2 * vcl_src.size() / 4;
133   viennacl::range vcl_r1(r1_start, r1_stop);
134 
135   std::size_t r2_start = 2 * vcl_src.size() / 4;
136   std::size_t r2_stop  = 3 * vcl_src.size() / 4;
137   viennacl::range vcl_r2(r2_start, r2_stop);
138 
139   viennacl::vector_range< viennacl::vector<FromNumericT> > vcl_range_src(vcl_src, vcl_r1);
140   viennacl::vector_range< viennacl::vector<ToNumericT> >   vcl_range_dest(vcl_dest, vcl_r2);
141 
142 
143 
144   std::size_t s1_start = 1 + vcl_src.size() / 5;
145   std::size_t s1_inc   = 3;
146   std::size_t s1_size  = vcl_src.size() / 4;
147   viennacl::slice vcl_s1(s1_start, s1_inc, s1_size);
148 
149   std::size_t s2_start = 2 * vcl_dest.size() / 5;
150   std::size_t s2_inc   = 2;
151   std::size_t s2_size  = vcl_dest.size() / 4;
152   viennacl::slice vcl_s2(s2_start, s2_inc, s2_size);
153 
154   viennacl::vector_slice< viennacl::vector<FromNumericT> > vcl_slice_src(vcl_src, vcl_s1);
155   viennacl::vector_slice< viennacl::vector<ToNumericT> >   vcl_slice_dest(vcl_dest, vcl_s2);
156 
157   //
158   // Now start running tests for vectors, ranges and slices:
159   //
160 
161   std::cout << " ** vcl_src = vector, vcl_dest = vector **" << std::endl;
162   retval = test(std_src,  0, 1, std_src.size(),
163                 std_dest, 0, 1, std_dest.size(),
164                 vcl_src, vcl_dest);
165   if (retval != EXIT_SUCCESS)
166     return EXIT_FAILURE;
167 
168   std::cout << " ** vcl_src = vector, vcl_dest = range **" << std::endl;
169   retval = test(std_src,  0, 1, small_size,
170                 std_dest, r2_start, 1, r2_stop - r2_start,
171                 vcl_src_small, vcl_range_dest);
172   if (retval != EXIT_SUCCESS)
173     return EXIT_FAILURE;
174 
175   std::cout << " ** vcl_src = vector, vcl_dest = slice **" << std::endl;
176   retval = test(std_src,  0, 1, small_size,
177                 std_dest, s2_start, s2_inc, s2_size,
178                 vcl_src_small, vcl_slice_dest);
179   if (retval != EXIT_SUCCESS)
180     return EXIT_FAILURE;
181 
182   ///////
183 
184   std::cout << " ** vcl_src = range, vcl_dest = vector **" << std::endl;
185   retval = test(std_src,  r1_start, 1, r1_stop - r1_start,
186                 std_dest, 0, 1, small_size,
187                 vcl_range_src, vcl_dest_small);
188   if (retval != EXIT_SUCCESS)
189     return EXIT_FAILURE;
190 
191   std::cout << " ** vcl_src = range, vcl_dest = range **" << std::endl;
192   retval = test(std_src,  r1_start, 1, r1_stop - r1_start,
193                 std_dest, r2_start, 1, r2_stop - r2_start,
194                 vcl_range_src, vcl_range_dest);
195   if (retval != EXIT_SUCCESS)
196     return EXIT_FAILURE;
197 
198   std::cout << " ** vcl_src = range, vcl_dest = slice **" << std::endl;
199   retval = test(std_src,  r1_start, 1, r1_stop - r1_start,
200                 std_dest, s2_start, s2_inc, s2_size,
201                 vcl_range_src, vcl_slice_dest);
202   if (retval != EXIT_SUCCESS)
203     return EXIT_FAILURE;
204 
205   ///////
206 
207   std::cout << " ** vcl_src = slice, vcl_dest = vector **" << std::endl;
208   retval = test(std_src,  s1_start, s1_inc, s1_size,
209                 std_dest, 0, 1, small_size,
210                 vcl_slice_src, vcl_dest_small);
211   if (retval != EXIT_SUCCESS)
212     return EXIT_FAILURE;
213 
214   std::cout << " ** vcl_src = slice, vcl_dest = range **" << std::endl;
215   retval = test(std_src,  s1_start, s1_inc, s1_size,
216                 std_dest, r2_start, 1, r2_stop - r2_start,
217                 vcl_slice_src, vcl_range_dest);
218   if (retval != EXIT_SUCCESS)
219     return EXIT_FAILURE;
220 
221   std::cout << " ** vcl_src = slice, vcl_dest = slice **" << std::endl;
222   retval = test(std_src,  s1_start, s1_inc, s1_size,
223                 std_dest, s2_start, s2_inc, s2_size,
224                 vcl_slice_src, vcl_slice_dest);
225   if (retval != EXIT_SUCCESS)
226     return EXIT_FAILURE;
227 
228   return EXIT_SUCCESS;
229 }
230 
231 
232 
233 //
234 // -------------------------------------------------------------
235 //
main()236 int main()
237 {
238   std::cout << std::endl;
239   std::cout << "----------------------------------------------" << std::endl;
240   std::cout << "----------------------------------------------" << std::endl;
241   std::cout << "## Test :: Type conversion test for vectors   " << std::endl;
242   std::cout << "----------------------------------------------" << std::endl;
243   std::cout << "----------------------------------------------" << std::endl;
244   std::cout << std::endl;
245 
246   int retval = EXIT_SUCCESS;
247 
248   //
249   // from int
250   //
251   retval = test<int, int>();
252   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
253   else return retval;
254 
255   retval = test<int, unsigned int>();
256   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
257   else return retval;
258 
259   retval = test<int, long>();
260   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
261   else return retval;
262 
263   retval = test<int, unsigned long>();
264   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
265   else return retval;
266 
267   retval = test<int, float>();
268   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
269   else return retval;
270 
271   retval = test<int, unsigned long>();
272   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
273   else return retval;
274 
275 #ifdef VIENNACL_WITH_OPENCL
276   if ( viennacl::ocl::current_device().double_support() )
277 #endif
278   {
279     retval = test<int, double>();
280     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
281     else return retval;
282   }
283 
284 
285   //
286   // from unsigned int
287   //
288   retval = test<unsigned int, int>();
289   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
290   else return retval;
291 
292   retval = test<unsigned int, unsigned int>();
293   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
294   else return retval;
295 
296   retval = test<unsigned int, long>();
297   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
298   else return retval;
299 
300   retval = test<unsigned int, unsigned long>();
301   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
302   else return retval;
303 
304   retval = test<unsigned int, float>();
305   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
306   else return retval;
307 
308   retval = test<unsigned int, unsigned long>();
309   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
310   else return retval;
311 
312 #ifdef VIENNACL_WITH_OPENCL
313   if ( viennacl::ocl::current_device().double_support() )
314 #endif
315   {
316     retval = test<unsigned int, double>();
317     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
318     else return retval;
319   }
320 
321 
322   //
323   // from long
324   //
325   retval = test<long, int>();
326   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
327   else return retval;
328 
329   retval = test<long, unsigned int>();
330   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
331   else return retval;
332 
333   retval = test<long, long>();
334   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
335   else return retval;
336 
337   retval = test<long, unsigned long>();
338   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
339   else return retval;
340 
341   retval = test<long, float>();
342   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
343   else return retval;
344 
345   retval = test<long, unsigned long>();
346   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
347   else return retval;
348 
349 #ifdef VIENNACL_WITH_OPENCL
350   if ( viennacl::ocl::current_device().double_support() )
351 #endif
352   {
353     retval = test<long, double>();
354     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
355     else return retval;
356   }
357 
358 
359   //
360   // from unsigned long
361   //
362   retval = test<unsigned long, int>();
363   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
364   else return retval;
365 
366   retval = test<unsigned long, unsigned int>();
367   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
368   else return retval;
369 
370   retval = test<unsigned long, long>();
371   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
372   else return retval;
373 
374   retval = test<unsigned long, unsigned long>();
375   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
376   else return retval;
377 
378   retval = test<unsigned long, float>();
379   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
380   else return retval;
381 
382   retval = test<unsigned long, unsigned long>();
383   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
384   else return retval;
385 
386 #ifdef VIENNACL_WITH_OPENCL
387   if ( viennacl::ocl::current_device().double_support() )
388 #endif
389   {
390     retval = test<unsigned long, double>();
391     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
392     else return retval;
393   }
394 
395   //
396   // from float
397   //
398   retval = test<float, int>();
399   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
400   else return retval;
401 
402   retval = test<float, unsigned int>();
403   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
404   else return retval;
405 
406   retval = test<float, long>();
407   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
408   else return retval;
409 
410   retval = test<float, unsigned long>();
411   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
412   else return retval;
413 
414   retval = test<float, float>();
415   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
416   else return retval;
417 
418   retval = test<float, unsigned long>();
419   if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
420   else return retval;
421 
422 #ifdef VIENNACL_WITH_OPENCL
423   if ( viennacl::ocl::current_device().double_support() )
424 #endif
425   {
426     retval = test<float, double>();
427     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
428     else return retval;
429   }
430 
431   //
432   // from double
433   //
434 #ifdef VIENNACL_WITH_OPENCL
435   if ( viennacl::ocl::current_device().double_support() )
436 #endif
437   {
438     retval = test<double, int>();
439     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
440     else return retval;
441 
442     retval = test<double, unsigned int>();
443     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
444     else return retval;
445 
446     retval = test<double, long>();
447     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
448     else return retval;
449 
450     retval = test<double, unsigned long>();
451     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
452     else return retval;
453 
454     retval = test<double, float>();
455     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
456     else return retval;
457 
458     retval = test<double, unsigned long>();
459     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
460     else return retval;
461 
462     retval = test<double, double>();
463     if ( retval == EXIT_SUCCESS ) std::cout << "# Test passed" << std::endl;
464     else return retval;
465   }
466 
467 
468   std::cout << std::endl;
469   std::cout << "------- Test completed --------" << std::endl;
470   std::cout << std::endl;
471 
472   return retval;
473 }
474