+// Copyright 2002 The Trustees of Indiana University.
+
+// 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)
+
+// Boost.MultiArray Library
+// Authors: Ronald Garcia
+// Jeremy Siek
+// Andrew Lumsdaine
+// See http://www.boost.org/libs/multi_array for documentation.
+
#ifndef BASE_RG071801_HPP
#define BASE_RG071801_HPP
#include "boost/multi_array/storage_order.hpp"
#include "boost/multi_array/types.hpp"
#include "boost/config.hpp"
-#include "boost/multi_array/iterator_adaptors.hpp"
+#include "boost/multi_array/concept_checks.hpp" //for ignore_unused_...
+#include "boost/mpl/eval_if.hpp"
+#include "boost/mpl/if.hpp"
+#include "boost/mpl/size_t.hpp"
+#include "boost/mpl/aux_/msvc_eti_base.hpp"
+#include "boost/iterator/reverse_iterator.hpp"
#include "boost/static_assert.hpp"
#include "boost/type.hpp"
-#include <cassert>
+#include "boost/assert.hpp"
#include <cstddef>
#include <memory>
template <typename T, std::size_t NumDims, typename TPtr = const T*>
class const_sub_array;
-template <typename T, std::size_t NumDims, typename value_type,
- typename reference_type, typename tag, typename difference_type>
-struct iterator_generator;
-
-template <typename T, std::size_t NumDims, typename value_type,
- typename reference_type, typename tag, typename difference_type>
-struct const_iterator_generator;
-
-template <typename T, std::size_t NumDims, typename value_type,
- typename reference_type, typename tag, typename difference_type>
-struct reverse_iterator_generator;
-
-template <typename T, std::size_t NumDims, typename value_type,
- typename reference_type, typename tag, typename difference_type>
-struct const_reverse_iterator_generator;
-
-template <typename T,typename TPtr>
-struct iterator_base;
-
-template <typename T, std::size_t NumDims>
-struct iterator_policies;
+template <typename T, typename TPtr, typename NumDims, typename Reference>
+class array_iterator;
template <typename T, std::size_t NumDims, typename TPtr = const T*>
class const_multi_array_view;
// used by array operator[] and iterators to get reference types.
template <typename Reference, typename TPtr>
Reference access(boost::type<Reference>,index idx,TPtr base,
- const size_type* extents,
- const index* strides,
- const index* index_base) const {
+ const size_type* extents,
+ const index* strides,
+ const index* index_bases) const {
+ BOOST_ASSERT(idx - index_bases[0] >= 0);
+ BOOST_ASSERT(size_type(idx - index_bases[0]) < extents[0]);
// return a sub_array<T,NDims-1> proxy object
TPtr newbase = base + idx * strides[0];
- return Reference(newbase,extents+1,strides+1,index_base+1);
+ return Reference(newbase,extents+1,strides+1,index_bases+1);
}
// used by array operator[] and iterators to get reference types.
template <typename Reference, typename TPtr>
Reference access(boost::type<Reference>,index idx,TPtr base,
- const size_type*,
- const index* strides,
- const index*) const {
+ const size_type* extents,
+ const index* strides,
+ const index* index_bases) const {
+
+ ignore_unused_variable_warning(index_bases);
+ ignore_unused_variable_warning(extents);
+ BOOST_ASSERT(idx - index_bases[0] >= 0);
+ BOOST_ASSERT(size_type(idx - index_bases[0]) < extents[0]);
return *(base + idx * strides[0]);
}
// choose value accessor begins
//
+template <typename T, std::size_t NumDims>
struct choose_value_accessor_n {
- template <typename T, std::size_t NumDims>
- struct bind {
- typedef value_accessor_n<T,NumDims> type;
- };
+ typedef value_accessor_n<T,NumDims> type;
};
+template <typename T>
struct choose_value_accessor_one {
- template <typename T, std::size_t NumDims>
- struct bind {
- typedef value_accessor_one<T> type;
- };
+ typedef value_accessor_one<T> type;
};
-
-template <std::size_t NumDims>
-struct value_accessor_gen_helper {
- typedef choose_value_accessor_n choice;
+template <typename T, typename NumDims>
+struct value_accessor_generator {
+ BOOST_STATIC_CONSTANT(std::size_t, dimensionality = NumDims::value);
+
+ typedef typename
+ mpl::eval_if_c<(dimensionality == 1),
+ choose_value_accessor_one<T>,
+ choose_value_accessor_n<T,dimensionality>
+ >::type type;
};
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+
+struct eti_value_accessor
+{
+ typedef int index;
+ typedef int size_type;
+ typedef int element;
+ typedef int index_range;
+ typedef int value_type;
+ typedef int reference;
+ typedef int const_reference;
+};
+
template <>
-struct value_accessor_gen_helper<1> {
- typedef choose_value_accessor_one choice;
+struct value_accessor_generator<int,int>
+{
+ typedef eti_value_accessor type;
};
-template <typename T, std::size_t NumDims>
-struct value_accessor_generator {
-private:
- typedef typename value_accessor_gen_helper<NumDims>::choice Choice;
-public:
- typedef typename Choice::template bind<T,NumDims>::type type;
-};
+template <class T, class NumDims>
+struct associated_types
+ : mpl::aux::msvc_eti_base<
+ typename value_accessor_generator<T,NumDims>::type
+ >::type
+{};
-//
-// choose value accessor ends
-/////////////////////////////////////////////////////////////////////////
+template <>
+struct associated_types<int,int> : eti_value_accessor {};
+#else
+template <class T, class NumDims>
+struct associated_types
+ : value_accessor_generator<T,NumDims>::type
+{};
+
+#endif
+
+//
+// choose value accessor ends
/////////////////////////////////////////////////////////////////////////
-// multi_array/sub_array base stuffs
-/////////////////////////////////////////////////////////////////////////
-template <std::size_t NumDims>
-struct iterator_tag_selector {
- typedef std::input_iterator_tag type;
-};
-template <>
-struct iterator_tag_selector<1> {
- typedef std::random_access_iterator_tag type;
-};
////////////////////////////////////////////////////////////////////////
// multi_array_base
////////////////////////////////////////////////////////////////////////
template <typename T, std::size_t NumDims>
-class multi_array_impl_base :
- public value_accessor_generator<T,NumDims>::type {
- typedef typename value_accessor_generator<T,NumDims>::type super_type;
+class multi_array_impl_base
+ :
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+ public mpl::aux::msvc_eti_base<
+ typename value_accessor_generator<T,mpl::size_t<NumDims> >::type
+ >::type
+#else
+ public value_accessor_generator<T,mpl::size_t<NumDims> >::type
+#endif
+{
+ typedef associated_types<T,mpl::size_t<NumDims> > types;
public:
- typedef typename super_type::index index;
- typedef typename super_type::size_type size_type;
- typedef typename super_type::element element;
- typedef typename super_type::index_range index_range;
- typedef typename super_type::value_type value_type;
- typedef typename super_type::reference reference;
- typedef typename super_type::const_reference const_reference;
+ typedef typename types::index index;
+ typedef typename types::size_type size_type;
+ typedef typename types::element element;
+ typedef typename types::index_range index_range;
+ typedef typename types::value_type value_type;
+ typedef typename types::reference reference;
+ typedef typename types::const_reference const_reference;
template <std::size_t NDims>
struct subarray {
//
// iterator support
//
+ typedef array_iterator<T,T*,mpl::size_t<NumDims>,reference> iterator;
+ typedef array_iterator<T,T const*,mpl::size_t<NumDims>,const_reference> const_iterator;
- typedef typename iterator_tag_selector<NumDims>::type iterator_tag;
-
- typedef typename
- iterator_generator<T,NumDims,value_type,
- reference,iterator_tag,index>::type iterator;
-
- typedef typename
- const_iterator_generator<T,NumDims,value_type,
- const_reference,iterator_tag,index>::type const_iterator;
-
- typedef typename
- reverse_iterator_generator<T,NumDims,value_type,
- reference,iterator_tag,index>::type reverse_iterator;
-
- typedef typename
- const_reverse_iterator_generator<T,NumDims,value_type,
- const_reference,iterator_tag,index>::type const_reverse_iterator;
+ typedef ::boost::reverse_iterator<iterator> reverse_iterator;
+ typedef ::boost::reverse_iterator<const_iterator> const_reverse_iterator;
+ BOOST_STATIC_CONSTANT(std::size_t, dimensionality = NumDims);
protected:
- typedef iterator_base<T,T*> iter_base;
- typedef iterator_base<T,const T*> const_iter_base;
multi_array_impl_base() { }
~multi_array_impl_base() { }
// Used by operator() in our array classes
template <typename Reference, typename IndexList, typename TPtr>
- Reference access_element(boost::type<Reference>, TPtr base,
- const IndexList& indices,
- const index* strides) const {
+ Reference access_element(boost::type<Reference>,
+ const IndexList& indices,
+ TPtr base,
+ const size_type* extents,
+ const index* strides,
+ const index* index_bases) const {
+
+ ignore_unused_variable_warning(index_bases);
+ ignore_unused_variable_warning(extents);
+#if !defined(NDEBUG) && !defined(BOOST_DISABLE_ASSERTS)
+ for (size_type i = 0; i != NumDims; ++i) {
+ BOOST_ASSERT(indices[i] - index_bases[i] >= 0);
+ BOOST_ASSERT(size_type(indices[i] - index_bases[i]) < extents[i]);
+ }
+#endif
+
index offset = 0;
for (size_type n = 0; n != NumDims; ++n)
offset += indices[n] * strides[n];
template <typename StrideList, typename ExtentList>
void compute_strides(StrideList& stride_list, ExtentList& extent_list,
- const general_storage_order<NumDims>& storage)
+ const general_storage_order<NumDims>& storage)
{
// invariant: stride = the stride for dimension n
index stride = 1;
index stride_sign = +1;
if (!storage.ascending(storage.ordering(n)))
- stride_sign = -1;
+ stride_sign = -1;
// The stride for this dimension is the product of the
// lengths of the ranks minor to it.
template <typename StrideList, typename ExtentList, typename BaseList>
index
calculate_origin_offset(const StrideList& stride_list,
- const ExtentList& extent_list,
- const general_storage_order<NumDims>& storage,
- const BaseList& index_base_list)
+ const ExtentList& extent_list,
+ const general_storage_order<NumDims>& storage,
+ const BaseList& index_base_list)
{
return
calculate_descending_dimension_offset(stride_list,extent_list,
- storage) +
+ storage) +
calculate_indexing_offset(stride_list,index_base_list);
}
template <typename StrideList, typename ExtentList>
index
calculate_descending_dimension_offset(const StrideList& stride_list,
- const ExtentList& extent_list,
- const general_storage_order<NumDims>& storage)
+ const ExtentList& extent_list,
+ const general_storage_order<NumDims>& storage)
{
index offset = 0;
if (!storage.all_dims_ascending())
for (size_type n = 0; n != NumDims; ++n)
- if (!storage.ascending(n))
- offset -= (extent_list[n] - 1) * stride_list[n];
+ if (!storage.ascending(n))
+ offset -= (extent_list[n] - 1) * stride_list[n];
return offset;
}
template <typename StrideList, typename BaseList>
index
calculate_indexing_offset(const StrideList& stride_list,
- const BaseList& index_base_list)
+ const BaseList& index_base_list)
{
index offset = 0;
for (size_type n = 0; n != NumDims; ++n)
- offset -= stride_list[n] * index_base_list[n];
+ offset -= stride_list[n] * index_base_list[n];
return offset;
}
template <typename ArrayRef, int NDims, typename TPtr>
ArrayRef
generate_array_view(boost::type<ArrayRef>,
- const boost::detail::multi_array::
- index_gen<NumDims,NDims>& indices,
- const size_type* extents,
- const index* strides,
- const index* index_bases,
- TPtr base) const {
+ const boost::detail::multi_array::
+ index_gen<NumDims,NDims>& indices,
+ const size_type* extents,
+ const index* strides,
+ const index* index_bases,
+ TPtr base) const {
boost::array<index,NDims> new_strides;
boost::array<index,NDims> new_extents;
index start = current_range.get_start(default_start);
index finish = current_range.get_finish(default_finish);
index index_factor = current_range.stride();
- index len = (finish - start) / index_factor;
+ index len = (finish - start + (index_factor - 1)) / index_factor;
+
+ BOOST_ASSERT(index_bases[n] <= start &&
+ start <= index_bases[n]+index(extents[n]));
+ BOOST_ASSERT(index_bases[n] <= finish &&
+ finish <= index_bases[n]+index(extents[n]));
+ BOOST_ASSERT(index_factor > 0);
// the array data pointer is modified to account for non-zero
// bases during slicing (see [Garcia] for the math involved)
if (!current_range.is_degenerate()) {
- // The index_factor for each dimension is included into the
- // strides for the array_view (see [Garcia] for the math involved).
- new_strides[dim] = index_factor * strides[n];
-
- // calculate new extents
- new_extents[dim] = len;
- ++dim;
+ // The index_factor for each dimension is included into the
+ // strides for the array_view (see [Garcia] for the math involved).
+ new_strides[dim] = index_factor * strides[n];
+
+ // calculate new extents
+ new_extents[dim] = len;
+ ++dim;
}
}
- assert (dim == NDims);
+ BOOST_ASSERT(dim == NDims);
return
ArrayRef(base+offset,
- new_extents,
- new_strides);
+ new_extents,
+ new_strides);
}
-
+
};