stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork

This commit is contained in:
2026-02-24 18:38:47 +00:00
parent da8c28aaeb
commit 65cb2619a7
13106 changed files with 2484322 additions and 1804 deletions
@@ -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, &current_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, &current_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