• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2013 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 #ifndef BOOST_COMPUTE_CONTAINER_ARRAY_HPP
12 #define BOOST_COMPUTE_CONTAINER_ARRAY_HPP
13 
14 #include <cstddef>
15 #include <iterator>
16 #include <exception>
17 
18 #include <boost/array.hpp>
19 #include <boost/throw_exception.hpp>
20 
21 #include <boost/compute/buffer.hpp>
22 #include <boost/compute/system.hpp>
23 #include <boost/compute/algorithm/fill.hpp>
24 #include <boost/compute/algorithm/swap_ranges.hpp>
25 #include <boost/compute/iterator/buffer_iterator.hpp>
26 #include <boost/compute/type_traits/detail/capture_traits.hpp>
27 #include <boost/compute/detail/buffer_value.hpp>
28 
29 namespace boost {
30 namespace compute {
31 
32 /// \class array
33 /// \brief A fixed-size container.
34 ///
35 /// The array container is very similar to the \ref vector container except
36 /// its size is fixed at compile-time rather than being dynamically resizable
37 /// at run-time.
38 ///
39 /// For example, to create a fixed-size array with eight values on the device:
40 /// \code
41 /// boost::compute::array<int, 8> values(context);
42 /// \endcode
43 ///
44 /// The Boost.Compute \c array class provides a STL-like API and is modeled
45 /// after the \c std::array class from the C++ standard library.
46 ///
47 /// \see \ref vector "vector<T>"
48 template<class T, std::size_t N>
49 class array
50 {
51 public:
52     typedef T value_type;
53     typedef std::size_t size_type;
54     typedef ptrdiff_t difference_type;
55     typedef detail::buffer_value<T> reference;
56     typedef const detail::buffer_value<T> const_reference;
57     typedef T* pointer;
58     typedef const T* const_pointer;
59     typedef buffer_iterator<T> iterator;
60     typedef buffer_iterator<T> const_iterator;
61     typedef std::reverse_iterator<iterator> reverse_iterator;
62     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
63 
64     enum {
65         static_size = N
66     };
67 
array(const context & context=system::default_context ())68     explicit array(const context &context = system::default_context())
69         : m_buffer(context, sizeof(T) * N)
70     {
71     }
72 
array(const array<T,N> & other)73     array(const array<T, N> &other)
74         : m_buffer(other.m_buffer.get_context(), sizeof(T) * N)
75     {
76         command_queue queue = default_queue();
77         boost::compute::copy(other.begin(), other.end(), begin(), queue);
78         queue.finish();
79     }
80 
array(const boost::array<T,N> & array,const context & context=system::default_context ())81     array(const boost::array<T, N> &array,
82           const context &context = system::default_context())
83         : m_buffer(context, sizeof(T) * N)
84     {
85         command_queue queue = default_queue();
86         boost::compute::copy(array.begin(), array.end(), begin(), queue);
87         queue.finish();
88     }
89 
array(const array<T,N> & other,const command_queue & queue)90     array(const array<T, N> &other,
91           const command_queue &queue)
92         : m_buffer(other.m_buffer.get_context(), sizeof(T) * N)
93     {
94         boost::compute::copy(other.begin(), other.end(), begin(), queue);
95     }
96 
operator =(const array<T,N> & other)97     array<T, N>& operator=(const array<T, N> &other)
98     {
99         if(this != &other){
100             command_queue queue = default_queue();
101             boost::compute::copy(other.begin(), other.end(), begin(), queue);
102             queue.finish();
103         }
104 
105         return *this;
106     }
107 
operator =(const boost::array<T,N> & array)108     array<T, N>& operator=(const boost::array<T, N> &array)
109     {
110         command_queue queue = default_queue();
111         boost::compute::copy(array.begin(), array.end(), begin(), queue);
112         queue.finish();
113 
114         return *this;
115     }
116 
~array()117     ~array()
118     {
119     }
120 
begin()121     iterator begin()
122     {
123         return buffer_iterator<T>(m_buffer, 0);
124     }
125 
begin() const126     const_iterator begin() const
127     {
128         return buffer_iterator<T>(m_buffer, 0);
129     }
130 
cbegin() const131     const_iterator cbegin() const
132     {
133         return begin();
134     }
135 
end()136     iterator end()
137     {
138         return buffer_iterator<T>(m_buffer, N);
139     }
140 
end() const141     const_iterator end() const
142     {
143         return buffer_iterator<T>(m_buffer, N);
144     }
145 
cend() const146     const_iterator cend() const
147     {
148         return end();
149     }
150 
rbegin()151     reverse_iterator rbegin()
152     {
153         return reverse_iterator(end() - 1);
154     }
155 
rbegin() const156     const_reverse_iterator rbegin() const
157     {
158         return reverse_iterator(end() - 1);
159     }
160 
crbegin() const161     const_reverse_iterator crbegin() const
162     {
163         return rbegin();
164     }
165 
rend()166     reverse_iterator rend()
167     {
168         return reverse_iterator(begin() - 1);
169     }
170 
rend() const171     const_reverse_iterator rend() const
172     {
173         return reverse_iterator(begin() - 1);
174     }
175 
crend() const176     const_reverse_iterator crend() const
177     {
178         return rend();
179     }
180 
size() const181     size_type size() const
182     {
183         return N;
184     }
185 
empty() const186     bool empty() const
187     {
188         return N == 0;
189     }
190 
max_size() const191     size_type max_size() const
192     {
193         return N;
194     }
195 
operator [](size_type index)196     reference operator[](size_type index)
197     {
198         return *(begin() + static_cast<difference_type>(index));
199     }
200 
operator [](size_type index) const201     const_reference operator[](size_type index) const
202     {
203         return *(begin() + static_cast<difference_type>(index));
204     }
205 
at(size_type index)206     reference at(size_type index)
207     {
208         if(index >= N){
209             BOOST_THROW_EXCEPTION(std::out_of_range("index out of range"));
210         }
211 
212         return operator[](index);
213     }
214 
at(size_type index) const215     const_reference at(size_type index) const
216     {
217         if(index >= N){
218             BOOST_THROW_EXCEPTION(std::out_of_range("index out of range"));
219         }
220 
221         return operator[](index);
222     }
223 
front()224     reference front()
225     {
226         return *begin();
227     }
228 
front() const229     const_reference front() const
230     {
231         return *begin();
232     }
233 
back()234     reference back()
235     {
236         return *(end() - static_cast<difference_type>(1));
237     }
238 
back() const239     const_reference back() const
240     {
241         return *(end() - static_cast<difference_type>(1));
242     }
243 
fill(const value_type & value,const command_queue & queue)244     void fill(const value_type &value, const command_queue &queue)
245     {
246         ::boost::compute::fill(begin(), end(), value, queue);
247     }
248 
swap(array<T,N> & other,const command_queue & queue)249     void swap(array<T, N> &other, const command_queue &queue)
250     {
251         ::boost::compute::swap_ranges(begin(), end(), other.begin(), queue);
252     }
253 
fill(const value_type & value)254     void fill(const value_type &value)
255     {
256         command_queue queue = default_queue();
257         ::boost::compute::fill(begin(), end(), value, queue);
258         queue.finish();
259     }
260 
swap(array<T,N> & other)261     void swap(array<T, N> &other)
262     {
263         command_queue queue = default_queue();
264         ::boost::compute::swap_ranges(begin(), end(), other.begin(), queue);
265         queue.finish();
266     }
267 
get_buffer() const268     const buffer& get_buffer() const
269     {
270         return m_buffer;
271     }
272 
273 private:
274     buffer m_buffer;
275 
default_queue() const276     command_queue default_queue() const
277     {
278         const context &context = m_buffer.get_context();
279         command_queue queue(context, context.get_device());
280         return queue;
281     }
282 };
283 
284 namespace detail {
285 
286 // set_kernel_arg specialization for array<T, N>
287 template<class T, std::size_t N>
288 struct set_kernel_arg<array<T, N> >
289 {
operator ()boost::compute::detail::set_kernel_arg290     void operator()(kernel &kernel_, size_t index, const array<T, N> &array)
291     {
292         kernel_.set_arg(index, array.get_buffer());
293     }
294 };
295 
296 // for capturing array<T, N> with BOOST_COMPUTE_CLOSURE()
297 template<class T, size_t N>
298 struct capture_traits<array<T, N> >
299 {
type_nameboost::compute::detail::capture_traits300     static std::string type_name()
301     {
302         return std::string("__global ") + ::boost::compute::type_name<T>() + "*";
303     }
304 };
305 
306 // meta_kernel streaming operator for array<T, N>
307 template<class T, size_t N>
operator <<(meta_kernel & k,const array<T,N> & array)308 meta_kernel& operator<<(meta_kernel &k, const array<T, N> &array)
309 {
310   return k << k.get_buffer_identifier<T>(array.get_buffer());
311 }
312 
313 } // end detail namespace
314 } // end compute namespace
315 } // end boost namespace
316 
317 #endif // BOOST_COMPUTE_CONTAINER_ARRAY_HPP
318