1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@gmail.com>
3 //
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
7 //
8 // See http://boostorg.github.com/compute for more information.
9 //---------------------------------------------------------------------------//
10
11 #include <iostream>
12
13 #include <Eigen/Core>
14 #include <Eigen/LU>
15
16 #include <boost/compute/function.hpp>
17 #include <boost/compute/system.hpp>
18 #include <boost/compute/algorithm/transform.hpp>
19 #include <boost/compute/container/vector.hpp>
20 #include <boost/compute/types/fundamental.hpp>
21
22 namespace compute = boost::compute;
23
24 // this example shows how to compute the determinant of many 4x4 matrices
25 // using a determinant function and the transform() algorithm. in OpenCL the
26 // float16 type can be used to store a 4x4 matrix and the components are laid
27 // out in the following order:
28 //
29 // M = [ s0 s4 s8 sc ]
30 // [ s1 s5 s9 sd ]
31 // [ s2 s6 sa se ]
32 // [ s3 s7 sb sf ]
33 //
34 // the input matrices are created using eigen's random matrix and then
35 // used again at the end to verify the results of the determinant function.
main()36 int main()
37 {
38 // get default device and setup context
39 compute::device gpu = compute::system::default_device();
40 compute::context context(gpu);
41 compute::command_queue queue(context, gpu);
42 std::cout << "device: " << gpu.name() << std::endl;
43
44 size_t n = 1000;
45
46 // create random 4x4 matrices on the host
47 std::vector<Eigen::Matrix4f> matrices(n);
48 for(size_t i = 0; i < n; i++){
49 matrices[i] = Eigen::Matrix4f::Random();
50 }
51
52 // copy matrices to the device
53 using compute::float16_;
54 compute::vector<float16_> input(n, context);
55 compute::copy(
56 matrices.begin(), matrices.end(), input.begin(), queue
57 );
58
59 // function returning the determinant of a 4x4 matrix.
60 BOOST_COMPUTE_FUNCTION(float, determinant4x4, (const float16_ m),
61 {
62 return m.s0*m.s5*m.sa*m.sf + m.s0*m.s6*m.sb*m.sd + m.s0*m.s7*m.s9*m.se +
63 m.s1*m.s4*m.sb*m.se + m.s1*m.s6*m.s8*m.sf + m.s1*m.s7*m.sa*m.sc +
64 m.s2*m.s4*m.s9*m.sf + m.s2*m.s5*m.sb*m.sc + m.s2*m.s7*m.s8*m.sd +
65 m.s3*m.s4*m.sa*m.sd + m.s3*m.s5*m.s8*m.se + m.s3*m.s6*m.s9*m.sc -
66 m.s0*m.s5*m.sb*m.se - m.s0*m.s6*m.s9*m.sf - m.s0*m.s7*m.sa*m.sd -
67 m.s1*m.s4*m.sa*m.sf - m.s1*m.s6*m.sb*m.sc - m.s1*m.s7*m.s8*m.se -
68 m.s2*m.s4*m.sb*m.sd - m.s2*m.s5*m.s8*m.sf - m.s2*m.s7*m.s9*m.sc -
69 m.s3*m.s4*m.s9*m.se - m.s3*m.s5*m.sa*m.sc - m.s3*m.s6*m.s8*m.sd;
70 });
71
72 // calculate determinants on the gpu
73 compute::vector<float> determinants(n, context);
74 compute::transform(
75 input.begin(), input.end(), determinants.begin(), determinant4x4, queue
76 );
77
78 // check determinants
79 std::vector<float> host_determinants(n);
80 compute::copy(
81 determinants.begin(), determinants.end(), host_determinants.begin(), queue
82 );
83
84 for(size_t i = 0; i < n; i++){
85 float det = matrices[i].determinant();
86
87 if(std::abs(det - host_determinants[i]) > 1e-6){
88 std::cerr << "error: wrong determinant at " << i << " ("
89 << host_determinants[i] << " != " << det << ")"
90 << std::endl;
91 return -1;
92 }
93 }
94
95 return 0;
96 }
97