#include "boost/multi_array/multi_array_ref.hpp"
#include "boost/multi_array/algorithm.hpp"
#include "boost/array.hpp"
+#include "boost/mpl/if.hpp"
#include "boost/type_traits.hpp"
#include <algorithm>
#include <cstddef>
namespace boost {
namespace detail {
namespace multi_array {
+
struct populate_index_ranges {
multi_array_types::index_range
+ // RG: underscore on extent_ to stifle strange MSVC warning.
operator()(multi_array_types::index base,
- multi_array_types::size_type extent) {
- return multi_array_types::index_range(base,base+extent);
+ multi_array_types::size_type extent_) {
+ return multi_array_types::index_range(base,base+extent_);
}
};
+
+#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+//
+// Compilers that don't support partial ordering may need help to
+// disambiguate multi_array's templated constructors. Even vc6/7 are
+// capable of some limited SFINAE, so we take the most-general version
+// out of the overload set with disable_multi_array_impl.
+//
+template <typename T, std::size_t NumDims, typename TPtr>
+char is_multi_array_impl_help(const_multi_array_view<T,NumDims,TPtr>&);
+template <typename T, std::size_t NumDims, typename TPtr>
+char is_multi_array_impl_help(const_sub_array<T,NumDims,TPtr>&);
+template <typename T, std::size_t NumDims, typename TPtr>
+char is_multi_array_impl_help(const_multi_array_ref<T,NumDims,TPtr>&);
+
+char ( &is_multi_array_impl_help(...) )[2];
+
+template <class T>
+struct is_multi_array_impl
+{
+ static T x;
+ BOOST_STATIC_CONSTANT(bool, value = sizeof((is_multi_array_impl_help)(x)) == 1);
+
+ typedef mpl::bool_<value> type;
+};
+
+template <bool multi_array = false>
+struct disable_multi_array_impl_impl
+{
+ typedef int type;
+};
+
+template <>
+struct disable_multi_array_impl_impl<true>
+{
+ // forming a pointer to a reference triggers SFINAE
+ typedef int& type;
+};
+
+
+template <class T>
+struct disable_multi_array_impl :
+ disable_multi_array_impl_impl<is_multi_array_impl<T>::value>
+{ };
+
+
+template <>
+struct disable_multi_array_impl<int>
+{
+ typedef int type;
+};
+
+
+#endif
+
} //namespace multi_array
} // namespace detail
};
explicit multi_array() :
- super_type((T*)initial_base_) {
- allocate_space();
+ super_type((T*)initial_base_,c_storage_order(),
+ /*index_bases=*/0, /*extents=*/0) {
+ allocate_space();
}
-
+
template <class ExtentList>
explicit multi_array(
ExtentList const& extents
#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
- , typename detail::multi_array::disable_non_sub_array<ExtentList>::type* = 0
-#endif
- ) :
+ , typename mpl::if_<
+ detail::multi_array::is_multi_array_impl<ExtentList>,
+ int&,int>::type* = 0
+#endif
+ ) :
super_type((T*)initial_base_,extents) {
boost::function_requires<
detail::multi_array::CollectionConcept<ExtentList> >();
allocate_space();
}
+
template <class ExtentList>
explicit multi_array(ExtentList const& extents,
multi_array(const multi_array& rhs) :
super_type(rhs), allocator_(rhs.allocator_) {
allocate_space();
- boost::copy_n(rhs.base_,rhs.num_elements(),base_);
+ boost::detail::multi_array::copy_n(rhs.base_,rhs.num_elements(),base_);
}
+
+ //
+ // A multi_array is constructible from any multi_array_ref, subarray, or
+ // array_view object. The following constructors ensure that.
+ //
+
+ // Due to limited support for partial template ordering,
+ // MSVC 6&7 confuse the following with the most basic ExtentList
+ // constructor.
+#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())
+ {
+ allocate_space();
+ // Warning! storage order may change, hence the following copy technique.
+ std::copy(rhs.begin(),rhs.end(),this->begin());
+ }
+
+ 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())
+ {
+ allocate_space();
+ std::copy(rhs.begin(),rhs.end(),this->begin());
+ }
+
+
template <typename OPtr>
multi_array(const detail::multi_array::
- const_sub_array<T,NumDims,OPtr>& rhs) :
- super_type(rhs) {
+ 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())
+ {
+ allocate_space();
+ std::copy(rhs.begin(),rhs.end(),this->begin());
+ }
+
+#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+ // 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())
+ {
+ allocate_space();
+ // Warning! storage order may change, hence the following copy technique.
+ std::copy(rhs.begin(),rhs.end(),this->begin());
+ }
+
+ 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())
+ {
+ allocate_space();
+ // Warning! storage order may change, hence the following copy technique.
+ std::copy(rhs.begin(),rhs.end(),this->begin());
+ }
+
+ multi_array(const detail::multi_array::
+ const_sub_array<T,NumDims>& rhs)
+ : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape())
+ {
+ 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())
+ {
allocate_space();
std::copy(rhs.begin(),rhs.end(),this->begin());
}
- // For some reason, gcc 2.95.2 doesn't pick the above template
- // member function when passed a subarray, so i was forced to
- // duplicate the functionality here...
+
multi_array(const detail::multi_array::
- sub_array<T,NumDims>& rhs) :
- super_type(rhs) {
+ const_multi_array_view<T,NumDims>& rhs)
+ : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape())
+ {
+ 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())
+ {
+ 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())
+ {
+ allocate_space();
+ // Warning! storage order may change, hence the following copy technique.
+ std::copy(rhs.begin(),rhs.end(),this->begin());
+ }
+
+ multi_array(const multi_array_ref<T,NumDims>& rhs,
+ const general_storage_order<NumDims>& so)
+ : super_type(0,so,rhs.index_bases(),rhs.shape())
+ {
+ allocate_space();
+ // Warning! storage order may change, hence the following copy technique.
+ std::copy(rhs.begin(),rhs.end(),this->begin());
+ }
+
+
+ multi_array(const detail::multi_array::
+ sub_array<T,NumDims>& rhs)
+ : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape())
+ {
+ 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())
+ {
+ 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())
+ {
+ 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())
+ {
allocate_space();
std::copy(rhs.begin(),rhs.end(),this->begin());
}
}
+ template <typename ExtentList>
+ multi_array& resize(const ExtentList& extents) {
+ boost::function_requires<
+ detail::multi_array::CollectionConcept<ExtentList> >();
+
+ typedef detail::multi_array::extent_gen<NumDims> gen_type;
+ gen_type ranges;
+
+ for (int i=0; i != NumDims; ++i) {
+ typedef typename gen_type::range range_type;
+ ranges.ranges_[i] = range_type(0,extents[i]);
+ }
+
+ return this->resize(ranges);
+ }
+
+
+
multi_array& resize(const detail::multi_array
::extent_gen<NumDims>& ranges) {
// build a multi_array with the specs given
- multi_array new_array(ranges);
+ multi_array new_array(ranges,this->storage_order());
// build a view of tmp with the minimum extents
std::transform(new_array.index_base_list_.begin(),
new_array.index_base_list_.end(),
- min_extents.begin(),old_idxes.ranges_.begin(),
+ min_extents.begin(),new_idxes.ranges_.begin(),
detail::multi_array::populate_index_ranges());
std::transform(this->index_base_list_.begin(),
this->index_base_list_.end(),
- min_extents.begin(),new_idxes.ranges_.begin(),
+ min_extents.begin(),old_idxes.ranges_.begin(),
detail::multi_array::populate_index_ranges());
// Build same-shape views of the two arrays