• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2014 Mageswaran.D <mageswaran1989@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 <boost/static_assert.hpp>
12 
13 #include <boost/compute/system.hpp>
14 #include <boost/compute/context.hpp>
15 #include <boost/compute/command_queue.hpp>
16 #include <boost/compute/algorithm/any_of.hpp>
17 #include <boost/compute/container/vector.hpp>
18 #include <boost/compute/utility/program_cache.hpp>
19 #include <boost/compute/type_traits/is_device_iterator.hpp>
20 
21 namespace boost {
22 namespace compute {
23 
24 namespace detail {
25 
26 const char lexicographical_compare_source[] =
27 "__kernel void lexicographical_compare(const uint size1,\n"
28 "                                      const uint size2,\n"
29 "                                      __global const T1 *range1,\n"
30 "                                      __global const T2 *range2,\n"
31 "                                      __global bool *result_buf)\n"
32 "{\n"
33 "   const uint i = get_global_id(0);\n"
34 "   if((i != size1) && (i != size2)){\n"
35         //Individual elements are compared and results are stored in parallel.
36         //0 is true
37 "       if(range1[i] < range2[i])\n"
38 "           result_buf[i] = 0;\n"
39 "       else\n"
40 "           result_buf[i] = 1;\n"
41 "   }\n"
42 "   else\n"
43 "       result_buf[i] = !((i == size1) && (i != size2));\n"
44 "}\n";
45 
46 template<class InputIterator1, class InputIterator2>
dispatch_lexicographical_compare(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2,command_queue & queue)47 inline bool dispatch_lexicographical_compare(InputIterator1 first1,
48                                              InputIterator1 last1,
49                                              InputIterator2 first2,
50                                              InputIterator2 last2,
51                                              command_queue &queue)
52 {
53     const boost::compute::context &context = queue.get_context();
54 
55     boost::shared_ptr<program_cache> cache =
56         program_cache::get_global_cache(context);
57 
58     size_t iterator_size1 = iterator_range_size(first1, last1);
59     size_t iterator_size2 = iterator_range_size(first2, last2);
60     size_t max_size = (std::max)(iterator_size1, iterator_size2);
61 
62     if(max_size == 0){
63         return false;
64     }
65 
66     boost::compute::vector<bool> result_vector(max_size, context);
67 
68 
69     typedef typename std::iterator_traits<InputIterator1>::value_type value_type1;
70     typedef typename std::iterator_traits<InputIterator2>::value_type value_type2;
71 
72     // load (or create) lexicographical compare program
73     std::string cache_key =
74             std::string("__boost_lexicographical_compare")
75             + type_name<value_type1>() + type_name<value_type2>();
76 
77     std::stringstream options;
78     options << " -DT1=" << type_name<value_type1>();
79     options << " -DT2=" << type_name<value_type2>();
80 
81     program lexicographical_compare_program = cache->get_or_build(
82         cache_key, options.str(), lexicographical_compare_source, context
83     );
84 
85     kernel lexicographical_compare_kernel(lexicographical_compare_program,
86                                           "lexicographical_compare");
87 
88     lexicographical_compare_kernel.set_arg<uint_>(0, iterator_size1);
89     lexicographical_compare_kernel.set_arg<uint_>(1, iterator_size2);
90     lexicographical_compare_kernel.set_arg(2, first1.get_buffer());
91     lexicographical_compare_kernel.set_arg(3, first2.get_buffer());
92     lexicographical_compare_kernel.set_arg(4, result_vector.get_buffer());
93 
94     queue.enqueue_1d_range_kernel(lexicographical_compare_kernel,
95                                   0,
96                                   max_size,
97                                   0);
98 
99     return boost::compute::any_of(result_vector.begin(),
100                                   result_vector.end(),
101                                   _1 == 0,
102                                   queue);
103 }
104 
105 } // end detail namespace
106 
107 /// Checks if the first range [first1, last1) is lexicographically
108 /// less than the second range [first2, last2).
109 ///
110 /// Space complexity:
111 /// \Omega(max(distance(\p first1, \p last1), distance(\p first2, \p last2)))
112 template<class InputIterator1, class InputIterator2>
lexicographical_compare(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2,command_queue & queue=system::default_queue ())113 inline bool lexicographical_compare(InputIterator1 first1,
114                                     InputIterator1 last1,
115                                     InputIterator2 first2,
116                                     InputIterator2 last2,
117                                     command_queue &queue = system::default_queue())
118 {
119     BOOST_STATIC_ASSERT(is_device_iterator<InputIterator1>::value);
120     BOOST_STATIC_ASSERT(is_device_iterator<InputIterator2>::value);
121 
122     return detail::dispatch_lexicographical_compare(first1, last1, first2, last2, queue);
123 }
124 
125 } // end compute namespace
126 } // end boost namespac
127