stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork
This commit is contained in:
@@ -0,0 +1,317 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_CONTAINER_ARRAY_HPP
|
||||
#define BOOST_COMPUTE_CONTAINER_ARRAY_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <exception>
|
||||
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <boost/compute/buffer.hpp>
|
||||
#include <boost/compute/system.hpp>
|
||||
#include <boost/compute/algorithm/fill.hpp>
|
||||
#include <boost/compute/algorithm/swap_ranges.hpp>
|
||||
#include <boost/compute/iterator/buffer_iterator.hpp>
|
||||
#include <boost/compute/type_traits/detail/capture_traits.hpp>
|
||||
#include <boost/compute/detail/buffer_value.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
/// \class array
|
||||
/// \brief A fixed-size container.
|
||||
///
|
||||
/// The array container is very similar to the \ref vector container except
|
||||
/// its size is fixed at compile-time rather than being dynamically resizable
|
||||
/// at run-time.
|
||||
///
|
||||
/// For example, to create a fixed-size array with eight values on the device:
|
||||
/// \code
|
||||
/// boost::compute::array<int, 8> values(context);
|
||||
/// \endcode
|
||||
///
|
||||
/// The Boost.Compute \c array class provides a STL-like API and is modeled
|
||||
/// after the \c std::array class from the C++ standard library.
|
||||
///
|
||||
/// \see \ref vector "vector<T>"
|
||||
template<class T, std::size_t N>
|
||||
class array
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef detail::buffer_value<T> reference;
|
||||
typedef const detail::buffer_value<T> const_reference;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef buffer_iterator<T> iterator;
|
||||
typedef buffer_iterator<T> const_iterator;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
enum {
|
||||
static_size = N
|
||||
};
|
||||
|
||||
explicit array(const context &context = system::default_context())
|
||||
: m_buffer(context, sizeof(T) * N)
|
||||
{
|
||||
}
|
||||
|
||||
array(const array<T, N> &other)
|
||||
: m_buffer(other.m_buffer.get_context(), sizeof(T) * N)
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
boost::compute::copy(other.begin(), other.end(), begin(), queue);
|
||||
queue.finish();
|
||||
}
|
||||
|
||||
array(const boost::array<T, N> &array,
|
||||
const context &context = system::default_context())
|
||||
: m_buffer(context, sizeof(T) * N)
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
boost::compute::copy(array.begin(), array.end(), begin(), queue);
|
||||
queue.finish();
|
||||
}
|
||||
|
||||
array(const array<T, N> &other,
|
||||
const command_queue &queue)
|
||||
: m_buffer(other.m_buffer.get_context(), sizeof(T) * N)
|
||||
{
|
||||
boost::compute::copy(other.begin(), other.end(), begin(), queue);
|
||||
}
|
||||
|
||||
array<T, N>& operator=(const array<T, N> &other)
|
||||
{
|
||||
if(this != &other){
|
||||
command_queue queue = default_queue();
|
||||
boost::compute::copy(other.begin(), other.end(), begin(), queue);
|
||||
queue.finish();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
array<T, N>& operator=(const boost::array<T, N> &array)
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
boost::compute::copy(array.begin(), array.end(), begin(), queue);
|
||||
queue.finish();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~array()
|
||||
{
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return buffer_iterator<T>(m_buffer, 0);
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return buffer_iterator<T>(m_buffer, 0);
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return begin();
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return buffer_iterator<T>(m_buffer, N);
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return buffer_iterator<T>(m_buffer, N);
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
reverse_iterator rbegin()
|
||||
{
|
||||
return reverse_iterator(end() - 1);
|
||||
}
|
||||
|
||||
const_reverse_iterator rbegin() const
|
||||
{
|
||||
return reverse_iterator(end() - 1);
|
||||
}
|
||||
|
||||
const_reverse_iterator crbegin() const
|
||||
{
|
||||
return rbegin();
|
||||
}
|
||||
|
||||
reverse_iterator rend()
|
||||
{
|
||||
return reverse_iterator(begin() - 1);
|
||||
}
|
||||
|
||||
const_reverse_iterator rend() const
|
||||
{
|
||||
return reverse_iterator(begin() - 1);
|
||||
}
|
||||
|
||||
const_reverse_iterator crend() const
|
||||
{
|
||||
return rend();
|
||||
}
|
||||
|
||||
size_type size() const
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return N == 0;
|
||||
}
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
reference operator[](size_type index)
|
||||
{
|
||||
return *(begin() + static_cast<difference_type>(index));
|
||||
}
|
||||
|
||||
const_reference operator[](size_type index) const
|
||||
{
|
||||
return *(begin() + static_cast<difference_type>(index));
|
||||
}
|
||||
|
||||
reference at(size_type index)
|
||||
{
|
||||
if(index >= N){
|
||||
BOOST_THROW_EXCEPTION(std::out_of_range("index out of range"));
|
||||
}
|
||||
|
||||
return operator[](index);
|
||||
}
|
||||
|
||||
const_reference at(size_type index) const
|
||||
{
|
||||
if(index >= N){
|
||||
BOOST_THROW_EXCEPTION(std::out_of_range("index out of range"));
|
||||
}
|
||||
|
||||
return operator[](index);
|
||||
}
|
||||
|
||||
reference front()
|
||||
{
|
||||
return *begin();
|
||||
}
|
||||
|
||||
const_reference front() const
|
||||
{
|
||||
return *begin();
|
||||
}
|
||||
|
||||
reference back()
|
||||
{
|
||||
return *(end() - static_cast<difference_type>(1));
|
||||
}
|
||||
|
||||
const_reference back() const
|
||||
{
|
||||
return *(end() - static_cast<difference_type>(1));
|
||||
}
|
||||
|
||||
void fill(const value_type &value, const command_queue &queue)
|
||||
{
|
||||
::boost::compute::fill(begin(), end(), value, queue);
|
||||
}
|
||||
|
||||
void swap(array<T, N> &other, const command_queue &queue)
|
||||
{
|
||||
::boost::compute::swap_ranges(begin(), end(), other.begin(), queue);
|
||||
}
|
||||
|
||||
void fill(const value_type &value)
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
::boost::compute::fill(begin(), end(), value, queue);
|
||||
queue.finish();
|
||||
}
|
||||
|
||||
void swap(array<T, N> &other)
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
::boost::compute::swap_ranges(begin(), end(), other.begin(), queue);
|
||||
queue.finish();
|
||||
}
|
||||
|
||||
const buffer& get_buffer() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
private:
|
||||
buffer m_buffer;
|
||||
|
||||
command_queue default_queue() const
|
||||
{
|
||||
const context &context = m_buffer.get_context();
|
||||
command_queue queue(context, context.get_device());
|
||||
return queue;
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
// set_kernel_arg specialization for array<T, N>
|
||||
template<class T, std::size_t N>
|
||||
struct set_kernel_arg<array<T, N> >
|
||||
{
|
||||
void operator()(kernel &kernel_, size_t index, const array<T, N> &array)
|
||||
{
|
||||
kernel_.set_arg(index, array.get_buffer());
|
||||
}
|
||||
};
|
||||
|
||||
// for capturing array<T, N> with BOOST_COMPUTE_CLOSURE()
|
||||
template<class T, size_t N>
|
||||
struct capture_traits<array<T, N> >
|
||||
{
|
||||
static std::string type_name()
|
||||
{
|
||||
return std::string("__global ") + ::boost::compute::type_name<T>() + "*";
|
||||
}
|
||||
};
|
||||
|
||||
// meta_kernel streaming operator for array<T, N>
|
||||
template<class T, size_t N>
|
||||
meta_kernel& operator<<(meta_kernel &k, const array<T, N> &array)
|
||||
{
|
||||
return k << k.get_buffer_identifier<T>(array.get_buffer());
|
||||
}
|
||||
|
||||
} // end detail namespace
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_CONTAINER_ARRAY_HPP
|
||||
@@ -0,0 +1,331 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_CONTAINER_BASIC_STRING_HPP
|
||||
#define BOOST_COMPUTE_CONTAINER_BASIC_STRING_HPP
|
||||
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
#include <boost/compute/cl.hpp>
|
||||
#include <boost/compute/algorithm/find.hpp>
|
||||
#include <boost/compute/algorithm/search.hpp>
|
||||
#include <boost/compute/container/vector.hpp>
|
||||
#include <boost/compute/system.hpp>
|
||||
#include <boost/compute/command_queue.hpp>
|
||||
#include <iosfwd>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
/// \class basic_string
|
||||
/// \brief A template for a dynamically-sized character sequence.
|
||||
///
|
||||
/// The \c basic_string class provides a generic template for a dynamically-
|
||||
/// sized character sequence. This is most commonly used through the \c string
|
||||
/// typedef (for \c basic_string<char>).
|
||||
///
|
||||
/// For example, to create a string on the device with its contents copied
|
||||
/// from a C-string on the host:
|
||||
/// \code
|
||||
/// boost::compute::string str("hello, world!");
|
||||
/// \endcode
|
||||
///
|
||||
/// \see \ref vector "vector<T>"
|
||||
template<class CharT, class Traits = std::char_traits<CharT> >
|
||||
class basic_string
|
||||
{
|
||||
public:
|
||||
typedef Traits traits_type;
|
||||
typedef typename Traits::char_type value_type;
|
||||
typedef size_t size_type;
|
||||
static const size_type npos = size_type(-1);
|
||||
typedef typename ::boost::compute::vector<CharT>::reference reference;
|
||||
typedef typename ::boost::compute::vector<CharT>::const_reference const_reference;
|
||||
typedef typename ::boost::compute::vector<CharT>::iterator iterator;
|
||||
typedef typename ::boost::compute::vector<CharT>::const_iterator const_iterator;
|
||||
typedef typename ::boost::compute::vector<CharT>::reverse_iterator reverse_iterator;
|
||||
typedef typename ::boost::compute::vector<CharT>::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
basic_string()
|
||||
{
|
||||
}
|
||||
|
||||
basic_string(size_type count, CharT ch)
|
||||
: m_data(count)
|
||||
{
|
||||
std::fill(m_data.begin(), m_data.end(), ch);
|
||||
}
|
||||
|
||||
basic_string(const basic_string &other,
|
||||
size_type pos,
|
||||
size_type count = npos)
|
||||
: m_data(other.begin() + pos,
|
||||
other.begin() + (std::min)(other.size(), count))
|
||||
{
|
||||
}
|
||||
|
||||
basic_string(const char *s, size_type count)
|
||||
: m_data(s, s + count)
|
||||
{
|
||||
}
|
||||
|
||||
basic_string(const char *s)
|
||||
: m_data(s, s + std::strlen(s))
|
||||
{
|
||||
}
|
||||
|
||||
template<class InputIterator>
|
||||
basic_string(InputIterator first, InputIterator last)
|
||||
: m_data(first, last)
|
||||
{
|
||||
}
|
||||
|
||||
basic_string(const basic_string<CharT, Traits> &other)
|
||||
: m_data(other.m_data)
|
||||
{
|
||||
}
|
||||
|
||||
basic_string<CharT, Traits>& operator=(const basic_string<CharT, Traits> &other)
|
||||
{
|
||||
if(this != &other){
|
||||
m_data = other.m_data;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~basic_string()
|
||||
{
|
||||
}
|
||||
|
||||
reference at(size_type pos)
|
||||
{
|
||||
return m_data.at(pos);
|
||||
}
|
||||
|
||||
const_reference at(size_type pos) const
|
||||
{
|
||||
return m_data.at(pos);
|
||||
}
|
||||
|
||||
reference operator[](size_type pos)
|
||||
{
|
||||
return m_data[pos];
|
||||
}
|
||||
|
||||
const_reference operator[](size_type pos) const
|
||||
{
|
||||
return m_data[pos];
|
||||
}
|
||||
|
||||
reference front()
|
||||
{
|
||||
return m_data.front();
|
||||
}
|
||||
|
||||
const_reference front() const
|
||||
{
|
||||
return m_data.front();
|
||||
}
|
||||
|
||||
reference back()
|
||||
{
|
||||
return m_data.back();
|
||||
}
|
||||
|
||||
const_reference back() const
|
||||
{
|
||||
return m_data.back();
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return m_data.begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return m_data.begin();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return m_data.cbegin();
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return m_data.end();
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return m_data.end();
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
{
|
||||
return m_data.cend();
|
||||
}
|
||||
|
||||
reverse_iterator rbegin()
|
||||
{
|
||||
return m_data.rbegin();
|
||||
}
|
||||
|
||||
const_reverse_iterator rbegin() const
|
||||
{
|
||||
return m_data.rbegin();
|
||||
}
|
||||
|
||||
const_reverse_iterator crbegin() const
|
||||
{
|
||||
return m_data.crbegin();
|
||||
}
|
||||
|
||||
reverse_iterator rend()
|
||||
{
|
||||
return m_data.rend();
|
||||
}
|
||||
|
||||
const_reverse_iterator rend() const
|
||||
{
|
||||
return m_data.rend();
|
||||
}
|
||||
|
||||
const_reverse_iterator crend() const
|
||||
{
|
||||
return m_data.crend();
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_data.empty();
|
||||
}
|
||||
|
||||
size_type size() const
|
||||
{
|
||||
return m_data.size();
|
||||
}
|
||||
|
||||
size_type length() const
|
||||
{
|
||||
return m_data.size();
|
||||
}
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return m_data.max_size();
|
||||
}
|
||||
|
||||
void reserve(size_type size)
|
||||
{
|
||||
m_data.reserve(size);
|
||||
}
|
||||
|
||||
size_type capacity() const
|
||||
{
|
||||
return m_data.capacity();
|
||||
}
|
||||
|
||||
void shrink_to_fit()
|
||||
{
|
||||
m_data.shrink_to_fit();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_data.clear();
|
||||
}
|
||||
|
||||
void swap(basic_string<CharT, Traits> &other)
|
||||
{
|
||||
if(this != &other)
|
||||
{
|
||||
::boost::compute::vector<CharT> temp_data(other.m_data);
|
||||
other.m_data = m_data;
|
||||
m_data = temp_data;
|
||||
}
|
||||
}
|
||||
|
||||
basic_string<CharT, Traits> substr(size_type pos = 0,
|
||||
size_type count = npos) const
|
||||
{
|
||||
return basic_string<CharT, Traits>(*this, pos, count);
|
||||
}
|
||||
|
||||
/// Finds the first character \p ch
|
||||
size_type find(CharT ch, size_type pos = 0) const
|
||||
{
|
||||
const_iterator iter = ::boost::compute::find(begin() + pos, end(), ch);
|
||||
if(iter == end()){
|
||||
return npos;
|
||||
}
|
||||
else {
|
||||
return static_cast<size_type>(std::distance(begin(), iter));
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds the first substring equal to \p str
|
||||
size_type find(basic_string& str, size_type pos = 0) const
|
||||
{
|
||||
const_iterator iter = ::boost::compute::search(begin() + pos, end(),
|
||||
str.begin(), str.end());
|
||||
if(iter == end()){
|
||||
return npos;
|
||||
}
|
||||
else {
|
||||
return static_cast<size_type>(std::distance(begin(), iter));
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds the first substring equal to the character string
|
||||
/// pointed to by \p s.
|
||||
/// The length of the string is determined by the first null character.
|
||||
///
|
||||
/// For example, the following code
|
||||
/// \snippet test/test_string.cpp string_find
|
||||
///
|
||||
/// will return 5 as position.
|
||||
size_type find(const char* s, size_type pos = 0) const
|
||||
{
|
||||
basic_string str(s);
|
||||
const_iterator iter = ::boost::compute::search(begin() + pos, end(),
|
||||
str.begin(), str.end());
|
||||
if(iter == end()){
|
||||
return npos;
|
||||
}
|
||||
else {
|
||||
return static_cast<size_type>(std::distance(begin(), iter));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
::boost::compute::vector<CharT> m_data;
|
||||
};
|
||||
|
||||
template<class CharT, class Traits>
|
||||
std::ostream&
|
||||
operator<<(std::ostream& stream,
|
||||
boost::compute::basic_string<CharT, Traits>const& outStr)
|
||||
{
|
||||
command_queue queue = ::boost::compute::system::default_queue();
|
||||
boost::compute::copy(outStr.begin(),
|
||||
outStr.end(),
|
||||
std::ostream_iterator<CharT>(stream),
|
||||
queue);
|
||||
return stream;
|
||||
}
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_CONTAINER_BASIC_STRING_HPP
|
||||
@@ -0,0 +1,61 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_CONTAINER_DETAIL_SCALAR_HPP
|
||||
#define BOOST_COMPUTE_CONTAINER_DETAIL_SCALAR_HPP
|
||||
|
||||
#include <boost/compute/buffer.hpp>
|
||||
#include <boost/compute/detail/read_write_single_value.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
namespace detail {
|
||||
|
||||
// scalar<T> provides a trivial "container" that stores a
|
||||
// single value in a memory buffer on a compute device
|
||||
template<class T>
|
||||
class scalar
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
scalar(const context &context)
|
||||
: m_buffer(context, sizeof(T))
|
||||
{
|
||||
}
|
||||
|
||||
~scalar()
|
||||
{
|
||||
}
|
||||
|
||||
T read(command_queue &queue) const
|
||||
{
|
||||
return read_single_value<T>(m_buffer, 0, queue);
|
||||
}
|
||||
|
||||
void write(const T &value, command_queue &queue)
|
||||
{
|
||||
write_single_value<T>(value, m_buffer, 0, queue);
|
||||
}
|
||||
|
||||
const buffer& get_buffer() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
private:
|
||||
buffer m_buffer;
|
||||
};
|
||||
|
||||
} // end detail namespace
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_CONTAINER_DETAIL_SCALAR_HPP
|
||||
@@ -0,0 +1,237 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_CONTAINER_DYNAMIC_BITSET_HPP
|
||||
#define BOOST_COMPUTE_CONTAINER_DYNAMIC_BITSET_HPP
|
||||
|
||||
#include <boost/compute/lambda.hpp>
|
||||
#include <boost/compute/algorithm/any_of.hpp>
|
||||
#include <boost/compute/algorithm/fill.hpp>
|
||||
#include <boost/compute/algorithm/transform_reduce.hpp>
|
||||
#include <boost/compute/container/vector.hpp>
|
||||
#include <boost/compute/functional/integer.hpp>
|
||||
#include <boost/compute/types/fundamental.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
/// \class dynamic_bitset
|
||||
/// \brief The dynamic_bitset class contains a resizable bit array.
|
||||
///
|
||||
/// For example, to create a dynamic-bitset with space for 1000 bits on the
|
||||
/// device:
|
||||
/// \code
|
||||
/// boost::compute::dynamic_bitset<> bits(1000, queue);
|
||||
/// \endcode
|
||||
///
|
||||
/// The Boost.Compute \c dynamic_bitset class provides a STL-like API and is
|
||||
/// modeled after the \c boost::dynamic_bitset class from Boost.
|
||||
///
|
||||
/// \see \ref vector "vector<T>"
|
||||
template<class Block = ulong_, class Alloc = buffer_allocator<Block> >
|
||||
class dynamic_bitset
|
||||
{
|
||||
public:
|
||||
typedef Block block_type;
|
||||
typedef Alloc allocator_type;
|
||||
typedef vector<Block, Alloc> container_type;
|
||||
typedef typename container_type::size_type size_type;
|
||||
|
||||
BOOST_STATIC_CONSTANT(size_type, bits_per_block = sizeof(block_type) * CHAR_BIT);
|
||||
BOOST_STATIC_CONSTANT(size_type, npos = static_cast<size_type>(-1));
|
||||
|
||||
/// Creates a new dynamic bitset with storage for \p size bits. Initializes
|
||||
/// all bits to zero.
|
||||
dynamic_bitset(size_type size, command_queue &queue)
|
||||
: m_bits(size / sizeof(block_type), queue.get_context()),
|
||||
m_size(size)
|
||||
{
|
||||
// initialize all bits to zero
|
||||
reset(queue);
|
||||
}
|
||||
|
||||
/// Creates a new dynamic bitset as a copy of \p other.
|
||||
dynamic_bitset(const dynamic_bitset &other)
|
||||
: m_bits(other.m_bits),
|
||||
m_size(other.m_size)
|
||||
{
|
||||
}
|
||||
|
||||
/// Copies the data from \p other to \c *this.
|
||||
dynamic_bitset& operator=(const dynamic_bitset &other)
|
||||
{
|
||||
if(this != &other){
|
||||
m_bits = other.m_bits;
|
||||
m_size = other.m_size;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Destroys the dynamic bitset.
|
||||
~dynamic_bitset()
|
||||
{
|
||||
}
|
||||
|
||||
/// Returns the size of the dynamic bitset.
|
||||
size_type size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
/// Returns the number of blocks to store the bits in the dynamic bitset.
|
||||
size_type num_blocks() const
|
||||
{
|
||||
return m_bits.size();
|
||||
}
|
||||
|
||||
/// Returns the maximum possible size for the dynamic bitset.
|
||||
size_type max_size() const
|
||||
{
|
||||
return m_bits.max_size() * bits_per_block;
|
||||
}
|
||||
|
||||
/// Returns \c true if the dynamic bitset is empty (i.e. \c size() == \c 0).
|
||||
bool empty() const
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/// Returns the number of set bits (i.e. '1') in the bitset.
|
||||
size_type count(command_queue &queue) const
|
||||
{
|
||||
ulong_ count = 0;
|
||||
transform_reduce(
|
||||
m_bits.begin(),
|
||||
m_bits.end(),
|
||||
&count,
|
||||
popcount<block_type>(),
|
||||
plus<ulong_>(),
|
||||
queue
|
||||
);
|
||||
return static_cast<size_type>(count);
|
||||
}
|
||||
|
||||
/// Resizes the bitset to contain \p num_bits. If the new size is greater
|
||||
/// than the current size the new bits are set to zero.
|
||||
void resize(size_type num_bits, command_queue &queue)
|
||||
{
|
||||
// resize bits
|
||||
const size_type current_block_count = m_bits.size();
|
||||
m_bits.resize(num_bits * bits_per_block, queue);
|
||||
|
||||
// fill new block with zeros (if new blocks were added)
|
||||
const size_type new_block_count = m_bits.size();
|
||||
if(new_block_count > current_block_count){
|
||||
fill_n(
|
||||
m_bits.begin() + current_block_count,
|
||||
new_block_count - current_block_count,
|
||||
block_type(0),
|
||||
queue
|
||||
);
|
||||
}
|
||||
|
||||
// store new size
|
||||
m_size = num_bits;
|
||||
}
|
||||
|
||||
/// Sets the bit at position \p n to \c true.
|
||||
void set(size_type n, command_queue &queue)
|
||||
{
|
||||
set(n, true, queue);
|
||||
}
|
||||
|
||||
/// Sets the bit at position \p n to \p value.
|
||||
void set(size_type n, bool value, command_queue &queue)
|
||||
{
|
||||
const size_type bit = n % bits_per_block;
|
||||
const size_type block = n / bits_per_block;
|
||||
|
||||
// load current block
|
||||
block_type block_value;
|
||||
copy_n(m_bits.begin() + block, 1, &block_value, queue);
|
||||
|
||||
// update block value
|
||||
if(value){
|
||||
block_value |= (size_type(1) << bit);
|
||||
}
|
||||
else {
|
||||
block_value &= ~(size_type(1) << bit);
|
||||
}
|
||||
|
||||
// store new block
|
||||
copy_n(&block_value, 1, m_bits.begin() + block, queue);
|
||||
}
|
||||
|
||||
/// Returns \c true if the bit at position \p n is set (i.e. '1').
|
||||
bool test(size_type n, command_queue &queue)
|
||||
{
|
||||
const size_type bit = n % (sizeof(block_type) * CHAR_BIT);
|
||||
const size_type block = n / (sizeof(block_type) * CHAR_BIT);
|
||||
|
||||
block_type block_value;
|
||||
copy_n(m_bits.begin() + block, 1, &block_value, queue);
|
||||
|
||||
return block_value & (size_type(1) << bit);
|
||||
}
|
||||
|
||||
/// Flips the value of the bit at position \p n.
|
||||
void flip(size_type n, command_queue &queue)
|
||||
{
|
||||
set(n, !test(n, queue), queue);
|
||||
}
|
||||
|
||||
/// Returns \c true if any bit in the bitset is set (i.e. '1').
|
||||
bool any(command_queue &queue) const
|
||||
{
|
||||
return any_of(
|
||||
m_bits.begin(), m_bits.end(), lambda::_1 != block_type(0), queue
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns \c true if all of the bits in the bitset are set to zero.
|
||||
bool none(command_queue &queue) const
|
||||
{
|
||||
return !any(queue);
|
||||
}
|
||||
|
||||
/// Sets all of the bits in the bitset to zero.
|
||||
void reset(command_queue &queue)
|
||||
{
|
||||
fill(m_bits.begin(), m_bits.end(), block_type(0), queue);
|
||||
}
|
||||
|
||||
/// Sets the bit at position \p n to zero.
|
||||
void reset(size_type n, command_queue &queue)
|
||||
{
|
||||
set(n, false, queue);
|
||||
}
|
||||
|
||||
/// Empties the bitset (e.g. \c resize(0)).
|
||||
void clear()
|
||||
{
|
||||
m_bits.clear();
|
||||
}
|
||||
|
||||
/// Returns the allocator used to allocate storage for the bitset.
|
||||
allocator_type get_allocator() const
|
||||
{
|
||||
return m_bits.get_allocator();
|
||||
}
|
||||
|
||||
private:
|
||||
container_type m_bits;
|
||||
size_type m_size;
|
||||
};
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_CONTAINER_DYNAMIC_BITSET_HPP
|
||||
@@ -0,0 +1,406 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_CONTAINER_FLAT_MAP_HPP
|
||||
#define BOOST_COMPUTE_CONTAINER_FLAT_MAP_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
#include <exception>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <boost/compute/exception.hpp>
|
||||
#include <boost/compute/algorithm/find.hpp>
|
||||
#include <boost/compute/algorithm/lower_bound.hpp>
|
||||
#include <boost/compute/algorithm/upper_bound.hpp>
|
||||
#include <boost/compute/container/vector.hpp>
|
||||
#include <boost/compute/functional/get.hpp>
|
||||
#include <boost/compute/iterator/transform_iterator.hpp>
|
||||
#include <boost/compute/types/pair.hpp>
|
||||
#include <boost/compute/detail/buffer_value.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
template<class Key, class T>
|
||||
class flat_map
|
||||
{
|
||||
public:
|
||||
typedef Key key_type;
|
||||
typedef T mapped_type;
|
||||
typedef typename ::boost::compute::vector<std::pair<Key, T> > vector_type;
|
||||
typedef typename vector_type::value_type value_type;
|
||||
typedef typename vector_type::size_type size_type;
|
||||
typedef typename vector_type::difference_type difference_type;
|
||||
typedef typename vector_type::reference reference;
|
||||
typedef typename vector_type::const_reference const_reference;
|
||||
typedef typename vector_type::pointer pointer;
|
||||
typedef typename vector_type::const_pointer const_pointer;
|
||||
typedef typename vector_type::iterator iterator;
|
||||
typedef typename vector_type::const_iterator const_iterator;
|
||||
typedef typename vector_type::reverse_iterator reverse_iterator;
|
||||
typedef typename vector_type::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
explicit flat_map(const context &context = system::default_context())
|
||||
: m_vector(context)
|
||||
{
|
||||
}
|
||||
|
||||
flat_map(const flat_map<Key, T> &other)
|
||||
: m_vector(other.m_vector)
|
||||
{
|
||||
}
|
||||
|
||||
flat_map<Key, T>& operator=(const flat_map<Key, T> &other)
|
||||
{
|
||||
if(this != &other){
|
||||
m_vector = other.m_vector;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~flat_map()
|
||||
{
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return m_vector.begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return m_vector.begin();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return m_vector.cbegin();
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return m_vector.end();
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return m_vector.end();
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
{
|
||||
return m_vector.cend();
|
||||
}
|
||||
|
||||
reverse_iterator rbegin()
|
||||
{
|
||||
return m_vector.rbegin();
|
||||
}
|
||||
|
||||
const_reverse_iterator rbegin() const
|
||||
{
|
||||
return m_vector.rbegin();
|
||||
}
|
||||
|
||||
const_reverse_iterator crbegin() const
|
||||
{
|
||||
return m_vector.crbegin();
|
||||
}
|
||||
|
||||
reverse_iterator rend()
|
||||
{
|
||||
return m_vector.rend();
|
||||
}
|
||||
|
||||
const_reverse_iterator rend() const
|
||||
{
|
||||
return m_vector.rend();
|
||||
}
|
||||
|
||||
const_reverse_iterator crend() const
|
||||
{
|
||||
return m_vector.crend();
|
||||
}
|
||||
|
||||
size_type size() const
|
||||
{
|
||||
return m_vector.size();
|
||||
}
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return m_vector.max_size();
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_vector.empty();
|
||||
}
|
||||
|
||||
size_type capacity() const
|
||||
{
|
||||
return m_vector.capacity();
|
||||
}
|
||||
|
||||
void reserve(size_type size, command_queue &queue)
|
||||
{
|
||||
m_vector.reserve(size, queue);
|
||||
}
|
||||
|
||||
void reserve(size_type size)
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
reserve(size, queue);
|
||||
queue.finish();
|
||||
}
|
||||
|
||||
void shrink_to_fit()
|
||||
{
|
||||
m_vector.shrink_to_fit();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_vector.clear();
|
||||
}
|
||||
|
||||
std::pair<iterator, bool>
|
||||
insert(const value_type &value, command_queue &queue)
|
||||
{
|
||||
iterator location = upper_bound(value.first, queue);
|
||||
|
||||
if(location != begin()){
|
||||
value_type current_value;
|
||||
::boost::compute::copy_n(location - 1, 1, ¤t_value, queue);
|
||||
if(value.first == current_value.first){
|
||||
return std::make_pair(location - 1, false);
|
||||
}
|
||||
}
|
||||
|
||||
m_vector.insert(location, value);
|
||||
return std::make_pair(location, true);
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert(const value_type &value)
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
std::pair<iterator, bool> result = insert(value, queue);
|
||||
queue.finish();
|
||||
return result;
|
||||
}
|
||||
|
||||
iterator erase(const const_iterator &position, command_queue &queue)
|
||||
{
|
||||
return erase(position, position + 1, queue);
|
||||
}
|
||||
|
||||
iterator erase(const const_iterator &position)
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
iterator iter = erase(position, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
iterator erase(const const_iterator &first,
|
||||
const const_iterator &last,
|
||||
command_queue &queue)
|
||||
{
|
||||
return m_vector.erase(first, last, queue);
|
||||
}
|
||||
|
||||
iterator erase(const const_iterator &first, const const_iterator &last)
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
iterator iter = erase(first, last, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
size_type erase(const key_type &value, command_queue &queue)
|
||||
{
|
||||
iterator position = find(value, queue);
|
||||
|
||||
if(position == end()){
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
erase(position, queue);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
iterator find(const key_type &value, command_queue &queue)
|
||||
{
|
||||
::boost::compute::get<0> get_key;
|
||||
|
||||
return ::boost::compute::find(
|
||||
::boost::compute::make_transform_iterator(begin(), get_key),
|
||||
::boost::compute::make_transform_iterator(end(), get_key),
|
||||
value,
|
||||
queue
|
||||
).base();
|
||||
}
|
||||
|
||||
iterator find(const key_type &value)
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
iterator iter = find(value, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
const_iterator find(const key_type &value, command_queue &queue) const
|
||||
{
|
||||
::boost::compute::get<0> get_key;
|
||||
|
||||
return ::boost::compute::find(
|
||||
::boost::compute::make_transform_iterator(begin(), get_key),
|
||||
::boost::compute::make_transform_iterator(end(), get_key),
|
||||
value,
|
||||
queue
|
||||
).base();
|
||||
}
|
||||
|
||||
const_iterator find(const key_type &value) const
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
const_iterator iter = find(value, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
size_type count(const key_type &value, command_queue &queue) const
|
||||
{
|
||||
return find(value, queue) != end() ? 1 : 0;
|
||||
}
|
||||
|
||||
size_type count(const key_type &value) const
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
size_type result = count(value, queue);
|
||||
queue.finish();
|
||||
return result;
|
||||
}
|
||||
|
||||
iterator lower_bound(const key_type &value, command_queue &queue)
|
||||
{
|
||||
::boost::compute::get<0> get_key;
|
||||
|
||||
return ::boost::compute::lower_bound(
|
||||
::boost::compute::make_transform_iterator(begin(), get_key),
|
||||
::boost::compute::make_transform_iterator(end(), get_key),
|
||||
value,
|
||||
queue
|
||||
).base();
|
||||
}
|
||||
|
||||
iterator lower_bound(const key_type &value)
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
iterator iter = lower_bound(value, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
const_iterator lower_bound(const key_type &value, command_queue &queue) const
|
||||
{
|
||||
::boost::compute::get<0> get_key;
|
||||
|
||||
return ::boost::compute::lower_bound(
|
||||
::boost::compute::make_transform_iterator(begin(), get_key),
|
||||
::boost::compute::make_transform_iterator(end(), get_key),
|
||||
value,
|
||||
queue
|
||||
).base();
|
||||
}
|
||||
|
||||
const_iterator lower_bound(const key_type &value) const
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
const_iterator iter = lower_bound(value, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
iterator upper_bound(const key_type &value, command_queue &queue)
|
||||
{
|
||||
::boost::compute::get<0> get_key;
|
||||
|
||||
return ::boost::compute::upper_bound(
|
||||
::boost::compute::make_transform_iterator(begin(), get_key),
|
||||
::boost::compute::make_transform_iterator(end(), get_key),
|
||||
value,
|
||||
queue
|
||||
).base();
|
||||
}
|
||||
|
||||
iterator upper_bound(const key_type &value)
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
iterator iter = upper_bound(value, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
const_iterator upper_bound(const key_type &value, command_queue &queue) const
|
||||
{
|
||||
::boost::compute::get<0> get_key;
|
||||
|
||||
return ::boost::compute::upper_bound(
|
||||
::boost::compute::make_transform_iterator(begin(), get_key),
|
||||
::boost::compute::make_transform_iterator(end(), get_key),
|
||||
value,
|
||||
queue
|
||||
).base();
|
||||
}
|
||||
|
||||
const_iterator upper_bound(const key_type &value) const
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
const_iterator iter = upper_bound(value, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
const mapped_type at(const key_type &key) const
|
||||
{
|
||||
const_iterator iter = find(key);
|
||||
if(iter == end()){
|
||||
BOOST_THROW_EXCEPTION(std::out_of_range("key not found"));
|
||||
}
|
||||
|
||||
return value_type(*iter).second;
|
||||
}
|
||||
|
||||
detail::buffer_value<mapped_type> operator[](const key_type &key)
|
||||
{
|
||||
iterator iter = find(key);
|
||||
if(iter == end()){
|
||||
iter = insert(std::make_pair(key, mapped_type())).first;
|
||||
}
|
||||
|
||||
size_t index = iter.get_index() * sizeof(value_type) + sizeof(key_type);
|
||||
|
||||
return detail::buffer_value<mapped_type>(m_vector.get_buffer(), index);
|
||||
}
|
||||
|
||||
private:
|
||||
::boost::compute::vector<std::pair<Key, T> > m_vector;
|
||||
};
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_CONTAINER_FLAT_MAP_HPP
|
||||
@@ -0,0 +1,339 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_CONTAINER_FLAT_SET_HPP
|
||||
#define BOOST_COMPUTE_CONTAINER_FLAT_SET_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/compute/algorithm/find.hpp>
|
||||
#include <boost/compute/algorithm/lower_bound.hpp>
|
||||
#include <boost/compute/algorithm/upper_bound.hpp>
|
||||
#include <boost/compute/container/vector.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
template<class T>
|
||||
class flat_set
|
||||
{
|
||||
public:
|
||||
typedef T key_type;
|
||||
typedef typename vector<T>::value_type value_type;
|
||||
typedef typename vector<T>::size_type size_type;
|
||||
typedef typename vector<T>::difference_type difference_type;
|
||||
typedef typename vector<T>::reference reference;
|
||||
typedef typename vector<T>::const_reference const_reference;
|
||||
typedef typename vector<T>::pointer pointer;
|
||||
typedef typename vector<T>::const_pointer const_pointer;
|
||||
typedef typename vector<T>::iterator iterator;
|
||||
typedef typename vector<T>::const_iterator const_iterator;
|
||||
typedef typename vector<T>::reverse_iterator reverse_iterator;
|
||||
typedef typename vector<T>::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
explicit flat_set(const context &context = system::default_context())
|
||||
: m_vector(context)
|
||||
{
|
||||
}
|
||||
|
||||
flat_set(const flat_set<T> &other)
|
||||
: m_vector(other.m_vector)
|
||||
{
|
||||
}
|
||||
|
||||
flat_set<T>& operator=(const flat_set<T> &other)
|
||||
{
|
||||
if(this != &other){
|
||||
m_vector = other.m_vector;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~flat_set()
|
||||
{
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return m_vector.begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return m_vector.begin();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return m_vector.cbegin();
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return m_vector.end();
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return m_vector.end();
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
{
|
||||
return m_vector.cend();
|
||||
}
|
||||
|
||||
reverse_iterator rbegin()
|
||||
{
|
||||
return m_vector.rbegin();
|
||||
}
|
||||
|
||||
const_reverse_iterator rbegin() const
|
||||
{
|
||||
return m_vector.rbegin();
|
||||
}
|
||||
|
||||
const_reverse_iterator crbegin() const
|
||||
{
|
||||
return m_vector.crbegin();
|
||||
}
|
||||
|
||||
reverse_iterator rend()
|
||||
{
|
||||
return m_vector.rend();
|
||||
}
|
||||
|
||||
const_reverse_iterator rend() const
|
||||
{
|
||||
return m_vector.rend();
|
||||
}
|
||||
|
||||
const_reverse_iterator crend() const
|
||||
{
|
||||
return m_vector.crend();
|
||||
}
|
||||
|
||||
size_type size() const
|
||||
{
|
||||
return m_vector.size();
|
||||
}
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return m_vector.max_size();
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_vector.empty();
|
||||
}
|
||||
|
||||
size_type capacity() const
|
||||
{
|
||||
return m_vector.capacity();
|
||||
}
|
||||
|
||||
void reserve(size_type size, command_queue &queue)
|
||||
{
|
||||
m_vector.reserve(size, queue);
|
||||
}
|
||||
|
||||
void reserve(size_type size)
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
reserve(size, queue);
|
||||
queue.finish();
|
||||
}
|
||||
|
||||
void shrink_to_fit()
|
||||
{
|
||||
m_vector.shrink_to_fit();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_vector.clear();
|
||||
}
|
||||
|
||||
std::pair<iterator, bool>
|
||||
insert(const value_type &value, command_queue &queue)
|
||||
{
|
||||
iterator location = upper_bound(value, queue);
|
||||
|
||||
if(location != begin()){
|
||||
value_type current_value;
|
||||
::boost::compute::copy_n(location - 1, 1, ¤t_value, queue);
|
||||
if(value == current_value){
|
||||
return std::make_pair(location - 1, false);
|
||||
}
|
||||
}
|
||||
|
||||
m_vector.insert(location, value, queue);
|
||||
return std::make_pair(location, true);
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert(const value_type &value)
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
std::pair<iterator, bool> result = insert(value, queue);
|
||||
queue.finish();
|
||||
return result;
|
||||
}
|
||||
|
||||
iterator erase(const const_iterator &position, command_queue &queue)
|
||||
{
|
||||
return erase(position, position + 1, queue);
|
||||
}
|
||||
|
||||
iterator erase(const const_iterator &position)
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
iterator iter = erase(position, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
iterator erase(const const_iterator &first,
|
||||
const const_iterator &last,
|
||||
command_queue &queue)
|
||||
{
|
||||
return m_vector.erase(first, last, queue);
|
||||
}
|
||||
|
||||
iterator erase(const const_iterator &first, const const_iterator &last)
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
iterator iter = erase(first, last, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
size_type erase(const key_type &value, command_queue &queue)
|
||||
{
|
||||
iterator position = find(value, queue);
|
||||
|
||||
if(position == end()){
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
erase(position, queue);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
size_type erase(const key_type &value)
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
size_type result = erase(value, queue);
|
||||
queue.finish();
|
||||
return result;
|
||||
}
|
||||
|
||||
iterator find(const key_type &value, command_queue &queue)
|
||||
{
|
||||
return ::boost::compute::find(begin(), end(), value, queue);
|
||||
}
|
||||
|
||||
iterator find(const key_type &value)
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
iterator iter = find(value, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
const_iterator find(const key_type &value, command_queue &queue) const
|
||||
{
|
||||
return ::boost::compute::find(begin(), end(), value, queue);
|
||||
}
|
||||
|
||||
const_iterator find(const key_type &value) const
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
const_iterator iter = find(value, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
size_type count(const key_type &value, command_queue &queue) const
|
||||
{
|
||||
return find(value, queue) != end() ? 1 : 0;
|
||||
}
|
||||
|
||||
size_type count(const key_type &value) const
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
size_type result = count(value, queue);
|
||||
queue.finish();
|
||||
return result;
|
||||
}
|
||||
|
||||
iterator lower_bound(const key_type &value, command_queue &queue)
|
||||
{
|
||||
return ::boost::compute::lower_bound(begin(), end(), value, queue);
|
||||
}
|
||||
|
||||
iterator lower_bound(const key_type &value)
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
iterator iter = lower_bound(value, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
const_iterator lower_bound(const key_type &value, command_queue &queue) const
|
||||
{
|
||||
return ::boost::compute::lower_bound(begin(), end(), value, queue);
|
||||
}
|
||||
|
||||
const_iterator lower_bound(const key_type &value) const
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
const_iterator iter = lower_bound(value, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
iterator upper_bound(const key_type &value, command_queue &queue)
|
||||
{
|
||||
return ::boost::compute::upper_bound(begin(), end(), value, queue);
|
||||
}
|
||||
|
||||
iterator upper_bound(const key_type &value)
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
iterator iter = upper_bound(value, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
const_iterator upper_bound(const key_type &value, command_queue &queue) const
|
||||
{
|
||||
return ::boost::compute::upper_bound(begin(), end(), value, queue);
|
||||
}
|
||||
|
||||
const_iterator upper_bound(const key_type &value) const
|
||||
{
|
||||
command_queue queue = m_vector.default_queue();
|
||||
const_iterator iter = upper_bound(value, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
private:
|
||||
vector<T> m_vector;
|
||||
};
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_CONTAINER_FLAT_SET_HPP
|
||||
@@ -0,0 +1,250 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_CONTAINER_MAPPED_VIEW_HPP
|
||||
#define BOOST_COMPUTE_CONTAINER_MAPPED_VIEW_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <boost/compute/buffer.hpp>
|
||||
#include <boost/compute/system.hpp>
|
||||
#include <boost/compute/context.hpp>
|
||||
#include <boost/compute/command_queue.hpp>
|
||||
#include <boost/compute/iterator/buffer_iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
/// \class mapped_view
|
||||
/// \brief A mapped view of host memory.
|
||||
///
|
||||
/// The mapped_view class simplifies mapping host-memory to a compute
|
||||
/// device. This allows for host-allocated memory to be used with the
|
||||
/// Boost.Compute algorithms.
|
||||
///
|
||||
/// The following example shows how to map a simple C-array containing
|
||||
/// data on the host to the device and run the reduce() algorithm to
|
||||
/// calculate the sum:
|
||||
///
|
||||
/// \snippet test/test_mapped_view.cpp reduce
|
||||
///
|
||||
/// \see buffer
|
||||
template<class T>
|
||||
class mapped_view
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef buffer_iterator<T> iterator;
|
||||
typedef buffer_iterator<T> const_iterator;
|
||||
|
||||
/// Creates a null mapped_view object.
|
||||
mapped_view()
|
||||
{
|
||||
m_mapped_ptr = 0;
|
||||
}
|
||||
|
||||
/// Creates a mapped_view for \p host_ptr with \p n elements. After
|
||||
/// constructing a mapped_view the data is available for use by a
|
||||
/// compute device. Use the \p unmap() method to make the updated data
|
||||
/// available to the host.
|
||||
mapped_view(T *host_ptr,
|
||||
size_type n,
|
||||
const context &context = system::default_context())
|
||||
: m_buffer(_make_mapped_buffer(host_ptr, n, context))
|
||||
{
|
||||
m_mapped_ptr = 0;
|
||||
}
|
||||
|
||||
/// Creates a read-only mapped_view for \p host_ptr with \p n elements.
|
||||
/// After constructing a mapped_view the data is available for use by a
|
||||
/// compute device. Use the \p unmap() method to make the updated data
|
||||
/// available to the host.
|
||||
mapped_view(const T *host_ptr,
|
||||
size_type n,
|
||||
const context &context = system::default_context())
|
||||
: m_buffer(_make_mapped_buffer(host_ptr, n, context))
|
||||
{
|
||||
m_mapped_ptr = 0;
|
||||
}
|
||||
|
||||
/// Creates a copy of \p other.
|
||||
mapped_view(const mapped_view<T> &other)
|
||||
: m_buffer(other.m_buffer)
|
||||
{
|
||||
m_mapped_ptr = 0;
|
||||
}
|
||||
|
||||
/// Copies the mapped buffer from \p other.
|
||||
mapped_view<T>& operator=(const mapped_view<T> &other)
|
||||
{
|
||||
if(this != &other){
|
||||
m_buffer = other.m_buffer;
|
||||
m_mapped_ptr = 0;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Destroys the mapped_view object.
|
||||
~mapped_view()
|
||||
{
|
||||
}
|
||||
|
||||
/// Returns an iterator to the first element in the mapped_view.
|
||||
iterator begin()
|
||||
{
|
||||
return ::boost::compute::make_buffer_iterator<T>(m_buffer, 0);
|
||||
}
|
||||
|
||||
/// Returns a const_iterator to the first element in the mapped_view.
|
||||
const_iterator begin() const
|
||||
{
|
||||
return ::boost::compute::make_buffer_iterator<T>(m_buffer, 0);
|
||||
}
|
||||
|
||||
/// Returns a const_iterator to the first element in the mapped_view.
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return begin();
|
||||
}
|
||||
|
||||
/// Returns an iterator to one past the last element in the mapped_view.
|
||||
iterator end()
|
||||
{
|
||||
return ::boost::compute::make_buffer_iterator<T>(m_buffer, size());
|
||||
}
|
||||
|
||||
/// Returns a const_iterator to one past the last element in the mapped_view.
|
||||
const_iterator end() const
|
||||
{
|
||||
return ::boost::compute::make_buffer_iterator<T>(m_buffer, size());
|
||||
}
|
||||
|
||||
/// Returns a const_iterator to one past the last element in the mapped_view.
|
||||
const_iterator cend() const
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
/// Returns the number of elements in the mapped_view.
|
||||
size_type size() const
|
||||
{
|
||||
return m_buffer.size() / sizeof(T);
|
||||
}
|
||||
|
||||
/// Returns the host data pointer.
|
||||
T* get_host_ptr()
|
||||
{
|
||||
return static_cast<T *>(m_buffer.get_info<void *>(CL_MEM_HOST_PTR));
|
||||
}
|
||||
|
||||
/// Returns the host data pointer.
|
||||
const T* get_host_ptr() const
|
||||
{
|
||||
return static_cast<T *>(m_buffer.get_info<void *>(CL_MEM_HOST_PTR));
|
||||
}
|
||||
|
||||
/// Resizes the mapped_view to \p size elements.
|
||||
void resize(size_type size)
|
||||
{
|
||||
T *old_ptr = get_host_ptr();
|
||||
|
||||
m_buffer = _make_mapped_buffer(old_ptr, size, m_buffer.get_context());
|
||||
}
|
||||
|
||||
/// Returns \c true if the mapped_view is empty.
|
||||
bool empty() const
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/// Returns the mapped buffer.
|
||||
const buffer& get_buffer() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
/// Maps the buffer into the host address space.
|
||||
///
|
||||
/// \see_opencl_ref{clEnqueueMapBuffer}
|
||||
void map(cl_map_flags flags, command_queue &queue)
|
||||
{
|
||||
BOOST_ASSERT(m_mapped_ptr == 0);
|
||||
|
||||
m_mapped_ptr = queue.enqueue_map_buffer(
|
||||
m_buffer, flags, 0, m_buffer.size()
|
||||
);
|
||||
}
|
||||
|
||||
/// Maps the buffer into the host address space for reading and writing.
|
||||
///
|
||||
/// Equivalent to:
|
||||
/// \code
|
||||
/// map(CL_MAP_READ | CL_MAP_WRITE, queue);
|
||||
/// \endcode
|
||||
void map(command_queue &queue)
|
||||
{
|
||||
map(CL_MAP_READ | CL_MAP_WRITE, queue);
|
||||
}
|
||||
|
||||
/// Unmaps the buffer from the host address space.
|
||||
///
|
||||
/// \see_opencl_ref{clEnqueueUnmapMemObject}
|
||||
void unmap(command_queue &queue)
|
||||
{
|
||||
BOOST_ASSERT(m_mapped_ptr != 0);
|
||||
|
||||
queue.enqueue_unmap_buffer(m_buffer, m_mapped_ptr);
|
||||
|
||||
m_mapped_ptr = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
/// \internal_
|
||||
static buffer _make_mapped_buffer(T *host_ptr,
|
||||
size_t n,
|
||||
const context &context)
|
||||
{
|
||||
return buffer(
|
||||
context,
|
||||
n * sizeof(T),
|
||||
buffer::read_write | buffer::use_host_ptr,
|
||||
host_ptr
|
||||
);
|
||||
}
|
||||
|
||||
/// \internal_
|
||||
static buffer _make_mapped_buffer(const T *host_ptr,
|
||||
size_t n,
|
||||
const context &context)
|
||||
{
|
||||
return buffer(
|
||||
context,
|
||||
n * sizeof(T),
|
||||
buffer::read_only | buffer::use_host_ptr,
|
||||
const_cast<void *>(static_cast<const void *>(host_ptr))
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
buffer m_buffer;
|
||||
void *m_mapped_ptr;
|
||||
};
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_CONTAINER_MAPPED_VIEW_HPP
|
||||
@@ -0,0 +1,81 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_CONTAINER_STACK_HPP
|
||||
#define BOOST_COMPUTE_CONTAINER_STACK_HPP
|
||||
|
||||
#include <boost/compute/container/vector.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
template<class T>
|
||||
class stack
|
||||
{
|
||||
public:
|
||||
typedef vector<T> container_type;
|
||||
typedef typename container_type::size_type size_type;
|
||||
typedef typename container_type::value_type value_type;
|
||||
|
||||
stack()
|
||||
{
|
||||
}
|
||||
|
||||
stack(const stack<T> &other)
|
||||
: m_vector(other.m_vector)
|
||||
{
|
||||
}
|
||||
|
||||
stack<T>& operator=(const stack<T> &other)
|
||||
{
|
||||
if(this != &other){
|
||||
m_vector = other.m_vector;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~stack()
|
||||
{
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_vector.empty();
|
||||
}
|
||||
|
||||
size_type size() const
|
||||
{
|
||||
return m_vector.size();
|
||||
}
|
||||
|
||||
value_type top() const
|
||||
{
|
||||
return m_vector.back();
|
||||
}
|
||||
|
||||
void push(const T &value)
|
||||
{
|
||||
m_vector.push_back(value);
|
||||
}
|
||||
|
||||
void pop()
|
||||
{
|
||||
m_vector.pop_back();
|
||||
}
|
||||
|
||||
private:
|
||||
container_type m_vector;
|
||||
};
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_CONTAINER_STACK_HPP
|
||||
@@ -0,0 +1,25 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_CONTAINER_STRING_HPP
|
||||
#define BOOST_COMPUTE_CONTAINER_STRING_HPP
|
||||
|
||||
#include <boost/compute/types/fundamental.hpp>
|
||||
#include <boost/compute/container/basic_string.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
typedef basic_string<char_> string;
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_CONTAINER_STRING_HPP
|
||||
@@ -0,0 +1,499 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_CONTAINER_VALARRAY_HPP
|
||||
#define BOOST_COMPUTE_CONTAINER_VALARRAY_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <valarray>
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
#include <boost/compute/buffer.hpp>
|
||||
#include <boost/compute/algorithm/copy.hpp>
|
||||
#include <boost/compute/algorithm/fill.hpp>
|
||||
#include <boost/compute/algorithm/max_element.hpp>
|
||||
#include <boost/compute/algorithm/min_element.hpp>
|
||||
#include <boost/compute/algorithm/transform.hpp>
|
||||
#include <boost/compute/algorithm/accumulate.hpp>
|
||||
#include <boost/compute/detail/buffer_value.hpp>
|
||||
#include <boost/compute/functional.hpp>
|
||||
#include <boost/compute/functional/bind.hpp>
|
||||
#include <boost/compute/iterator/buffer_iterator.hpp>
|
||||
#include <boost/compute/type_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
template<class T>
|
||||
class valarray
|
||||
{
|
||||
public:
|
||||
explicit valarray(const context &context = system::default_context())
|
||||
: m_buffer(context, 0)
|
||||
{
|
||||
}
|
||||
|
||||
explicit valarray(size_t size,
|
||||
const context &context = system::default_context())
|
||||
: m_buffer(context, size * sizeof(T))
|
||||
{
|
||||
}
|
||||
|
||||
valarray(const T &value,
|
||||
size_t size,
|
||||
const context &context = system::default_context())
|
||||
: m_buffer(context, size * sizeof(T))
|
||||
{
|
||||
fill(begin(), end(), value);
|
||||
}
|
||||
|
||||
valarray(const T *values,
|
||||
size_t size,
|
||||
const context &context = system::default_context())
|
||||
: m_buffer(context, size * sizeof(T))
|
||||
{
|
||||
copy(values, values + size, begin());
|
||||
}
|
||||
|
||||
valarray(const valarray<T> &other)
|
||||
: m_buffer(other.m_buffer.get_context(), other.size() * sizeof(T))
|
||||
{
|
||||
}
|
||||
|
||||
valarray(const std::valarray<T> &valarray,
|
||||
const context &context = system::default_context())
|
||||
: m_buffer(context, valarray.size() * sizeof(T))
|
||||
{
|
||||
copy(&valarray[0], &valarray[valarray.size()], begin());
|
||||
}
|
||||
|
||||
valarray<T>& operator=(const valarray<T> &other)
|
||||
{
|
||||
if(this != &other){
|
||||
// change to other's OpenCL context
|
||||
m_buffer = buffer(other.m_buffer.get_context(), other.size() * sizeof(T));
|
||||
copy(other.begin(), other.end(), begin());
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
valarray<T>& operator=(const std::valarray<T> &valarray)
|
||||
{
|
||||
m_buffer = buffer(m_buffer.get_context(), valarray.size() * sizeof(T));
|
||||
copy(&valarray[0], &valarray[valarray.size()], begin());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
valarray<T>& operator*=(const T&);
|
||||
|
||||
valarray<T>& operator/=(const T&);
|
||||
|
||||
valarray<T>& operator%=(const T& val);
|
||||
|
||||
valarray<T> operator+() const
|
||||
{
|
||||
// This operator can be used with any type.
|
||||
valarray<T> result(size());
|
||||
copy(begin(), end(), result.begin());
|
||||
return result;
|
||||
}
|
||||
|
||||
valarray<T> operator-() const
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
is_fundamental<T>::value,
|
||||
"This operator can be used with all OpenCL built-in scalar"
|
||||
" and vector types"
|
||||
);
|
||||
valarray<T> result(size());
|
||||
BOOST_COMPUTE_FUNCTION(T, unary_minus, (T x),
|
||||
{
|
||||
return -x;
|
||||
});
|
||||
transform(begin(), end(), result.begin(), unary_minus);
|
||||
return result;
|
||||
}
|
||||
|
||||
valarray<T> operator~() const
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
is_fundamental<T>::value &&
|
||||
!is_floating_point<typename scalar_type<T>::type>::value,
|
||||
"This operator can be used with all OpenCL built-in scalar"
|
||||
" and vector types except the built-in scalar and vector float types"
|
||||
);
|
||||
valarray<T> result(size());
|
||||
BOOST_COMPUTE_FUNCTION(T, bitwise_not, (T x),
|
||||
{
|
||||
return ~x;
|
||||
});
|
||||
transform(begin(), end(), result.begin(), bitwise_not);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// In OpenCL there cannot be memory buffer with bool type, for
|
||||
/// this reason return type is valarray<char> instead of valarray<bool>.
|
||||
/// 1 means true, 0 means false.
|
||||
valarray<char> operator!() const
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
is_fundamental<T>::value,
|
||||
"This operator can be used with all OpenCL built-in scalar"
|
||||
" and vector types"
|
||||
);
|
||||
valarray<char> result(size());
|
||||
BOOST_COMPUTE_FUNCTION(char, logical_not, (T x),
|
||||
{
|
||||
return !x;
|
||||
});
|
||||
transform(begin(), end(), &result[0], logical_not);
|
||||
return result;
|
||||
}
|
||||
|
||||
valarray<T>& operator+=(const T&);
|
||||
|
||||
valarray<T>& operator-=(const T&);
|
||||
|
||||
valarray<T>& operator^=(const T&);
|
||||
|
||||
valarray<T>& operator&=(const T&);
|
||||
|
||||
valarray<T>& operator|=(const T&);
|
||||
|
||||
valarray<T>& operator<<=(const T&);
|
||||
|
||||
valarray<T>& operator>>=(const T&);
|
||||
|
||||
valarray<T>& operator*=(const valarray<T>&);
|
||||
|
||||
valarray<T>& operator/=(const valarray<T>&);
|
||||
|
||||
valarray<T>& operator%=(const valarray<T>&);
|
||||
|
||||
valarray<T>& operator+=(const valarray<T>&);
|
||||
|
||||
valarray<T>& operator-=(const valarray<T>&);
|
||||
|
||||
valarray<T>& operator^=(const valarray<T>&);
|
||||
|
||||
valarray<T>& operator&=(const valarray<T>&);
|
||||
|
||||
valarray<T>& operator|=(const valarray<T>&);
|
||||
|
||||
valarray<T>& operator<<=(const valarray<T>&);
|
||||
|
||||
valarray<T>& operator>>=(const valarray<T>&);
|
||||
|
||||
~valarray()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return m_buffer.size() / sizeof(T);
|
||||
}
|
||||
|
||||
void resize(size_t size, T value = T())
|
||||
{
|
||||
m_buffer = buffer(m_buffer.get_context(), size * sizeof(T));
|
||||
fill(begin(), end(), value);
|
||||
}
|
||||
|
||||
detail::buffer_value<T> operator[](size_t index)
|
||||
{
|
||||
return *(begin() + static_cast<ptrdiff_t>(index));
|
||||
}
|
||||
|
||||
const detail::buffer_value<T> operator[](size_t index) const
|
||||
{
|
||||
return *(begin() + static_cast<ptrdiff_t>(index));
|
||||
}
|
||||
|
||||
T (min)() const
|
||||
{
|
||||
return *(boost::compute::min_element(begin(), end()));
|
||||
}
|
||||
|
||||
T (max)() const
|
||||
{
|
||||
return *(boost::compute::max_element(begin(), end()));
|
||||
}
|
||||
|
||||
T sum() const
|
||||
{
|
||||
return boost::compute::accumulate(begin(), end(), T(0));
|
||||
}
|
||||
|
||||
template<class UnaryFunction>
|
||||
valarray<T> apply(UnaryFunction function) const
|
||||
{
|
||||
valarray<T> result(size());
|
||||
transform(begin(), end(), result.begin(), function);
|
||||
return result;
|
||||
}
|
||||
|
||||
const buffer& get_buffer() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
buffer_iterator<T> begin() const
|
||||
{
|
||||
return buffer_iterator<T>(m_buffer, 0);
|
||||
}
|
||||
|
||||
buffer_iterator<T> end() const
|
||||
{
|
||||
return buffer_iterator<T>(m_buffer, size());
|
||||
}
|
||||
|
||||
private:
|
||||
buffer m_buffer;
|
||||
};
|
||||
|
||||
/// \internal_
|
||||
#define BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(op, op_name, assert) \
|
||||
template<class T> \
|
||||
inline valarray<T>& \
|
||||
valarray<T>::operator op##=(const T& val) \
|
||||
{ \
|
||||
assert \
|
||||
transform(begin(), end(), begin(), \
|
||||
::boost::compute::bind(op_name<T>(), placeholders::_1, val)); \
|
||||
return *this; \
|
||||
} \
|
||||
\
|
||||
template<class T> \
|
||||
inline valarray<T>& \
|
||||
valarray<T>::operator op##=(const valarray<T> &rhs) \
|
||||
{ \
|
||||
assert \
|
||||
transform(begin(), end(), rhs.begin(), begin(), op_name<T>()); \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
/// \internal_
|
||||
#define BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(op, op_name) \
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(op, op_name, \
|
||||
BOOST_STATIC_ASSERT_MSG( \
|
||||
is_fundamental<T>::value, \
|
||||
"This operator can be used with all OpenCL built-in scalar" \
|
||||
" and vector types" \
|
||||
); \
|
||||
)
|
||||
|
||||
/// \internal_
|
||||
/// For some operators class T can't be floating point type.
|
||||
/// See OpenCL specification, operators chapter.
|
||||
#define BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(op, op_name) \
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(op, op_name, \
|
||||
BOOST_STATIC_ASSERT_MSG( \
|
||||
is_fundamental<T>::value && \
|
||||
!is_floating_point<typename scalar_type<T>::type>::value, \
|
||||
"This operator can be used with all OpenCL built-in scalar" \
|
||||
" and vector types except the built-in scalar and vector float types" \
|
||||
); \
|
||||
)
|
||||
|
||||
// defining operators
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(+, plus)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(-, minus)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(*, multiplies)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(/, divides)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(^, bit_xor)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(&, bit_and)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(|, bit_or)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(<<, shift_left)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(>>, shift_right)
|
||||
|
||||
// The remainder (%) operates on
|
||||
// integer scalar and integer vector data types only.
|
||||
// See OpenCL specification.
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(%, modulus,
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
is_integral<typename scalar_type<T>::type>::value,
|
||||
"This operator can be used only with OpenCL built-in integer types"
|
||||
);
|
||||
)
|
||||
|
||||
#undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY
|
||||
#undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP
|
||||
|
||||
#undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT
|
||||
|
||||
/// \internal_
|
||||
/// Macro for defining binary operators for valarray
|
||||
#define BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR(op, op_name, assert) \
|
||||
template<class T> \
|
||||
valarray<T> operator op (const valarray<T>& lhs, const valarray<T>& rhs) \
|
||||
{ \
|
||||
assert \
|
||||
valarray<T> result(lhs.size()); \
|
||||
transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
|
||||
buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
|
||||
buffer_iterator<T>(rhs.get_buffer(), 0), \
|
||||
buffer_iterator<T>(result.get_buffer(), 0), \
|
||||
op_name<T>()); \
|
||||
return result; \
|
||||
} \
|
||||
\
|
||||
template<class T> \
|
||||
valarray<T> operator op (const T& val, const valarray<T>& rhs) \
|
||||
{ \
|
||||
assert \
|
||||
valarray<T> result(rhs.size()); \
|
||||
transform(buffer_iterator<T>(rhs.get_buffer(), 0), \
|
||||
buffer_iterator<T>(rhs.get_buffer(), rhs.size()), \
|
||||
buffer_iterator<T>(result.get_buffer(), 0), \
|
||||
::boost::compute::bind(op_name<T>(), val, placeholders::_1)); \
|
||||
return result; \
|
||||
} \
|
||||
\
|
||||
template<class T> \
|
||||
valarray<T> operator op (const valarray<T>& lhs, const T& val) \
|
||||
{ \
|
||||
assert \
|
||||
valarray<T> result(lhs.size()); \
|
||||
transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
|
||||
buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
|
||||
buffer_iterator<T>(result.get_buffer(), 0), \
|
||||
::boost::compute::bind(op_name<T>(), placeholders::_1, val)); \
|
||||
return result; \
|
||||
}
|
||||
|
||||
/// \internal_
|
||||
#define BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(op, op_name) \
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR(op, op_name, \
|
||||
BOOST_STATIC_ASSERT_MSG( \
|
||||
is_fundamental<T>::value, \
|
||||
"This operator can be used with all OpenCL built-in scalar" \
|
||||
" and vector types" \
|
||||
); \
|
||||
)
|
||||
|
||||
/// \internal_
|
||||
/// For some operators class T can't be floating point type.
|
||||
/// See OpenCL specification, operators chapter.
|
||||
#define BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(op, op_name) \
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR(op, op_name, \
|
||||
BOOST_STATIC_ASSERT_MSG( \
|
||||
is_fundamental<T>::value && \
|
||||
!is_floating_point<typename scalar_type<T>::type>::value, \
|
||||
"This operator can be used with all OpenCL built-in scalar" \
|
||||
" and vector types except the built-in scalar and vector float types" \
|
||||
); \
|
||||
)
|
||||
|
||||
// defining binary operators for valarray
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(+, plus)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(-, minus)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(*, multiplies)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(/, divides)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(^, bit_xor)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(&, bit_and)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(|, bit_or)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(<<, shift_left)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(>>, shift_right)
|
||||
|
||||
#undef BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY
|
||||
#undef BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP
|
||||
|
||||
#undef BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR
|
||||
|
||||
/// \internal_
|
||||
/// Macro for defining valarray comparison operators.
|
||||
/// For return type valarray<char> is used instead of valarray<bool> because
|
||||
/// in OpenCL there cannot be memory buffer with bool type.
|
||||
///
|
||||
/// Note it's also used for defining binary logical operators (==, &&)
|
||||
#define BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(op, op_name) \
|
||||
template<class T> \
|
||||
valarray<char> operator op (const valarray<T>& lhs, const valarray<T>& rhs) \
|
||||
{ \
|
||||
BOOST_STATIC_ASSERT_MSG( \
|
||||
is_fundamental<T>::value, \
|
||||
"This operator can be used with all OpenCL built-in scalar" \
|
||||
" and vector types" \
|
||||
); \
|
||||
valarray<char> result(lhs.size()); \
|
||||
transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
|
||||
buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
|
||||
buffer_iterator<T>(rhs.get_buffer(), 0), \
|
||||
buffer_iterator<char>(result.get_buffer(), 0), \
|
||||
op_name<T>()); \
|
||||
return result; \
|
||||
} \
|
||||
\
|
||||
template<class T> \
|
||||
valarray<char> operator op (const T& val, const valarray<T>& rhs) \
|
||||
{ \
|
||||
BOOST_STATIC_ASSERT_MSG( \
|
||||
is_fundamental<T>::value, \
|
||||
"This operator can be used with all OpenCL built-in scalar" \
|
||||
" and vector types" \
|
||||
); \
|
||||
valarray<char> result(rhs.size()); \
|
||||
transform(buffer_iterator<T>(rhs.get_buffer(), 0), \
|
||||
buffer_iterator<T>(rhs.get_buffer(), rhs.size()), \
|
||||
buffer_iterator<char>(result.get_buffer(), 0), \
|
||||
::boost::compute::bind(op_name<T>(), val, placeholders::_1)); \
|
||||
return result; \
|
||||
} \
|
||||
\
|
||||
template<class T> \
|
||||
valarray<char> operator op (const valarray<T>& lhs, const T& val) \
|
||||
{ \
|
||||
BOOST_STATIC_ASSERT_MSG( \
|
||||
is_fundamental<T>::value, \
|
||||
"This operator can be used with all OpenCL built-in scalar" \
|
||||
" and vector types" \
|
||||
); \
|
||||
valarray<char> result(lhs.size()); \
|
||||
transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
|
||||
buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
|
||||
buffer_iterator<char>(result.get_buffer(), 0), \
|
||||
::boost::compute::bind(op_name<T>(), placeholders::_1, val)); \
|
||||
return result; \
|
||||
}
|
||||
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(==, equal_to)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(!=, not_equal_to)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(>, greater)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(<, less)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(>=, greater_equal)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(<=, less_equal)
|
||||
|
||||
/// \internal_
|
||||
/// Macro for defining binary logical operators for valarray.
|
||||
///
|
||||
/// For return type valarray<char> is used instead of valarray<bool> because
|
||||
/// in OpenCL there cannot be memory buffer with bool type.
|
||||
/// 1 means true, 0 means false.
|
||||
#define BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR(op, op_name) \
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(op, op_name)
|
||||
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR(&&, logical_and)
|
||||
BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR(||, logical_or)
|
||||
|
||||
#undef BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR
|
||||
|
||||
#undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR
|
||||
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_CONTAINER_VALARRAY_HPP
|
||||
@@ -0,0 +1,779 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// See http://boostorg.github.com/compute for more information.
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef BOOST_COMPUTE_CONTAINER_VECTOR_HPP
|
||||
#define BOOST_COMPUTE_CONTAINER_VECTOR_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <exception>
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <boost/compute/config.hpp>
|
||||
|
||||
#ifndef BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
|
||||
#include <initializer_list>
|
||||
#endif
|
||||
|
||||
#include <boost/compute/buffer.hpp>
|
||||
#include <boost/compute/device.hpp>
|
||||
#include <boost/compute/system.hpp>
|
||||
#include <boost/compute/context.hpp>
|
||||
#include <boost/compute/command_queue.hpp>
|
||||
#include <boost/compute/algorithm/copy.hpp>
|
||||
#include <boost/compute/algorithm/copy_n.hpp>
|
||||
#include <boost/compute/algorithm/fill_n.hpp>
|
||||
#include <boost/compute/allocator/buffer_allocator.hpp>
|
||||
#include <boost/compute/iterator/buffer_iterator.hpp>
|
||||
#include <boost/compute/type_traits/detail/capture_traits.hpp>
|
||||
#include <boost/compute/detail/buffer_value.hpp>
|
||||
#include <boost/compute/detail/iterator_range_size.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace compute {
|
||||
|
||||
/// \class vector
|
||||
/// \brief A resizable array of values.
|
||||
///
|
||||
/// The vector<T> class stores a dynamic array of values. Internally, the data
|
||||
/// is stored in an OpenCL buffer object.
|
||||
///
|
||||
/// The vector class is the prefered container for storing and accessing data
|
||||
/// on a compute device. In most cases it should be used instead of directly
|
||||
/// dealing with buffer objects. If the undelying buffer is needed, it can be
|
||||
/// accessed with the get_buffer() method.
|
||||
///
|
||||
/// The internal storage is allocated in a specific OpenCL context which is
|
||||
/// passed as an argument to the constructor when the vector is created.
|
||||
///
|
||||
/// For example, to create a vector on the device containing space for ten
|
||||
/// \c int values:
|
||||
/// \code
|
||||
/// boost::compute::vector<int> vec(10, context);
|
||||
/// \endcode
|
||||
///
|
||||
/// Allocation and data transfer can also be performed in a single step:
|
||||
/// \code
|
||||
/// // values on the host
|
||||
/// int data[] = { 1, 2, 3, 4 };
|
||||
///
|
||||
/// // create a vector of size four and copy the values from data
|
||||
/// boost::compute::vector<int> vec(data, data + 4, queue);
|
||||
/// \endcode
|
||||
///
|
||||
/// The Boost.Compute \c vector class provides a STL-like API and is modeled
|
||||
/// after the \c std::vector class from the C++ standard library. It can be
|
||||
/// used with any of the STL-like algorithms provided by Boost.Compute
|
||||
/// including \c copy(), \c transform(), and \c sort() (among many others).
|
||||
///
|
||||
/// For example:
|
||||
/// \code
|
||||
/// // a vector on a compute device
|
||||
/// boost::compute::vector<float> vec = ...
|
||||
///
|
||||
/// // copy data to the vector from a host std:vector
|
||||
/// boost::compute::copy(host_vec.begin(), host_vec.end(), vec.begin(), queue);
|
||||
///
|
||||
/// // copy data from the vector to a host std::vector
|
||||
/// boost::compute::copy(vec.begin(), vec.end(), host_vec.begin(), queue);
|
||||
///
|
||||
/// // sort the values in the vector
|
||||
/// boost::compute::sort(vec.begin(), vec.end(), queue);
|
||||
///
|
||||
/// // calculate the sum of the values in the vector (also see reduce())
|
||||
/// float sum = boost::compute::accumulate(vec.begin(), vec.end(), 0, queue);
|
||||
///
|
||||
/// // reverse the values in the vector
|
||||
/// boost::compute::reverse(vec.begin(), vec.end(), queue);
|
||||
///
|
||||
/// // fill the vector with ones
|
||||
/// boost::compute::fill(vec.begin(), vec.end(), 1, queue);
|
||||
/// \endcode
|
||||
///
|
||||
/// \see \ref array "array<T, N>", buffer
|
||||
template<class T, class Alloc = buffer_allocator<T> >
|
||||
class vector
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef Alloc allocator_type;
|
||||
typedef typename allocator_type::size_type size_type;
|
||||
typedef typename allocator_type::difference_type difference_type;
|
||||
typedef detail::buffer_value<T> reference;
|
||||
typedef const detail::buffer_value<T> const_reference;
|
||||
typedef typename allocator_type::pointer pointer;
|
||||
typedef typename allocator_type::const_pointer const_pointer;
|
||||
typedef buffer_iterator<T> iterator;
|
||||
typedef buffer_iterator<T> const_iterator;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
/// Creates an empty vector in \p context.
|
||||
explicit vector(const context &context = system::default_context())
|
||||
: m_size(0),
|
||||
m_allocator(context)
|
||||
{
|
||||
m_data = m_allocator.allocate(_minimum_capacity());
|
||||
}
|
||||
|
||||
/// Creates a vector with space for \p count elements in \p context.
|
||||
///
|
||||
/// Note that unlike \c std::vector's constructor, this will not initialize
|
||||
/// the values in the container. Either call the vector constructor which
|
||||
/// takes a value to initialize with or use the fill() algorithm to set
|
||||
/// the initial values.
|
||||
///
|
||||
/// For example:
|
||||
/// \code
|
||||
/// // create a vector on the device with space for ten ints
|
||||
/// boost::compute::vector<int> vec(10, context);
|
||||
/// \endcode
|
||||
explicit vector(size_type count,
|
||||
const context &context = system::default_context())
|
||||
: m_size(count),
|
||||
m_allocator(context)
|
||||
{
|
||||
m_data = m_allocator.allocate((std::max)(count, _minimum_capacity()));
|
||||
}
|
||||
|
||||
/// Creates a vector with space for \p count elements and sets each equal
|
||||
/// to \p value.
|
||||
///
|
||||
/// For example:
|
||||
/// \code
|
||||
/// // creates a vector with four values set to nine (e.g. [9, 9, 9, 9]).
|
||||
/// boost::compute::vector<int> vec(4, 9, queue);
|
||||
/// \endcode
|
||||
vector(size_type count,
|
||||
const T &value,
|
||||
command_queue &queue = system::default_queue())
|
||||
: m_size(count),
|
||||
m_allocator(queue.get_context())
|
||||
{
|
||||
m_data = m_allocator.allocate((std::max)(count, _minimum_capacity()));
|
||||
|
||||
::boost::compute::fill_n(begin(), count, value, queue);
|
||||
}
|
||||
|
||||
/// Creates a vector with space for the values in the range [\p first,
|
||||
/// \p last) and copies them into the vector with \p queue.
|
||||
///
|
||||
/// For example:
|
||||
/// \code
|
||||
/// // values on the host
|
||||
/// int data[] = { 1, 2, 3, 4 };
|
||||
///
|
||||
/// // create a vector of size four and copy the values from data
|
||||
/// boost::compute::vector<int> vec(data, data + 4, queue);
|
||||
/// \endcode
|
||||
template<class InputIterator>
|
||||
vector(InputIterator first,
|
||||
InputIterator last,
|
||||
command_queue &queue = system::default_queue())
|
||||
: m_size(detail::iterator_range_size(first, last)),
|
||||
m_allocator(queue.get_context())
|
||||
{
|
||||
m_data = m_allocator.allocate((std::max)(m_size, _minimum_capacity()));
|
||||
|
||||
::boost::compute::copy(first, last, begin(), queue);
|
||||
}
|
||||
|
||||
/// Creates a new vector and copies the values from \p other.
|
||||
vector(const vector &other,
|
||||
command_queue &queue = system::default_queue())
|
||||
: m_size(other.m_size),
|
||||
m_allocator(other.m_allocator)
|
||||
{
|
||||
m_data = m_allocator.allocate((std::max)(m_size, _minimum_capacity()));
|
||||
|
||||
if(!other.empty()){
|
||||
if(other.get_buffer().get_context() != queue.get_context()){
|
||||
command_queue other_queue = other.default_queue();
|
||||
::boost::compute::copy(other.begin(), other.end(), begin(), other_queue);
|
||||
other_queue.finish();
|
||||
}
|
||||
else {
|
||||
::boost::compute::copy(other.begin(), other.end(), begin(), queue);
|
||||
queue.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new vector and copies the values from \p other.
|
||||
template<class OtherAlloc>
|
||||
vector(const vector<T, OtherAlloc> &other,
|
||||
command_queue &queue = system::default_queue())
|
||||
: m_size(other.size()),
|
||||
m_allocator(queue.get_context())
|
||||
{
|
||||
m_data = m_allocator.allocate((std::max)(m_size, _minimum_capacity()));
|
||||
|
||||
if(!other.empty()){
|
||||
::boost::compute::copy(other.begin(), other.end(), begin(), queue);
|
||||
queue.finish();
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new vector and copies the values from \p vector.
|
||||
template<class OtherAlloc>
|
||||
vector(const std::vector<T, OtherAlloc> &vector,
|
||||
command_queue &queue = system::default_queue())
|
||||
: m_size(vector.size()),
|
||||
m_allocator(queue.get_context())
|
||||
{
|
||||
m_data = m_allocator.allocate((std::max)(m_size, _minimum_capacity()));
|
||||
|
||||
::boost::compute::copy(vector.begin(), vector.end(), begin(), queue);
|
||||
}
|
||||
|
||||
#ifndef BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
|
||||
vector(std::initializer_list<T> list,
|
||||
command_queue &queue = system::default_queue())
|
||||
: m_size(list.size()),
|
||||
m_allocator(queue.get_context())
|
||||
{
|
||||
m_data = m_allocator.allocate((std::max)(m_size, _minimum_capacity()));
|
||||
|
||||
::boost::compute::copy(list.begin(), list.end(), begin(), queue);
|
||||
}
|
||||
#endif // BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
|
||||
|
||||
vector& operator=(const vector &other)
|
||||
{
|
||||
if(this != &other){
|
||||
command_queue queue = default_queue();
|
||||
resize(other.size(), queue);
|
||||
::boost::compute::copy(other.begin(), other.end(), begin(), queue);
|
||||
queue.finish();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class OtherAlloc>
|
||||
vector& operator=(const vector<T, OtherAlloc> &other)
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
resize(other.size(), queue);
|
||||
::boost::compute::copy(other.begin(), other.end(), begin(), queue);
|
||||
queue.finish();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class OtherAlloc>
|
||||
vector& operator=(const std::vector<T, OtherAlloc> &vector)
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
resize(vector.size(), queue);
|
||||
::boost::compute::copy(vector.begin(), vector.end(), begin(), queue);
|
||||
queue.finish();
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
|
||||
/// Move-constructs a new vector from \p other.
|
||||
vector(vector&& other)
|
||||
: m_data(std::move(other.m_data)),
|
||||
m_size(other.m_size),
|
||||
m_allocator(std::move(other.m_allocator))
|
||||
{
|
||||
other.m_size = 0;
|
||||
}
|
||||
|
||||
/// Move-assigns the data from \p other to \c *this.
|
||||
vector& operator=(vector&& other)
|
||||
{
|
||||
if(m_size){
|
||||
m_allocator.deallocate(m_data, m_size);
|
||||
}
|
||||
|
||||
m_data = std::move(other.m_data);
|
||||
m_size = other.m_size;
|
||||
m_allocator = std::move(other.m_allocator);
|
||||
|
||||
other.m_size = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
|
||||
|
||||
/// Destroys the vector object.
|
||||
~vector()
|
||||
{
|
||||
if(m_size){
|
||||
m_allocator.deallocate(m_data, m_size);
|
||||
}
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return ::boost::compute::make_buffer_iterator<T>(m_data.get_buffer(), 0);
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return ::boost::compute::make_buffer_iterator<T>(m_data.get_buffer(), 0);
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return begin();
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return ::boost::compute::make_buffer_iterator<T>(m_data.get_buffer(), m_size);
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return ::boost::compute::make_buffer_iterator<T>(m_data.get_buffer(), m_size);
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
reverse_iterator rbegin()
|
||||
{
|
||||
return reverse_iterator(end() - 1);
|
||||
}
|
||||
|
||||
const_reverse_iterator rbegin() const
|
||||
{
|
||||
return reverse_iterator(end() - 1);
|
||||
}
|
||||
|
||||
const_reverse_iterator crbegin() const
|
||||
{
|
||||
return rbegin();
|
||||
}
|
||||
|
||||
reverse_iterator rend()
|
||||
{
|
||||
return reverse_iterator(begin() - 1);
|
||||
}
|
||||
|
||||
const_reverse_iterator rend() const
|
||||
{
|
||||
return reverse_iterator(begin() - 1);
|
||||
}
|
||||
|
||||
const_reverse_iterator crend() const
|
||||
{
|
||||
return rend();
|
||||
}
|
||||
|
||||
/// Returns the number of elements in the vector.
|
||||
size_type size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return m_allocator.max_size();
|
||||
}
|
||||
|
||||
/// Resizes the vector to \p size.
|
||||
void resize(size_type size, command_queue &queue)
|
||||
{
|
||||
if(size <= capacity()){
|
||||
m_size = size;
|
||||
}
|
||||
else {
|
||||
// allocate new buffer
|
||||
pointer new_data =
|
||||
m_allocator.allocate(
|
||||
static_cast<size_type>(
|
||||
static_cast<float>(size) * _growth_factor()
|
||||
)
|
||||
);
|
||||
|
||||
// copy old values to the new buffer
|
||||
::boost::compute::copy(m_data, m_data + m_size, new_data, queue);
|
||||
|
||||
// free old memory
|
||||
m_allocator.deallocate(m_data, m_size);
|
||||
|
||||
// set new data and size
|
||||
m_data = new_data;
|
||||
m_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
/// \overload
|
||||
void resize(size_type size)
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
resize(size, queue);
|
||||
queue.finish();
|
||||
}
|
||||
|
||||
/// Returns \c true if the vector is empty.
|
||||
bool empty() const
|
||||
{
|
||||
return m_size == 0;
|
||||
}
|
||||
|
||||
/// Returns the capacity of the vector.
|
||||
size_type capacity() const
|
||||
{
|
||||
return m_data.get_buffer().size() / sizeof(T);
|
||||
}
|
||||
|
||||
void reserve(size_type size, command_queue &queue)
|
||||
{
|
||||
(void) size;
|
||||
(void) queue;
|
||||
}
|
||||
|
||||
void reserve(size_type size)
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
reserve(size, queue);
|
||||
queue.finish();
|
||||
}
|
||||
|
||||
void shrink_to_fit(command_queue &queue)
|
||||
{
|
||||
(void) queue;
|
||||
}
|
||||
|
||||
void shrink_to_fit()
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
shrink_to_fit(queue);
|
||||
queue.finish();
|
||||
}
|
||||
|
||||
reference operator[](size_type index)
|
||||
{
|
||||
return *(begin() + static_cast<difference_type>(index));
|
||||
}
|
||||
|
||||
const_reference operator[](size_type index) const
|
||||
{
|
||||
return *(begin() + static_cast<difference_type>(index));
|
||||
}
|
||||
|
||||
reference at(size_type index)
|
||||
{
|
||||
if(index >= size()){
|
||||
BOOST_THROW_EXCEPTION(std::out_of_range("index out of range"));
|
||||
}
|
||||
|
||||
return operator[](index);
|
||||
}
|
||||
|
||||
const_reference at(size_type index) const
|
||||
{
|
||||
if(index >= size()){
|
||||
BOOST_THROW_EXCEPTION(std::out_of_range("index out of range"));
|
||||
}
|
||||
|
||||
return operator[](index);
|
||||
}
|
||||
|
||||
reference front()
|
||||
{
|
||||
return *begin();
|
||||
}
|
||||
|
||||
const_reference front() const
|
||||
{
|
||||
return *begin();
|
||||
}
|
||||
|
||||
reference back()
|
||||
{
|
||||
return *(end() - static_cast<difference_type>(1));
|
||||
}
|
||||
|
||||
const_reference back() const
|
||||
{
|
||||
return *(end() - static_cast<difference_type>(1));
|
||||
}
|
||||
|
||||
template<class InputIterator>
|
||||
void assign(InputIterator first,
|
||||
InputIterator last,
|
||||
command_queue &queue)
|
||||
{
|
||||
// resize vector for new contents
|
||||
resize(detail::iterator_range_size(first, last), queue);
|
||||
|
||||
// copy values into the vector
|
||||
::boost::compute::copy(first, last, begin(), queue);
|
||||
}
|
||||
|
||||
template<class InputIterator>
|
||||
void assign(InputIterator first, InputIterator last)
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
assign(first, last, queue);
|
||||
queue.finish();
|
||||
}
|
||||
|
||||
void assign(size_type n, const T &value, command_queue &queue)
|
||||
{
|
||||
// resize vector for new contents
|
||||
resize(n, queue);
|
||||
|
||||
// fill vector with value
|
||||
::boost::compute::fill_n(begin(), n, value, queue);
|
||||
}
|
||||
|
||||
void assign(size_type n, const T &value)
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
assign(n, value, queue);
|
||||
queue.finish();
|
||||
}
|
||||
|
||||
/// Inserts \p value at the end of the vector (resizing if neccessary).
|
||||
///
|
||||
/// Note that calling \c push_back() to insert data values one at a time
|
||||
/// is inefficient as there is a non-trivial overhead in performing a data
|
||||
/// transfer to the device. It is usually better to store a set of values
|
||||
/// on the host (for example, in a \c std::vector) and then transfer them
|
||||
/// in bulk using the \c insert() method or the copy() algorithm.
|
||||
void push_back(const T &value, command_queue &queue)
|
||||
{
|
||||
insert(end(), value, queue);
|
||||
}
|
||||
|
||||
/// \overload
|
||||
void push_back(const T &value)
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
push_back(value, queue);
|
||||
queue.finish();
|
||||
}
|
||||
|
||||
void pop_back(command_queue &queue)
|
||||
{
|
||||
resize(size() - 1, queue);
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
pop_back(queue);
|
||||
queue.finish();
|
||||
}
|
||||
|
||||
iterator insert(iterator position, const T &value, command_queue &queue)
|
||||
{
|
||||
if(position == end()){
|
||||
resize(m_size + 1, queue);
|
||||
position = begin() + position.get_index();
|
||||
::boost::compute::copy_n(&value, 1, position, queue);
|
||||
}
|
||||
else {
|
||||
::boost::compute::vector<T, Alloc> tmp(position, end(), queue);
|
||||
resize(m_size + 1, queue);
|
||||
position = begin() + position.get_index();
|
||||
::boost::compute::copy_n(&value, 1, position, queue);
|
||||
::boost::compute::copy(tmp.begin(), tmp.end(), position + 1, queue);
|
||||
}
|
||||
|
||||
return position + 1;
|
||||
}
|
||||
|
||||
iterator insert(iterator position, const T &value)
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
iterator iter = insert(position, value, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
void insert(iterator position,
|
||||
size_type count,
|
||||
const T &value,
|
||||
command_queue &queue)
|
||||
{
|
||||
::boost::compute::vector<T, Alloc> tmp(position, end(), queue);
|
||||
resize(size() + count, queue);
|
||||
|
||||
position = begin() + position.get_index();
|
||||
|
||||
::boost::compute::fill_n(position, count, value, queue);
|
||||
::boost::compute::copy(
|
||||
tmp.begin(),
|
||||
tmp.end(),
|
||||
position + static_cast<difference_type>(count),
|
||||
queue
|
||||
);
|
||||
}
|
||||
|
||||
void insert(iterator position, size_type count, const T &value)
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
insert(position, count, value, queue);
|
||||
queue.finish();
|
||||
}
|
||||
|
||||
/// Inserts the values in the range [\p first, \p last) into the vector at
|
||||
/// \p position using \p queue.
|
||||
template<class InputIterator>
|
||||
void insert(iterator position,
|
||||
InputIterator first,
|
||||
InputIterator last,
|
||||
command_queue &queue)
|
||||
{
|
||||
::boost::compute::vector<T, Alloc> tmp(position, end(), queue);
|
||||
|
||||
size_type count = detail::iterator_range_size(first, last);
|
||||
resize(size() + count, queue);
|
||||
|
||||
position = begin() + position.get_index();
|
||||
|
||||
::boost::compute::copy(first, last, position, queue);
|
||||
::boost::compute::copy(
|
||||
tmp.begin(),
|
||||
tmp.end(),
|
||||
position + static_cast<difference_type>(count),
|
||||
queue
|
||||
);
|
||||
}
|
||||
|
||||
/// \overload
|
||||
template<class InputIterator>
|
||||
void insert(iterator position, InputIterator first, InputIterator last)
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
insert(position, first, last, queue);
|
||||
queue.finish();
|
||||
}
|
||||
|
||||
iterator erase(iterator position, command_queue &queue)
|
||||
{
|
||||
return erase(position, position + 1, queue);
|
||||
}
|
||||
|
||||
iterator erase(iterator position)
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
iterator iter = erase(position, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
iterator erase(iterator first, iterator last, command_queue &queue)
|
||||
{
|
||||
if(last != end()){
|
||||
::boost::compute::vector<T, Alloc> tmp(last, end(), queue);
|
||||
::boost::compute::copy(tmp.begin(), tmp.end(), first, queue);
|
||||
}
|
||||
|
||||
difference_type count = std::distance(first, last);
|
||||
resize(size() - static_cast<size_type>(count), queue);
|
||||
|
||||
return begin() + first.get_index() + count;
|
||||
}
|
||||
|
||||
iterator erase(iterator first, iterator last)
|
||||
{
|
||||
command_queue queue = default_queue();
|
||||
iterator iter = erase(first, last, queue);
|
||||
queue.finish();
|
||||
return iter;
|
||||
}
|
||||
|
||||
/// Swaps the contents of \c *this with \p other.
|
||||
void swap(vector &other)
|
||||
{
|
||||
std::swap(m_data, other.m_data);
|
||||
std::swap(m_size, other.m_size);
|
||||
std::swap(m_allocator, other.m_allocator);
|
||||
}
|
||||
|
||||
/// Removes all elements from the vector.
|
||||
void clear()
|
||||
{
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
allocator_type get_allocator() const
|
||||
{
|
||||
return m_allocator;
|
||||
}
|
||||
|
||||
/// Returns the underlying buffer.
|
||||
const buffer& get_buffer() const
|
||||
{
|
||||
return m_data.get_buffer();
|
||||
}
|
||||
|
||||
/// \internal_
|
||||
///
|
||||
/// Returns a command queue usable to issue commands for the vector's
|
||||
/// memory buffer. This is used when a member function is called without
|
||||
/// specifying an existing command queue to use.
|
||||
command_queue default_queue() const
|
||||
{
|
||||
const context &context = m_allocator.get_context();
|
||||
command_queue queue(context, context.get_device());
|
||||
return queue;
|
||||
}
|
||||
|
||||
private:
|
||||
/// \internal_
|
||||
BOOST_CONSTEXPR size_type _minimum_capacity() const { return 4; }
|
||||
|
||||
/// \internal_
|
||||
BOOST_CONSTEXPR float _growth_factor() const { return 1.5; }
|
||||
|
||||
private:
|
||||
pointer m_data;
|
||||
size_type m_size;
|
||||
allocator_type m_allocator;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
// set_kernel_arg specialization for vector<T>
|
||||
template<class T, class Alloc>
|
||||
struct set_kernel_arg<vector<T, Alloc> >
|
||||
{
|
||||
void operator()(kernel &kernel_, size_t index, const vector<T, Alloc> &vector)
|
||||
{
|
||||
kernel_.set_arg(index, vector.get_buffer());
|
||||
}
|
||||
};
|
||||
|
||||
// for capturing vector<T> with BOOST_COMPUTE_CLOSURE()
|
||||
template<class T, class Alloc>
|
||||
struct capture_traits<vector<T, Alloc> >
|
||||
{
|
||||
static std::string type_name()
|
||||
{
|
||||
return std::string("__global ") + ::boost::compute::type_name<T>() + "*";
|
||||
}
|
||||
};
|
||||
|
||||
// meta_kernel streaming operator for vector<T>
|
||||
template<class T, class Alloc>
|
||||
meta_kernel& operator<<(meta_kernel &k, const vector<T, Alloc> &vector)
|
||||
{
|
||||
return k << k.get_buffer_identifier<T>(vector.get_buffer());
|
||||
}
|
||||
|
||||
} // end detail namespace
|
||||
} // end compute namespace
|
||||
} // end boost namespace
|
||||
|
||||
#endif // BOOST_COMPUTE_CONTAINER_VECTOR_HPP
|
||||
Reference in New Issue
Block a user