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