You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1204 lines
34 KiB
1204 lines
34 KiB
11 years ago
|
/*
|
||
|
* Copyright 2008-2012 NVIDIA Corporation
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
|
||
|
/*! \file vector_base.inl
|
||
|
* \brief Inline file for vector_base.h.
|
||
|
*/
|
||
|
|
||
|
#include <thrust/detail/vector_base.h>
|
||
|
#include <thrust/detail/copy.h>
|
||
|
#include <thrust/detail/overlapped_copy.h>
|
||
|
#include <thrust/equal.h>
|
||
|
#include <thrust/distance.h>
|
||
|
#include <thrust/advance.h>
|
||
|
#include <thrust/detail/type_traits.h>
|
||
|
#include <thrust/detail/minmax.h>
|
||
|
#include <thrust/iterator/iterator_traits.h>
|
||
|
#include <thrust/detail/temporary_array.h>
|
||
|
|
||
|
#include <stdexcept>
|
||
|
|
||
|
namespace thrust
|
||
|
{
|
||
|
|
||
|
namespace detail
|
||
|
{
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
vector_base<T,Alloc>
|
||
|
::vector_base(void)
|
||
|
:m_storage(),
|
||
|
m_size(0)
|
||
|
{
|
||
|
;
|
||
|
} // end vector_base::vector_base()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
vector_base<T,Alloc>
|
||
|
::vector_base(size_type n)
|
||
|
:m_storage(),
|
||
|
m_size(0)
|
||
|
{
|
||
|
default_init(n);
|
||
|
} // end vector_base::vector_base()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
vector_base<T,Alloc>
|
||
|
::vector_base(size_type n, const value_type &value)
|
||
|
:m_storage(),
|
||
|
m_size(0)
|
||
|
{
|
||
|
fill_init(n,value);
|
||
|
} // end vector_base::vector_base()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
vector_base<T,Alloc>
|
||
|
::vector_base(const vector_base &v)
|
||
|
:m_storage(),
|
||
|
m_size(0)
|
||
|
{
|
||
|
range_init(v.begin(), v.end());
|
||
|
} // end vector_base::vector_base()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
vector_base<T,Alloc> &
|
||
|
vector_base<T,Alloc>
|
||
|
::operator=(const vector_base &v)
|
||
|
{
|
||
|
if(this != &v)
|
||
|
{
|
||
|
assign(v.begin(), v.end());
|
||
|
} // end if
|
||
|
|
||
|
return *this;
|
||
|
} // end vector_base::operator=()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename OtherT, typename OtherAlloc>
|
||
|
vector_base<T,Alloc>
|
||
|
::vector_base(const vector_base<OtherT,OtherAlloc> &v)
|
||
|
:m_storage(),
|
||
|
m_size(0)
|
||
|
{
|
||
|
range_init(v.begin(), v.end());
|
||
|
} // end vector_base::vector_base()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename OtherT, typename OtherAlloc>
|
||
|
vector_base<T,Alloc> &
|
||
|
vector_base<T,Alloc>
|
||
|
::operator=(const vector_base<OtherT,OtherAlloc> &v)
|
||
|
{
|
||
|
assign(v.begin(), v.end());
|
||
|
|
||
|
return *this;
|
||
|
} // end vector_base::operator=()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename OtherT, typename OtherAlloc>
|
||
|
vector_base<T,Alloc>
|
||
|
::vector_base(const std::vector<OtherT,OtherAlloc> &v)
|
||
|
:m_storage(),
|
||
|
m_size(0)
|
||
|
{
|
||
|
range_init(v.begin(), v.end());
|
||
|
} // end vector_base::vector_base()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename OtherT, typename OtherAlloc>
|
||
|
vector_base<T,Alloc> &
|
||
|
vector_base<T,Alloc>
|
||
|
::operator=(const std::vector<OtherT,OtherAlloc> &v)
|
||
|
{
|
||
|
assign(v.begin(), v.end());
|
||
|
|
||
|
return *this;
|
||
|
} // end vector_base::operator=()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename IteratorOrIntegralType>
|
||
|
void vector_base<T,Alloc>
|
||
|
::init_dispatch(IteratorOrIntegralType n,
|
||
|
IteratorOrIntegralType value,
|
||
|
true_type)
|
||
|
{
|
||
|
fill_init(n,value);
|
||
|
} // end vector_base::init_dispatch()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
void vector_base<T,Alloc>
|
||
|
::default_init(size_type n)
|
||
|
{
|
||
|
if(n > 0)
|
||
|
{
|
||
|
m_storage.allocate(n);
|
||
|
m_size = n;
|
||
|
|
||
|
m_storage.default_construct_n(begin(), size());
|
||
|
} // end if
|
||
|
} // end vector_base::default_init()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
void vector_base<T,Alloc>
|
||
|
::fill_init(size_type n, const T &x)
|
||
|
{
|
||
|
if(n > 0)
|
||
|
{
|
||
|
m_storage.allocate(n);
|
||
|
m_size = n;
|
||
|
|
||
|
m_storage.uninitialized_fill_n(begin(), size(), x);
|
||
|
} // end if
|
||
|
} // end vector_base::fill_init()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename InputIterator>
|
||
|
void vector_base<T,Alloc>
|
||
|
::init_dispatch(InputIterator first,
|
||
|
InputIterator last,
|
||
|
false_type)
|
||
|
{
|
||
|
range_init(first, last);
|
||
|
} // end vector_base::init_dispatch()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename InputIterator>
|
||
|
void vector_base<T,Alloc>
|
||
|
::range_init(InputIterator first,
|
||
|
InputIterator last)
|
||
|
{
|
||
|
range_init(first, last,
|
||
|
typename thrust::iterator_traversal<InputIterator>::type());
|
||
|
} // end vector_base::range_init()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename InputIterator>
|
||
|
void vector_base<T,Alloc>
|
||
|
::range_init(InputIterator first,
|
||
|
InputIterator last,
|
||
|
thrust::incrementable_traversal_tag)
|
||
|
{
|
||
|
for(; first != last; ++first)
|
||
|
push_back(*first);
|
||
|
} // end vector_base::range_init()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename ForwardIterator>
|
||
|
void vector_base<T,Alloc>
|
||
|
::range_init(ForwardIterator first,
|
||
|
ForwardIterator last,
|
||
|
thrust::random_access_traversal_tag)
|
||
|
{
|
||
|
size_type new_size = thrust::distance(first, last);
|
||
|
|
||
|
allocate_and_copy(new_size, first, last, m_storage);
|
||
|
m_size = new_size;
|
||
|
} // end vector_base::range_init()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename InputIterator>
|
||
|
vector_base<T,Alloc>
|
||
|
::vector_base(InputIterator first,
|
||
|
InputIterator last)
|
||
|
:m_storage(),
|
||
|
m_size(0)
|
||
|
{
|
||
|
// check the type of InputIterator: if it's an integral type,
|
||
|
// we need to interpret this call as (size_type, value_type)
|
||
|
typedef thrust::detail::is_integral<InputIterator> Integer;
|
||
|
|
||
|
init_dispatch(first, last, Integer());
|
||
|
} // end vector_basee::vector_base()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
void vector_base<T,Alloc>
|
||
|
::resize(size_type new_size)
|
||
|
{
|
||
|
if(new_size < size())
|
||
|
{
|
||
|
iterator new_end = begin();
|
||
|
thrust::advance(new_end, new_size);
|
||
|
erase(new_end, end());
|
||
|
} // end if
|
||
|
else
|
||
|
{
|
||
|
append(new_size - size());
|
||
|
} // end else
|
||
|
} // end vector_base::resize()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
void vector_base<T,Alloc>
|
||
|
::resize(size_type new_size, const value_type &x)
|
||
|
{
|
||
|
if(new_size < size())
|
||
|
{
|
||
|
iterator new_end = begin();
|
||
|
thrust::advance(new_end, new_size);
|
||
|
erase(new_end, end());
|
||
|
} // end if
|
||
|
else
|
||
|
{
|
||
|
insert(end(), new_size - size(), x);
|
||
|
} // end else
|
||
|
} // end vector_base::resize()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::size_type
|
||
|
vector_base<T,Alloc>
|
||
|
::size(void) const
|
||
|
{
|
||
|
return m_size;
|
||
|
} // end vector_base::size()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::size_type
|
||
|
vector_base<T,Alloc>
|
||
|
::max_size(void) const
|
||
|
{
|
||
|
return m_storage.max_size();
|
||
|
} // end vector_base::max_size()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
void vector_base<T,Alloc>
|
||
|
::reserve(size_type n)
|
||
|
{
|
||
|
if(n > capacity())
|
||
|
{
|
||
|
allocate_and_copy(n, begin(), end(), m_storage);
|
||
|
} // end if
|
||
|
} // end vector_base::reserve()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::size_type
|
||
|
vector_base<T,Alloc>
|
||
|
::capacity(void) const
|
||
|
{
|
||
|
return m_storage.size();
|
||
|
} // end vector_base::capacity()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
void vector_base<T,Alloc>
|
||
|
::shrink_to_fit(void)
|
||
|
{
|
||
|
// use the swap trick
|
||
|
vector_base(*this).swap(*this);
|
||
|
} // end vector_base::shrink_to_fit()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::reference
|
||
|
vector_base<T,Alloc>
|
||
|
::operator[](const size_type n)
|
||
|
{
|
||
|
return m_storage[n];
|
||
|
} // end vector_base::operator[]
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::const_reference
|
||
|
vector_base<T,Alloc>
|
||
|
::operator[](const size_type n) const
|
||
|
{
|
||
|
return m_storage[n];
|
||
|
} // end vector_base::operator[]
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::iterator
|
||
|
vector_base<T,Alloc>
|
||
|
::begin(void)
|
||
|
{
|
||
|
return m_storage.begin();
|
||
|
} // end vector_base::begin()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::const_iterator
|
||
|
vector_base<T,Alloc>
|
||
|
::begin(void) const
|
||
|
{
|
||
|
return m_storage.begin();
|
||
|
} // end vector_base::begin()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::const_iterator
|
||
|
vector_base<T,Alloc>
|
||
|
::cbegin(void) const
|
||
|
{
|
||
|
return begin();
|
||
|
} // end vector_base::cbegin()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::reverse_iterator
|
||
|
vector_base<T,Alloc>
|
||
|
::rbegin(void)
|
||
|
{
|
||
|
return reverse_iterator(end());
|
||
|
} // end vector_base::rbegin()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::const_reverse_iterator
|
||
|
vector_base<T,Alloc>
|
||
|
::rbegin(void) const
|
||
|
{
|
||
|
return const_reverse_iterator(end());
|
||
|
} // end vector_base::rbegin()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::const_reverse_iterator
|
||
|
vector_base<T,Alloc>
|
||
|
::crbegin(void) const
|
||
|
{
|
||
|
return rbegin();
|
||
|
} // end vector_base::crbegin()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::iterator
|
||
|
vector_base<T,Alloc>
|
||
|
::end(void)
|
||
|
{
|
||
|
iterator result = begin();
|
||
|
thrust::advance(result, size());
|
||
|
return result;
|
||
|
} // end vector_base::end()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::const_iterator
|
||
|
vector_base<T,Alloc>
|
||
|
::end(void) const
|
||
|
{
|
||
|
const_iterator result = begin();
|
||
|
thrust::advance(result, size());
|
||
|
return result;
|
||
|
} // end vector_base::end()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::const_iterator
|
||
|
vector_base<T,Alloc>
|
||
|
::cend(void) const
|
||
|
{
|
||
|
return end();
|
||
|
} // end vector_base::cend()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::reverse_iterator
|
||
|
vector_base<T,Alloc>
|
||
|
::rend(void)
|
||
|
{
|
||
|
return reverse_iterator(begin());
|
||
|
} // end vector_base::rend()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::const_reverse_iterator
|
||
|
vector_base<T,Alloc>
|
||
|
::rend(void) const
|
||
|
{
|
||
|
return const_reverse_iterator(begin());
|
||
|
} // end vector_base::rend()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::const_reverse_iterator
|
||
|
vector_base<T,Alloc>
|
||
|
::crend(void) const
|
||
|
{
|
||
|
return rend();
|
||
|
} // end vector_base::crend()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::const_reference
|
||
|
vector_base<T,Alloc>
|
||
|
::front(void) const
|
||
|
{
|
||
|
return *begin();
|
||
|
} // end vector_base::front()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::reference
|
||
|
vector_base<T,Alloc>
|
||
|
::front(void)
|
||
|
{
|
||
|
return *begin();
|
||
|
} // end vector_base::front()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::const_reference
|
||
|
vector_base<T,Alloc>
|
||
|
::back(void) const
|
||
|
{
|
||
|
const_iterator ptr_to_back = end();
|
||
|
--ptr_to_back;
|
||
|
return *ptr_to_back;
|
||
|
} // end vector_base::vector_base
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::reference
|
||
|
vector_base<T,Alloc>
|
||
|
::back(void)
|
||
|
{
|
||
|
iterator ptr_to_back = end();
|
||
|
--ptr_to_back;
|
||
|
return *ptr_to_back;
|
||
|
} // end vector_base::vector_base
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::pointer
|
||
|
vector_base<T,Alloc>
|
||
|
::data(void)
|
||
|
{
|
||
|
return &front();
|
||
|
} // end vector_base::data()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::const_pointer
|
||
|
vector_base<T,Alloc>
|
||
|
::data(void) const
|
||
|
{
|
||
|
return &front();
|
||
|
} // end vector_base::data()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
vector_base<T,Alloc>
|
||
|
::~vector_base(void)
|
||
|
{
|
||
|
// destroy every living thing
|
||
|
m_storage.destroy(begin(),end());
|
||
|
} // end vector_base::~vector_base()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
void vector_base<T,Alloc>
|
||
|
::clear(void)
|
||
|
{
|
||
|
resize(0);
|
||
|
} // end vector_base::~vector_dev()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
bool vector_base<T,Alloc>
|
||
|
::empty(void) const
|
||
|
{
|
||
|
return size() == 0;
|
||
|
} // end vector_base::empty();
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
void vector_base<T,Alloc>
|
||
|
::push_back(const value_type &x)
|
||
|
{
|
||
|
insert(end(), x);
|
||
|
} // end vector_base::push_back()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
void vector_base<T,Alloc>
|
||
|
::pop_back(void)
|
||
|
{
|
||
|
iterator e = end();
|
||
|
iterator ptr_to_back = e;
|
||
|
--ptr_to_back;
|
||
|
m_storage.destroy(ptr_to_back, e);
|
||
|
--m_size;
|
||
|
} // end vector_base::pop_back()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::iterator vector_base<T,Alloc>
|
||
|
::erase(iterator pos)
|
||
|
{
|
||
|
iterator end = pos;
|
||
|
++end;
|
||
|
return erase(pos,end);
|
||
|
} // end vector_base::erase()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::iterator vector_base<T,Alloc>
|
||
|
::erase(iterator first, iterator last)
|
||
|
{
|
||
|
// overlap copy the range [last,end()) to first
|
||
|
// XXX this copy only potentially overlaps
|
||
|
iterator i = thrust::detail::overlapped_copy(last, end(), first);
|
||
|
|
||
|
// destroy everything after i
|
||
|
m_storage.destroy(i, end());
|
||
|
|
||
|
// modify our size
|
||
|
m_size -= (last - first);
|
||
|
|
||
|
// return an iterator pointing to the position of the first element
|
||
|
// following the erased range
|
||
|
return first;
|
||
|
} // end vector_base::erase()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
void vector_base<T,Alloc>
|
||
|
::swap(vector_base &v)
|
||
|
{
|
||
|
thrust::swap(m_storage, v.m_storage);
|
||
|
thrust::swap(m_size, v.m_size);
|
||
|
} // end vector_base::swap()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
void vector_base<T,Alloc>
|
||
|
::assign(size_type n, const T &x)
|
||
|
{
|
||
|
fill_assign(n, x);
|
||
|
} // end vector_base::assign()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename InputIterator>
|
||
|
void vector_base<T,Alloc>
|
||
|
::assign(InputIterator first, InputIterator last)
|
||
|
{
|
||
|
// we could have received assign(n, x), so disambiguate on the
|
||
|
// type of InputIterator
|
||
|
typedef typename thrust::detail::is_integral<InputIterator> integral;
|
||
|
|
||
|
assign_dispatch(first, last, integral());
|
||
|
} // end vector_base::assign()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::allocator_type
|
||
|
vector_base<T,Alloc>
|
||
|
::get_allocator(void) const
|
||
|
{
|
||
|
return m_storage.get_allocator();
|
||
|
} // end vector_base::get_allocator()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
typename vector_base<T,Alloc>::iterator
|
||
|
vector_base<T,Alloc>
|
||
|
::insert(iterator position, const T &x)
|
||
|
{
|
||
|
// find the index of the insertion
|
||
|
size_type index = thrust::distance(begin(), position);
|
||
|
|
||
|
// make the insertion
|
||
|
insert(position, 1, x);
|
||
|
|
||
|
// return an iterator pointing back to position
|
||
|
iterator result = begin();
|
||
|
thrust::advance(result, index);
|
||
|
return result;
|
||
|
} // end vector_base::insert()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
void vector_base<T,Alloc>
|
||
|
::insert(iterator position, size_type n, const T &x)
|
||
|
{
|
||
|
fill_insert(position, n, x);
|
||
|
} // end vector_base::insert()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename InputIterator>
|
||
|
void vector_base<T,Alloc>
|
||
|
::insert(iterator position, InputIterator first, InputIterator last)
|
||
|
{
|
||
|
// we could have received insert(position, n, x), so disambiguate on the
|
||
|
// type of InputIterator
|
||
|
typedef typename thrust::detail::is_integral<InputIterator> integral;
|
||
|
|
||
|
insert_dispatch(position, first, last, integral());
|
||
|
} // end vector_base::insert()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename InputIterator>
|
||
|
void vector_base<T,Alloc>
|
||
|
::assign_dispatch(InputIterator first, InputIterator last, false_type)
|
||
|
{
|
||
|
range_assign(first, last);
|
||
|
} // end vector_base::assign_dispatch()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename Integral>
|
||
|
void vector_base<T,Alloc>
|
||
|
::assign_dispatch(Integral n, Integral x, true_type)
|
||
|
{
|
||
|
fill_assign(n, x);
|
||
|
} // end vector_base::assign_dispatch()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename InputIterator>
|
||
|
void vector_base<T,Alloc>
|
||
|
::insert_dispatch(iterator position, InputIterator first, InputIterator last, false_type)
|
||
|
{
|
||
|
copy_insert(position, first, last);
|
||
|
} // end vector_base::insert_dispatch()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename Integral>
|
||
|
void vector_base<T,Alloc>
|
||
|
::insert_dispatch(iterator position, Integral n, Integral x, true_type)
|
||
|
{
|
||
|
fill_insert(position, n, x);
|
||
|
} // end vector_base::insert_dispatch()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename ForwardIterator>
|
||
|
void vector_base<T,Alloc>
|
||
|
::copy_insert(iterator position,
|
||
|
ForwardIterator first,
|
||
|
ForwardIterator last)
|
||
|
{
|
||
|
if(first != last)
|
||
|
{
|
||
|
// how many new elements will we create?
|
||
|
const size_type num_new_elements = thrust::distance(first, last);
|
||
|
if(capacity() - size() >= num_new_elements)
|
||
|
{
|
||
|
// we've got room for all of them
|
||
|
// how many existing elements will we displace?
|
||
|
const size_type num_displaced_elements = end() - position;
|
||
|
iterator old_end = end();
|
||
|
|
||
|
if(num_displaced_elements > num_new_elements)
|
||
|
{
|
||
|
// construct copy n displaced elements to new elements
|
||
|
// following the insertion
|
||
|
m_storage.uninitialized_copy(end() - num_new_elements, end(), end());
|
||
|
|
||
|
// extend the size
|
||
|
m_size += num_new_elements;
|
||
|
|
||
|
// copy num_displaced_elements - num_new_elements elements to existing elements
|
||
|
// this copy overlaps
|
||
|
const size_type copy_length = (old_end - num_new_elements) - position;
|
||
|
thrust::detail::overlapped_copy(position, old_end - num_new_elements, old_end - copy_length);
|
||
|
|
||
|
// finally, copy the range to the insertion point
|
||
|
thrust::copy(first, last, position);
|
||
|
} // end if
|
||
|
else
|
||
|
{
|
||
|
ForwardIterator mid = first;
|
||
|
thrust::advance(mid, num_displaced_elements);
|
||
|
|
||
|
// construct copy new elements at the end of the vector
|
||
|
m_storage.uninitialized_copy(mid, last, end());
|
||
|
|
||
|
// extend the size
|
||
|
m_size += num_new_elements - num_displaced_elements;
|
||
|
|
||
|
// construct copy the displaced elements
|
||
|
m_storage.uninitialized_copy(position, old_end, end());
|
||
|
|
||
|
// extend the size
|
||
|
m_size += num_displaced_elements;
|
||
|
|
||
|
// copy to elements which already existed
|
||
|
thrust::copy(first, mid, position);
|
||
|
} // end else
|
||
|
} // end if
|
||
|
else
|
||
|
{
|
||
|
const size_type old_size = size();
|
||
|
|
||
|
// compute the new capacity after the allocation
|
||
|
size_type new_capacity = old_size + thrust::max THRUST_PREVENT_MACRO_SUBSTITUTION (old_size, num_new_elements);
|
||
|
|
||
|
// allocate exponentially larger new storage
|
||
|
new_capacity = thrust::max THRUST_PREVENT_MACRO_SUBSTITUTION <size_type>(new_capacity, 2 * capacity());
|
||
|
|
||
|
// do not exceed maximum storage
|
||
|
new_capacity = thrust::min THRUST_PREVENT_MACRO_SUBSTITUTION <size_type>(new_capacity, max_size());
|
||
|
|
||
|
if(new_capacity > max_size())
|
||
|
{
|
||
|
throw std::length_error("insert(): insertion exceeds max_size().");
|
||
|
} // end if
|
||
|
|
||
|
storage_type new_storage(new_capacity);
|
||
|
|
||
|
// record how many constructors we invoke in the try block below
|
||
|
iterator new_end = new_storage.begin();
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// construct copy elements before the insertion to the beginning of the newly
|
||
|
// allocated storage
|
||
|
new_end = m_storage.uninitialized_copy(begin(), position, new_storage.begin());
|
||
|
|
||
|
// construct copy elements to insert
|
||
|
new_end = m_storage.uninitialized_copy(first, last, new_end);
|
||
|
|
||
|
// construct copy displaced elements from the old storage to the new storage
|
||
|
// remember [position, end()) refers to the old storage
|
||
|
new_end = m_storage.uninitialized_copy(position, end(), new_end);
|
||
|
} // end try
|
||
|
catch(...)
|
||
|
{
|
||
|
// something went wrong, so destroy & deallocate the new storage
|
||
|
m_storage.destroy(new_storage.begin(), new_end);
|
||
|
new_storage.deallocate();
|
||
|
|
||
|
// rethrow
|
||
|
throw;
|
||
|
} // end catch
|
||
|
|
||
|
// call destructors on the elements in the old storage
|
||
|
m_storage.destroy(begin(), end());
|
||
|
|
||
|
// record the vector's new state
|
||
|
m_storage.swap(new_storage);
|
||
|
m_size = old_size + num_new_elements;
|
||
|
} // end else
|
||
|
} // end if
|
||
|
} // end vector_base::copy_insert()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
void vector_base<T,Alloc>
|
||
|
::append(size_type n)
|
||
|
{
|
||
|
if(n != 0)
|
||
|
{
|
||
|
if(capacity() - size() >= n)
|
||
|
{
|
||
|
// we've got room for all of them
|
||
|
|
||
|
// default construct new elements at the end of the vector
|
||
|
m_storage.default_construct_n(end(), n);
|
||
|
|
||
|
// extend the size
|
||
|
m_size += n;
|
||
|
} // end if
|
||
|
else
|
||
|
{
|
||
|
const size_type old_size = size();
|
||
|
|
||
|
// compute the new capacity after the allocation
|
||
|
size_type new_capacity = old_size + thrust::max THRUST_PREVENT_MACRO_SUBSTITUTION (old_size, n);
|
||
|
|
||
|
// allocate exponentially larger new storage
|
||
|
new_capacity = thrust::max THRUST_PREVENT_MACRO_SUBSTITUTION <size_type>(new_capacity, 2 * capacity());
|
||
|
|
||
|
// do not exceed maximum storage
|
||
|
new_capacity = thrust::min THRUST_PREVENT_MACRO_SUBSTITUTION <size_type>(new_capacity, max_size());
|
||
|
|
||
|
// create new storage
|
||
|
storage_type new_storage(new_capacity);
|
||
|
|
||
|
// record how many constructors we invoke in the try block below
|
||
|
iterator new_end = new_storage.begin();
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// construct copy all elements into the newly allocated storage
|
||
|
new_end = m_storage.uninitialized_copy(begin(), end(), new_storage.begin());
|
||
|
|
||
|
// construct new elements to insert
|
||
|
m_storage.default_construct_n(new_end, n);
|
||
|
new_end += n;
|
||
|
} // end try
|
||
|
catch(...)
|
||
|
{
|
||
|
// something went wrong, so destroy & deallocate the new storage
|
||
|
m_storage.destroy(new_storage.begin(), new_end);
|
||
|
new_storage.deallocate();
|
||
|
|
||
|
// rethrow
|
||
|
throw;
|
||
|
} // end catch
|
||
|
|
||
|
// call destructors on the elements in the old storage
|
||
|
m_storage.destroy(begin(), end());
|
||
|
|
||
|
// record the vector's new state
|
||
|
m_storage.swap(new_storage);
|
||
|
m_size = old_size + n;
|
||
|
} // end else
|
||
|
} // end if
|
||
|
} // end vector_base::append()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
void vector_base<T,Alloc>
|
||
|
::fill_insert(iterator position, size_type n, const T &x)
|
||
|
{
|
||
|
if(n != 0)
|
||
|
{
|
||
|
if(capacity() - size() >= n)
|
||
|
{
|
||
|
// we've got room for all of them
|
||
|
// how many existing elements will we displace?
|
||
|
const size_type num_displaced_elements = end() - position;
|
||
|
iterator old_end = end();
|
||
|
|
||
|
if(num_displaced_elements > n)
|
||
|
{
|
||
|
// construct copy n displaced elements to new elements
|
||
|
// following the insertion
|
||
|
m_storage.uninitialized_copy(end() - n, end(), end());
|
||
|
|
||
|
// extend the size
|
||
|
m_size += n;
|
||
|
|
||
|
// copy num_displaced_elements - n elements to existing elements
|
||
|
// this copy overlaps
|
||
|
const size_type copy_length = (old_end - n) - position;
|
||
|
thrust::detail::overlapped_copy(position, old_end - n, old_end - copy_length);
|
||
|
|
||
|
// finally, fill the range to the insertion point
|
||
|
thrust::fill_n(position, n, x);
|
||
|
} // end if
|
||
|
else
|
||
|
{
|
||
|
// construct new elements at the end of the vector
|
||
|
m_storage.uninitialized_fill_n(end(), n - num_displaced_elements, x);
|
||
|
|
||
|
// extend the size
|
||
|
m_size += n - num_displaced_elements;
|
||
|
|
||
|
// construct copy the displaced elements
|
||
|
m_storage.uninitialized_copy(position, old_end, end());
|
||
|
|
||
|
// extend the size
|
||
|
m_size += num_displaced_elements;
|
||
|
|
||
|
// fill to elements which already existed
|
||
|
thrust::fill(position, old_end, x);
|
||
|
} // end else
|
||
|
} // end if
|
||
|
else
|
||
|
{
|
||
|
const size_type old_size = size();
|
||
|
|
||
|
// compute the new capacity after the allocation
|
||
|
size_type new_capacity = old_size + thrust::max THRUST_PREVENT_MACRO_SUBSTITUTION (old_size, n);
|
||
|
|
||
|
// allocate exponentially larger new storage
|
||
|
new_capacity = thrust::max THRUST_PREVENT_MACRO_SUBSTITUTION <size_type>(new_capacity, 2 * capacity());
|
||
|
|
||
|
// do not exceed maximum storage
|
||
|
new_capacity = thrust::min THRUST_PREVENT_MACRO_SUBSTITUTION <size_type>(new_capacity, max_size());
|
||
|
|
||
|
if(new_capacity > max_size())
|
||
|
{
|
||
|
throw std::length_error("insert(): insertion exceeds max_size().");
|
||
|
} // end if
|
||
|
|
||
|
storage_type new_storage(new_capacity);
|
||
|
|
||
|
// record how many constructors we invoke in the try block below
|
||
|
iterator new_end = new_storage.begin();
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// construct copy elements before the insertion to the beginning of the newly
|
||
|
// allocated storage
|
||
|
new_end = m_storage.uninitialized_copy(begin(), position, new_storage.begin());
|
||
|
|
||
|
// construct new elements to insert
|
||
|
m_storage.uninitialized_fill_n(new_end, n, x);
|
||
|
new_end += n;
|
||
|
|
||
|
// construct copy displaced elements from the old storage to the new storage
|
||
|
// remember [position, end()) refers to the old storage
|
||
|
new_end = m_storage.uninitialized_copy(position, end(), new_end);
|
||
|
} // end try
|
||
|
catch(...)
|
||
|
{
|
||
|
// something went wrong, so destroy & deallocate the new storage
|
||
|
m_storage.destroy(new_storage.begin(), new_end);
|
||
|
new_storage.deallocate();
|
||
|
|
||
|
// rethrow
|
||
|
throw;
|
||
|
} // end catch
|
||
|
|
||
|
// call destructors on the elements in the old storage
|
||
|
m_storage.destroy(begin(), end());
|
||
|
|
||
|
// record the vector's new state
|
||
|
m_storage.swap(new_storage);
|
||
|
m_size = old_size + n;
|
||
|
} // end else
|
||
|
} // end if
|
||
|
} // end vector_base::fill_insert()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename InputIterator>
|
||
|
void vector_base<T,Alloc>
|
||
|
::range_assign(InputIterator first,
|
||
|
InputIterator last)
|
||
|
{
|
||
|
// dispatch on traversal
|
||
|
range_assign(first, last,
|
||
|
typename thrust::iterator_traversal<InputIterator>::type());
|
||
|
} // end range_assign()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename InputIterator>
|
||
|
void vector_base<T,Alloc>
|
||
|
::range_assign(InputIterator first,
|
||
|
InputIterator last,
|
||
|
thrust::incrementable_traversal_tag)
|
||
|
{
|
||
|
iterator current(begin());
|
||
|
|
||
|
// assign to elements which already exist
|
||
|
for(; first != last && current != end(); ++current, ++first)
|
||
|
{
|
||
|
*current = *first;
|
||
|
} // end for
|
||
|
|
||
|
// either just the input was exhausted or both
|
||
|
// the input and vector elements were exhausted
|
||
|
if(first == last)
|
||
|
{
|
||
|
// if we exhausted the input, erase leftover elements
|
||
|
erase(current, end());
|
||
|
} // end if
|
||
|
else
|
||
|
{
|
||
|
// insert the rest of the input at the end of the vector
|
||
|
insert(end(), first, last);
|
||
|
} // end else
|
||
|
} // end vector_base::range_assign()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename RandomAccessIterator>
|
||
|
void vector_base<T,Alloc>
|
||
|
::range_assign(RandomAccessIterator first,
|
||
|
RandomAccessIterator last,
|
||
|
thrust::random_access_traversal_tag)
|
||
|
{
|
||
|
const size_type n = thrust::distance(first, last);
|
||
|
|
||
|
if(n > capacity())
|
||
|
{
|
||
|
storage_type new_storage;
|
||
|
allocate_and_copy(n, first, last, new_storage);
|
||
|
|
||
|
// call destructors on the elements in the old storage
|
||
|
m_storage.destroy(begin(), end());
|
||
|
|
||
|
// record the vector's new state
|
||
|
m_storage.swap(new_storage);
|
||
|
m_size = n;
|
||
|
} // end if
|
||
|
else if(size() >= n)
|
||
|
{
|
||
|
// we can already accomodate the new range
|
||
|
iterator new_end = thrust::copy(first, last, begin());
|
||
|
|
||
|
// destroy the elements we don't need
|
||
|
m_storage.destroy(new_end, end());
|
||
|
|
||
|
// update size
|
||
|
m_size = n;
|
||
|
} // end else if
|
||
|
else
|
||
|
{
|
||
|
// range fits inside allocated storage, but some elements
|
||
|
// have not been constructed yet
|
||
|
|
||
|
// XXX TODO we could possibly implement this with one call
|
||
|
// to transform rather than copy + uninitialized_copy
|
||
|
|
||
|
// copy to elements which already exist
|
||
|
RandomAccessIterator mid = first;
|
||
|
thrust::advance(mid, size());
|
||
|
thrust::copy(first, mid, begin());
|
||
|
|
||
|
// uninitialize_copy to elements which must be constructed
|
||
|
m_storage.uninitialized_copy(mid, last, end());
|
||
|
|
||
|
// update size
|
||
|
m_size = n;
|
||
|
} // end else
|
||
|
} // end vector_base::assign()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
void vector_base<T,Alloc>
|
||
|
::fill_assign(size_type n, const T &x)
|
||
|
{
|
||
|
if(n > capacity())
|
||
|
{
|
||
|
// XXX we should also include a copy of the allocator:
|
||
|
// vector_base<T,Alloc> temp(n, x, get_allocator());
|
||
|
vector_base<T,Alloc> temp(n, x);
|
||
|
temp.swap(*this);
|
||
|
} // end if
|
||
|
else if(n > size())
|
||
|
{
|
||
|
// fill to existing elements
|
||
|
thrust::fill(begin(), end(), x);
|
||
|
|
||
|
// construct uninitialized elements
|
||
|
m_storage.uninitialized_fill_n(end(), n - size(), x);
|
||
|
|
||
|
// adjust size
|
||
|
m_size += (n - size());
|
||
|
} // end else if
|
||
|
else
|
||
|
{
|
||
|
// fill to existing elements
|
||
|
iterator new_end = thrust::fill_n(begin(), n, x);
|
||
|
|
||
|
// erase the elements after the fill
|
||
|
erase(new_end, end());
|
||
|
} // end else
|
||
|
} // end vector_base::fill_assign()
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
template<typename ForwardIterator>
|
||
|
void vector_base<T,Alloc>
|
||
|
::allocate_and_copy(size_type requested_size,
|
||
|
ForwardIterator first, ForwardIterator last,
|
||
|
storage_type &new_storage)
|
||
|
{
|
||
|
if(requested_size == 0)
|
||
|
{
|
||
|
new_storage.deallocate();
|
||
|
return;
|
||
|
} // end if
|
||
|
|
||
|
// allocate exponentially larger new storage
|
||
|
size_type allocated_size = thrust::max<size_type>(requested_size, 2 * capacity());
|
||
|
|
||
|
// do not exceed maximum storage
|
||
|
allocated_size = thrust::min<size_type>(allocated_size, max_size());
|
||
|
|
||
|
if(requested_size > allocated_size)
|
||
|
{
|
||
|
throw std::length_error("assignment exceeds max_size().");
|
||
|
} // end if
|
||
|
|
||
|
new_storage.allocate(allocated_size);
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// construct the range to the newly allocated storage
|
||
|
m_storage.uninitialized_copy(first, last, new_storage.begin());
|
||
|
} // end try
|
||
|
catch(...)
|
||
|
{
|
||
|
// something went wrong, so destroy & deallocate the new storage
|
||
|
// XXX seems like this destroys too many elements -- should just be last - first instead of requested_size
|
||
|
iterator new_storage_end = new_storage.begin();
|
||
|
thrust::advance(new_storage_end, requested_size);
|
||
|
m_storage.destroy(new_storage.begin(), new_storage_end);
|
||
|
new_storage.deallocate();
|
||
|
|
||
|
// rethrow
|
||
|
throw;
|
||
|
} // end catch
|
||
|
} // end vector_base::allocate_and_copy()
|
||
|
|
||
|
|
||
|
} // end detail
|
||
|
|
||
|
template<typename T, typename Alloc>
|
||
|
void swap(detail::vector_base<T,Alloc> &a,
|
||
|
detail::vector_base<T,Alloc> &b)
|
||
|
{
|
||
|
a.swap(b);
|
||
|
} // end swap()
|
||
|
|
||
|
|
||
|
|
||
|
namespace detail
|
||
|
{
|
||
|
|
||
|
// iterator tags match
|
||
|
template <typename InputIterator1, typename InputIterator2>
|
||
|
bool vector_equal(InputIterator1 first1, InputIterator1 last1,
|
||
|
InputIterator2 first2,
|
||
|
thrust::detail::true_type)
|
||
|
{
|
||
|
return thrust::equal(first1, last1, first2);
|
||
|
}
|
||
|
|
||
|
// iterator tags differ
|
||
|
template <typename InputIterator1, typename InputIterator2>
|
||
|
bool vector_equal(InputIterator1 first1, InputIterator1 last1,
|
||
|
InputIterator2 first2,
|
||
|
thrust::detail::false_type)
|
||
|
{
|
||
|
typename thrust::iterator_difference<InputIterator1>::type n = thrust::distance(first1,last1);
|
||
|
|
||
|
typedef typename thrust::iterator_system<InputIterator1>::type FromSystem1;
|
||
|
typedef typename thrust::iterator_system<InputIterator2>::type FromSystem2;
|
||
|
|
||
|
// bring both ranges to the host system
|
||
|
// note that these copies are no-ops if the range is already convertible to the host system
|
||
|
FromSystem1 from_system1;
|
||
|
FromSystem2 from_system2;
|
||
|
thrust::host_system_tag to_system;
|
||
|
thrust::detail::move_to_system<InputIterator1, FromSystem1, thrust::host_system_tag> rng1(from_system1, to_system, first1, last1);
|
||
|
thrust::detail::move_to_system<InputIterator2, FromSystem2, thrust::host_system_tag> rng2(from_system2, to_system, first2, first2 + n);
|
||
|
|
||
|
return thrust::equal(rng1.begin(), rng1.end(), rng2.begin());
|
||
|
}
|
||
|
|
||
|
template <typename InputIterator1, typename InputIterator2>
|
||
|
bool vector_equal(InputIterator1 first1, InputIterator1 last1,
|
||
|
InputIterator2 first2)
|
||
|
{
|
||
|
typedef typename thrust::iterator_system<InputIterator1>::type system1;
|
||
|
typedef typename thrust::iterator_system<InputIterator2>::type system2;
|
||
|
|
||
|
// dispatch on the sameness of the two systems
|
||
|
return vector_equal(first1, last1, first2,
|
||
|
thrust::detail::is_same<system1,system2>());
|
||
|
}
|
||
|
|
||
|
} // end namespace detail
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
template<typename T1, typename Alloc1,
|
||
|
typename T2, typename Alloc2>
|
||
|
bool operator==(const detail::vector_base<T1,Alloc1>& lhs,
|
||
|
const detail::vector_base<T2,Alloc2>& rhs)
|
||
|
{
|
||
|
return lhs.size() == rhs.size() && detail::vector_equal(lhs.begin(), lhs.end(), rhs.begin());
|
||
|
}
|
||
|
|
||
|
template<typename T1, typename Alloc1,
|
||
|
typename T2, typename Alloc2>
|
||
|
bool operator==(const detail::vector_base<T1,Alloc1>& lhs,
|
||
|
const std::vector<T2,Alloc2>& rhs)
|
||
|
{
|
||
|
return lhs.size() == rhs.size() && detail::vector_equal(lhs.begin(), lhs.end(), rhs.begin());
|
||
|
}
|
||
|
|
||
|
template<typename T1, typename Alloc1,
|
||
|
typename T2, typename Alloc2>
|
||
|
bool operator==(const std::vector<T1,Alloc1>& lhs,
|
||
|
const detail::vector_base<T2,Alloc2>& rhs)
|
||
|
{
|
||
|
return lhs.size() == rhs.size() && detail::vector_equal(lhs.begin(), lhs.end(), rhs.begin());
|
||
|
}
|
||
|
|
||
|
template<typename T1, typename Alloc1,
|
||
|
typename T2, typename Alloc2>
|
||
|
bool operator!=(const detail::vector_base<T1,Alloc1>& lhs,
|
||
|
const detail::vector_base<T2,Alloc2>& rhs)
|
||
|
{
|
||
|
return !(lhs == rhs);
|
||
|
}
|
||
|
|
||
|
template<typename T1, typename Alloc1,
|
||
|
typename T2, typename Alloc2>
|
||
|
bool operator!=(const detail::vector_base<T1,Alloc1>& lhs,
|
||
|
const std::vector<T2,Alloc2>& rhs)
|
||
|
{
|
||
|
return !(lhs == rhs);
|
||
|
}
|
||
|
|
||
|
template<typename T1, typename Alloc1,
|
||
|
typename T2, typename Alloc2>
|
||
|
bool operator!=(const std::vector<T1,Alloc1>& lhs,
|
||
|
const detail::vector_base<T2,Alloc2>& rhs)
|
||
|
{
|
||
|
return !(lhs == rhs);
|
||
|
}
|
||
|
|
||
|
} // end thrust
|
||
|
|