// Copyright 2002 The Trustees of Indiana University.
+// Copyright 2018 Glen Joseph Fernandes
+// (glenjofe@gmail.com)
+
// Use, modification and distribution is subject to 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)
#include "boost/multi_array/subarray.hpp"
#include "boost/multi_array/multi_array_ref.hpp"
#include "boost/multi_array/algorithm.hpp"
+#include "boost/core/alloc_construct.hpp"
+#include "boost/core/empty_value.hpp"
#include "boost/array.hpp"
#include "boost/mpl/if.hpp"
#include "boost/type_traits.hpp"
template<typename T, std::size_t NumDims,
typename Allocator>
class multi_array :
- public multi_array_ref<T,NumDims>
+ public multi_array_ref<T,NumDims>,
+ private boost::empty_value<Allocator>
{
+ typedef boost::empty_value<Allocator> alloc_base;
typedef multi_array_ref<T,NumDims> super_type;
public:
typedef typename super_type::value_type value_type;
typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
};
- explicit multi_array() :
+ explicit multi_array(const Allocator& alloc = Allocator()) :
super_type((T*)initial_base_,c_storage_order(),
- /*index_bases=*/0, /*extents=*/0) {
+ /*index_bases=*/0, /*extents=*/0),
+ alloc_base(boost::empty_init_t(),alloc) {
allocate_space();
}
template <class ExtentList>
explicit multi_array(
- ExtentList const& extents
+ ExtentList const& extents,
+ const Allocator& alloc = Allocator()
#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
, typename mpl::if_<
detail::multi_array::is_multi_array_impl<ExtentList>,
int&,int>::type* = 0
#endif
) :
- super_type((T*)initial_base_,extents) {
+ super_type((T*)initial_base_,extents),
+ alloc_base(boost::empty_init_t(),alloc) {
boost::function_requires<
detail::multi_array::CollectionConcept<ExtentList> >();
allocate_space();
template <class ExtentList>
explicit multi_array(ExtentList const& extents,
const general_storage_order<NumDims>& so) :
- super_type((T*)initial_base_,extents,so) {
+ super_type((T*)initial_base_,extents,so),
+ alloc_base(boost::empty_init_t()) {
boost::function_requires<
detail::multi_array::CollectionConcept<ExtentList> >();
allocate_space();
explicit multi_array(ExtentList const& extents,
const general_storage_order<NumDims>& so,
Allocator const& alloc) :
- super_type((T*)initial_base_,extents,so), allocator_(alloc) {
+ super_type((T*)initial_base_,extents,so),
+ alloc_base(boost::empty_init_t(),alloc) {
boost::function_requires<
detail::multi_array::CollectionConcept<ExtentList> >();
allocate_space();
explicit multi_array(const detail::multi_array
- ::extent_gen<NumDims>& ranges) :
- super_type((T*)initial_base_,ranges) {
+ ::extent_gen<NumDims>& ranges,
+ const Allocator& alloc = Allocator()) :
+ super_type((T*)initial_base_,ranges),
+ alloc_base(boost::empty_init_t(),alloc) {
allocate_space();
}
explicit multi_array(const detail::multi_array
::extent_gen<NumDims>& ranges,
const general_storage_order<NumDims>& so) :
- super_type((T*)initial_base_,ranges,so) {
+ super_type((T*)initial_base_,ranges,so),
+ alloc_base(boost::empty_init_t()) {
allocate_space();
}
::extent_gen<NumDims>& ranges,
const general_storage_order<NumDims>& so,
Allocator const& alloc) :
- super_type((T*)initial_base_,ranges,so), allocator_(alloc) {
+ super_type((T*)initial_base_,ranges,so),
+ alloc_base(boost::empty_init_t(),alloc) {
allocate_space();
}
multi_array(const multi_array& rhs) :
- super_type(rhs), allocator_(rhs.allocator_) {
+ super_type(rhs),
+ alloc_base(static_cast<const alloc_base&>(rhs)) {
allocate_space();
boost::detail::multi_array::copy_n(rhs.base_,rhs.num_elements(),base_);
}
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
template <typename OPtr>
multi_array(const const_multi_array_ref<T,NumDims,OPtr>& rhs,
- const general_storage_order<NumDims>& so = c_storage_order())
- : super_type(0,so,rhs.index_bases(),rhs.shape())
+ const general_storage_order<NumDims>& so = c_storage_order(),
+ const Allocator& alloc = Allocator())
+ : super_type(0,so,rhs.index_bases(),rhs.shape()),
+ alloc_base(boost::empty_init_t(),alloc)
{
allocate_space();
// Warning! storage order may change, hence the following copy technique.
template <typename OPtr>
multi_array(const detail::multi_array::
const_sub_array<T,NumDims,OPtr>& rhs,
- const general_storage_order<NumDims>& so = c_storage_order())
- : super_type(0,so,rhs.index_bases(),rhs.shape())
+ const general_storage_order<NumDims>& so = c_storage_order(),
+ const Allocator& alloc = Allocator())
+ : super_type(0,so,rhs.index_bases(),rhs.shape()),
+ alloc_base(boost::empty_init_t(),alloc)
{
allocate_space();
std::copy(rhs.begin(),rhs.end(),this->begin());
template <typename OPtr>
multi_array(const detail::multi_array::
const_multi_array_view<T,NumDims,OPtr>& rhs,
- const general_storage_order<NumDims>& so = c_storage_order())
- : super_type(0,so,rhs.index_bases(),rhs.shape())
+ const general_storage_order<NumDims>& so = c_storage_order(),
+ const Allocator& alloc = Allocator())
+ : super_type(0,so,rhs.index_bases(),rhs.shape()),
+ alloc_base(boost::empty_init_t(),alloc)
{
allocate_space();
std::copy(rhs.begin(),rhs.end(),this->begin());
// More limited support for MSVC
- multi_array(const const_multi_array_ref<T,NumDims>& rhs)
- : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape())
+ multi_array(const const_multi_array_ref<T,NumDims>& rhs,
+ const Allocator& alloc = Allocator())
+ : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()),
+ alloc_base(boost::empty_init_t(),alloc)
{
allocate_space();
// Warning! storage order may change, hence the following copy technique.
}
multi_array(const const_multi_array_ref<T,NumDims>& rhs,
- const general_storage_order<NumDims>& so)
- : super_type(0,so,rhs.index_bases(),rhs.shape())
+ const general_storage_order<NumDims>& so,
+ const Allocator& alloc = Allocator())
+ : super_type(0,so,rhs.index_bases(),rhs.shape()),
+ alloc_base(boost::empty_init_t(),alloc)
{
allocate_space();
// Warning! storage order may change, hence the following copy technique.
}
multi_array(const detail::multi_array::
- const_sub_array<T,NumDims>& rhs)
- : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape())
+ const_sub_array<T,NumDims>& rhs,
+ const Allocator& alloc = Allocator())
+ : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()),
+ alloc_base(boost::empty_init_t(),alloc)
{
allocate_space();
std::copy(rhs.begin(),rhs.end(),this->begin());
multi_array(const detail::multi_array::
const_sub_array<T,NumDims>& rhs,
- const general_storage_order<NumDims>& so)
- : super_type(0,so,rhs.index_bases(),rhs.shape())
+ const general_storage_order<NumDims>& so,
+ const Allocator& alloc = Allocator())
+ : super_type(0,so,rhs.index_bases(),rhs.shape()),
+ alloc_base(boost::empty_init_t(),alloc)
{
allocate_space();
std::copy(rhs.begin(),rhs.end(),this->begin());
multi_array(const detail::multi_array::
- const_multi_array_view<T,NumDims>& rhs)
- : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape())
+ const_multi_array_view<T,NumDims>& rhs,
+ const Allocator& alloc = Allocator())
+ : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()),
+ alloc_base(boost::empty_init_t(),alloc)
{
allocate_space();
std::copy(rhs.begin(),rhs.end(),this->begin());
multi_array(const detail::multi_array::
const_multi_array_view<T,NumDims>& rhs,
- const general_storage_order<NumDims>& so)
- : super_type(0,so,rhs.index_bases(),rhs.shape())
+ const general_storage_order<NumDims>& so,
+ const Allocator& alloc = Allocator())
+ : super_type(0,so,rhs.index_bases(),rhs.shape()),
+ alloc_base(boost::empty_init_t(),alloc)
{
allocate_space();
std::copy(rhs.begin(),rhs.end(),this->begin());
#endif // !BOOST_NO_FUNCTION_TEMPLATE_ORDERING
// Thes constructors are necessary because of more exact template matches.
- multi_array(const multi_array_ref<T,NumDims>& rhs)
- : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape())
+ multi_array(const multi_array_ref<T,NumDims>& rhs,
+ const Allocator& alloc = Allocator())
+ : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()),
+ alloc_base(boost::empty_init_t(),alloc)
{
allocate_space();
// Warning! storage order may change, hence the following copy technique.
}
multi_array(const multi_array_ref<T,NumDims>& rhs,
- const general_storage_order<NumDims>& so)
- : super_type(0,so,rhs.index_bases(),rhs.shape())
+ const general_storage_order<NumDims>& so,
+ const Allocator& alloc = Allocator())
+ : super_type(0,so,rhs.index_bases(),rhs.shape()),
+ alloc_base(boost::empty_init_t(),alloc)
{
allocate_space();
// Warning! storage order may change, hence the following copy technique.
multi_array(const detail::multi_array::
- sub_array<T,NumDims>& rhs)
- : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape())
+ sub_array<T,NumDims>& rhs,
+ const Allocator& alloc = Allocator())
+ : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()),
+ alloc_base(boost::empty_init_t(),alloc)
{
allocate_space();
std::copy(rhs.begin(),rhs.end(),this->begin());
multi_array(const detail::multi_array::
sub_array<T,NumDims>& rhs,
- const general_storage_order<NumDims>& so)
- : super_type(0,so,rhs.index_bases(),rhs.shape())
+ const general_storage_order<NumDims>& so,
+ const Allocator& alloc = Allocator())
+ : super_type(0,so,rhs.index_bases(),rhs.shape()),
+ alloc_base(boost::empty_init_t(),alloc)
{
allocate_space();
std::copy(rhs.begin(),rhs.end(),this->begin());
multi_array(const detail::multi_array::
- multi_array_view<T,NumDims>& rhs)
- : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape())
+ multi_array_view<T,NumDims>& rhs,
+ const Allocator& alloc = Allocator())
+ : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()),
+ alloc_base(boost::empty_init_t(),alloc)
{
allocate_space();
std::copy(rhs.begin(),rhs.end(),this->begin());
multi_array(const detail::multi_array::
multi_array_view<T,NumDims>& rhs,
- const general_storage_order<NumDims>& so)
- : super_type(0,so,rhs.index_bases(),rhs.shape())
+ const general_storage_order<NumDims>& so,
+ const Allocator& alloc = Allocator())
+ : super_type(0,so,rhs.index_bases(),rhs.shape()),
+ alloc_base(boost::empty_init_t(),alloc)
{
allocate_space();
std::copy(rhs.begin(),rhs.end(),this->begin());
// build a multi_array with the specs given
- multi_array new_array(ranges,this->storage_order());
+ multi_array new_array(ranges,this->storage_order(),allocator());
// build a view of tmp with the minimum extents
using std::swap;
// Swap the internals of these arrays.
swap(this->super_type::base_,new_array.super_type::base_);
+ swap(this->allocator(),new_array.allocator());
swap(this->storage_,new_array.storage_);
swap(this->extent_list_,new_array.extent_list_);
swap(this->stride_list_,new_array.stride_list_);
swap(this->origin_offset_,new_array.origin_offset_);
swap(this->directional_offset_,new_array.directional_offset_);
swap(this->num_elements_,new_array.num_elements_);
- swap(this->allocator_,new_array.allocator_);
swap(this->base_,new_array.base_);
swap(this->allocated_elements_,new_array.allocated_elements_);
}
private:
+ friend inline bool operator==(const multi_array& a, const multi_array& b) {
+ return a.base() == b.base();
+ }
+
+ friend inline bool operator!=(const multi_array& a, const multi_array& b) {
+ return !(a == b);
+ }
+
+ const super_type& base() const {
+ return *this;
+ }
+
+ const Allocator& allocator() const {
+ return alloc_base::get();
+ }
+
+ Allocator& allocator() {
+ return alloc_base::get();
+ }
+
void allocate_space() {
- typename Allocator::const_pointer no_hint=0;
- base_ = allocator_.allocate(this->num_elements(),no_hint);
+ base_ = allocator().allocate(this->num_elements());
this->set_base_ptr(base_);
allocated_elements_ = this->num_elements();
- std::uninitialized_fill_n(base_,allocated_elements_,T());
+ boost::alloc_construct_n(allocator(),base_,allocated_elements_);
}
void deallocate_space() {
if(base_) {
- for(T* i = base_; i != base_+allocated_elements_; ++i)
- allocator_.destroy(i);
- allocator_.deallocate(base_,allocated_elements_);
+ boost::alloc_destroy_n(allocator(),base_,allocated_elements_);
+ allocator().deallocate(base_,allocated_elements_);
}
}
typedef boost::array<size_type,NumDims> size_list;
typedef boost::array<index,NumDims> index_list;
- Allocator allocator_;
T* base_;
size_type allocated_elements_;
enum {initial_base_ = 0};